diff --git a/src/assets/js/RouteManageViewer.js b/src/assets/js/RouteManageViewer.js
index 2b6d3c0..4096064 100644
--- a/src/assets/js/RouteManageViewer.js
+++ b/src/assets/js/RouteManageViewer.js
@@ -1,14 +1,14 @@
-import {DataSource} from "cesium";
+import {Cartesian3, DataSource} from "cesium";
 import * as Cesium from 'cesium'
 
 
 export default class RouteManageViewer {
-    constructor(viewer, isClose, height) {
+    constructor(viewer, isClose) {
         this.viewer = viewer
         this.scene = viewer.scene
         this.routeParams = {
             isClose: isClose,
-            height: height,
+            height: 0,
         }
         this.positions = []
         this.temPositions = []      // 鼠标移动时产生的临时点
@@ -16,8 +16,66 @@ export default class RouteManageViewer {
         this.lineEntity = undefined // 折线元素
         this.lineEntitys = []       // 折线元素数组,每完成一次航线绘制,将折线元素加入此数组
     }
-
-    // -------------------------------------------//
+    
+    /**
+     * 显示航线
+     * @param line Airline
+     */
+    addAirLine(line){
+        let res = this.viewer.entities.getById( "航线" + line.unicode)
+        if(res!==undefined){
+            return res
+        }
+        
+        let degreesArr = []
+        for (let i = 0; i < line.points.length; i++) {
+            let coord = new Cartesian3.fromDegrees(line.points[i].lon,line.points[i].lat,line.points[i].alt)
+            degreesArr.push(coord)
+        }
+        if(line.isClose)
+            degreesArr.push(new Cartesian3.fromDegrees(line.points[0].lon,line.points[0].lat,line.points[0].alt))
+        
+        let airlineEntity = new Cesium.Entity({
+            name: line.name,
+            id: "航线" + line.unicode,
+            polyline: {
+                positions: degreesArr,
+                width: 3,
+                material: Cesium.Color.ORANGE,
+                clampToGround: false,
+            }
+        })
+        this.viewer.entities.add(airlineEntity)
+        degreesArr.forEach((pt,index)=>{
+            let vertexEntity = new Cesium.Entity({
+                id:  line.unicode + "-航点" + index,
+                position:  pt,
+                point: {
+                    color: Cesium.Color.WHITE,
+                    pixelSize: 6,
+                    outlineColor: Cesium.Color.RED,
+                    outlineWidth: 2,
+                    disableDepthTestDistance:99000000,
+                    // heightReference:Cesium.HeightReference.CLAMP_TO_GROUND,
+                }
+            });
+            this.viewer.entities.add(vertexEntity)
+        })
+        return airlineEntity
+    }
+    
+    /**
+     * 删除航线
+     * @param line Airline
+     */
+    removeRoute(line){
+        this.viewer.entities.removeById( "航线" + line.unicode)
+        line.points.forEach((_,index)=>{
+            this.viewer.entities.removeById(line.unicode + "-航点" + index)
+        })
+    }
+    
+    // -----------------绘制航线相关功能--------------------------//
     //开始绘制
     start() {
         this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
diff --git a/src/assets/js/TypeInitial.ts b/src/assets/js/TypeInitial.ts
new file mode 100644
index 0000000..1ed7fd6
--- /dev/null
+++ b/src/assets/js/TypeInitial.ts
@@ -0,0 +1,13 @@
+import {Airline, AirlinePoint} from "@/types/entityoptions.ts";
+
+export function newAirlinePt() {
+    let pt: AirlinePoint = {alt: undefined, ch1: 0, ch2: 0, lat: undefined, lon: undefined, nPt: undefined, speed: 0}
+    return pt
+}
+
+export function newAirline() {
+    let flyLine: Airline = {
+        PtNum: undefined, code: undefined, isClose: false, name: "", points: [], totalDistance: undefined
+    }
+    return flyLine
+}
\ No newline at end of file
diff --git a/src/assets/js/measureViewer.js b/src/assets/js/measureViewer.js
index a40afcd..05ae9fc 100644
--- a/src/assets/js/measureViewer.js
+++ b/src/assets/js/measureViewer.js
@@ -322,6 +322,11 @@ export default class MeasureViewer {
      * @param line Airline
      */
     showAirLine(line){
+        let res = this.viewer.entities.getById( "航线" + line.code + "-" +line.name,)
+        if(res!==undefined){
+            return res
+        }
+        
         let degreesArr = []
         for (let i = 0; i < line.points.length; i++) {
             let coord = new Cartesian3.fromDegrees(line.points[i].lon,line.points[i].lat,line.points[i].alt)
@@ -329,10 +334,10 @@ export default class MeasureViewer {
         }
         if(line.isClose)
             degreesArr.push(new Cartesian3.fromDegrees(line.points[0].lon,line.points[0].lat,line.points[0].alt))
-
+        
         let airlineEntity = new Cesium.Entity({
             name: line.name,
-            id: line.name + line.totalDistance,
+            id: "航线" + line.code + "-" +line.name,
             polyline: {
                 positions: degreesArr,
                 width: 3,
@@ -341,21 +346,24 @@ export default class MeasureViewer {
             }
         })
         this.viewer.entities.add(airlineEntity)
-        for (let pt in degreesArr) {
+        degreesArr.forEach((pt,index)=>{
             let vertexEntity = new Cesium.Entity({
-                // id: "航点" + ,
+                id:  line.code + "-航点" + index,
                 position:  pt,
                 point: {
                     color: Cesium.Color.FUCHSIA,
                     pixelSize: 6,
+                    outlineColor: Cesium.Color.RED,
+                    outlineWidth: 2,
                     disableDepthTestDistance:99000000,
                     // heightReference:Cesium.HeightReference.CLAMP_TO_GROUND,
                 }
             });
             this.viewer.entities.add(vertexEntity)
-        }
-
+        })
+        return airlineEntity
     }
+    
 
     addAirplaneEntity(modelPath,StrUavTypeID){
         this.viewer.scene.globe.depthTestAgainstTerrain = true;
diff --git a/src/assets/js/request.js b/src/assets/js/request.js
deleted file mode 100644
index 8a945b4..0000000
--- a/src/assets/js/request.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import axios from "axios";
-
-function login(username, password)
-{
-    return axios({
-        method: "POST",
-        url: "/onlinetest/htfp/cac/logIn",
-        headers: {"Content-Type": "application/json"},
-        data: {
-            username: username,
-            password: password,
-            forceLogOutOtherDeviceAccount: false
-        }
-    })
-}
-
-function requestAirline(uavID){
-    return axios({
-        method: "POST",
-        url: "/onlinetest/htfp/cac/queryUavBundledRouteList",
-        headers: [{"Content-Type": "application/json"},{"X-Authorization-With": sessionStorage.getItem("token")}],
-        data: {
-            uavId: uavID,
-        }
-    })
-}
-export {login, requestAirline}
diff --git a/src/assets/js/testData.ts b/src/assets/js/testData.ts
new file mode 100644
index 0000000..453e155
--- /dev/null
+++ b/src/assets/js/testData.ts
@@ -0,0 +1,38 @@
+import {Airline, getUnicode} from "@/types/entityoptions.ts";
+
+// let route: AirlinePoint = {alt: 0, ch1: 0, ch2: 0, lat: 0, lon: 0, nPt: 0, speed: 0}
+const route: Airline = {
+    PtNum: 5, code: 1, isClose: false, name: "测试航线1", totalDistance: 12323,
+    unicode:getUnicode(),
+    points: [
+        { lon: 120.23234234, lat: 30.232323,alt: 550, ch1: 0, ch2: 3,  nPt: 1, speed: 0},
+        { lon: 120.34233234, lat: 30.232312,alt: 550, ch1: 0, ch2: 3,  nPt: 2, speed: 0},
+        { lon: 120.23234324, lat: 30.21223,alt: 550, ch1: 0, ch2: 3,  nPt: 3, speed: 0},
+        { lon: 120.23289964, lat: 30.256323,alt: 550, ch1: 0, ch2: 3,  nPt: 4, speed: 0},
+        { lon: 120.53564234, lat: 30.132323,alt: 550, ch1: 0, ch2: 1,  nPt: 5, speed: 0},
+    ],
+}
+const route2: Airline = {
+    PtNum: 4, code: 2, isClose: true, name: "测试航线2", totalDistance: 2341234,
+    unicode:getUnicode(),
+    points: [
+        { lon: 120.23234234, lat: 30.232323,alt: 550, ch1: 0, ch2: 3,  nPt: 0, speed: 0},
+        { lon: 120.34233234, lat: 30.232312,alt: 550, ch1: 0, ch2: 3,  nPt: 1, speed: 0},
+        { lon: 120.23234324, lat: 30.21223,alt: 550, ch1: 0, ch2: 3,  nPt: 2, speed: 0},
+        { lon: 120.53564234, lat: 30.132323,alt: 550, ch1: 2, ch2: 1,  nPt: 4, speed: 0},
+    ],
+}
+const route3: Airline = {
+    PtNum: 7, code: 3, isClose: false, name: "测试航线3", totalDistance: 3234134,
+    unicode:getUnicode(),
+    points: [
+        { lon: 123.23234234, lat: 30.232323,alt: 550, ch1: 0, ch2: 3,  nPt: 0, speed: 0},
+        { lon: 123.34233234, lat: 30.232312,alt: 550, ch1: 0, ch2: 3,  nPt: 1, speed: 0},
+        { lon: 123.23234324, lat: 30.21223,alt: 550, ch1: 0, ch2: 3,  nPt: 2, speed: 0},
+        { lon: 123.23289964, lat: 30.256323,alt: 550, ch1: 0, ch2: 3,  nPt: 3, speed: 0},
+        { lon: 123.53564234, lat: 30.132323,alt: 550, ch1: 0, ch2: 1,  nPt: 4, speed: 0},
+        { lon: 123.53564234, lat: 30.132323,alt: 550, ch1: 0, ch2: 1,  nPt: 4, speed: 0},
+        { lon: 123.53564234, lat: 30.132323,alt: 550, ch1: 0, ch2: 1,  nPt: 4, speed: 0},
+    ],
+}
+export {route,route2,route3}
\ No newline at end of file
diff --git a/src/assets/js/useBlockDialog.js b/src/assets/js/useBlockDialog.js
deleted file mode 100644
index e365bc2..0000000
--- a/src/assets/js/useBlockDialog.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import { defineAsyncComponent, render, createVNode } from "vue";
-export class routeDialog {
-     constructor() {
-         this.component = defineAsyncComponent(
-             () => import("@/components/RouteOptions.vue"));
-         this.vnode = null;
-         this.node = null;
-         this.props = {
-             width: "40%",
-             height: "auto",
-         };
-     }
-     installRouteDialog() {
-         if (!this.vnode) {
-             const dialog = createVNode(this.component, this.props);
-             const container = document.createElement('div');
-             render(dialog, container);
-             this.vnode = dialog;
-             this.node = container.childNodes[0];
-             document.body.appendChild(this.node);
-         }
-     }
-     /**
-      *
-      * @returns {Promise<string>}
-      * @param points 经纬度坐标点数组
-      */
-     show(points) {
-         // 发送信号,显示窗口
-         const event = new CustomEvent('route-dialog-show', { detail:
-                 { show: true, pts: points }
-         });
-         document.dispatchEvent(event);
-         return new Promise((resolve,reject) => {
-             document.addEventListener('route-dialog-confirm', event => {
-                 if(event.detail==='cancel'){
-                     reject('cancel')
-                 }else{
-                     resolve(event.detail);
-                 }
-             });
-         })
-     }
- }
- const aDialog = new routeDialog();
-
- /**
-  * 展示一个阻塞式对话框
-  * @returns {Promise<string>}
-  * @param point 经纬度坐标点数组
-  */
- export async function showRouteDialog(point) {
-     return aDialog.show(point);
- }
\ No newline at end of file
diff --git a/src/assets/js/weatherRequest.ts b/src/assets/js/weatherRequest.ts
new file mode 100644
index 0000000..9e818bc
--- /dev/null
+++ b/src/assets/js/weatherRequest.ts
@@ -0,0 +1,39 @@
+import axios from "axios";
+
+type WeatherResponse = {
+    success: boolean,
+    code: number,
+    message: number,
+    data: any  //响应数据
+}
+
+//查询未来24小时,指定位置的地面气象变量信息
+function query_surface_forecast(lat:number, lon: number)
+{
+    return axios({
+        method: "POST",
+        url: "/onlinetest/htfp/weather/v1surface/querySurfaceForecast",
+        headers: {"Content-Type": "application/json"},
+        data: {
+            latitude: lat,
+            longitude: lon,
+        }
+    })
+}
+
+//查询未来24小时,指定位置和高度的高空气象变量信息
+function query_upper_forecast(lat:number, lon: number, level:number){
+    return axios({
+        method: "POST",
+        url: "/onlinetest/htfp/weather/v1upper/queryUpperForecast",
+        headers: {"Content-Type": "application/json"},
+        data: {
+            latitude: lat,
+            longitude:lon,
+            level: level
+        }
+    })
+}
+
+
+export {query_upper_forecast, query_surface_forecast}
diff --git a/src/components/BottomBar.vue b/src/components/BottomBar.vue
index ac04461..1dc8068 100644
--- a/src/components/BottomBar.vue
+++ b/src/components/BottomBar.vue
@@ -72,7 +72,7 @@ function lonlatClick() {
   position: absolute;
   bottom: 1px;
   left: 0;
-  width: 100vw;
+  width: 100%;
   height: 1.7rem;
   background-color: rgba(47, 53, 60, 0.8);
   color: #fff;
diff --git a/src/components/RouteOptions.vue b/src/components/RouteOptions.vue
index e4e06a5..33ba264 100644
--- a/src/components/RouteOptions.vue
+++ b/src/components/RouteOptions.vue
@@ -8,7 +8,8 @@ import {defineEmits, ref} from "vue";
 
 let emit = defineEmits(['routeDraw','cancelDraw'])
 let routeParams = ref({
-  code: 0,
+  name: '',
+	code: 0,
   isClose: false,
   height: 0,
   routePts: []
@@ -26,6 +27,9 @@ let routeCode = [
   },{
     label: "任务航线4",
     value: 4,
+  },{
+    label: "任务航线5",
+    value: 5,
   }
 ]
 const done = ()=>{
@@ -59,6 +63,9 @@ const cancel = ()=>{
             </n-switch>
           </n-form-item>
           <n-form-item label="航线名称">
+						<n-input v-model:value="routeParams.name" placeholder="输入名称"></n-input>
+          </n-form-item>
+					<n-form-item label="航线类型">
             <n-select v-model:value="routeParams.code"  :options="routeCode" />
           </n-form-item>
           <n-form-item label="航线高度/m">
diff --git a/src/components/page/RouteManagePage.vue b/src/components/page/RouteManagePage.vue
index 96c0baf..f8ddbbc 100644
--- a/src/components/page/RouteManagePage.vue
+++ b/src/components/page/RouteManagePage.vue
@@ -1,11 +1,370 @@
 <script setup lang="ts">
+import SceneViewer from "@/components/SceneViewer.vue";
+import BottomBar from "@/components/BottomBar.vue";
+import {ArrowBackOutline,ArrowForwardOutline,Save,Add, SaveOutline} from "@vicons/ionicons5";
+import {nextTick, onMounted, ref} from "vue";
+import {darkTheme, useMessage} from "naive-ui";
+import {route,route2,route3} from "@/assets/js/testData.ts";
+import {useRouteStore} from "@/store/RouteStore.ts";
+import {Airline} from "@/types/entityoptions.ts";
+import {newAirline, newAirlinePt} from "@/assets/js/TypeInitial.ts";
+import * as echarts from "echarts";
+import {EChartsType} from "echarts";
+import {transLonlat2Car3} from "@/utils/map/geocomputation.ts";
+import {drawEcharts_RouteDetection, profileAnalyse} from "@/utils/map/SpatialAnalysis.ts";
+import RouteManageViewer from "@/assets/js/RouteManageViewer.js";
 
+let myChart: EChartsType = undefined
+let routeStore = useRouteStore()
+let selectedRouteCode = ref(null)
+let showPtList = ref(true)
+let selectedRoute = ref<Airline>(newAirline())
+let routesInstore = ref<{ value: string|number; label: string}[]>(null)
+let routeViewer = null
+let routePtNumber = ref(1)
+let uiMsg = useMessage()
+
+let PtOptions =  [
+	{label: '删除航点', key: 'deletePt'},
+	{label: '插入航点', key: 'insertPt'},
+]
+let routeCode = [
+	{
+		label: "任务航线1",
+		value: 1,
+	},{
+		label: "任务航线2",
+		value: 2,
+	},{
+		label: "任务航线3",
+		value: 3,
+	},{
+		label: "任务航线4",
+		value: 4,
+	},{
+		label: "任务航线5",
+		value: 5,
+	}
+]
+
+onMounted(()=>{
+	myChart = echarts.init(document.getElementById('echarts-profile'),'dark')
+
+	routeStore.addRoute(route)
+	routeStore.addRoute(route2)
+	routeStore.addRoute(route3)
+
+	routesInstore.value = routeStore.flyRoute.map((route)=> {
+		return {
+			value: route.unicode,
+			label: route.name
+		}
+	})
+
+})
+
+// 航线选择回调
+function checkRoute(key:number|string){
+	new Promise((resolve,reject)=>{
+		selectedRoute.value = routeStore.flyRoute.filter(element => element.unicode === String(key))[0]
+		if(selectedRoute.value == null) 	reject('未找到航线')
+
+		routeViewer = new RouteManageViewer(window.viewer,selectedRoute.value.isClose)
+		window.viewer.flyTo(routeViewer.addAirLine(selectedRoute.value), {duration: 2})
+		setTimeout(()=>resolve('success'),2500)
+
+	}).then((result)=>{
+		//绘制图表
+		let Cartain3 = transLonlat2Car3(selectedRoute.value.points)
+		// 计算地形剖面,默认采样间隔为1km
+		let res = profileAnalyse(window.viewer, Cartain3, 1000)
+		// 计算航线距离数组
+		let orderArr = []
+		let hArr = []
+		Cartain3.forEach((_,index) => {
+			orderArr.push(index + 1)
+			hArr.push(selectedRoute.value.points[index].alt)
+		})
+		console.log(orderArr,hArr)
+		// 弹出图表窗口
+		drawEcharts_RouteDetection(myChart, res.distanceArray, res.elevationArray, orderArr, hArr)
+	}).catch((err)=>{
+		uiMsg.error(err)
+	})
+}
+
+// 在尾部添加航点
+function addPtToTail() {
+	let newPt = newAirlinePt()
+	newPt.nPt = selectedRoute.value.points.at(-1).nPt + 1
+	selectedRoute.value.points.push(newPt)
+}
+
+// 保存航点编辑
+// 1 重新编辑航点的ch2属性
+// 2 刷新航线属性
+// 3 将改动更新到store中
+function savePt() {
+	selectedRoute.value.points.forEach((pt,index) => {
+		pt.ch2 = 3
+		pt.nPt = index+1	//航点序号从1起
+	})
+	selectedRoute.value.points.at(-1).ch2 = 1
+	selectedRoute.value.PtNum = selectedRoute.value.points.length
+	routeStore.addRoute(selectedRoute.value)
+}
+
+/** 删除或在此前插入航点
+ *
+ * @param key 下拉菜单key
+ * @param index 航点索引
+ */
+function handlePtSelect(key:any, index:number) {
+	if(key=='deletePt'){
+		selectedRoute.value.points.splice(index,1)
+		selectedRoute.value.points.forEach((pt,i) => {
+			pt.nPt = i+1
+		})
+		showPtList.value = false
+		nextTick(()=>{
+			showPtList.value = true
+		})
+	}
+	else if(key=='insertPt'){
+		selectedRoute.value.points.forEach((pt,i) => {
+			if(i>=index) pt.nPt = i + 2
+		})
+		let newPt = newAirlinePt()
+		newPt.nPt = index + 1
+		showPtList.value = false
+		nextTick(()=>{
+			selectedRoute.value.points.splice(index,0,newPt)
+			showPtList.value = true
+		})
+
+	}
+}
+
+//查询上一航点的气象信息
+function prevPtWeather() {
+	routePtNumber.value -= 1
+	//TODO: 查询气象接口,使用返回值promise
+}
+
+//查询下一航点的气象信息
+function nextPtWeather() {
+	routePtNumber.value += 1
+	console.log(selectedRoute.value.points.length)
+	//TODO: 查询气象接口,使用返回值promise
+}
 </script>
 
 <template>
+	<n-config-provider :theme="darkTheme">
+	<div style="display: flex;">
+		<div id="left">
+			<n-layout style="height: 100%;">
+				<n-layout-header :bordered="true">
+					<n-popover trigger="hover">
+						<template #trigger>
+					<n-button quaternary type="success" size="large">
+						<template #icon>
+							<n-icon><ArrowBackOutline/></n-icon>
+						</template>
+					</n-button>
+						</template>
+						返回
+					</n-popover>
+					<n-popover trigger="hover">
+						<template #trigger>
+							<n-button quaternary  type="success" size="large">
+								<template #icon>
+									<n-icon><Save/></n-icon>
+								</template>
+							</n-button>
+						</template>
+						保存编辑
+						</n-popover>
+				</n-layout-header>
+				<n-layout-content>
+					<n-flex vertical style="margin-left: 1.2rem; margin-top: .5rem;overflow: hidden">
+						<n-ellipsis><h3>航线列表</h3></n-ellipsis>
+						<n-radio-group v-model:value="selectedRouteCode" name="radiogroup" @update:value="checkRoute">
+							<n-scrollbar style="height: 20vh">
+							<n-space vertical>
+								<n-space v-for="r in routesInstore" justify="space-between"
+												 style="margin-right: 2rem; border-bottom: #383737 1px solid">
+									<n-radio :key="r.value" :value="r.value">
+										{{ r.label }}
+									</n-radio>
+									<n-button size="small" type="error" style="height: 1.5rem; padding-top: 1px">删除</n-button>
+								</n-space>
+
+							</n-space>
+							</n-scrollbar>
+						</n-radio-group>
+
+						<n-divider style="margin: .2rem -.5rem"></n-divider>
+						<n-space vertical>
+							<n-space>
+								<n-space>
+									<n-ellipsis>开闭</n-ellipsis>
+									<n-switch v-model:value="selectedRoute.isClose" size="small">
+										<template #checked>
+											闭
+										</template>
+										<template #unchecked>
+											开
+										</template>
+									</n-switch>
+								</n-space>
+								<n-space style="margin-left: .5rem">
+								<n-ellipsis>航点数</n-ellipsis>
+									<n-input-number :show-button="false" disabled size="tiny" style="width: 5rem"
+																	v-model:value="selectedRoute.PtNum"></n-input-number>
+								</n-space>
+							</n-space>
+							<n-space>
+								<n-ellipsis style="width: 4rem">航线名称</n-ellipsis>
+								<n-input size="tiny" style="width:10rem" v-model:value="selectedRoute.name"></n-input>
+							</n-space>
+							<n-space>
+								<n-ellipsis style="width: 4rem">航线类型</n-ellipsis>
+								<n-select style="width:10rem" size="tiny" v-model:value="selectedRoute.code" :options="routeCode"/>
+							</n-space>
+						</n-space>
+
+						<n-divider style="margin: .2rem -.5rem"></n-divider>
+						<n-ellipsis><h3>地形剖面图</h3></n-ellipsis>
+						<n-space justify="start">
+							<n-ellipsis>采样间隔</n-ellipsis>
+							<n-input-number size="tiny" placeholder="默认1000米"
+															style="width:8vw" :min="100" :step="100">
+							</n-input-number>
+							<n-button type="success" size="tiny">重新绘图</n-button>
+						</n-space>
+						<div id="echarts-profile">
+						<!--	Echarts绘图区	-->
+						</div>
+					</n-flex>
+				</n-layout-content>
+			</n-layout>
+		</div>
+
+		<div id="map2">
+			<SceneViewer id="scene-viewer-route"></SceneViewer>
+			<BottomBar></BottomBar>
+		</div>
+
+		<div id="right">
+			<n-layout style="height: 100%">
+				<n-layout-header :bordered="true">
+					<n-space justify="center">
+						<n-button quaternary type="default" size="large"><h4>航点详情 {{'— '+selectedRoute.name}}</h4></n-button>
+					</n-space>
+				</n-layout-header>
+				<n-layout-content>
+					<n-flex vertical >
+						<n-space justify="space-around" style="margin-top:.5rem;">
+							<n-ellipsis style="margin-left:.2rem; width: 2rem">序号</n-ellipsis>
+							<n-ellipsis style="width: 5.5rem">经度</n-ellipsis>
+							<n-ellipsis style="width: 5.5rem">纬度</n-ellipsis>
+							<n-ellipsis style="width: 3rem">高度</n-ellipsis>
+						</n-space>
+						<n-scrollbar style="height: 30vh">
+							<div v-if="selectedRoute.points.length>0 && showPtList" >
+								<n-space justify="space-around" style="margin: .2rem 0" v-for="(pt,index) in selectedRoute.points" >
+									<n-dropdown trigger="hover" size="small" placement="top-start" :show-arrow="true"
+															:options="PtOptions" @select="handlePtSelect($event,index)">
+										<n-button secondary type="info" size="tiny" style="margin-left:.2rem; width: 1.7rem">{{ pt.nPt }}</n-button>
+									</n-dropdown>
+									<n-input-number size="tiny" v-model:value="pt.lon" :show-button="false" style="width: 5.5rem"
+																	placeholder="经度" max="180" min="-180"></n-input-number>
+									<n-input-number size="tiny" v-model:value="pt.lat" :show-button="false" style="width: 5.5rem"
+																	placeholder="纬度" max="90" min="-90"></n-input-number>
+									<n-input-number size="tiny" v-model:value="pt.alt" :show-button="false" style="width: 3rem"
+																	placeholder="高度" max="12000" min="-500"></n-input-number>
+								</n-space>
+
+								<n-space justify="center" style="margin: .5rem 0">
+									<n-button type="info" size="small" @click="addPtToTail">
+										<template #icon>
+											<Add/>
+										</template>
+										添加点
+									</n-button>
+									<n-button type="info" size="small" @click="savePt">
+										<template #icon>
+											<SaveOutline/>
+										</template>
+										保存编辑
+									</n-button>
+								</n-space>
+							</div>
+
+							<n-space v-else justify="space-around">
+								<n-empty style="margin-top:3rem " description="无内容">
+								</n-empty>
+							</n-space>
+						</n-scrollbar>
+
+					</n-flex>
+					<n-divider style="margin: .2rem -.5rem"></n-divider>
+
+					<n-flex vertical style="height: 45vh; margin-left: 1rem; margin-top: .5rem;" >
+						<n-row><n-ellipsis><h3>气象信息</h3></n-ellipsis></n-row>
+						<n-space justify="space-around" class="routePtSelector">
+							<n-button size="small"  @click="prevPtWeather" :disabled="routePtNumber<=1">
+								<template #icon><ArrowBackOutline/></template>
+							</n-button>
+							<n-ellipsis>航点 {{routePtNumber}}</n-ellipsis>
+							<n-button size="small" @click="nextPtWeather" :disabled="selectedRoute.points.length<=routePtNumber">
+								<template #icon><ArrowForwardOutline/></template>
+							</n-button>
+						</n-space>
+					</n-flex>
+				</n-layout-content>
+			</n-layout>
+		</div>
+	</div>
+	</n-config-provider>
+
 
 </template>
 
 <style scoped>
+#left{
+	width: 20vw;
+	height: 100vh;
+}
+#map2 {
+	width: 60vw;
+	height: 100vh;
+	position: relative;
+}
+#right{
+	width: 20vw;
+	height: 100vh;
+}
+
+#echarts-profile{
+	margin-left: -1rem;
+	margin-top: -.5rem;
+	height: 40vh;
+}
+#scene-viewer-route {
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+}
+.routePtSelector {
+	width: 110%;
+	color: #63e2b7;
+	font-weight: bold;
+	margin-left: -1rem
 
+}
+.routePtSelector:hover{
+	background: rgb(24, 24, 28);
+}
 </style>
\ No newline at end of file
diff --git a/src/components/toolbar.vue b/src/components/toolbar.vue
index db5c017..6d2ebc4 100644
--- a/src/components/toolbar.vue
+++ b/src/components/toolbar.vue
@@ -23,6 +23,7 @@ import RouteOptions from "@/components/RouteOptions.vue";
 import {useRouteStore} from "@/store/RouteStore";
 import MarkerDialog from "@/components/MarkerDialog.vue";
 import { useRouter, useRoute } from 'vue-router'
+import {getUnicode} from "@/types/entityoptions.ts";
 const router = useRouter()
 const route = useRoute()
 
@@ -77,7 +78,7 @@ function handleEditSelect(key) {
   else{
     // 转到航线管理页面
 		router.push({
-			name: 'Test',
+			name: 'routeManage',
 		})
   }
 }
@@ -283,11 +284,12 @@ function manageLayer(){
 
 /**
  * 绘制航线,目前只绘制任务航线
- * @param routeParams 航线属性
+ * @param routeParams 航线属性,type:{name: string,code: number,isOpen: bool,height: number,routePts: []}
  */
-function startDrawRoute(routeParams /*{code: number,isOpen: bool,height: number,routePts: []}*/) {
+function startDrawRoute(routeParams) {
   showRouteModal.value = false
-  let drawLine = new RouteManageViewer(window.viewer, routeParams.isClose, routeParams.height)
+  let drawLine = new RouteManageViewer(window.viewer, routeParams.isClose)
+	drawLine.routeParams.height = routeParams.height
   drawLine.start().then(result => {
     console.log(result)
     // result是经纬度坐标数组,需转换为 AirlinePoint数组
@@ -299,9 +301,10 @@ function startDrawRoute(routeParams /*{code: number,isOpen: bool,height: number,
 		AirlinePoints.at(-1).ch2 = 0x01;
     // 航线加入store
     let aRoute = {
-      code: routeParams.code, PtNum: result.length, isClose: routeParams.isClose, name: "", points: AirlinePoints, totalDistance: 0
+      code: routeParams.code, PtNum: result.length, isClose: routeParams.isClose, unicode: getUnicode(),
+			name: routeParams.name, points: AirlinePoints, totalDistance: 0
     }
-    useRouteStore().route.push(aRoute)
+    useRouteStore().flyRoute.push(aRoute)
     // fixme: 航线加入图层管理
 
   }).catch(reject => {
diff --git a/src/router/index.js b/src/router/index.js
index 65db1c8..8ce9b7f 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -14,9 +14,9 @@ const router = createRouter({
             component: ()=>import('@/components/RouteOptions.vue')
         },
         {
-            path: '/test2',
-            name: 'Test2',
-            component: ()=>import('@/components/MarkerDialog.vue')
+            path: '/routeManage',
+            name: 'routeManage',
+            component: ()=>import('@/components/page/RouteManagePage.vue')
         }
     ]
 });
diff --git a/src/store/RouteStore.ts b/src/store/RouteStore.ts
index 646a8ee..b2b9a06 100644
--- a/src/store/RouteStore.ts
+++ b/src/store/RouteStore.ts
@@ -5,9 +5,20 @@ import {Airline} from "@/types/entityoptions.ts";
 export const useRouteStore = defineStore('RouteStore', {
     state: ()=>{
         return {
-            route: [] as Airline[]  //地图中绘制的航线,用于发送给后端(QT)
+            flyRoute: [] as Airline[]  //地图中绘制的航线,用于发送给后端(QT)
         }
     },
     actions: {
+        /**
+         * 向store中添加航线,code为唯一码,如冲突,则会替换原有值
+         * @param route
+         */
+        addRoute(route:Airline){
+            let index = this.flyRoute.findIndex((item: Airline)=>item.code===route.code)
+            if(index > -1){
+                this.flyRoute.splice(index,1);
+            }
+            this.flyRoute.push(route)
+        }
     }
 })
\ No newline at end of file
diff --git a/src/types/entityoptions.ts b/src/types/entityoptions.ts
index 26ce27e..38d0b01 100644
--- a/src/types/entityoptions.ts
+++ b/src/types/entityoptions.ts
@@ -49,6 +49,7 @@ export type AirlinePoint = {
 export type Airline = {
   name: string,
   code: number,       //航线编号
+  unicode: string,    //航线唯一码,前端有效(用于图层管理、store管理和地图Entity管理)
   PtNum: number,
   isClose: boolean,
   totalDistance: number,
@@ -60,3 +61,19 @@ export type routeTerrain = {
   distanceArray: number[],
   elevationArray: number[],
 }
+
+/**
+ * 生成唯一码(随机字符串+时间戳)
+ * @param len 随机字符串长度,默认12
+ */
+export function getUnicode(len:number = 12): string{
+  let timestamp = new Date().getTime();
+  /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
+  let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
+  let maxPos = $chars.length;
+  let randomStr = '';
+  for (let i = 0; i < len; i++) {
+    randomStr += $chars.charAt(Math.floor(Math.random() * maxPos));
+  }
+  return randomStr + timestamp;
+}
\ No newline at end of file
diff --git a/src/utils/map/SpatialAnalysis.ts b/src/utils/map/SpatialAnalysis.ts
index d198ab2..647fd48 100644
--- a/src/utils/map/SpatialAnalysis.ts
+++ b/src/utils/map/SpatialAnalysis.ts
@@ -683,3 +683,129 @@ export const drawEchartsVisibility = (xData:number[], yData:number[],startHeight
   ],
  });
 }
+
+/**
+ *  航线管理页面图表
+ * @param myChart
+ * @param xData 地形距离数组,地面距离
+ * @param yData 地形高度数组,以面积线绘制
+ * @param routeArr 航点序号数组
+ * @param routeHeight  航线高度数组,以折线绘制
+ */
+export const drawEcharts_RouteDetection = (myChart: EChartsType,xData:number[], yData:number[],
+                                           routeArr: number[], routeHeight:number[]) => {
+
+ // 绘制图表
+ myChart.setOption({
+  backgroundColor:'#101014',
+  grid: {
+   top: "17%",
+   right: "6%",
+   left:" 15%",
+   bottom: "20%",
+  },
+  legend: {
+   show: true,
+   type: 'plain',
+   top: '7%',
+   right: '5%',
+   data: [
+    { //地形剖面图例
+     name: '地形剖面',
+     itemStyle: {fontSize: 14},
+     lineStyle: 'inherit',
+    },
+    { //视线图例
+     name: '航线高度',
+     lineStyle: 'inherit',
+     itemStyle: {fontSize: 14}
+    }
+    ],
+   selectedMode: true,  //图例选择模式
+   inactiveColor: '#626161',
+  },
+  tooltip: {
+   show: true,
+   trigger: 'axis',
+   axisPointer: {
+    type: 'cross'
+   },
+   formatter:'地表高度: {c0}<br> 航点高度:{c1}'
+  },
+  xAxis: [
+    {
+      boundaryGap : false,
+      min: 0,
+      data: xData,
+      nameTextStyle: {
+       fontWeight:'bolder',
+       fontSize: 10
+      },
+      axisLine:{
+       onZero: false,
+       show: true,    // 是否显示坐标轴轴线
+       symbol: ['none', 'arrow'],
+       symbolSize: [7, 10]
+      },
+      axisLabel: {
+       formatter: '{value}',
+       margin: 7,
+      },
+   },
+   {
+    position: 'bottom',
+    boundaryGap: false,
+    data: routeArr,
+    offset: 30,
+    axisTick:{ show: true, inside: true }, // 是否显示坐标轴刻度
+    axisLine:{
+     onZero: false,
+     symbol: ['none', 'arrow'],
+     symbolSize: [7, 10]
+    },
+    axisLabel: {
+     formatter: '航点{value}',
+     margin: 7,
+    },
+   }
+  ],
+  yAxis: {
+   type: 'value',
+   name: '高度/ m',
+   nameTextStyle: {
+    fontSize: 14
+   },
+   nameLocation: 'end',
+   position: 'left',
+   axisLabel: {
+    formatter: '{value}'
+   },
+   axisLine: {
+    show: true,
+    symbol: ['none', 'arrow'],
+    symbolSize: [7, 10]
+   }
+  },
+  series: [
+   {
+    name:'地形剖面',
+    xAxisIndex: 0,
+    type: 'line',
+    data: yData,
+    areaStyle: {
+     color: '#37a5fb',
+     opacity: 0.5
+    }
+   },
+   {
+    name:'航线高度',
+    xAxisIndex: 1,
+    type: 'line',
+    data: routeHeight,
+    lineStyle: {
+     color: '#8ae73d',
+    }
+   },
+  ],
+ });
+}
diff --git a/src/utils/map/geocomputation.ts b/src/utils/map/geocomputation.ts
index d84e5f5..dd2431e 100644
--- a/src/utils/map/geocomputation.ts
+++ b/src/utils/map/geocomputation.ts
@@ -15,6 +15,7 @@ import {
   Viewer
 } from 'cesium'
 import {Angle} from "@/utils/map/angle.ts";
+import {AirlinePoint} from "@/types/entityoptions.ts";
 
 /**
  * 计算空间中一点到一条直线的最短距离的交点(在不考虑地球曲率的情况下)
@@ -184,4 +185,17 @@ export function ByDirectionAndLen(position: Cartesian3, angle:number, distance:n
   return Matrix4.multiplyByPoint(matrix, new Cartesian3(0, distance, 0),
       new Cartesian3());
 }
+
+/**
+ * 把航点数组转为笛卡尔3坐标数组
+ * @param coords
+ */
+export function transLonlat2Car3(coords: AirlinePoint[]):Cartesian3[] {
+  let coordCar3: Cartesian3[] = []
+  coords.forEach(coord => {
+    let car3 = Cartesian3.fromDegrees(coord.lon, coord.lat, coord.alt)
+    coordCar3.push(car3)
+  })
+  return coordCar3
+}
 export { getClosestPoint, isOnLineSegment, getDistance, getAzimuth, getPolygonArea }