main
徐景良 2025-07-15 14:57:12 +08:00
parent 4b39b95b64
commit 378380aee9
8 changed files with 500 additions and 84 deletions

View File

@ -1,7 +1,9 @@
<template>
<div>
<div style="width:100%;height: calc( 100vh - 80px);" >
<Map :workPlanFormShow="workPlanFormShow" :airRoute="airRoute" @exitDraw="exitDraw" @flyToThere="flyToThere" :wayline="wayline" :waylineInfo="waylineInfo"></Map>
<div class="map-out-container">
<div class="map-inner-container">
<Map :workPlanFormShow="workPlanFormShow" :airRoute="airRoute" @exitDraw="exitDraw" @flyToThere="flyToThere" :wayline="wayline" :waylineInfo="waylineInfo"></Map>
</div>
</div>
<!-- 航线库 -->
@ -17,7 +19,7 @@
</div>
</template>
<script lang="ts" setup>
import {ref,watch} from 'vue';
import {ref,watch,onMounted} from 'vue';
import airLineList from '../workplan/components/airLineList.vue';
import createAirLine from '../workplan/components/createAirLine.vue'
import Map from '../workplan/components/map.vue'
@ -91,7 +93,8 @@ const toCreateWorkPlan = (data)=> {
}
// 线
const handlerCreateAirLine = ()=>{
const handlerCreateAirLine = (data)=>{
console.log("data123",data);
createAirLineShow.value = true;
}
@ -100,12 +103,13 @@ const cancleCreateAirLine = ()=>{
}
const handlerCreateAirRoute = (info)=>{
console.log("info",info);
//
workPlanFormShow.value = false;
ariLineShow.value = false;
aircraftShow.value = false;
planListShow.value = false;
createAirLineShow.value = false;
airRoute.value = info
}
@ -197,5 +201,25 @@ const extractKmz = async (kmzBlob)=>{
throw new Error('KMZ文件中未找到WMPL文件');
}
onMounted(()=>{
let element = window.document.getElementsByClassName("mars3d-locationbar")[0] as HTMLElement;
element.style.bottom = '40px';
})
</script>
<style scoped>
.map-out-container{
width: 100%;
height: calc( 100vh - 80px);
overflow: hidden;
}
.map-inner-container{
width: calc( 100% + 80px);
height: calc( 100% + 80px);
position: relative;
top:-40px;
left:-40px;
}
</style>

View File

@ -215,7 +215,7 @@ import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/index.
const emits = defineEmits(["setFlyPoint","checkPoint","exitDraw"])
const props = defineProps(["airPoints","airInfo","polygonAirForm"])
const props = defineProps(["airPoints","airInfo","polygonAirForm","airRoute"])
const areaOptionsShow = ref(false);
const airInfo = ref({
@ -276,7 +276,7 @@ const pointInfo = ref({
"executeHeight": 172.948656023051,
"waypointSpeed": 10,
"waypointHeadingParam": {
"waypointHeadingMode": "followWayline",
"waypointHeadingMode": "followWayline", //
"waypointHeadingAngle": 0,
"waypointPoiPoint": "0.000000,0.000000,0.000000",
"waypointHeadingAngleEnable": 0,
@ -341,8 +341,17 @@ const pointInfo = ref({
"waypointWorkType": 0
})
//
const handlerPointInfo = ()=>{
if(props.airPoints?.length<=0){
message.warning("请添加航点!");
return null;
}
props.airPoints?.forEach((item,index)=>{
console.log("item123",item);
let point = {
"Point": {
"coordinates": item.lng+","+item.lat
@ -352,7 +361,7 @@ const handlerPointInfo = ()=>{
"waypointSpeed": 10,
"waypointHeadingParam": {
"waypointHeadingMode": "followWayline", //
"waypointHeadingAngle": 0, // [-180, 180] wpml:waypointHeadingModesmoothTransition
"waypointHeadingAngle": item.aircraftHorizontalAngle, // [-180, 180] wpml:waypointHeadingModesmoothTransition
"waypointPoiPoint": "0.000000,0.000000,0.000000", // wpml:waypointHeadingModetowardPOI
"waypointHeadingAngleEnable": 0,
"waypointHeadingPathMode": "followBadArc", //
@ -408,18 +417,21 @@ const handlerPointInfo = ()=>{
}
]
},
"waypointGimbalHeadingParam": { //
"waypointGimbalPitchAngle": 0, // [-90, -30]
"waypointGimbalYawAngle": 0 //
"waypointGimbalHeadingParam": {
"waypointGimbalPitchAngle": item.cameraVerticalAngle, // [-90, -30]
"waypointGimbalYawAngle": 0 //
},
"isRisky": 0,
"waypointWorkType": 0
}
folder.value.Placemark.push(point);
})
return true;
}
// waylines.json
// waylines.json
const waylinesJson = ref(
{
"kml": {
@ -431,33 +443,30 @@ const waylinesJson = ref(
}
)
// 退
const backPage = ()=>{
emits("exitDraw")
}
// 线
const saveAirLine = ()=>{
handlerPointInfo();
let handlerResult = handlerPointInfo();
const builder = new XMLBuilder();
if(handlerResult){
const builder = new XMLBuilder();
let lineData = {...waylinesJson.value}
let lineData = {...waylinesJson.value}
let obj = handlerPrefixWpml(lineData);
let obj = handlerPrefixWpml(lineData);
let xmlString = builder.build(obj);
let xmlString = builder.build(obj);
let xmlString2 = xmlString.replace(/<\/?\d+>/g, "")
let xmlString2 = xmlString.replace(/<\/?\d+>/g, "")
let xmlString3 = xmlString2.replace("<kml>",`<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">`)
let xmlString3 = xmlString2.replace("<kml>",`<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">`)
console.log("xmlString3",xmlString3);
handlerCreateFile(xmlString3);
}
return null;
handlerCreateFile(xmlString3);
}
// wmpl:
@ -489,7 +498,7 @@ const handlerPrefixWpml = (obj) => {
//
const submitForm = ref({
"id": "",
"airLineName": null,
"airLineName": props.airRoute.name,
"airLineType": "waypoint",
"uavId": "",
"flyToFirstPointMode": "",
@ -505,38 +514,31 @@ const submitForm = ref({
"wpml": ""
})
// xml
// xml线
const handlerCreateFile =async (content)=>{
const blob = new Blob([content], { type: 'wmpl/plain' });
// FormData
const formData = new FormData();
formData.append('xmlFile', blob);
let res = await uploadXmlFile(formData);
if(res){
submitForm.value.wpml = res.path;
let addAirLineRes =await addAirLine(submitForm.value);
if(addAirLineRes){
message.success("操作成功!");
backPage();
}else{
message.error("操作失败!");
}
}else{
message.error("操作失败!");
}
}
// 退
const backPage = ()=>{
emits("exitDraw")
}
</script>

View File

@ -184,4 +184,18 @@ const config = ref({
::v-deep .ant-slider .ant-slider-rail{
background:#fff!important;
}
::v-deep .ant-input-number-input{
background:#3c3c3c!important ;
border:0px solid #ccc!important;
border-top-left-radius: 3px !important;
border-bottom-left-radius: 3px !important;
color:#fff!important;
}
::v-deep .ant-input-number-input::placeholder{
color:rgba(255, 255, 255, 0.533)!important;
}
</style>

View File

@ -1,14 +1,16 @@
<template>
<div class="containner">
<div class="title">
<LeftOutlined @click="backPage" />
<div>面状航线</div>
<SaveOutlined/>
<div style="flex:1;">
<a-input size="small" placeholder="航线名称" />
<a-input v-model:value="submitForm.airLineName" size="small" placeholder="航线名称" />
</div>
</div>
<div class="area-info">
<div class="item">
<div>测区面积</div>
@ -194,9 +196,6 @@
</div>
<div class="unit"> m/s</div>
</div>
</div>
</div>
@ -205,10 +204,12 @@
import {ref,defineEmits,defineProps} from 'vue'
import { SaveOutlined,LeftOutlined } from '@ant-design/icons-vue';
import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/index.ts';
import {uploadXmlFile,addAirLine} from '@/api/sys/workplan';
import { message } from 'ant-design-vue';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
const emits = defineEmits(["setFlyPoint","exitDraw"])
const props = defineProps(["airInfo","polygonAirForm"])
const props = defineProps(["airInfo","polygonAirForm","airPoints","airRoute"])
const airInfo = ref({
area:0.0,
@ -266,9 +267,331 @@ const folder = ref({
"distance": 410.047576904297,
"duration": 80.3239784240723,
"autoFlightSpeed": 10,
"Placemark": []
"Placemark":[]
})
//
const pointInfo = {
"Point": {
"coordinates": "118.295430406842,35.1352868743403" //
},
"index": 0, //
"executeHeight": 167, //
"waypointSpeed": 12.7125370218057, //
"waypointHeadingParam": { //
"waypointHeadingMode": "followWayline", // 线
"waypointHeadingAngle": -96.9990577342362,
"waypointPoiPoint": "0.000000,0.000000,0.000000",
"waypointHeadingAngleEnable": 1,
"waypointHeadingPathMode": "followBadArc",
"waypointHeadingPoiIndex": 0
},
"waypointTurnParam": {
"waypointTurnMode": "toPointAndStopWithDiscontinuityCurvature",
"waypointTurnDampingDist": 0
},
"useStraightLine": 1,
"actionGroup": [
{
"#text": "z",
"actionGroupId": 0,
"actionGroupStartIndex": 0,
"actionGroupEndIndex": 13,
"actionGroupMode": "sequence",
"actionTrigger": {
"actionTriggerType": "betweenAdjacentPoints"
},
"action": [
{
"actionId": 0,
"actionActuatorFunc": "gimbalAngleLock"
},
{
"actionId": 1,
"actionActuatorFunc": "gimbalRotate",
"actionActuatorFuncParam": {
"gimbalHeadingYawBase": "aircraft",
"gimbalRotateMode": "absoluteAngle",
"gimbalPitchRotateEnable": 1,
"gimbalPitchRotateAngle": -90,
"gimbalRollRotateEnable": 0,
"gimbalRollRotateAngle": 0,
"gimbalYawRotateEnable": 0,
"gimbalYawRotateAngle": 0,
"gimbalRotateTimeEnable": 0,
"gimbalRotateTime": 10,
"payloadPositionIndex": 0
}
},
{
"actionId": 2,
"actionActuatorFunc": "startTimeLapse",
"actionActuatorFuncParam": {
"payloadPositionIndex": 0,
"useGlobalPayloadLensIndex": 0,
"payloadLensIndex": "visable",
"minShootInterval": 1.52472746372223
}
}
]
},
{
"actionGroupId": 1,
"actionGroupStartIndex": 0,
"actionGroupEndIndex": 13,
"actionGroupMode": "sequence",
"actionTrigger": {
"actionTriggerType": "multipleTiming",
"actionTriggerParam": 2
},
"action": {
"actionId": 0,
"actionActuatorFunc": "gimbalRotate",
"actionActuatorFuncParam": {
"gimbalHeadingYawBase": "aircraft",
"gimbalRotateMode": "absoluteAngle",
"gimbalPitchRotateEnable": 1,
"gimbalPitchRotateAngle": -90,
"gimbalRollRotateEnable": 0,
"gimbalRollRotateAngle": 0,
"gimbalYawRotateEnable": 0,
"gimbalYawRotateAngle": 0,
"gimbalRotateTimeEnable": 0,
"gimbalRotateTime": 10,
"payloadPositionIndex": 0
}
}
}
],
"waypointGimbalHeadingParam": {
"waypointGimbalPitchAngle": 0,
"waypointGimbalYawAngle": 0
},
"isRisky": 0,
"waypointWorkType": 0
}
//
const handlerPointInfo = ()=>{
if(props.airPoints?.length<=0){
message.warning("请添加航点!");
return null;
}
props.airPoints?.forEach((item,index)=>{
let point = {
"Point": {
"coordinates": item.lng+","+item.lat //
},
"index": index, //
"executeHeight": 167, //
"waypointSpeed": 12.7125370218057, //
"waypointHeadingParam": { //
"waypointHeadingMode": "followWayline", // 线
"waypointHeadingAngle": -96.9990577342362,
"waypointPoiPoint": "0.000000,0.000000,0.000000",
"waypointHeadingAngleEnable": 1,
"waypointHeadingPathMode": "followBadArc",
"waypointHeadingPoiIndex": 0
},
"waypointTurnParam": {
"waypointTurnMode": "toPointAndStopWithDiscontinuityCurvature",
"waypointTurnDampingDist": 0
},
"useStraightLine": 1,
"actionGroup": [
{
"#text": "z",
"actionGroupId": 0,
"actionGroupStartIndex": 0,
"actionGroupEndIndex": 13,
"actionGroupMode": "sequence",
"actionTrigger": {
"actionTriggerType": "betweenAdjacentPoints"
},
"action": [
{
"actionId": 0,
"actionActuatorFunc": "gimbalAngleLock"
},
{
"actionId": 1,
"actionActuatorFunc": "gimbalRotate",
"actionActuatorFuncParam": {
"gimbalHeadingYawBase": "aircraft",
"gimbalRotateMode": "absoluteAngle",
"gimbalPitchRotateEnable": 1,
"gimbalPitchRotateAngle": -90,
"gimbalRollRotateEnable": 0,
"gimbalRollRotateAngle": 0,
"gimbalYawRotateEnable": 0,
"gimbalYawRotateAngle": 0,
"gimbalRotateTimeEnable": 0,
"gimbalRotateTime": 10,
"payloadPositionIndex": 0
}
},
{
"actionId": 2,
"actionActuatorFunc": "startTimeLapse",
"actionActuatorFuncParam": {
"payloadPositionIndex": 0,
"useGlobalPayloadLensIndex": 0,
"payloadLensIndex": "visable",
"minShootInterval": 1.52472746372223
}
}
]
},
{
"actionGroupId": 1,
"actionGroupStartIndex": 0,
"actionGroupEndIndex": 13,
"actionGroupMode": "sequence",
"actionTrigger": {
"actionTriggerType": "multipleTiming",
"actionTriggerParam": 2
},
"action": {
"actionId": 0,
"actionActuatorFunc": "gimbalRotate",
"actionActuatorFuncParam": {
"gimbalHeadingYawBase": "aircraft",
"gimbalRotateMode": "absoluteAngle",
"gimbalPitchRotateEnable": 1,
"gimbalPitchRotateAngle": -90,
"gimbalRollRotateEnable": 0,
"gimbalRollRotateAngle": 0,
"gimbalYawRotateEnable": 0,
"gimbalYawRotateAngle": 0,
"gimbalRotateTimeEnable": 0,
"gimbalRotateTime": 10,
"payloadPositionIndex": 0
}
}
}
],
"waypointGimbalHeadingParam": {
"waypointGimbalPitchAngle": 0,
"waypointGimbalYawAngle": 0
},
"isRisky": 0,
"waypointWorkType": 0
}
folder.value.Placemark?.push(point);
})
return true;
}
// waylines.json
const waylinesJson = ref(
{
"kml": {
"Document": {
"missionConfig":missionConfig.value,
"Folder":folder.value
}
}
}
)
// 线
const saveAirLine = ()=>{
let handlerResult = handlerPointInfo();
if(handlerResult){
const builder = new XMLBuilder();
let lineData = {...waylinesJson.value}
let obj = handlerPrefixWpml(lineData);
let xmlString = builder.build(obj);
let xmlString2 = xmlString.replace(/<\/?\d+>/g, "")
let xmlString3 = xmlString2.replace("<kml>",`<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">`)
handlerCreateFile(xmlString3);
}
}
// wmpl:
const handlerPrefixWpml = (obj) => {
for (const key in obj) {
//
if (typeof obj[key] === 'object' && obj[key] !== null) {
handlerPrefixWpml(obj[key]); //
const newAttrs = {};
for (const attrName in obj[key]) {
//
if (/^[a-z]/.test(attrName)) {
newAttrs[`wmpl:${attrName}`] = obj[key][attrName];
} else {
newAttrs[attrName] = obj[key][attrName];
}
}
obj[key] = newAttrs;
}
}
return obj;
}
//
const submitForm = ref({
"id": "",
"airLineName": props.airRoute.name,
"airLineType": "waypoint",
"uavId": "",
"flyToFirstPointMode": "",
"safeTakeoffAltitude": 0,
"safeTakeoffSpeed": 0,
"globalRouteSpeed": 0,
"taskCompletionAction": "",
"outOfControlOption": "",
"typeOfOutOfControlAction": "",
"globalWayPointType": "",
"ptzControlMode": "",
"aircraftYawAngleMode": "",
"wpml": ""
})
// xml线
const handlerCreateFile =async (content)=>{
const blob = new Blob([content], { type: 'wmpl/plain' });
// FormData
const formData = new FormData();
formData.append('xmlFile', blob);
let res = await uploadXmlFile(formData);
if(res){
submitForm.value.wpml = res.path;
let addAirLineRes =await addAirLine(submitForm.value);
if(addAirLineRes){
message.success("操作成功!");
backPage();
}else{
message.error("操作失败!");
}
}else{
message.error("操作失败!");
}
}
// 退
const backPage = ()=>{

View File

@ -169,13 +169,29 @@
}
const getCheckedData = () => {
// 线
airLineType.value?.forEach((item,idx)=>{
if(item.checked){
airLineInfo.value.airLineType = item.name;
}
})
console.log("airLineInfo.value.airLineType",airLineInfo.value);
//
airType.value?.forEach((item,index)=>{
if(item.checked){
airLineInfo.value.airType = item.name;
}
})
//
airModel.value?.forEach((item,index)=>{
if(item.checked){
airLineInfo.value.airModel = item.name;
}
})
}

View File

@ -90,11 +90,14 @@
</a-form-item>
<a-form-item ref="accuracy" label="设置时间" name="accuracy">
<a-form-item v-if="false" ref="accuracy" label="设置时间" name="accuracy">
<a-button type="primary" @click="handlerSetTime"></a-button>
</a-form-item>
<a-form-item v-if="submitForm.periodicFormula == 1" ref="accuracy" label="设置时间" name="accuracy">
<a-date-picker style="width:100%;" show-time placeholder="选择时间" @change="onChange" @ok="onOk" />
</a-form-item>
</div>
@ -618,4 +621,23 @@ const togglePopover = (e)=> {
::v-deep .ant-btn{
border-radius: 15px!important;
}
::v-deep .ant-picker{
background:#050608 !important;
border:0px solid #ccc!important;
color:#fff!important;
border-radius: 15px!important;
}
::v-deep .ant-picker::placeholder{
color:#fff!important;
}
::v-deep .ant-picker .ant-picker-input >input{
color:#fff!important;
}
::v-deep .ant-picker .ant-picker-input >input::placeholder{
color:#fff!important;
}
</style>

View File

@ -8,6 +8,7 @@
@setFlyPoint="setFlyPoint"
@exitDraw="exitDraw"
:airInfo="lineInfo"
:airRoute="props.airRoute"
:polygonAirForm="polygonAirForm"
@checkPoint="checkPoint"
></airPoint>
@ -19,13 +20,14 @@
@setFlyPoint="setFlyPoint"
:airInfo="airInfo"
:polygonAirForm="polygonAirForm"
:airRoute="props.airRoute"
@exitDraw="exitDraw"
></airPolygon>
</div>
<!-- 航点航线配置 -->
<div class="airpoint-config-container" v-if="airPointConfigShow">
<airPointConfig :currentAirPoint="currentAirPoint"></airPointConfig>
<airPointConfig :currentAirPoint="currentAirPoint" ></airPointConfig>
</div>
</div>
</template>
@ -99,7 +101,6 @@ watch(
// 线
const generatePreviewPoint = (placemark)=>{
//
startPosition.value = [props.waylineInfo?.taskOffLng, props.waylineInfo?.taskOffLat, 70];
@ -186,6 +187,8 @@ const generatePreviewPoint = (placemark)=>{
let map: mars3d.Map; //
let graphicLayer: mars3d.layer.GraphicLayer;
let drawGraphicLayer:mars3d.layer.GraphicLayer;
let uavGraphicLayer: mars3d.layer.GraphicLayer;
// 线
@ -207,6 +210,7 @@ const generatePreviewPoint = (placemark)=>{
const exitDraw = () => {
//
graphicLayer ? graphicLayer.clear() : null;
drawGraphicLayer ? drawGraphicLayer.clear() : null;
stickGroundPointLayer ? stickGroundPointLayer.clear() : null;
lineGroundPointLayer ? lineGroundPointLayer.clear() : null;
@ -355,11 +359,11 @@ const generatePreviewPoint = (placemark)=>{
"icon": "https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png",
"type": "group",
"layers": [
// {
// "name": "",
// "type": "tdt",
// "layer": "img_d"
// },
{
"name": "底图",
"type": "tdt",
"layer": "img_d"
},
{
"name": "注记",
"type": "tdt",
@ -384,6 +388,10 @@ const generatePreviewPoint = (placemark)=>{
isAutoEditing: false, //
});
drawGraphicLayer = new mars3d.layer.GraphicLayer({
isAutoEditing:false,
})
graphicLayer.bindContextMenu([
{
text: '按轴平移',
@ -429,6 +437,7 @@ const generatePreviewPoint = (placemark)=>{
]);
map.addLayer(graphicLayer);
map.addLayer(drawGraphicLayer);
//
stickGroundPointLayer = new mars3d.layer.GraphicLayer({
@ -458,8 +467,8 @@ const generatePreviewPoint = (placemark)=>{
if (props.uavTrack) {
setUAVPosition();
}
//
loadChangGuangLayer();
//
// loadChangGuangLayer();
emits('mapOnLoad',map)
});
};
@ -613,7 +622,10 @@ const loadChangGuangLayer = ()=>{
//
const setFlyPoint = async () => {
const graphic = await graphicLayer.startDraw({
drawGraphicLayer ? drawGraphicLayer.clear : null;
const graphic = await drawGraphicLayer.startDraw({
type: 'billboardP',
style: {
image: '/map/start.png',
@ -1449,29 +1461,29 @@ const loadChangGuangLayer = ()=>{
const preViewPointWayLine = (position) => {
if (moveTool) {
moveTool.destroy();
moveTool = null;
moveTool = null;
}
let uuid = buildUUID();
//
console.log('position', startPosition.value);
let startGraphic = new mars3d.graphic.BillboardEntity({
id: 'start-graphic',
position: startPosition.value,
style: {
image: '/map/start.png',
scale: 1,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
label: {
text: '参考起飞点',
font_size: 14,
color: '#ffffff',
outline: true,
outlineColor: '#000000',
pixelOffsetY: -35,
},
},
id: 'start-graphic',
position: startPosition.value,
style: {
image: '/map/start.png',
scale: 1,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
label: {
text: '参考起飞点',
font_size: 14,
color: '#ffffff',
outline: true,
outlineColor: '#000000',
pixelOffsetY: -35,
},
},
});
graphicLayer.addGraphic(startGraphic);
@ -1677,8 +1689,8 @@ const loadChangGuangLayer = ()=>{
overflow-y: hidden;
position: absolute;
height: calc(100vh - 80px);
top: 0px;
left: 0px;
top: 40px;
left: 40px;
z-index: 999;
}
@ -1688,8 +1700,8 @@ const loadChangGuangLayer = ()=>{
overflow-y: hidden;
position: absolute;
height: calc(100vh - 80px);
top: 0px;
left: 0px;
top: 40px;
left: 40px;
z-index: 999;
}
@ -1699,8 +1711,8 @@ const loadChangGuangLayer = ()=>{
overflow-y: hidden;
position: absolute;
height: calc(100vh - 80px);
top: 0px;
right: 0px;
top: 40px;
right: 40px;
z-index: 999;
}
</style>

View File

@ -29,6 +29,9 @@
<aircraft @checkAriLine="checkDronePort" @closeAirCraft="closeAirCraft" ></aircraft>
</div>
<!-- 航线计算 -->
</div>
<!-- 创建计划弹窗 -->