Просмотр исходного кода

清理: 删除整条 /transition 路由 + Cesium 过渡链

/transition 路由从未被任何代码导航 (grep 整个 src/ 0 命中 push/router-link),
登录直接 push /main, 整条 Cesium 过渡流程实际未使用。完整删除链:

- src/views/TransitionPage.vue      (路由对应视图)
- src/components/CesiumTransition.vue (省份高亮过渡组件)
- src/components/GlobeTransition.vue  (废弃的地球过渡, 已被 CesiumTransition 替代)
- src/utils/cesiumPreloader.js        (Login 预加载 + CesiumTransition 复用)

同步清理引用:
- router/index.js 删 TransitionPage import + /transition 路由项
- Login.vue created() 钩子整段删 (不再预加载 Cesium)

收益:
- 源码 -1894 行
- app.js 1040 → 1023 KiB (-17 KiB, -1.6%)
- Login 不再 dynamic import cesiumPreloader, 首屏加载更快
- vendors.js 暂不变, 下一 commit 卸载 cesium 包后会大幅下降
画安 недель назад: 3
Родитель
Сommit
eaecd11a85

+ 0 - 559
src/components/CesiumTransition.vue

@@ -1,559 +0,0 @@
-<template>
-  <div class="cesium-transition-wrapper">
-    <div ref="cesiumContainer" class="cesium-container"></div>
-    <img
-      v-if="microImage"
-      ref="microOverlay"
-      :src="microImage"
-      class="micro-overlay"
-    />
-    <div class="ui-layer">
-      <div
-        v-if="poi"
-        ref="poiLabel"
-        class="html-label"
-        :style="{ color: poi.fontColor || '#00ffff', fontSize: (poi.fontSize || 20) + 'px', opacity: 0, display: 'none' }"
-      >
-        {{ poi.label }}
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import CesiumPreloader from '@/utils/cesiumPreloader';
-const Cesium = window.Cesium;
-
-function createOuterRingTexture(color) {
-  const size = 1024, cx = size / 2, cy = size / 2, radius = size / 2 - 20;
-  const lineWidth = 16, baseColorStr = color.toCssColorString();
-  const canvas = document.createElement('canvas'); canvas.width = size; canvas.height = size; const ctx = canvas.getContext('2d');
-  const solidCanvas = document.createElement('canvas'); solidCanvas.width = size; solidCanvas.height = size; const solidCtx = solidCanvas.getContext('2d'); solidCtx.lineWidth = lineWidth; solidCtx.strokeStyle = baseColorStr; solidCtx.shadowBlur = 10; solidCtx.shadowColor = baseColorStr; solidCtx.beginPath(); solidCtx.arc(cx, cy, radius, 0, Math.PI * 2); solidCtx.stroke();
-  const dashedCanvas = document.createElement('canvas'); dashedCanvas.width = size; dashedCanvas.height = size; const dashedCtx = dashedCanvas.getContext('2d'); dashedCtx.lineWidth = lineWidth; dashedCtx.strokeStyle = baseColorStr; dashedCtx.setLineDash([12, 12]); dashedCtx.shadowBlur = 10; dashedCtx.shadowColor = baseColorStr; dashedCtx.beginPath(); dashedCtx.arc(cx, cy, radius, 0, Math.PI * 2); dashedCtx.stroke();
-  const solidMask = ctx.createConicGradient(0, cx, cy); solidMask.addColorStop(0.0, 'rgba(0,0,0,0)'); solidMask.addColorStop(0.10, 'rgba(0,0,0,0)'); solidMask.addColorStop(0.18, 'rgba(0,0,0,1)'); solidMask.addColorStop(0.48, 'rgba(0,0,0,1)'); solidMask.addColorStop(0.50, 'rgba(0,0,0,0)'); solidMask.addColorStop(0.60, 'rgba(0,0,0,0)'); solidMask.addColorStop(0.68, 'rgba(0,0,0,1)'); solidMask.addColorStop(0.98, 'rgba(0,0,0,1)'); solidMask.addColorStop(1.0, 'rgba(0,0,0,0)');
-  const dashedMask = ctx.createConicGradient(0, cx, cy); dashedMask.addColorStop(0.0, 'rgba(0,0,0,0)'); dashedMask.addColorStop(0.02, 'rgba(0,0,0,1)'); dashedMask.addColorStop(0.10, 'rgba(0,0,0,1)'); dashedMask.addColorStop(0.18, 'rgba(0,0,0,0)'); dashedMask.addColorStop(0.50, 'rgba(0,0,0,0)'); dashedMask.addColorStop(0.52, 'rgba(0,0,0,1)'); dashedMask.addColorStop(0.60, 'rgba(0,0,0,1)'); dashedMask.addColorStop(0.68, 'rgba(0,0,0,0)'); dashedMask.addColorStop(1.0, 'rgba(0,0,0,0)');
-  ctx.drawImage(solidCanvas, 0, 0); ctx.globalCompositeOperation = 'destination-in'; ctx.fillStyle = solidMask; ctx.fillRect(0, 0, size, size);
-  const tempCanvas = document.createElement('canvas'); tempCanvas.width = size; tempCanvas.height = size; const tempCtx = tempCanvas.getContext('2d'); tempCtx.drawImage(dashedCanvas, 0, 0); tempCtx.globalCompositeOperation = 'destination-in'; tempCtx.fillStyle = dashedMask; tempCtx.fillRect(0, 0, size, size);
-  ctx.globalCompositeOperation = 'lighter'; ctx.drawImage(tempCanvas, 0, 0);
-  ctx.globalCompositeOperation = 'destination-over'; ctx.shadowBlur = 40; ctx.shadowColor = color.withAlpha(0.3).toCssColorString(); ctx.strokeStyle = color.withAlpha(0.08).toCssColorString(); ctx.lineWidth = 20; ctx.beginPath(); ctx.arc(cx, cy, radius, 0, Math.PI * 2); ctx.stroke();
-  return canvas.toDataURL();
-}
-
-function createScannerTexture(color) {
-  const canvas = document.createElement('canvas'); canvas.width = 512; canvas.height = 512; const ctx = canvas.getContext('2d');
-  const sharpColor = color.withAlpha(1.0).toCssColorString(); ctx.lineWidth = 3; ctx.strokeStyle = sharpColor; ctx.shadowBlur = 20; ctx.shadowColor = sharpColor; ctx.beginPath(); ctx.moveTo(256, 256); ctx.lineTo(506, 256); ctx.stroke(); return canvas.toDataURL();
-}
-
-function createLightBeamTexture(color) {
-  const canvas = document.createElement('canvas'); canvas.width = 64; canvas.height = 256; const ctx = canvas.getContext('2d');
-  const gradient = ctx.createLinearGradient(0, 256, 0, 0);
-  gradient.addColorStop(0, color.withAlpha(0.6).toCssColorString()); gradient.addColorStop(0.4, color.withAlpha(0.1).toCssColorString()); gradient.addColorStop(1, color.withAlpha(0.0).toCssColorString());
-  ctx.fillStyle = gradient; ctx.fillRect(0, 0, 64, 256); return canvas.toDataURL();
-}
-
-const TWO_PI = Math.PI * 2;
-
-export default {
-  name: 'CesiumTransition',
-  props: {
-    // 要高亮的省份名称
-    province: {
-      type: String,
-      default: '北京市'
-    },
-    // 微观标记点(null 则不显示POI)
-    poi: {
-      type: Object,
-      default: null
-    },
-    // 区域中心坐标 [lon, lat](无POI时用于相机定位)
-    districtCenter: {
-      type: Array,
-      default: null
-    },
-    // 路网数据
-    roads: {
-      type: Array,
-      default: () => [
-        { name: "阜石路-阜成路快速路", width: 12, glowPower: 0.3, color: '#00ffff', path: [[116.18, 39.93], [116.22, 39.93], [116.26, 39.928], [116.30, 39.925]] },
-        { name: "石景山路-复兴路", width: 12, glowPower: 0.3, color: '#ff3333', path: [[116.18, 39.907], [116.224, 39.907], [116.25, 39.906], [116.30, 39.905]] },
-        { name: "莲石东路快速路", width: 12, glowPower: 0.3, color: '#00ff00', path: [[116.18, 39.89], [116.22, 39.888], [116.26, 39.885], [116.30, 39.88]] },
-        { name: "西五环路", width: 10, glowPower: 0.25, color: '#ffaa00', path: [[116.205, 39.95], [116.203, 39.92], [116.202, 39.89], [116.20, 39.86]] },
-        { name: "玉泉路", width: 10, glowPower: 0.25, color: '#cc00ff', path: [[116.25, 39.94], [116.25, 39.907], [116.248, 39.88], [116.245, 39.86]] },
-        { name: "西四环路", width: 10, glowPower: 0.25, color: '#ffff00', path: [[116.285, 39.94], [116.283, 39.91], [116.28, 39.88], [116.278, 39.85]] }
-      ]
-    },
-    // 微观区域卫星底图
-    satelliteImage: {
-      type: Object,
-      default: () => ({
-        url: './beijing-satellite.jpg',
-        bounds: [116.10, 39.80, 116.38, 39.98]  // [west, south, east, north]
-      })
-    },
-    // 中国边界 GeoJSON 路径
-    boundaryUrl: {
-      type: String,
-      default: './china.json'
-    },
-    // 微观俯冲视角高度(米)
-    microViewRange: {
-      type: Number,
-      default: 10000
-    },
-    // 微观覆盖图片路径(淡入淡出展示)
-    microImage: {
-      type: String,
-      default: null
-    }
-  },
-  data() {
-    return {
-      isAnimating: false
-    };
-  },
-  mounted() {
-    this._viewer = null;
-    this._preRenderListener = null;
-    this._chinaDataSource = null;
-    this._chinaEffectsSource = null;
-    this._microEffectsSource = null;
-    this._macroAlpha = 0.0;
-    this._destroyed = false;
-    this._pendingTimers = [];
-
-    this._coords = { start: [-15.0, 35.86, 45000000], china: [104.19, 35.86, 14000000] };
-
-    this.$nextTick(async () => {
-      if (!this.$refs.cesiumContainer) return;
-      // 尝试复用预加载的 Viewer
-      const preloaded = await CesiumPreloader.acquire(this.$refs.cesiumContainer);
-      this.initCesium(preloaded);
-      if (!preloaded) {
-        await this.waitForGlobeReady();
-      }
-      if (!this._destroyed) this.startTransition();
-    });
-  },
-  beforeDestroy() {
-    this._destroyed = true;
-    this._pendingTimers.forEach(id => clearTimeout(id));
-    this._pendingTimers = [];
-    if (this._viewer) {
-      if (this._preRenderListener) {
-        this._viewer.scene.preRender.removeEventListener(this._preRenderListener);
-      }
-      // Cesium destroy() 内部会 removeChild,但 Vue 可能已移除 DOM,需要先确保容器在文档中
-      const cesiumWidget = this._viewer.cesiumWidget && this._viewer.cesiumWidget.container;
-      if (cesiumWidget && !cesiumWidget.parentNode) {
-        document.body.appendChild(cesiumWidget);
-      }
-      try {
-        this._viewer.destroy();
-      } catch (e) {
-        // 忽略 DOM 已被 Vue 移除导致的 removeChild 错误
-      }
-      this._viewer = null;
-    }
-  },
-  methods: {
-    waitForGlobeReady() {
-      return new Promise(resolve => {
-        const startTime = Date.now();
-        const maxWait = 3000; // 最多等待3秒,避免卡住
-        const check = () => {
-          if (this._destroyed) { resolve(); return; }
-          if ((this._viewer && this._viewer.scene.globe.tilesLoaded) || (Date.now() - startTime > maxWait)) {
-            resolve();
-          } else {
-            requestAnimationFrame(check);
-          }
-        };
-        requestAnimationFrame(check);
-      });
-    },
-
-    initCesium(preloadedViewer) {
-      this._baseGold = Cesium.Color.GOLD;
-      this._baseWhite = Cesium.Color.WHITE;
-      this._baseBlack = Cesium.Color.BLACK;
-      this._dynamicGold = this._baseGold.withAlpha(0);
-      this._dynamicWhite = this._baseWhite.withAlpha(0);
-      this._dynamicBlack = this._baseBlack.withAlpha(0);
-      this._poiThemeColor = Cesium.Color.fromCssColorString(
-        (this.poi && this.poi.themeColor) || '#00bfff'
-      );
-
-      // 将 props 中的 roads 转为 Cesium 颜色对象
-      this._majorRoads = this.roads.map(r => ({
-        ...r,
-        color: Cesium.Color.fromCssColorString(r.color)
-      }));
-
-      if (preloadedViewer) {
-        // 复用预加载的 Viewer(瓦片已渲染好)
-        this._viewer = preloadedViewer;
-      } else {
-        // 降级:从头创建
-        this._viewer = new Cesium.Viewer(this.$refs.cesiumContainer, {
-          animation: false, timeline: false, baseLayerPicker: false, geocoder: false,
-          homeButton: false, sceneModePicker: false, navigationHelpButton: false, infoBox: false,
-          fullscreenButton: false, selectionIndicator: false, shadows: false, shouldAnimate: false,
-          requestRenderMode: false,
-          imageryProvider: new Cesium.UrlTemplateImageryProvider({
-            url: './tiles/{z}/{y}/{x}.jpg',
-            maximumLevel: 12
-          })
-        });
-
-        this._viewer.cesiumWidget.creditContainer.style.display = "none";
-      }
-
-      const scene = this._viewer.scene;
-      scene.fog.enabled = false;
-      scene.skyAtmosphere.show = false;
-      scene.globe.showGroundAtmosphere = false;
-      scene.globe.enableLighting = true;
-      scene.globe.tileCacheSize = 300;
-      scene.globe.maximumScreenSpaceError = 1.5;
-
-      this._viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date('2026-01-01T01:30:00Z'));
-      this._viewer.clock.shouldAnimate = false;
-
-      const baseLayer = this._viewer.imageryLayers.get(0);
-      if (baseLayer) { 
-        baseLayer.brightness = 0.75; // 亮度:1.0 是原图,小于 1.0 变暗,大于 1.0 变亮
-        baseLayer.contrast = 1.3;    // 对比度
-        baseLayer.gamma = 1; // 新增这一行:默认值是 1.0,调高可以显著提亮暗部环境
-      }
-      
-
-      const cam = this._viewer.scene.screenSpaceCameraController;
-      cam.enableRotate = false;
-      cam.enableTranslate = false;
-      cam.enableZoom = false;
-      cam.enableTilt = false;
-      cam.enableLook = false;
-
-      // 微观区域高清卫星底图(有 microImage 覆盖层时跳过,避免重复)
-      if (!this.microImage && this.satelliteImage && this.satelliteImage.url) {
-        const b = this.satelliteImage.bounds;
-        this._viewer.imageryLayers.addImageryProvider(
-          new Cesium.SingleTileImageryProvider({
-            url: this.satelliteImage.url,
-            rectangle: Cesium.Rectangle.fromDegrees(b[0], b[1], b[2], b[3])
-          })
-        );
-
-        // 针对本地大图的专项优化
-        this._viewer.scene.globe.maximumScreenSpaceError = 1.0; // 降低误差,强制渲染高清
-        this._viewer.scene.globe.tileCacheSize = 200;           // 增加缓存
-
-      }
-
-      this._viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(...this._coords.start) });
-
-      this.buildMacroLayer();
-      this.buildMicroLayer();
-
-      this._preRenderListener = this._viewer.scene.preRender.addEventListener(() => {
-        if (!this._microEffectsSource || !this._microEffectsSource.show) return;
-
-        // POI 标签跟踪
-        if (this.poi && this.$refs.poiLabel && this.$refs.poiLabel.style.opacity !== "0") {
-          const pos3D = Cesium.Cartesian3.fromDegrees(this.poi.lon, this.poi.lat);
-          const screenPos = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this._viewer.scene, pos3D);
-          if (screenPos && screenPos.y > 0) {
-            this.$refs.poiLabel.style.display = 'flex';
-            this.$refs.poiLabel.style.left = screenPos.x + 'px';
-            this.$refs.poiLabel.style.top = (screenPos.y - 150) + 'px';
-          } else {
-            this.$refs.poiLabel.style.display = 'none';
-          }
-        }
-
-      });
-    },
-
-    buildMacroLayer() {
-      this._chinaEffectsSource = new Cesium.CustomDataSource('chinaEffects');
-      this._viewer.dataSources.add(this._chinaEffectsSource);
-      this._chinaEffectsSource.show = false;
-
-      Cesium.GeoJsonDataSource.load(this.boundaryUrl).then(ds => {
-        if (this._destroyed) return;
-        this._chinaDataSource = ds;
-
-        const entities = ds.entities.values;
-        const provinceMainLand = {};
-
-        for (let i = 0; i < entities.length; i++) {
-          const entity = entities[i];
-          if (entity.polygon) {
-            entity.polygon.fill = false;
-            entity.polygon.outline = false;
-            const positions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
-            entity.polyline = new Cesium.PolylineGraphics({
-              positions, width: 2,
-              material: new Cesium.PolylineGlowMaterialProperty({
-                glowPower: 0.05,
-                color: new Cesium.CallbackProperty(() => this._dynamicGold, false)
-              })
-            });
-            if (entity.name === this.province) {
-              const pointCount = positions.length;
-              if (!provinceMainLand[entity.name] || pointCount > provinceMainLand[entity.name].pointCount) {
-                provinceMainLand[entity.name] = { pointCount, center: Cesium.BoundingSphere.fromPoints(positions).center };
-              }
-            }
-          }
-        }
-
-        this._viewer.dataSources.add(ds);
-
-        for (const name in provinceMainLand) {
-          const mainCenter = provinceMainLand[name].center;
-          this._chinaEffectsSource.entities.add({
-            position: mainCenter,
-            label: {
-              text: name, font: 'bold 28px Microsoft YaHei',
-              fillColor: new Cesium.CallbackProperty(() => this._dynamicWhite, false),
-              outlineColor: new Cesium.CallbackProperty(() => this._dynamicBlack, false),
-              outlineWidth: 3, style: Cesium.LabelStyle.FILL_AND_OUTLINE,
-              heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
-              pixelOffset: new Cesium.Cartesian2(0, -10),
-              distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 20000000)
-            }
-          });
-          for (let i = 0; i < 3; i++) {
-            const offset = (4000 / 3) * i, startTime = Date.now() + offset;
-            this._chinaEffectsSource.entities.add({
-              position: mainCenter,
-              ellipse: {
-                semiMinorAxis: new Cesium.CallbackProperty(() => 350000 * (((Date.now() - startTime) % 4000) / 4000), false),
-                semiMajorAxis: new Cesium.CallbackProperty(() => 350000 * (((Date.now() - startTime) % 4000) / 4000), false),
-                material: new Cesium.ColorMaterialProperty(new Cesium.CallbackProperty(() => {
-                  const t = ((Date.now() - startTime) % 4000) / 4000;
-                  return Cesium.Color.DEEPSKYBLUE.withAlpha((1.0 - t) * 0.8 * this._macroAlpha);
-                }, false)), height: 5000 + i * 100
-              }
-            });
-          }
-        }
-      });
-    },
-
-    buildMicroLayer() {
-      this._microEffectsSource = new Cesium.CustomDataSource('microEffects');
-      this._viewer.dataSources.add(this._microEffectsSource);
-      this._microEffectsSource.show = false;
-
-      // POI 标记(可选)
-      if (this.poi) {
-        const pos3D = Cesium.Cartesian3.fromDegrees(this.poi.lon, this.poi.lat);
-        const slowRingImg = createOuterRingTexture(this._poiThemeColor);
-        const fastScannerImg = createScannerTexture(this._poiThemeColor);
-        const beamImg = createLightBeamTexture(this._poiThemeColor);
-
-        this._microEffectsSource.entities.add({ position: pos3D, ellipse: { semiMinorAxis: this.poi.radarRadius, semiMajorAxis: this.poi.radarRadius, material: new Cesium.ImageMaterialProperty({ image: slowRingImg, transparent: true }), stRotation: new Cesium.CallbackProperty(() => (Date.now() / 5000.0) % TWO_PI, false), height: 20 } });
-        this._microEffectsSource.entities.add({ position: pos3D, ellipse: { semiMinorAxis: this.poi.radarRadius, semiMajorAxis: this.poi.radarRadius, material: new Cesium.ImageMaterialProperty({ image: fastScannerImg, transparent: true }), stRotation: new Cesium.CallbackProperty(() => (Date.now() / 300.0) % TWO_PI, false), height: 21 } });
-        this._microEffectsSource.entities.add({ position: Cesium.Cartesian3.fromDegrees(this.poi.lon, this.poi.lat, 2000.0), cylinder: { length: 4000, topRadius: 20, bottomRadius: 200, material: new Cesium.ImageMaterialProperty({ image: beamImg, transparent: true }) } });
-        this._microEffectsSource.entities.add({ position: Cesium.Cartesian3.fromDegrees(this.poi.lon, this.poi.lat, 50), point: { pixelSize: 15, color: Cesium.Color.WHITE, outlineColor: this._poiThemeColor, outlineWidth: 3 } });
-      }
-
-    },
-
-    fadeMacroLayer(startAlpha, endAlpha, durationMs) {
-      return new Promise(resolve => {
-        if (startAlpha < endAlpha && this._chinaDataSource) {
-          this._chinaDataSource.show = true;
-          this._chinaEffectsSource.show = true;
-        }
-        const startTime = Date.now();
-        const animateFade = () => {
-          if (this._destroyed) { resolve(); return; }
-          let p = (Date.now() - startTime) / durationMs; if (p >= 1.0) p = 1.0;
-          this._macroAlpha = startAlpha + (endAlpha - startAlpha) * p;
-          this._dynamicGold = this._baseGold.withAlpha(this._macroAlpha);
-          this._dynamicWhite = this._baseWhite.withAlpha(this._macroAlpha);
-          this._dynamicBlack = this._baseBlack.withAlpha(this._macroAlpha);
-          if (p < 1.0) {
-            requestAnimationFrame(animateFade);
-          } else {
-            if (endAlpha === 0 && this._chinaDataSource) {
-              this._chinaDataSource.show = false;
-              this._chinaEffectsSource.show = false;
-            }
-            resolve();
-          }
-        };
-        requestAnimationFrame(animateFade);
-      });
-    },
-
-    animatePathGrowing(roadObj, delayTime) {
-      return new Promise(resolve => {
-        const timerId = setTimeout(() => {
-          if (this._destroyed) { resolve(); return; }
-          const positions = roadObj.path.map(p => Cesium.Cartesian3.fromDegrees(p[0], p[1]));
-          const distances = [0]; let totalLength = 0;
-          for (let i = 1; i < positions.length; i++) {
-            totalLength += Cesium.Cartesian3.distance(positions[i - 1], positions[i]);
-            distances.push(totalLength);
-          }
-          let progress = 0.0, isFinished = false;
-
-          this._microEffectsSource.entities.add({
-            polyline: {
-              positions: new Cesium.CallbackProperty(function () {
-                if (isFinished) return positions;
-                progress += 0.025;
-                if (progress >= 1.0) { isFinished = true; resolve(); return positions; }
-                const targetDist = progress * totalLength;
-                const pts = [];
-                for (let i = 1; i < positions.length; i++) {
-                  pts.push(positions[i - 1]);
-                  if (targetDist <= distances[i]) {
-                    const seg = (targetDist - distances[i - 1]) / (distances[i] - distances[i - 1]);
-                    const p = new Cesium.Cartesian3();
-                    Cesium.Cartesian3.lerp(positions[i - 1], positions[i], seg, p);
-                    pts.push(p); break;
-                  }
-                }
-                return pts;
-              }, false),
-              width: roadObj.width,
-              material: new Cesium.PolylineGlowMaterialProperty({ glowPower: roadObj.glowPower, color: roadObj.color })
-            }
-          });
-        }, delayTime);
-        this._pendingTimers.push(timerId);
-      });
-    },
-
-    _safeDelay(ms) {
-      return new Promise(resolve => {
-        const id = setTimeout(resolve, ms);
-        this._pendingTimers.push(id);
-      });
-    },
-
-    async startTransition() {
-      if (this.isAnimating) return;
-      this.isAnimating = true;
-
-      // 阶段1: 飞向中国 (2s)
-      this._viewer.camera.flyTo({
-        destination: Cesium.Cartesian3.fromDegrees(...this._coords.china), duration: 2
-      });
-      const fadeInId = setTimeout(() => {
-        if (!this._destroyed) this.fadeMacroLayer(0.0, 1.0, 1000);
-      }, 800);
-      this._pendingTimers.push(fadeInId);
-
-      await this._safeDelay(3000);
-      if (this._destroyed) return;
-
-      // 阶段2: 俯冲到微观
-      const targetCenter = this.poi
-        ? [this.poi.lon, this.poi.lat]
-        : (this.districtCenter || [116.70, 39.80]);
-      const targetSphere = Cesium.BoundingSphere.fromPoints([Cesium.Cartesian3.fromDegrees(targetCenter[0], targetCenter[1])]);
-      this._viewer.camera.flyToBoundingSphere(targetSphere, {
-        offset: new Cesium.HeadingPitchRange(0.0, Cesium.Math.toRadians(-45), this.microViewRange),
-        duration: 2, easingFunction: Cesium.EasingFunction.CUBIC_IN_OUT
-      });
-      this.fadeMacroLayer(1.0, 0.0, 800);
-
-      // 阶段3: 显示微观效果
-      await this._safeDelay(1500);
-      if (this._destroyed) return;
-      this._microEffectsSource.show = true;
-      if (this.poi && this.$refs.poiLabel) this.$refs.poiLabel.style.opacity = 1;
-
-      // 阶段4: 微观图片淡入
-      if (this.microImage && this.$refs.microOverlay) {
-        await this._safeDelay(500);
-        if (this._destroyed) return;
-        this.$refs.microOverlay.style.opacity = 1;
-        await this._safeDelay(2000); // 等待淡入完成 + 停留展示
-      } else {
-        await this._safeDelay(1000);
-      }
-      if (this._destroyed) return;
-      this.$emit('complete');
-    }
-  }
-};
-</script>
-
-<style scoped>
-.cesium-transition-wrapper {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100vw;
-  height: 100vh;
-  z-index: 9999;
-  background: #020813;
-  overflow: hidden;
-  font-family: "Microsoft YaHei", sans-serif;
-}
-
-.cesium-container {
-  width: 100%;
-  height: 100%;
-  margin: 0;
-  padding: 0;
-}
-
-.micro-overlay {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-  opacity: 0;
-  transition: opacity 1.5s ease;
-  z-index: 2;
-  pointer-events: none;
-}
-
-.ui-layer {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  pointer-events: none;
-}
-
-.html-label {
-  position: absolute;
-  padding: 4px 10px;
-  border-radius: 2px;
-  pointer-events: none;
-  transition: opacity 0.5s;
-  transform: translate(-50%, -100%);
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  white-space: nowrap;
-  font-weight: bold;
-  z-index: 5;
-  border: 1px solid currentColor;
-  background: rgba(0, 20, 30, 0.7);
-  box-shadow: inset 0 0 10px currentColor;
-  text-shadow: 0 0 5px #000;
-}
-
-.html-label::after {
-  content: '';
-  width: 2px;
-  height: 35px;
-  background: currentColor;
-  margin-top: 5px;
-  box-shadow: 0 0 5px currentColor;
-}
-</style>

