diff --git a/index.html b/index.html
index 8422405..fb8f3e1 100644
--- a/index.html
+++ b/index.html
@@ -24,11 +24,6 @@
       cesium="true"
       src="public/Cesium/Cesium.js"
     ></script>
-    <!-- <script
-      type="text/javascript"
-      cesium="true"
-      src="https://api.tianditu.gov.cn/cdn/demo/sanwei/static/cesium/Cesium.js"
-    ></script> -->
     <script
       type="text/javascript"
       cesium="true"
diff --git a/package.json b/package.json
index 1c3b66c..f17f7e0 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,6 @@
   "scripts": {
     "dev": "vite",
     "build": "vite build",
-    "build-localhost": "vite build && node update-index.mjs",
     "preview": "vite preview",
     "lint": "eslint src",
     "fix": "eslint src --fix",
diff --git a/src/assets/js/cesium-map/measureDistance.js b/src/assets/js/cesium-map/measureDistance.js
index 2d226f7..98c0c67 100644
--- a/src/assets/js/cesium-map/measureDistance.js
+++ b/src/assets/js/cesium-map/measureDistance.js
@@ -1,6 +1,6 @@
 import * as Cesium from 'cesium'
 import {Cartesian3} from 'cesium'
-import {geojson2kml} from "@/assets/js/DataUtils.js";
+import {useStaticStore} from "@/store/staticOptions.js";
 
 export default class MeasureDistance {
     constructor(viewer) {
@@ -8,17 +8,18 @@ export default class MeasureDistance {
         this.scene = viewer.scene
         this.isMeasure = false
         this.positions = []
-        this.temPositions = []      // 鼠标移动时产生的临时点
-        this.vertexEntities = []    // 节点元素
-        this.lineEntity = undefined // 距离测量折线元素
-        this.lineEntitys = []       // 距离测量折线元素数组,每完成一次距离测量,将折线元素加入此数组
-        this.totalDistance = 0      // 总距离
+        this.temPositions = []      // 距离测量-鼠标移动时产生的临时点
+        this.vertexEntities = []    // 距离测量-节点元素
+        this.lineEntity = undefined // 距离测量-折线元素
+        this.lineEntitys = []       // 距离测量-折线元素数组,每完成一次距离测量,将折线元素加入此数组
+        this.totalDistance = 0      // 距离测量-总距离
 
-        this.activeShapePoints = []    //面积测量多边形顶点
+        this.activeShapePoints = []    //面积测量-多边形顶点
         this.polygon = undefined
         this.measAreaStatus = false    //是否在测量面积
 
-        this.graphics = []
+        this.analyseGraphs = []  //分析工具的图形容器
+        this.graphics = []      //图形绘制容器
         this.dynamicData = {
             lon: undefined,
             lat: undefined,
@@ -30,15 +31,90 @@ export default class MeasureDistance {
             borderWidth: 1,
             material: Cesium.Color.GREEN.withAlpha(0.5),
         }
+    }
+
+    profileAnalyse(){
+        //解绑鼠标事件
+        if(this.handler)    this.unRegisterEvents()
+        let count = 0
+        let profilePts = []      //点集合
+        let line = undefined
+        let movePoint = undefined
+        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
+        // 绑定鼠标左击事件
+        this.handler.setInputAction(e => {
+            let position = this.viewer.scene.pickPosition(e.position);
+            if (!position) {
+                const ellipsoid = this.viewer.scene.globe.ellipsoid;
+                position = this.viewer.scene.camera.pickEllipsoid(e.position, ellipsoid);
+            }
+            if (!position) return;
+            count++
+            profilePts.push(position)
+            let nodeEntity = this._createPointEntity(position, count.toString())
+            this.viewer.entities.add(nodeEntity)
+            this.analyseGraphs.push(nodeEntity)
+            if(!line){
+                line = this.viewer.entities.add({
+                    polyline: {
+                        positions: new Cesium.CallbackProperty(e => {
+                            return profilePts.concat(movePoint);
+                        }, false),
+                        width: 2,
+                        material: Cesium.Color.YELLOW,
+                        clampToGround: true,
+                    },
+                })
+            }
+            //通视分析仅支持选择两个点
+            if(useStaticStore().analysisVars.analysisType===2&&profilePts.length===2){
+                this.unRegisterEvents()
+                useStaticStore().analysisVars.profilePts = profilePts
+            }
+        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+
+        this.handler.setInputAction(e => {
+            let position = this.viewer.scene.pickPosition(e.endPosition);
+            if (!position) {
+                position = this.viewer.scene.camera.pickEllipsoid(e.startPosition, this.viewer.scene.globe.ellipsoid);
+            }
+            if (!position) return;
+            movePoint = position
+            this.viewer.scene.requestRender()
+        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
+
+        this.handler.setInputAction(e => {
+            let position = this.viewer.scene.pickPosition(e.position);
+            if (!position) {
+                const ellipsoid = this.viewer.scene.globe.ellipsoid;
+                position = this.viewer.scene.camera.pickEllipsoid(e.position, ellipsoid);
+            }
+            if (!position) return;
+            count++
+            profilePts.push(position)
+            let endEntity = this._createPointEntity(position, count.toString())
+            this.viewer.entities.add(endEntity)
+            this.analyseGraphs.push(endEntity)
+            this.analyseGraphs.push(line)
+            this.unRegisterEvents()
+            useStaticStore().analysisVars.profilePts = profilePts
+        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
 
+        return false
     }
+
+    clearProfileEntities(){
+        this.analyseGraphs.forEach((item)=>{
+            this.viewer.entities.remove(item)
+        })
+    }
+
     updateDynamicData(data){
         this.dynamicData.lon = data.lon;
         this.dynamicData.lat = data.lat;
         this.dynamicData.alt = data.alt;
         this.dynamicData.heading = data.heading;
         this.viewer.scene.requestRender()
-
     }
 
     addKml(kml_file){
@@ -692,7 +768,7 @@ export default class MeasureDistance {
         })
         this.graphics = []
     }
-/**********************   图形绘制  ***************************************/
+/**********************   实时图形绘制  ***************************************/
     drawGraphics(key){
         this.viewer.scene.globe.depthTestAgainstTerrain = true
         // 清除可能会用到的监听事件
@@ -920,4 +996,31 @@ export default class MeasureDistance {
             }
         }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
     }
+    _createPointEntity(position, label=""){
+        return new Cesium.Entity({
+            position:  position,
+            point: {
+                pixelSize: 4,
+                color: Cesium.Color.RED,
+                outlineColor: Cesium.Color.WHITE,
+                outlineWidth: 1,
+                disableDepthTestDistance:99000000,
+                heightReference:Cesium.HeightReference.CLAMP_TO_GROUND,
+            },
+            label: {
+                text: label,
+                font: "2rem sans-serif",
+                fillColor: Cesium.Color.WHITE,
+                style: Cesium.LabelStyle.FILL,
+                pixelOffset: new Cesium.Cartesian2(20, -10),
+                eyeOffset: new Cesium.Cartesian3(0, 0, 0),
+                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+                scale: 0.5,
+                clampToGround: true,
+                heightReference:Cesium.HeightReference.CLAMP_TO_GROUND,
+                disableDepthTestDistance:99000000,
+            },
+        })
+    }
 }
diff --git a/src/components/ProfileAnalysis.vue b/src/components/ProfileAnalysis.vue
deleted file mode 100644
index 0beb8b4..0000000
--- a/src/components/ProfileAnalysis.vue
+++ /dev/null
@@ -1,238 +0,0 @@
-<!--
-  文件描述:地形剖面图组件
-  创建时间:2024/4/23 9:55
-  创建人:Zhaipeixiu
--->
-<script setup lang="ts">
-import {ref} from 'vue'
-import * as echarts from 'echarts'
-const emit = defineEmits(['confirmDia'])
-let showDia = ref<boolean>(false)
-
-const openDia = (): void => {
-  showDia.value = true
-}
-
-const closeDia = (): void => {
-  showDia.value = false
-}
-
-const confirmDia = (): void => {
-  emit('confirmDia', '弹窗内容事件处理完毕,信息传给父组件。')
-}
-
-/**
- *  绘制折线图(航线碰撞检测)
- * @param xData x数组
- * @param yData y数组,以面积线绘制
- * @param yData2 y数组,以折线绘制
- */
-const drawChart_AirlineDetect = (xData:number[],yData:number[],yData2:number[]) => {
-  let myChart = echarts.init(document.getElementById('profileChart'))
-  // 绘制图表
-  myChart.setOption({
-    legend:{
-      show: true,
-      type: 'plain',
-      top: '7%',
-      data:[
-        {
-          name: 'groundLine',
-          itemStyle: 'inherit',
-          lineStyle: 'inherit',
-        },
-        {
-        name: 'airLine',
-        itemStyle: 'inherit',
-        lineStyle: 'inherit',
-      }]
-    },
-    tooltip: {
-      show: true,
-      trigger: 'axis',
-      axisPointer: {
-        type: 'cross'
-      },
-      formatter:'地表高度: {c0}<br>航线高度: {c1}'
-    },
-    xAxis: {
-      data: xData,
-      name: '距离',
-      nameTextStyle: {
-        fontWeight:'bolder',
-        fontSize: 14
-      },
-      nameLocation: 'end',
-      axisLine:{
-        onZero: false,
-        show: true,    // 是否显示坐标轴轴线
-        symbol: ['none', 'arrow'],
-        symbolSize: [7, 10]
-      },
-      axisLabel: {
-        formatter: '{value} m',
-        margin: 5,
-      },
-      axisTick: {
-        show: true,    // 是否显示坐标轴刻度
-        inside: true,     // 坐标轴刻度是否朝内,默认朝外
-        alignWithLabel: true,
-        lineStyle: {
-          color: '#000000',     //刻度线的颜色
-          type: 'solid',    //坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)
-        },
-      }
-    },
-    yAxis: {
-      type: 'value',
-      name: '高度',
-      nameTextStyle: {
-        fontWeight:'bolder',
-        fontSize: 14
-      },
-      nameLocation: 'end',
-      position: 'left',
-      axisLabel: {
-        formatter: '{value} m'
-      },
-      axisLine: {
-        show: true,
-        symbol: ['none', 'arrow'],
-        symbolSize: [7, 10]
-      }
-    },
-    series: [
-      {
-        name:'groundLine',
-        type: 'line',
-        data: yData,
-        areaStyle: {
-          color: '#37a5fb',
-          opacity: 0.5
-        }
-      },
-      {
-        name:'airLine',
-        type: 'line',
-        data: yData2,
-      }
-    ]
-  });
-}
-/**
- *  绘制折线图(地形剖面)
- * @param xData x数组
- * @param yData y数组,以面积线绘制
- */
-const drawChart_TerrainProfile = (xData:number[],yData:number[]) => {
-  let myChart = echarts.init(document.getElementById('profileChart'))
-  // 绘制图表
-  myChart.setOption({
-    legend:{
-      show: true,
-      type: 'plain',
-      top: '7%',
-      data:[
-        {
-          name: 'groundLine',
-          itemStyle: 'inherit',
-          lineStyle: 'inherit',
-        },
-        {
-          name: 'airLine',
-          itemStyle: 'inherit',
-          lineStyle: 'inherit',
-        }]
-    },
-    tooltip: {
-      show: true,
-      trigger: 'axis',
-      axisPointer: {
-        type: 'cross'
-      },
-      formatter:'地表高度: {c0}'
-    },
-    xAxis: {
-      data: xData,
-      name: '距离',
-      nameTextStyle: {
-        fontWeight:'bolder',
-        fontSize: 14
-      },
-      nameLocation: 'end',
-      axisLine:{
-        onZero: false,
-        show: true,    // 是否显示坐标轴轴线
-        symbol: ['none', 'arrow'],
-        symbolSize: [7, 10]
-      },
-      axisLabel: {
-        formatter: '{value} m',
-        margin: 5,
-      },
-      axisTick: {
-        show: true,    // 是否显示坐标轴刻度
-        inside: true,     // 坐标轴刻度是否朝内,默认朝外
-        alignWithLabel: true,
-        lineStyle: {
-          color: '#000000',     //刻度线的颜色
-          type: 'solid',    //坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)
-        },
-      }
-    },
-    yAxis: {
-      type: 'value',
-      name: '高度',
-      nameTextStyle: {
-        fontWeight:'bolder',
-        fontSize: 14
-      },
-      nameLocation: 'end',
-      position: 'left',
-      axisLabel: {
-        formatter: '{value} m'
-      },
-      axisLine: {
-        show: true,
-        symbol: ['none', 'arrow'],
-        symbolSize: [7, 10]
-      }
-    },
-    series: [
-      {
-        name:'groundLine',
-        type: 'line',
-        data: yData,
-        areaStyle: {
-          color: '#37a5fb',
-          opacity: 0.5
-        }
-      }
-    ]
-  });
-}
-
-// vue3中规定,使用了 <script setup> 的组件是默认私有的:
-// 一个父组件无法访问到一个使用了 <script setup> 的子组件中的任何东西,除非子组件在其中通过 defineExpose 宏显式暴露
-defineExpose({
-  openDia,
-  closeDia,
-  drawChart_AirlineDetect,
-  drawChart_TerrainProfile
-})
-
-
-</script>
-
-<template>
-<div id="profileChart" v-show="showDia">
-</div>
-</template>
-
-<style scoped>
-#profileChart{
-  width: 700px;
-  height: 500px;
-  position: relative;
-}
-</style>
diff --git a/src/components/SpatialAnalysis.vue b/src/components/SpatialAnalysis.vue
new file mode 100644
index 0000000..a329258
--- /dev/null
+++ b/src/components/SpatialAnalysis.vue
@@ -0,0 +1,196 @@
+<!--
+  文件描述:地形剖面图组件
+  创建时间:2024/4/23 9:55
+  创建人:Zhaipeixiu
+-->
+<script setup lang="ts">
+import {nextTick, ref, watch} from "vue";
+import {
+  drawEchartsProfileAnalyse,
+  drawEchartsVisibility, elevationProfile,
+  profileAnalyse
+} from "@/utils/map/SpatialAnalysis.ts";
+import {useStaticStore} from "@/store/staticOptions";
+import {useMessage} from "naive-ui";
+import {Cartesian3} from "cesium";
+let showResultModal = ref(false)
+let store = useStaticStore()
+let message = useMessage()
+let showParamsDialog = ref(false)
+let ifInputCoords = ref(false)
+//TODO: 表单未校验
+let formParams = ref({
+  interval: 100,
+  startClearance: 40,   //起点离地高度
+  endClearance: 10,   //起点离地高度
+})
+
+// 关闭地形分析结果窗口德回调
+const handleCloseProfile = ()=>{
+  //移除图形元素
+  window.measureViewer.clearProfileEntities()
+  //地形点数组归零
+  store.analysisVars.profilePts = []
+  store.analysisVars.analysisType = -1
+}
+
+// 执行地形分析
+function executeTopographicAnalyse(polyline:Cartesian3[]) {
+  // 剖面分析
+  if(store.analysisVars.analysisType === 1){
+    // 计算地形剖面
+    let res = profileAnalyse(window.viewer, polyline,formParams.value.interval)
+    // 弹出图表窗口
+    showResultModal.value = true
+    nextTick(()=>{
+      drawEchartsProfileAnalyse(res.distanceArray, res.elevationArray)
+    })
+  }
+  // 通视分析
+  else if (store.analysisVars.analysisType === 2){
+    console.log(store.analysisVars.analysisType)
+    // 计算地形剖面
+    let res = profileAnalyse(window.viewer, polyline,formParams.value.interval)
+    // 计算视线起始点距离和高度
+    let eyeRes = elevationProfile(window.viewer,polyline[0],polyline[1],-1)
+    eyeRes.elevationArray[0] += Number(formParams.value.startClearance)
+    eyeRes.elevationArray[1] += Number(formParams.value.endClearance)
+    // 弹出图表窗口
+    showResultModal.value = true
+    nextTick(()=>{
+      drawEchartsVisibility(res.distanceArray, res.elevationArray, eyeRes.elevationArray[0],eyeRes.elevationArray[1])
+    })
+  }
+
+}
+watch(()=>store.analysisVars.profilePts, (newValue, OldValue): void => {
+  console.log("数据变化了", newValue)
+  if(newValue.length==1) {
+    message.error('请至少选择两个点')
+    return;
+  }
+  if(newValue.length<1) return;
+  executeTopographicAnalyse(newValue)
+})
+
+function inputCoords(){
+  ifInputCoords.value = !ifInputCoords.value
+}
+function pickPoints() {
+  window.measureViewer.profileAnalyse()
+  showParamsDialog.value = false
+}
+defineExpose({
+  openParamsDialog:()=>{
+    showParamsDialog.value = true
+  }
+})
+
+const pickedCoords = ref([
+  {
+    lon: null,
+    lat: null
+  }
+])
+const onCreate = ()=> {
+  return {lon: null, lat: null}
+}
+
+//输入坐标结束之后,进行地形分析
+const afterCoordInput = ()=> {
+  console.log(pickedCoords.value)
+  //关闭参数窗口
+  showParamsDialog.value = false
+
+  let polyline: Cartesian3[] = []
+  pickedCoords.value.forEach((coord) => {
+    let lon1,lat1
+    lon1 = Number(coord.lon)
+    lat1 = Number(coord.lat)
+    let Certain3 = Cartesian3.fromDegrees(lon1, lat1)
+    polyline.push(Certain3)
+  })
+  // 执行地形分析
+  executeTopographicAnalyse(polyline)
+}
+
+</script>
+
+<template>
+  <n-modal v-model:show="showResultModal" style="width: 50rem; height: 38rem"
+           preset="card" draggable :mask-closable="false" :on-after-leave="handleCloseProfile"
+           :title="store.analysisVars.analysisType==2? '通视分析结果':'剖面分析结果'">
+    <template v-slot:default>
+      <div id="profileEChart"></div>
+    </template>
+  </n-modal>
+
+  <n-modal v-model:show="showParamsDialog" style="width: 20rem;" preset="card"
+           draggable :title="store.analysisVars.analysisType==2? '通视分析参数设置':'剖面分析参数设置'"
+           :mask-closable="false">
+    <template v-slot:default>
+      <n-space>
+        <n-form ref="formRef" :model="formParams"
+                label-placement="left" label-width="auto"
+                require-mark-placement="right-hanging">
+          <n-form-item label="采样间隔" path="numberParam" >
+            <n-input round v-model:value="formParams.interval">
+              <template #suffix>
+                米
+              </template>
+            </n-input>
+          </n-form-item>
+          <n-form-item label="起点离地高度" path="numberParam" v-show="store.analysisVars.analysisType==2">
+            <n-input round v-model:value="formParams.startClearance">
+              <template #suffix>
+                米
+              </template>
+            </n-input>
+          </n-form-item>
+          <n-form-item label="终点离地高度" path="numberParam" v-show="store.analysisVars.analysisType==2">
+            <n-input round v-model:value="formParams.endClearance">
+              <template #suffix>
+                米
+              </template>
+            </n-input>
+          </n-form-item>
+        </n-form>
+      </n-space>
+      <n-row justify-content="space-around">
+        <n-tooltip placement="bottom" trigger="hover">
+          <template #trigger>
+            <n-button type="info" size="small" @click="pickPoints">地图选取</n-button>
+          </template>
+          <span>左键单击选点,右键结束</span>
+        </n-tooltip>
+        <n-button :type="ifInputCoords? 'warning':'info'" size="small"
+                  @click="inputCoords">{{ifInputCoords? '取消输入':'输入坐标' }}
+        </n-button>
+        <n-button type="info" size="small">导入文件</n-button>
+      </n-row>
+      <n-divider v-show="ifInputCoords"/>
+      <n-dynamic-input v-model:value="pickedCoords" :on-create="onCreate" v-show="ifInputCoords"
+                       :min="2" :max="store.analysisVars.analysisType==2? 2:10">
+        <template #default="{ value }">
+            <n-input size="tiny" v-model:value="value.lon" placeholder="经度"/>
+            <n-input size="tiny" v-model:value="value.lat" placeholder="纬度"/>
+        </template>
+      </n-dynamic-input>
+      <n-row justify-content="space-around" style="margin-top:.5rem;">
+      <n-button type="primary"  size="small"  v-show="ifInputCoords"
+                @click="afterCoordInput" :disabled="pickedCoords.length<2"> 确定 </n-button>
+      </n-row>
+    </template>
+  </n-modal>
+
+</template>
+
+<style scoped>
+
+#profileEChart{
+  width: 47rem;
+  height: 37rem;
+  position: relative;
+  margin-top: -2rem;
+}
+</style>
diff --git a/src/components/UnitTest.vue b/src/components/UnitTest.vue
new file mode 100644
index 0000000..745ff41
--- /dev/null
+++ b/src/components/UnitTest.vue
@@ -0,0 +1,22 @@
+<script lang="ts">
+import {defineComponent} from 'vue'
+import {drawEchartsVisibility} from "@/utils/map/SpatialAnalysis.ts";
+
+export default defineComponent({
+  name: "UnitTest",
+  mounted() {
+    let xdt = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
+    let ydt = [23,34,3,4,5,6,7,8,9,23,123,122,90,45,34,16,17,142,53,2,10];
+    drawEchartsVisibility(xdt, ydt, 30, 20);
+  }
+})
+</script>
+
+<template>
+<div id="Echarts-UnitTest"
+     style="width: 100%; height: 40rem;position: absolute;"></div>
+</template>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/components/map/SceneViewer.vue b/src/components/map/SceneViewer.vue
index f23109e..5c0c439 100644
--- a/src/components/map/SceneViewer.vue
+++ b/src/components/map/SceneViewer.vue
@@ -7,12 +7,11 @@
 -->
 <template>
   <div id="cesium-viewer" ref="viewerDivRef"></div>
-  <ProfileAnalysis ref="profileChart"></ProfileAnalysis>
 </template>
 
 <script setup lang="ts">
-import {onMounted, ref, watch} from 'vue'
-import {Viewer, Ion, CustomDataSource, Cartesian3} from 'cesium'
+import {onMounted, ref} from 'vue'
+import {Viewer, Ion, CustomDataSource} from 'cesium'
 import 'cesium/Build/Cesium/Widgets/widgets.css'
 import {
   TDTLayerType,
@@ -22,20 +21,15 @@ import {
 } from '@/utils/map/TDTProvider'
 import { initViewer, perfViewer, showNavigator } from '@/utils/map/sceneViewer'
 import { flyToChina } from '@/utils/map/camera'
-import ProfileAnalysis from "@/components/ProfileAnalysis.vue";
 import MeasureDistance from "@/assets/js/cesium-map/measureDistance";
 
 const viewerDivRef = ref<HTMLDivElement>()
 let viewer: Viewer
-// window.CESIUM_BASE_URL = 'node_modules/cesium/Build/Cesium/'
-window.CESIUM_BASE_URL = 'public/Cesium/' //打包部署
-
+window.CESIUM_BASE_URL = 'public/Cesium/'
 Ion.defaultAccessToken =
   'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3YjU4MjJlMS0wMWE4LTRhOWQtYjQ1OC04MTgzMzFhMzQ5ZjAiLCJpZCI6MTE1ODUxLCJpYXQiOjE2NjkyMDM1MzN9.8ajEuv3VKYg8wvFiQlUWWY6Ng6JfY4PuVgRyStL1B-E'
 
-// 绑定地形剖面图弹窗
-let profileChart = ref<InstanceType<typeof ProfileAnalysis> | null>(null)
-let linePoints = ref<number>(-1)
+
 
 onMounted(() => {
   //初始化
@@ -63,29 +57,17 @@ onMounted(() => {
 
   // 挂载在window,供全局组件共享
   window.viewer = viewer
-
   window.measureViewer = new MeasureDistance(viewer);
-  //绘制多边形
-  // const drawPolyline = new CreatePolyline(viewer,false,true,{})
-  // linePoints.value = drawPolyline.positions.length
-  // drawPolyline.start()
-  // profileChart.value?.openDia()
-  //
-  // 绘制地形剖面线
-  // profileChart.value?.drawChart_TerrainProfile([0,1,2,3,4,5,6,7,8,9],
-  //     [-70,800,300,400,23,232,435,243,234,343])
-})
 
-
-watch(linePoints, (newValue, OldValue): void => {
-  console.log("数据变化了",linePoints.value, newValue, OldValue)
 })
 
-</script>
 
+</script>
+<!--样式修改-->
 <style scoped>
 #cesium-viewer {
   width: 100%;
   height: 100%;
 }
+
 </style>
diff --git a/src/components/toolbar.vue b/src/components/toolbar.vue
index f07673d..f442454 100644
--- a/src/components/toolbar.vue
+++ b/src/components/toolbar.vue
@@ -13,26 +13,17 @@ import {ref} from "vue";
 import {useStaticStore} from "@/store/staticOptions.js";
 import {login, requestAirline} from "@/assets/js/request.js";
 import {dataProcess, getAirline} from "@/assets/js/websocketProtocol.ts";
+import SpatialAnalysis from "@/components/SpatialAnalysis.vue";
 
 const message = useMessage();
-let file, SceneValue;
+let SceneValue;
 let showModal = ref(false);
 let hasPlane = ref(false);
 let store = useStaticStore();
 
-// --------------------------------------
-
-
+const spatialAnalyse= ref(null)
 SceneValue = ref('untrace');
-let sceneOptions= [
- {
-    label: '第三视角跟随',
-    value: 'fallow'
-  },{
-    label: '不跟随',
-    value: 'untrace'
-  }
-];
+
 function handleSceneSelect(key){
   if(!hasPlane.value)   return;
 
@@ -42,50 +33,9 @@ function handleSceneSelect(key){
     window.viewer.trackedEntity = window.viewer.entities.getById('websocket-flying-plane');
   }
 }
-let EditOptions = [
-  {
-    label: '查询航线',
-    key: 'requestLine'
-  },
-  {
-    label: '航线管理',
-    key: 'manage'
-  }]
-
 let layerValue = ref('layer1');
 let barIsOpen = ref(true);
-let MeasureOptions = [
-  {
-    label: '距离测量',
-    key: 'distance'
-  },
-  {
-    label: '面积测量',
-    key: 'area'
-  },
-  {
-    label: '清除',
-    key: 'clear'
-  },
-]
 
-let DrawOptions = [
-  {
-    label: '多边形',
-    key: 'polygon'
-  },
-  {
-    label: '矩形',
-    key: 'rec'
-  },{
-    label: '圆形',
-    key: 'circle'
-  },
-  {
-    label: '清除',
-    key: 'clear'
-  },
-]
 function handleEditSelect(key) {
   if(key === 'requestLine') {
     getUavAirline()
@@ -94,6 +44,19 @@ function handleEditSelect(key) {
     // 航线管理页面
   }
 }
+function handleAnalyseSelect(key) {
+  if(key === 'visibility') {
+    store.analysisVars.analysisType = 2
+    //弹出参数窗口
+    spatialAnalyse.value?.openParamsDialog()
+  }
+  if(key === 'profile') {
+    store.analysisVars.analysisType = 1
+    //弹出参数窗口
+    spatialAnalyse.value?.openParamsDialog()
+  }
+
+}
 
 function handleDrawSelect(key) {
   if(key === 'clear') {
@@ -173,6 +136,10 @@ function measureArea() {
   window.measureViewer.activateAreaMeasure();
 }
 
+/**
+ * 连接websocket
+ * @returns {Promise<void>}
+ */
 async function connectWebSocket() {
   await login(store.temp.userName, store.temp.password).then(rsp => {
     let resData = JSON.parse(rsp.data.data)
@@ -185,9 +152,9 @@ async function connectWebSocket() {
   })
   if(sessionStorage.getItem('token') === 'err')  return
 
-  store.server.ws = new WebSocket('ws://123.57.54.1:8048/htfp/websocket/uavGlobal/sysUser003', sessionStorage.getItem('token'))
+  store.webskt.ws = new WebSocket('ws://123.57.54.1:8048/htfp/websocket/uavGlobal/sysUser003', sessionStorage.getItem('token'))
   // store.server.ws = new WebSocket('ws://'+store.server.ws_config.address+':'+store.server.ws_config.port);
-  store.server.ws.onmessage = (event) => {
+  store.webskt.ws.onmessage = (event) => {
     //收到消息后的处理流程....
     let data = dataProcess(JSON.parse(event.data))
     console.log(data);
@@ -203,12 +170,18 @@ async function connectWebSocket() {
   };
 }
 
+/**
+ * 关闭websocket连接
+ */
 function closeWS(){
-  if(store.server.ws){
-    store.server.ws.close();
+  if(store.webskt.ws){
+    store.webskt.ws.close();
   }
 }
 
+/**
+ * 请求航线接口
+ */
 function getUavAirline() {
   if(sessionStorage.getItem('uavId')){
     requestAirline(sessionStorage.getItem('uavId')).then(rsp => {
@@ -219,11 +192,13 @@ function getUavAirline() {
     message.warning('当前未连接飞机')
   }
 }
+
+
 </script>
 
 <template>
   <n-flex id="panel">
-    <n-popselect v-model:value="layerValue" :options="store.templateValue.layerOptions" size="medium">
+    <n-popselect v-model:value="layerValue" :options="store.menuOptions.layerOptions" size="medium">
       <n-button tertiary circle type="warning">
         <template #icon>
           <n-icon><Layers/></n-icon>
@@ -240,31 +215,30 @@ function getUavAirline() {
       </template>
       <span> 添加数据 </span>
     </n-tooltip>
-    <n-tooltip placement="bottom" trigger="hover">
-      <template #trigger>
-      <n-button tertiary circle type="warning">
-        <template #icon>
-          <n-icon><TerrainSharp/></n-icon>
-        </template>
-      </n-button>
-        </template>
-    <span> 地形分析 </span>
-    </n-tooltip>
-    <n-dropdown :options="EditOptions" @select="handleEditSelect">
+
+    <n-dropdown :options="store.menuOptions.AnalyzeOptions" @select="handleAnalyseSelect">
+    <n-button tertiary circle type="warning">
+      <template #icon>
+        <n-icon><TerrainSharp/></n-icon>
+      </template>
+    </n-button>
+    </n-dropdown>
+
+    <n-dropdown :options="store.menuOptions.EditOptions" @select="handleEditSelect">
     <n-button tertiary circle type="warning">
       <template #icon>
         <n-icon><CreateOutline/></n-icon>
       </template>
     </n-button>
     </n-dropdown>
-    <n-dropdown :options="MeasureOptions" @select="handleSelect">
+    <n-dropdown :options="store.menuOptions.MeasureOptions" @select="handleSelect">
     <n-button tertiary circle type="warning">
       <template #icon>
       <n-icon><RulerAlt/></n-icon>
       </template>
     </n-button>
     </n-dropdown>
-    <n-dropdown :options="DrawOptions" @select="handleDrawSelect">
+    <n-dropdown :options="store.menuOptions.DrawOptions" @select="handleDrawSelect">
     <n-button tertiary circle type="warning">
       <template #icon>
         <n-icon><DrawPolygon/></n-icon>
@@ -281,8 +255,8 @@ function getUavAirline() {
       </template>
       <span> WebSocket配置 </span>
     </n-tooltip>
-    <n-popselect v-model:value="SceneValue" :options="sceneOptions" @update:value="handleSceneSelect"
-                 size="medium">
+    <n-popselect v-model:value="SceneValue" :options="store.menuOptions.sceneOptions"
+                 @update:value="handleSceneSelect" size="medium">
 <!--                 :disabled="!hasPlane" -->
 
       <n-button tertiary circle type="warning">
@@ -309,15 +283,15 @@ function getUavAirline() {
     </template>
     <div style="margin: 2rem 2rem .5rem 1rem">
       <n-space>
-        <n-form ref="formRef" :model="store.server.ws_config"
+        <n-form ref="formRef" :model="store.webskt.ws_config"
                 label-placement="left"
                 label-width="auto"
                 require-mark-placement="right-hanging">
           <n-form-item label="服务器地址">
-            <n-input v-model:value="store.server.ws_config.address"  placeholder="127.0.0.1"/>
+            <n-input v-model:value="store.webskt.ws_config.address"  placeholder="127.0.0.1"/>
           </n-form-item>
           <n-form-item label="端口号">
-            <n-input-number v-model:value="store.server.ws_config.port" placeholder=8000 />
+            <n-input-number v-model:value="store.webskt.ws_config.port" placeholder=8000 />
           </n-form-item>
         </n-form>
       </n-space>
@@ -328,6 +302,8 @@ function getUavAirline() {
       </n-space>
     </div>
   </n-modal>
+
+  <SpatialAnalysis ref="spatialAnalyse"></SpatialAnalysis>
 </template>
 
 <style scoped>
diff --git a/src/router/index.js b/src/router/index.js
index a121f94..27eed2b 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -7,6 +7,11 @@ const router = createRouter({
             path: '/',
             name: 'Home',
             component: ()=>import( '@/components/HomePage.vue'),
+        },
+        {
+            path: '/test',
+            name: 'Test',
+            component: ()=>import('@/components/UnitTest.vue')
         }
     ]
 });
diff --git a/src/store/staticOptions.js b/src/store/staticOptions.js
index 2a20428..7d5ba30 100644
--- a/src/store/staticOptions.js
+++ b/src/store/staticOptions.js
@@ -1,5 +1,6 @@
 import {defineStore} from "pinia";
 import cesiumAirPlane from "@/assets/models/Cesium_Air.glb";
+import {ref} from "vue";
 export const useStaticStore = defineStore('staticOptions',{
     state: ()=>{
         return {
@@ -8,10 +9,42 @@ export const useStaticStore = defineStore('staticOptions',{
                 password:"sysUser003",
                 token:"",
             },
-            server: {
+            menuOptions:{
+                EditOptions: [
+                    {label: '查询航线', key: 'requestLine'},
+                    {label: '航线管理', key: 'manage'}
+                ],
+                sceneOptions:[
+                    {label: '第三视角跟随', value: 'fallow'},
+                    {label: '不跟随', value: 'untrace'}
+                ],
+                MeasureOptions:[
+                    {label: '距离测量', key: 'distance'},
+                    {label: '面积测量', key: 'area'},
+                    {label: '清除', key: 'clear'},
+                ],
+                DrawOptions:[
+                    {label: '多边形', key: 'polygon'},
+                    {label: '矩形', key: 'rec'},
+                    {label: '圆形', key: 'circle'},
+                    {label: '清除', key: 'clear'},
+                ],
+                AnalyzeOptions:[
+                    {label: '通视分析', key: 'visibility'},
+                    {label: '地形剖面', key: 'profile'}
+                ],
+                //图层选项,动态
+                layerOptions: [
+                    {
+                        label: '图层1',
+                        value: 'layer1'
+                    }
+                ],
+            },
+            webskt: {
                 ws: null,
                 isOpen: false,
-                ws_config:{
+                ws_config: {
                     address: '127.0.0.1',
                     port: 8000,
                 },
@@ -20,15 +53,10 @@ export const useStaticStore = defineStore('staticOptions',{
                 defaultAirPlane: cesiumAirPlane,
             },
             hasPlane: false,
-            templateValue:{
-                //图层选项,动态
-                layerOptions: [
-                    {
-                        label: '图层1',
-                        value: 'layer1'
-                    }
-                ],
-
+            analysisVars: {
+                //当前的空间分析类型,剖面1 通视2
+                analysisType: -1,
+                profilePts: [],     //地形分析的点数组
             }
         }
     }
diff --git a/src/utils/map/SpatialAnalysis.ts b/src/utils/map/SpatialAnalysis.ts
index 2d7d765..400a53f 100644
--- a/src/utils/map/SpatialAnalysis.ts
+++ b/src/utils/map/SpatialAnalysis.ts
@@ -6,6 +6,7 @@
 
 import {getDistance, getElevation} from "@/utils/map/geocomputation.ts";
 import {Cartesian3, Viewer} from "cesium";
+import * as echarts from "echarts";
 type ProfileResult = {
  distanceArray:number[],
  elevationArray:number[],
@@ -24,23 +25,29 @@ export function elevationProfile(viewer: Viewer, start:Cartesian3, end:Cartesian
  let distanceFromStart:number[] = []  //断点至起点的距离m
  // 计算首尾点距离 m
  let totalLen = getDistance(start, end) * 1000
- // 获取起点高度
- breakPointsHeight.push(getElevation(viewer, start))
+ // 获取起点高度及其与起点的距离
+ breakPointsHeight.push(Math.round(getElevation(viewer, start)))
  distanceFromStart.push(0)
- //断点数量
- let breakNum = Math.floor(totalLen/interval)
- // 如果采样间隔小于首尾点距离,则获取每个断点的坐标 并获取其高度
- if(breakNum>=1){
-  for (let i = 1; i <= breakNum; i++) {
-   let breakP = Cartesian3.lerp(start, end, i/breakNum, new Cartesian3())
-   breakPointsHeight.push(getElevation(viewer, breakP))
-   distanceFromStart.push(getDistance(start,breakP)*1000)
+
+ //获取中间断点的高度及其与起点的距离
+ if(interval > 0){
+  //断点数量
+  let breakNum = Math.floor(totalLen/interval)
+  // 如果采样间隔小于首尾点距离,则获取每个断点的坐标 并获取其高度
+  if(breakNum>=1){
+   for (let i = 1; i < breakNum; i++) {
+    let breakP = Cartesian3.lerp(start, end, i/breakNum, new Cartesian3())
+    breakPointsHeight.push(Math.round(getElevation(viewer, breakP)))        //单位 米
+    distanceFromStart.push(Math.round(getDistance(start,breakP)*1000))  //单位 米
+   }
   }
  }
- // 获取终点高度
- breakPointsHeight.push(getElevation(viewer, end))
- distanceFromStart.push(totalLen)
- return { distanceArray:distanceFromStart, elevationArray:breakPointsHeight }
+
+ // 获取终点高度及其与起点的距离
+ breakPointsHeight.push(Math.round(getElevation(viewer, end)))
+ distanceFromStart.push(Math.round(totalLen))
+
+ return { distanceArray: distanceFromStart, elevationArray: breakPointsHeight }
 }
 
 /**
@@ -50,12 +57,18 @@ export function elevationProfile(viewer: Viewer, start:Cartesian3, end:Cartesian
  * @param interval 线段采样间隔 m为单位
  * @return 从折线起点至终点剖面线的海拔高度数组
  */
-export function profileAnalyse(viewer: Viewer, polyline:Cartesian3[],interval: number){
- let result:ProfileResult = { distanceArray:[], elevationArray:[] }
- for (let i = 0; i < polyline.length - 2; i++) {
-  let temp = elevationProfile(viewer,polyline[i],polyline[i+1],interval)
+export function profileAnalyse(viewer: Viewer, polyline:Cartesian3[], interval: number){
+ let result: ProfileResult = { distanceArray:[], elevationArray:[] }
+ let temp_dis = 0  //每两点之间的距离
+ for (let i = 0; i <= polyline.length - 2; i++) {
+  let temp = elevationProfile(viewer, polyline[i], polyline[i+1], interval)
   result.elevationArray = result.elevationArray.concat(temp.elevationArray)
-  result.distanceArray = result.distanceArray.concat(temp.distanceArray)
+  temp.distanceArray.forEach(distance => {
+   result.distanceArray.push(distance+temp_dis)
+  })
+  if(temp.distanceArray.length > 0){
+   temp_dis += temp.distanceArray[temp.distanceArray.length-1]
+  }
  }
  return result
 }
@@ -66,19 +79,21 @@ export function profileAnalyse(viewer: Viewer, polyline:Cartesian3[],interval: n
  * @param viewer 地图
  * @param viewpoint 视点
  * @param target 目标点
- * @param h 视点地面抬高,默认为1m
+ * @param h1 视点地面挂高 m
+ * @param h2 目标点地面挂高 m
+ * @param curvature 是否考虑地球曲率
  * @param breakNum 采样间隔,默认为100个断点
  */
 export function visibilityAnalyse(viewer: Viewer, viewpoint:Cartesian3, target:Cartesian3,
-                                  h= 1, breakNum = 100) {
+                                  h1:number, h2:number,curvature:boolean, breakNum = 100) {
  // 获取视点高度和目标点高度
- let viewpointH = getElevation(viewer, viewpoint) + h
- let targetH = getElevation(viewer, target)
- if (viewpointH === -9999.2024 + h ) {
+ let viewpointH = getElevation(viewer, viewpoint) + h1
+ let targetH = getElevation(viewer, target)  + h2
+ if (viewpointH === -9999.2024 + h1 ) {
   console.log("无法获取视点海拔高度!")
   return undefined
  }
- if (targetH === -9999.2024 ) {
+ if (targetH === -9999.2024 + h2 ) {
   console.log("无法获取目标点海拔高度!")
   return undefined
  }
@@ -98,5 +113,350 @@ export function visibilityAnalyse(viewer: Viewer, viewpoint:Cartesian3, target:C
    return false
   }
  }
+
+ if(curvature){
+  let Rmax = 2.898 * (Math.sqrt(h1)+Math.sqrt(h2))
+  if (Rmax < totalLen/1000.0)  return false
+ }
  return true
 }
+
+/**
+ *  绘制地形剖面折线图
+ * @param xData x数组
+ * @param yData y数组,以面积线绘制
+ */
+export function drawEchartsProfileAnalyse(xData:number[], yData:number[]) {
+ let myChart = echarts.init(document.getElementById('profileEChart'))
+ // 绘制图表
+ myChart.setOption({
+  legend: {
+   show: true,
+   type: 'plain',
+   top: '5%',
+   data:[
+    {
+     name: 'groundLine',
+     itemStyle: 'inherit',
+     lineStyle: 'inherit',
+    },
+    ]
+  },
+  tooltip: {
+   show: true,
+   trigger: 'axis',
+   axisPointer: {
+    type: 'cross'
+   },
+   formatter:'地表高度: {c0}'
+  },
+  xAxis: {
+   data: xData,
+   name: '距离/米',
+   nameTextStyle: {
+    fontWeight:'bolder',
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   axisLine:{
+    onZero: false,
+    show: true,    // 是否显示坐标轴轴线
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   },
+   axisLabel: {
+    formatter: '{value}',
+    margin: 5,
+   },
+   axisTick: {
+    show: true,    // 是否显示坐标轴刻度
+    inside: true,     // 坐标轴刻度是否朝内,默认朝外
+    alignWithLabel: true,
+    lineStyle: {
+     color: '#000000',     //刻度线的颜色
+     type: 'solid',    //坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)
+    },
+   }
+  },
+  yAxis: {
+   type: 'value',
+   name: '高度/米',
+   nameTextStyle: {
+    fontWeight:'bolder',
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   position: 'left',
+   axisLabel: {
+    formatter: '{value}'
+   },
+   axisLine: {
+    show: true,
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   }
+  },
+  series: [
+   {
+    name:'groundLine',
+    type: 'line',
+    data: yData,
+    areaStyle: {
+     color: '#37a5fb',
+     opacity: 0.5
+    }
+   }
+  ]
+ });
+}
+
+
+/**
+ *  绘制折线图(航线碰撞检测)
+ * @param xData x数组
+ * @param yData y数组,以面积线绘制
+ * @param yData2 y数组,以折线绘制
+ */
+export const drawEchartsAirlineDetect = (xData:number[],yData:number[],yData2:number[]) => {
+ let myChart = echarts.init(document.getElementById('profileEChart'))
+ // 绘制图表
+ myChart.setOption({
+  legend:{
+   show: true,
+   type: 'plain',
+   top: '7%',
+   data:[
+    {
+     name: 'groundLine',
+     itemStyle: 'inherit',
+     lineStyle: 'inherit',
+    },
+    {
+     name: 'airLine',
+     itemStyle: 'inherit',
+     lineStyle: 'inherit',
+    }]
+  },
+  tooltip: {
+   show: true,
+   trigger: 'axis',
+   axisPointer: {
+    type: 'cross'
+   },
+   formatter:'地表高度: {c0}<br>航线高度: {c1}'
+  },
+  xAxis: {
+   data: xData,
+   name: '距离',
+   nameTextStyle: {
+    fontWeight:'bolder',
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   axisLine:{
+    onZero: false,
+    show: true,    // 是否显示坐标轴轴线
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   },
+   axisLabel: {
+    formatter: '{value} m',
+    margin: 5,
+   },
+   axisTick: {
+    show: true,    // 是否显示坐标轴刻度
+    inside: true,     // 坐标轴刻度是否朝内,默认朝外
+    alignWithLabel: true,
+    lineStyle: {
+     color: '#000000',     //刻度线的颜色
+     type: 'solid',    //坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)
+    },
+   }
+  },
+  yAxis: {
+   type: 'value',
+   name: '高度',
+   nameTextStyle: {
+    fontWeight:'bolder',
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   position: 'left',
+   axisLabel: {
+    formatter: '{value} m'
+   },
+   axisLine: {
+    show: true,
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   }
+  },
+  series: [
+   {
+    name:'groundLine',
+    type: 'line',
+    data: yData,
+    areaStyle: {
+     color: '#37a5fb',
+     opacity: 0.5
+    }
+   },
+   {
+    name:'airLine',
+    type: 'line',
+    data: yData2,
+   }
+  ]
+ });
+}
+
+
+/**
+ *  绘制通视分析图 面积线和直线
+ * @param xData x数组,地面距离
+ * @param yData y数组,以面积线绘制
+ * @param startHeight 视线起始点高度(包含地面挂高)
+ * @param endHeight  视线终点高度(包含地面挂高)
+ */
+export const drawEchartsVisibility = (xData:number[], yData:number[],startHeight:number, endHeight:number) => {
+ console.group()
+ console.log(0, startHeight)
+ console.log(xData.at(-1), endHeight)
+ console.groupEnd()
+ console.log(xData)
+ let myChart = echarts.init(document.getElementById('profileEChart')) //Echarts-UnitTest
+ // 绘制图表
+ myChart.setOption({
+  legend: {
+   show: true,
+   type: 'plain',
+   top: '7%',
+   data: [
+    { //地形剖面图例
+     name: '剖面线',
+     itemStyle: {
+      fontSize: 18
+     },
+     lineStyle: 'inherit',
+    },
+    { //视线图例
+     name: '视线',
+     lineStyle: {
+      type: 'dotted',
+      width: 3,
+      color: '#f8364d'
+     },
+     itemStyle: {
+      fontSize: 18
+     }
+    }
+    ],
+   selectedMode: false,  //图例选择模式关闭
+  },
+  tooltip: {
+   show: true,
+   trigger: 'axis',
+   axisPointer: {
+    type: 'cross'
+   },
+   formatter:'地表高度: {c0}'
+  },
+  xAxis: {
+   boundaryGap : false,
+   max: (value:any)=>{
+    return value.max * 1.01;
+   },
+   min: 0,
+   data: xData,
+   name: '距离/m',
+   nameTextStyle: {
+    fontWeight:'bolder',
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   axisLine:{
+    onZero: false,
+    show: true,    // 是否显示坐标轴轴线
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   },
+   axisLabel: {
+    formatter: '{value}',
+    margin: 5,
+   },
+   axisTick: {
+    show: true,    // 是否显示坐标轴刻度
+    inside: true,     // 坐标轴刻度是否朝内,默认朝外
+    alignWithLabel: true,
+    lineStyle: {
+     color: '#000000',     //刻度线的颜色
+     type: 'solid',    //坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)
+    },
+   }
+  },
+  yAxis: {
+   max: (value:any)=>{
+    return Math.floor(Math.max(value.max,startHeight,endHeight)*1.01)
+   },
+   min: (value:any)=>{
+    return Math.floor(Math.min(value.min,startHeight,endHeight)*0.99)
+   },
+   type: 'value',
+   name: '高度/ m',
+   nameTextStyle: {
+    fontWeight:'bolder',
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   position: 'left',
+   axisLabel: {
+    formatter: '{value}'
+   },
+   axisLine: {
+    show: true,
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   }
+  },
+  series: [
+   {
+    name:'剖面线',
+    type: 'line',
+    data: yData,
+    areaStyle: {
+     color: '#37a5fb',
+     opacity: 0.5
+    },
+    markLine: {
+     data: [
+         [
+             {coord: ['0', startHeight.toString()]},
+             {coord: [xData.at(-1)?.toString(), endHeight.toString()]}
+             // Markline中的坐标点必须为string,否则异常
+         ]
+     ],
+     symbol:['circle', 'arrow'],
+     label:{
+      formatter: "模 拟 视 线",
+      show: true,
+      position: 'middle',
+      fontSize: 15,
+      fontWeight: 'bold',
+      color: '#e73d3d',
+     },
+     lineStyle: {                 //标注线样式
+      type: 'dashed',
+      color: 'red',
+      with: 10
+     }
+    },
+   },
+   { /* 视线的series */
+    type: 'line',
+    symbol: 'none',
+    name: '视线',
+    color: 'transparent'
+   }
+  ],
+ });
+}
diff --git a/update-index.mjs b/update-index.mjs
deleted file mode 100644
index b8150a8..0000000
--- a/update-index.mjs
+++ /dev/null
@@ -1,16 +0,0 @@
-import fs from 'fs';
-
-console.time('转换用时');
-const distPath = './dist/index.html';   //打包路径的index.html
-let htmlText = fs.readFileSync(distPath, 'utf8');
-let resultText = '';
-let htmlArr = htmlText.match(/.*\n/g) || [];
-htmlArr.forEach(str => {
-    str = str.replace(/\s?nomodule\s?/g,' ');
-    str = str.replace(/\s?crossorigin\s?/g,' ');
-    str = str.replace(/data-src/g,'src');
-    if(!/type="module"/i.test(str))
-        resultText += str;
-});
-fs.writeFileSync(distPath,resultText,'utf8');
-console.timeEnd('转换用时');
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index b737f7c..df4b634 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -19,7 +19,7 @@ export default defineConfig({
     }),
   ],
   base: './',
-  build:{
+  build: {
     target: ['es2015', 'chrome63'],
   },
   resolve: {