Разница между файлами не показана из-за своего большого размера
+ 0 - 1041
src/components/GlobeTransition.vue


+ 0 - 2
src/router/index.js

@@ -4,7 +4,6 @@ import Router from "vue-router";
 import Login from "@/views/Login.vue";
 import Home from "@/views/Home.vue";
 import Main from "@/views/Main.vue";
-import TransitionPage from "@/views/TransitionPage.vue";
 import StatusMonitoring from "@/views/StatusMonitoring.vue";
 import SpecialSituationMonitoring from "@/views/SpecialSituationMonitoring.vue";
 import DataAnalysis from "@/views/DataAnalysis.vue";
@@ -18,7 +17,6 @@ export default new Router({
     { path: "/", redirect: "/login" },
     { path: "/login", component: Login },
     { path: "/main", component: Main },
-    { path: "/transition", component: TransitionPage },
     { path: "/home", component: Home },
     { path: "/watch", component: DataAnalysis },
     { path: "/surve", component: StatusMonitoring },

+ 0 - 170
src/utils/cesiumPreloader.js

@@ -1,170 +0,0 @@
-/**
- * Cesium 预加载服务
- * 在登录页提前创建隐藏的 Cesium Viewer,预渲染瓦片
- * TransitionPage 挂载时直接复用已渲染好的实例
- */
-
-let _viewer = null;
-let _container = null;
-let _ready = false;
-let _readyCallbacks = [];
-
-const CesiumPreloader = {
-  /**
-   * 启动预加载(在 Login 页调用)
-   */
-  start() {
-    if (_viewer || _container) return; // 已启动
-
-    // 等 Cesium CDN 加载完再执行
-    const Cesium = window.Cesium;
-    if (!Cesium) {
-      setTimeout(() => this.start(), 500);
-      return;
-    }
-    _container = document.createElement('div');
-    _container.id = 'cesium-preload-container';
-    _container.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:-1;opacity:0;pointer-events:none;';
-    document.body.appendChild(_container);
-
-    _viewer = new Cesium.Viewer(_container, {
-      animation: false, timeline: false, baseLayerPicker: false, geocoder: false,
-      homeButton: false, sceneModePicker: false, navigationHelpButton: false, infoBox: false,
-      fullscreenButton: false, selectionIndicator: false, shadows: false, shouldAnimate: false,
-
-      // 关键:关闭默认底图,否则会覆盖
-      imageryProvider: false,
-      baseLayer: false
-    });
-
-    const GeoToken = '5f1c0062177713e6c61bc0b414367256';
-    // 加载 ArcGIS 卫星图 = 谷歌卫星同款清晰度,国内秒加载
-    const arcGIS_Satellite = new Cesium.UrlTemplateImageryProvider({
-      url: `https://api.open.geovisearth.com/map/v1/img/{z}/{x}/{y}?token=${GeoToken}&format=webp&tmsIds=w`,
-      tilingScheme: new Cesium.WebMercatorTilingScheme(),
-      maximumLevel: 19
-    });
-    _viewer.imageryLayers.addImageryProvider(arcGIS_Satellite)
-
-    _viewer.cesiumWidget.creditContainer.style.display = 'none';
-
-    const scene = _viewer.scene;
-    scene.fog.enabled = false;
-    scene.skyAtmosphere.show = false;
-    scene.globe.showGroundAtmosphere = false;
-    scene.globe.enableLighting = true;
-    scene.globe.tileCacheSize = 300;
-    scene.globe.maximumScreenSpaceError = 1.5;
-
-    _viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date('2024-01-01T23:30:00Z'));
-    _viewer.clock.shouldAnimate = false;
-
-    const baseLayer = _viewer.imageryLayers.get(0);
-    if (baseLayer) { baseLayer.brightness = 0.45; baseLayer.contrast = 1.3; }
-
-    // 设置初始视角并预加载瓦片
-    const startView = Cesium.Cartesian3.fromDegrees(-15.0, 35.86, 45000000);
-    _viewer.camera.setView({ destination: startView });
-
-    // 预加载:依次渲染初始视角和中国视角的瓦片
-    const chinaView = Cesium.Cartesian3.fromDegrees(104.19, 35.86, 14000000);
-    let phase = 0;
-
-    const check = () => {
-      if (!_viewer || _viewer.isDestroyed()) return;
-      if (_viewer.scene.globe.tilesLoaded) {
-        if (phase === 0) {
-          // 初始视角瓦片加载完,切到中国视角预加载
-          phase = 1;
-          _viewer.camera.setView({ destination: chinaView });
-          requestAnimationFrame(check);
-        } else {
-          // 中国视角也加载完,切回初始视角
-          _viewer.camera.setView({ destination: startView });
-          _ready = true;
-          _readyCallbacks.forEach(cb => cb());
-          _readyCallbacks = [];
-        }
-      } else {
-        requestAnimationFrame(check);
-      }
-    };
-    requestAnimationFrame(check);
-
-    // 超时保底:5秒后无论如何标记就绪
-    setTimeout(() => {
-      if (!_ready) {
-        _ready = true;
-        _readyCallbacks.forEach(cb => cb());
-        _readyCallbacks = [];
-      }
-    }, 5000);
-  },
-
-  /**
-   * 将预加载的 Viewer 移到目标容器(在 CesiumTransition 中调用)
-   * @param {HTMLElement} targetContainer 目标 DOM 容器
-   * @returns {Promise<Cesium.Viewer|null>}
-   */
-  acquire(targetContainer) {
-    return new Promise(resolve => {
-      const doAcquire = () => {
-        if (!_viewer || _viewer.isDestroyed()) {
-          resolve(null);
-          return;
-        }
-        // 将 canvas 容器移到目标 DOM
-        const cesiumWidget = _container.querySelector('.cesium-viewer');
-        if (cesiumWidget) {
-          targetContainer.appendChild(cesiumWidget);
-        }
-        // 移除隐藏容器
-        if (_container && _container.parentNode) {
-          _container.parentNode.removeChild(_container);
-        }
-        _container = null;
-
-        // 调整尺寸适配新容器
-        _viewer.resize();
-
-        const viewer = _viewer;
-        _viewer = null;
-        _ready = false;
-        resolve(viewer);
-      };
-
-      if (_ready) {
-        doAcquire();
-      } else if (_viewer) {
-        _readyCallbacks.push(doAcquire);
-      } else {
-        resolve(null); // 未启动预加载
-      }
-    });
-  },
-
-  /**
-   * 是否已启动预加载
-   */
-  isStarted() {
-    return !!_viewer;
-  },
-
-  /**
-   * 清理(如果未被 acquire 就离开了登录页)
-   */
-  destroy() {
-    if (_viewer && !_viewer.isDestroyed()) {
-      _viewer.destroy();
-    }
-    if (_container && _container.parentNode) {
-      _container.parentNode.removeChild(_container);
-    }
-    _viewer = null;
-    _container = null;
-    _ready = false;
-    _readyCallbacks = [];
-  }
-};
-
-export default CesiumPreloader;

+ 0 - 3
src/views/Login.vue

@@ -51,9 +51,6 @@ import brand from "@/utils/brand";
 export default {
   name: "LoginPage",
   components: { LoginForm, FullscreenToggle },
-  created() {
-    import('@/utils/cesiumPreloader').then(m => m.default.start());
-  },
   data() {
     return {
       brand,

+ 0 - 119
src/views/TransitionPage.vue

@@ -1,119 +0,0 @@
-<template>
-  <div class="page">
-    <transition name="fade">
-      <CesiumTransition
-        v-if="isTransitioning && isDataReady"
-        :province="province"
-        :poi="poi"
-        :district-center="districtCenter"
-        :roads="roads"
-        :satellite-image="satelliteImage"
-        :boundary-url="boundaryUrl"
-        :micro-view-range="microViewRange"
-        :micro-image="microImage"
-        @complete="onTransitionComplete"
-      />
-    </transition>
-  </div>
-</template>
-
-<script>
-import CesiumTransition from '@/components/CesiumTransition.vue';
-
-export default {
-  name: "TransitionPage",
-  components: { CesiumTransition },
-  data() {
-    return {
-      isTransitioning: true,
-      isDataReady: false, // 控制加载时机
-
-      // ====== 以下数据将在 initCityData 中被动态替换,这里填入默认兜底值 ======
-      province: '北京市',
-      districtCenter: [116.70, 39.80],
-      microViewRange: 80000,
-      
-      // 中国边界 GeoJSON
-      boundaryUrl: './china.json',
-
-      // 微观标记点(可根据城市动态配置,暂设为null)
-      poi: null,
-
-      // 路网数据和卫星底图(因为不同城市的数据不同,如果是动态全国切换,建议默认清空)
-      // 如果你需要保留北京的默认路网,可以在 if(targetCity === '北京市') 里面再单独赋回来
-      roads: [],
-      satelliteImage: null,
-
-      // 微观覆盖图片(过渡动画最后淡入展示)
-      microImage: './beijing-gov-satellite.jpg'
-    };
-  },
-  created() {
-    // 组件创建时,立即去获取城市数据
-    this.initCityData();
-  },
-  methods: {
-    async initCityData() {
-      // 1. 获取登录页通过路由传过来的城市名称,默认走北京
-      // 例如:this.$router.push({ path: '/transition', query: { city: '成都市' } })
-      const targetCity = this.$route.query.city || '北京市';
-      
-      try {
-        // 2. 动态请求 public 目录下的全量城市配置文件
-        // 请确保通过上一步的脚本生成的 cities.json 已经放置在 public 目录下
-        const response = await fetch('./cities.json');
-        
-        if (!response.ok) {
-          throw new Error(`HTTP error! status: ${response.status}`);
-        }
-        
-        const allCitiesConfig = await response.json();
-        
-        // 3. 查找当前匹配城市的配置
-        const config = allCitiesConfig[targetCity];
-        
-        if (config) {
-          this.province = config.province; // 用于宏观视角高亮对应省份边界
-          this.districtCenter = config.districtCenter; // 用于微观俯冲视角的中心点
-          this.microViewRange = config.microViewRange; // 用于微观视角的相机高度
-
-          // 动态提取卫星图:如果有配置则加载,没有则设为 null(避免显示错位)
-          this.satelliteImage = config.satellite || null;
-
-          // 如果不是北京,建议清空路网,或者根据需要加载该城市的路网
-          this.roads = (targetCity === '北京市') ? this.defaultBeijingRoads : [];
-
-        } else {
-          console.warn(`⚠️ 未在 cities.json 中匹配到【${targetCity}】的配置,将使用默认北京视角`);
-        }
-      } catch (error) {
-        console.error("加载城市配置 cities.json 失败,请检查文件是否在 public 目录下!", error);
-      } finally {
-        // 4. 无论成功还是失败(走兜底),都开放渲染条件,开始地球动画
-        this.isDataReady = true;
-      }
-    },
-    onTransitionComplete() {
-      this.isTransitioning = false;
-      console.log("地球过渡动画结束,正式进入系统首页!");
-      this.$router.replace("/main");
-    }
-  }
-}
-</script>
-
-<style scoped>
-.page {
-  width: 100vw;
-  height: 100vh;
-  overflow: hidden;
-  background-color: #000;
-}
-
-.fade-enter-active, .fade-leave-active {
-  transition: opacity 1.5s ease;
-}
-.fade-enter, .fade-leave-to {
-  opacity: 0;
-}
-</style>