Browse Source

Merge branch 'ctw' of http://124.70.32.114:3100/woka/cesium-map-object into mh

# Conflicts:
#	ruoyi-ui/src/views/childRoom/RightPanel.vue
#	ruoyi-ui/src/views/childRoom/index.vue
master
menghao 2 months ago
parent
commit
b4d4f4a71e
  1. 1
      ruoyi-ui/src/store/getters.js
  2. 7
      ruoyi-ui/src/store/modules/user.js
  3. 4
      ruoyi-ui/src/views/cesiumMap/DrawingToolbar.vue
  4. 1377
      ruoyi-ui/src/views/cesiumMap/index.vue
  5. 367
      ruoyi-ui/src/views/childRoom/RightPanel.vue
  6. 221
      ruoyi-ui/src/views/childRoom/index.vue
  7. 50
      ruoyi-ui/src/views/dialogs/PlatformEditDialog.vue
  8. 6
      ruoyi-ui/src/views/selectRoom/index.vue
  9. 2
      ruoyi-ui/vue.config.js

1
ruoyi-ui/src/store/getters.js

@ -13,6 +13,7 @@ const getters = {
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permissions: state => state.user.permissions,
userLevel: state => state.user.userLevel,
permission_routes: state => state.permission.routes,
topbarRouters: state => state.permission.topbarRouters,
defaultRoutes: state => state.permission.defaultRoutes,

7
ruoyi-ui/src/store/modules/user.js

@ -13,7 +13,8 @@ const user = {
nickName: '',
avatar: '',
roles: [],
permissions: []
permissions: [],
userLevel: ''
},
mutations: {
@ -37,6 +38,9 @@ const user = {
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
},
SET_USER_LEVEL: (state, userLevel) => {
state.userLevel = userLevel
}
},
@ -77,6 +81,7 @@ const user = {
commit('SET_NAME', user.userName)
commit('SET_NICK_NAME', user.nickName)
commit('SET_AVATAR', avatar)
commit('SET_USER_LEVEL', user.userLevel || '')
/* 初始密码提示 */
if(res.isDefaultModifyPwd) {
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {

4
ruoyi-ui/src/views/cesiumMap/DrawingToolbar.vue

@ -40,6 +40,10 @@ export default {
{ id: 'polygon', name: '面', icon: 'el-icon-s-grid' },
{ id: 'rectangle', name: '矩形', icon: 'el-icon-s-data' },
{ id: 'circle', name: '圆形', icon: 'el-icon-circle-plus-outline' },
{ id: 'sector', name: '扇形', icon: 'el-icon-s-operation' },
{ id: 'arrow', name: '箭头', icon: 'el-icon-right' },
{ id: 'text', name: '文本', icon: 'el-icon-document' },
{ id: 'image', name: '图片', icon: 'el-icon-picture-outline' },
{ id: 'locate', name: '定位', icon: 'el-icon-aim' },
{ id: 'clear', name: '清除', icon: 'el-icon-delete' },
{ id: 'import', name: '导入', icon: 'el-icon-upload' },

1377
ruoyi-ui/src/views/cesiumMap/index.vue

File diff suppressed because it is too large

367
ruoyi-ui/src/views/childRoom/RightPanel.vue

@ -26,100 +26,79 @@
新建方案
</el-button>
</div>
<div class="route-list">
<div class="tree-list">
<!-- 方案列表 -->
<div
v-for="plan in plans"
:key="plan.id"
class="route-item"
class="tree-item plan-item"
:class="{ selected: selectedPlanId === plan.id }"
@click="handleSelectPlan(plan)"
>
<i class="el-icon-folder-opened"></i>
<div class="route-info">
<div class="route-name">{{ plan.name }}</div>
<div class="route-meta">{{ plan.routes.length }}个航线</div>
</div>
<div class="route-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenPlanDialog(plan)"></i>
</div>
</div>
</div>
</div>
<div v-if="selectedPlanDetails" class="section">
<div class="section-header">
<div class="section-title">航线列表</div>
<el-button
type="primary"
size="mini"
@click="handleCreateRoute"
class="create-route-btn-new"
>
新建航线
</el-button>
</div>
<div class="route-list">
<div
v-for="route in routes"
:key="route.id"
class="route-item"
:class="{ 'active': activeRouteIds.includes(route.id) }"
@click="$emit('select-route', route)"
>
<i class="el-icon-map-location"></i>
<div class="route-info">
<div class="route-name">{{ route.name }}</div>
<div class="route-meta">{{ route.points }}个航点</div>
</div>
<el-tag
v-if="route.conflict"
size="mini"
type="danger"
class="conflict-tag"
>
冲突
</el-tag>
<div class="route-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenRouteDialog(route)"></i>
<i class="el-icon-delete" title="删除" @click.stop="$emit('delete-route', route)"></i>
</div>
</div>
</div>
</div>
<div v-if="selectedRouteDetails" class="section">
<div class="section-title">航点列表</div>
<div class="waypoint-list">
<div
v-for="point in selectedRouteDetails.waypoints"
:key="point.name"
class="waypoint-item"
>
<i class="el-icon-location"></i>
<div class="waypoint-info">
<div class="waypoint-name">{{ point.name }}</div>
<div class="waypoint-meta">高度: {{ point.altitude }}m | 速度: {{ point.speed }}</div>
<div class="tree-item-header" @click="togglePlan(plan.id)">
<i :class="expandedPlans.includes(plan.id) ? 'el-icon-folder-opened' : 'el-icon-folder'" class="tree-icon"></i>
<div class="tree-item-info">
<div class="tree-item-name">{{ plan.name }}</div>
<div class="tree-item-meta">{{ routes.filter(r => r.scenarioId === plan.id).length }}个航线</div>
</div>
<div class="tree-item-actions">
<i class="el-icon-plus" title="新建航线" @click.stop="handleCreateRouteForPlan(plan)"></i>
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenPlanDialog(plan)"></i>
<i class="el-icon-delete" title="删除" @click.stop="handleDeletePlan(plan)"></i>
</div>
</div>
<div class="waypoint-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenWaypointDialog(point)"></i>
<i class="el-icon-delete" title="删除" ></i>
<!-- 航线列表 -->
<div v-if="expandedPlans.includes(plan.id)" class="tree-children route-children">
<div
v-for="route in routes.filter(r => r.scenarioId === plan.id)"
:key="route.id"
class="tree-item route-item"
:class="getRouteClasses(route.id)"
>
<div class="tree-item-header" @click="toggleRoute(route.id)">
<i :class="expandedRoutes.includes(route.id) ? 'el-icon-map-location' : 'el-icon-map-location'" class="tree-icon"></i>
<div class="tree-item-info">
<div class="tree-item-name">{{ route.name }}</div>
<div class="tree-item-meta">{{ route.points }}个航点</div>
</div>
<el-tag
v-if="route.conflict"
size="mini"
type="danger"
class="conflict-tag"
>
冲突
</el-tag>
<div class="tree-item-actions">
<i class="el-icon-view" title="显示/隐藏" @click.stop="handleToggleRouteVisibility(route)"></i>
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenRouteDialog(route)"></i>
<i class="el-icon-delete" title="删除" @click.stop="handleDeleteRoute(route)"></i>
</div>
</div>
<!-- 航点列表 -->
<div v-if="expandedRoutes.includes(route.id)" class="tree-children waypoint-children">
<div
v-for="point in (expandedRoutes.includes(route.id) && route.waypoints ? route.waypoints : [])"
:key="point.name"
class="tree-item waypoint-item"
>
<div class="tree-item-header">
<i class="el-icon-location tree-icon"></i>
<div class="tree-item-info">
<div class="tree-item-name">{{ point.name }}</div>
<div class="tree-item-meta">高度: {{ point.altitude }}m | 速度: {{ point.speed }}</div>
</div>
<div class="tree-item-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenWaypointDialog(point)"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<el-button type="primary" size="mini" icon="el-icon-circle-plus" class="blue-btn" @click="handleAddWaypoint">
添加航点
</el-button>
<el-button size="mini" class="blue-btn" @click="handleCancelRoute">
取消
</el-button>
</div>
</div>
<div v-if="activeTab === 'conflict'" class="tab-content conflict-content">
<div v-if="conflicts.length > 0" class="conflict-list">
<div
@ -164,7 +143,6 @@
</el-button>
</div>
</div>
<div v-if="activeTab === 'platform'" class="tab-content platform-content">
<div class="platform-categories">
<el-tabs v-model="activePlatformTab" type="card" size="mini" class="blue-tabs">
@ -189,7 +167,6 @@
</div>
</div>
</el-tab-pane>
<el-tab-pane label="海上" name="sea">
<div class="platform-list">
<div
@ -211,7 +188,6 @@
</div>
</div>
</el-tab-pane>
<el-tab-pane label="地面" name="ground">
<div class="platform-list">
<div
@ -303,10 +279,82 @@ export default {
},
data() {
return {
activePlatformTab: 'air'
activePlatformTab: 'air',
expandedPlans: [], //
expandedRoutes: [] // 线
}
},
watch: {
activeRouteIds: {
handler(newVal) {
console.log('activeRouteIds updated:', newVal);
},
deep: true
}
},
methods: {
// /
togglePlan(planId) {
const index = this.expandedPlans.indexOf(planId)
if (index > -1) {
// 线
this.expandedPlans.splice(index, 1)
const planRoutes = this.routes.filter(r => r.scenarioId === planId)
planRoutes.forEach(route => {
if (this.activeRouteIds.includes(route.id)) {
// 线
this.handleToggleRouteVisibility(route)
}
})
//
this.$emit('select-plan', { id: null })
} else {
//
this.expandedPlans.push(planId)
const plan = this.plans.find(p => p.id === planId)
if (plan) {
this.$emit('select-plan', plan)
}
// 线
const planRoutes = this.routes.filter(r => r.scenarioId === planId)
planRoutes.forEach(route => {
if (!this.activeRouteIds.includes(route.id)) {
this.handleSelectRoute(route)
}
})
}
},
// 线/
toggleRoute(routeId) {
const route = this.routes.find(r => r.id === routeId)
if (!route) return
const isRouteSelected = this.activeRouteIds.includes(routeId)
const isRouteExpanded = this.expandedRoutes.includes(routeId)
if (isRouteSelected) {
// 线
if (isRouteExpanded) {
// 线
const index = this.expandedRoutes.indexOf(routeId)
this.expandedRoutes.splice(index, 1)
} else {
// 线
this.expandedRoutes.push(routeId)
}
} else {
// 线线
this.handleSelectRoute(route)
//
this.$nextTick(() => {
if (!this.expandedRoutes.includes(routeId)) {
this.expandedRoutes.push(routeId)
}
})
}
},
handleHide() {
this.$emit('hide')
},
@ -317,6 +365,7 @@ export default {
},
handleSelectRoute(route) {
// 线
this.$emit('select-route', route)
},
@ -328,6 +377,14 @@ export default {
this.$emit('create-route')
},
handleCreateRouteForPlan(plan) {
this.$emit('create-route', plan)
},
handleDeletePlan(plan) {
//
},
handleOpenPlanDialog(plan) {
this.$emit('open-plan-dialog', plan)
},
@ -336,16 +393,27 @@ export default {
this.$emit('open-route-dialog', route)
},
handleOpenWaypointDialog(point) {
this.$emit('open-waypoint-dialog', point)
handleToggleRouteVisibility(route) {
this.$emit('toggle-route-visibility', route)
// 线
const routeIndex = this.expandedRoutes.indexOf(route.id)
if (routeIndex > -1) {
this.expandedRoutes.splice(routeIndex, 1)
}
},
handleAddWaypoint() {
this.$emit('add-waypoint')
getRouteClasses(routeId) {
return {
active: this.activeRouteIds.includes(routeId)
}
},
handleCancelRoute() {
this.$emit('cancel-route')
handleDeleteRoute(route) {
//
},
handleOpenWaypointDialog(point) {
this.$emit('open-waypoint-dialog', point)
},
handleViewConflict(conflict) {
@ -469,115 +537,90 @@ export default {
opacity: 0.9;
}
.route-list {
.tree-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.route-item {
.tree-item {
border-radius: 6px;
transition: all 0.3s;
border: 1px solid rgba(0, 138, 255, 0.1);
}
.tree-item-header {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
border: 1px solid rgba(0, 138, 255, 0.1);
position: relative;
border-radius: 6px;
}
.route-item:hover {
.tree-item-header:hover {
background: rgba(0, 138, 255, 0.1);
transform: translateX(-2px);
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15);
}
.route-item.active {
background: rgba(0, 138, 255, 0.15);
border-color: rgba(0, 138, 255, 0.3);
box-shadow: 0 2px 10px rgba(0, 138, 255, 0.25);
.tree-item.plan-item .tree-item-header {
background: rgba(255, 255, 255, 0.9) !important;
}
.route-info {
flex: 1;
.tree-item.route-item .tree-item-header {
background: rgba(255, 255, 255, 0.8) !important;
}
.route-name {
font-size: 14px;
font-weight: 500;
color: #333;
.tree-item.route-item:not(.active) .tree-item-header {
background: rgba(255, 255, 255, 0.8) !important;
}
.route-meta {
font-size: 12px;
color: #999;
}
.route-actions {
display: flex;
gap: 8px;
}
.route-actions i {
cursor: pointer;
color: #008aff;
font-size: 14px;
padding: 4px;
border-radius: 4px;
transition: all 0.2s;
.tree-item.waypoint-item .tree-item-header {
background: rgba(224, 238, 255, 0.8);
}
.route-actions i:hover {
background: rgba(0, 138, 255, 0.1);
transform: scale(1.2);
}
.waypoint-list {
display: flex;
flex-direction: column;
gap: 8px;
.tree-item.active .tree-item-header {
background: rgba(0, 138, 255, 0.15) !important;
border-color: rgba(0, 138, 255, 0.3);
box-shadow: 0 2px 10px rgba(0, 138, 255, 0.25);
}
.waypoint-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
transition: all 0.3s;
border: 1px solid rgba(0, 138, 255, 0.1);
.tree-item.selected .tree-item-header {
background: rgba(0, 138, 255, 0.1) !important;
border-color: rgba(0, 138, 255, 0.2);
}
.waypoint-item:hover {
background: rgba(0, 138, 255, 0.1);
transform: translateX(-2px);
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15);
.tree-icon {
font-size: 16px;
color: #008aff;
flex-shrink: 0;
}
.waypoint-info {
.tree-item-info {
flex: 1;
}
.waypoint-name {
.tree-item-name {
font-size: 14px;
font-weight: 500;
color: #333;
}
.waypoint-meta {
.tree-item-meta {
font-size: 12px;
color: #999;
}
.waypoint-actions {
.tree-item-actions {
display: flex;
gap: 8px;
flex-shrink: 0;
}
.waypoint-actions i {
.tree-item-actions i {
cursor: pointer;
color: #008aff;
font-size: 14px;
@ -586,11 +629,27 @@ export default {
transition: all 0.2s;
}
.waypoint-actions i:hover {
.tree-item-actions i:hover {
background: rgba(0, 138, 255, 0.1);
transform: scale(1.2);
}
.tree-children {
margin-left: 20px;
margin-top: 4px;
display: flex;
flex-direction: column;
gap: 4px;
}
.route-children {
margin-left: 25px;
}
.waypoint-children {
margin-left: 50px;
}
.action-buttons {
display: flex;
gap: 10px;

221
ruoyi-ui/src/views/childRoom/index.vue

@ -106,6 +106,7 @@
<!-- 右侧实体列表浮动- 蓝色主题 -->
<right-panel
ref="rightPanel"
:is-hidden="isRightPanelHidden"
:active-tab="activeRightTab"
:plans="plans"
@ -123,14 +124,14 @@
@hide="hideRightPanel"
@select-plan="selectPlan"
@select-route="selectRoute"
@create-plan="createPlan"
@create-route="createRoute"
@delete-route="handleDeleteRoute"
@create-plan="createPlan"
@open-plan-dialog="openPlanDialog"
@open-route-dialog="openRouteDialog"
@open-waypoint-dialog="openWaypointDialog"
@add-waypoint="addWaypoint"
@cancel-route="cancelRoute"
@toggle-route-visibility="toggleRouteVisibility"
@view-conflict="viewConflict"
@resolve-conflict="resolveConflict"
@run-conflict-check="runConflictCheck"
@ -329,6 +330,8 @@ export default {
// -线-
selectedPlanId: null,
selectedPlanDetails: null,
selectedRouteId: null,
selectedRouteDetails: null,
// -
topNavItems: [
@ -391,7 +394,6 @@ export default {
//
activeRightTab: 'plan',
activeRouteIds: [], // 线ID
selectedRouteDetails: null,
//
conflictCount: 2,
@ -439,18 +441,13 @@ export default {
id: 1,
name: '方案A',
routes: [
{ id: 101, name: 'Alpha进场航线', points: 8, conflict: true },
{ id: 102, name: 'Beta巡逻航线', points: 6, conflict: false },
{ id: 103, name: '侦察覆盖区', points: 4, conflict: false },
]
]
},
{
id: 2,
name: '方案B',
routes: [
{ id: 201, name: 'Gamma突击航线', points: 10, conflict: false },
{ id: 202, name: 'Delta支援航线', points: 5, conflict: true },
]
]
}
],
@ -471,8 +468,6 @@ export default {
this.isMenuHidden = true;
//
this.isRightPanelHidden = true;
//
this.selectPlan(this.plans[0]);
//
this.updateTime();
@ -542,7 +537,13 @@ export default {
}
},
// 线
createRoute() {
createRoute(plan) {
// 线
if (plan) {
this.selectedPlanId = plan.id;
this.selectedPlanDetails = plan;
}
if (this.$refs.cesiumMap) {
this.$refs.cesiumMap.startMissionRouteDrawing();
this.$message.success('进入航线规划模式');
@ -580,7 +581,7 @@ export default {
},
/** 从数据库拉取最新的航线列表数据 */
async getList() {
const query = { scenarioId: 1 };
const query = {}; // scenarioId线
try {
const response = await listRoutes(query);
if (response.code === 200) {
@ -588,7 +589,9 @@ export default {
id: item.id,
name: item.callSign,
points: item.waypoints ? item.waypoints.length : 0,
conflict: false
waypoints: item.waypoints || [],
conflict: false,
scenarioId: item.scenarioId
}));
}
} catch (error) {
@ -620,7 +623,7 @@ export default {
// Routes
const routeData = {
callSign: this.newRouteName,
scenarioId: currentScenarioId,
scenarioId: currentScenarioId || 1, // 使ID1
platformId: 1,
attributes: "{}",
waypoints: this.tempMapPoints.map((p, index) => ({
@ -741,9 +744,7 @@ export default {
this.isMenuHidden = true;
},
selectTopNav(item) {
console.log('选中顶部导航:', item);
},
//
showRightPanel() {
@ -751,6 +752,11 @@ export default {
this.$message.info('显示右侧面板');
},
//
selectTopNav(item) {
this.activeMenu = item.id;
},
//
savePlan() {
this.$message.success('保存计划');
@ -758,35 +764,43 @@ export default {
importPlanFile() {
this.$message.success('导入计划');
//
},
importACD() {
this.$message.success('导入ACD');
// ACD
},
importATO() {
this.$message.success('导入ATO');
// ATO
},
importLayer() {
this.$message.success('导入图层');
//
},
importRoute() {
this.$message.success('导入航线');
// 线
},
exportPlan() {
this.$message.success('导出计划');
//
},
//
routeEdit() {
this.$message.success('航线编辑');
// 线
},
militaryMarking() {
this.$message.success('军事标绘');
//
},
iconEdit() {
@ -879,31 +893,38 @@ export default {
timeSettings() {
this.$message.success('时间设置');
//
},
aircraftSettings() {
this.$message.success('机型设置');
//
},
keyEventEdit() {
this.$message.success('关键事件编辑');
//
},
missileLaunch() {
this.$message.success('导弹发射');
//
},
//
toggle2D3D() {
this.$message.success('2D/3D切换');
// 2D/3D
},
toggleRuler() {
this.$message.success('显示/隐藏标尺');
// /
},
toggleGrid() {
this.$message.success('显示/隐藏网格');
// /
},
saveScale(scale) {
@ -915,10 +936,12 @@ export default {
//
loadTerrain() {
this.$message.success('加载/切换地形');
// /
},
changeProjection() {
this.$message.success('投影');
//
},
loadAeroChart() {
@ -938,18 +961,22 @@ export default {
//
routeCalculation() {
this.$message.success('航线计算');
// 线
},
conflictDisplay() {
this.$message.success('冲突显示');
//
},
dataMaterials() {
this.$message.success('数据资料');
//
},
coordinateConversion() {
this.$message.success('坐标换算');
//
},
//
@ -1013,17 +1040,20 @@ export default {
systemDescription() {
this.$message.success('系统说明');
//
},
//
layerFavorites() {
this.$message.success('图层收藏');
//
},
routeFavorites() {
this.$message.success('航线收藏');
},
hideRightPanel() {
this.isRightPanelHidden = true;
this.$message.info('隐藏右侧面板');
@ -1035,6 +1065,11 @@ export default {
this.handleMenuAction(item.action)
}
//
if (item.id === 'file' || item.id === 'start' || item.id === 'insert') {
this.drawDom = false;
}
//
if (item.id === 'file') {
//
@ -1062,14 +1097,19 @@ export default {
}
} else if(item.id === 'modify'){
this.drawDom = !this.drawDom
//
this.isRightPanelHidden = true;
console.log(this.drawDom,999999)
}
if (item.id === 'deduction') {
} else if (item.id === 'deduction') {
// /K
this.showKTimePopup = !this.showKTimePopup;
}
if (item.id === 'save') {
this.savePlan();
//
this.drawDom = false;
} else {
//
this.isRightPanelHidden = true;
//
this.drawDom = false;
}
},
@ -1161,49 +1201,83 @@ export default {
const minutes = (val % 4) * 15;
return `K+${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:00`;
},
// 线
selectPlan(plan) {
if (plan && plan.id) {
this.selectedPlanId = plan.id;
this.selectedPlanDetails = plan;
} else {
this.selectedPlanId = null;
this.selectedPlanDetails = null;
}
this.selectedRouteId = null;
this.selectedRouteDetails = null;
},
/** 切换航线:实现多选/开关逻辑 */
async selectRoute(route) {
const index = this.activeRouteIds.indexOf(route.id);
const isRouteExpanded = this.$refs.rightPanel ? this.$refs.rightPanel.expandedRoutes.includes(route.id) : false;
// 线
if (index > -1) {
this.activeRouteIds.splice(index, 1);
if (this.$refs.cesiumMap) {
this.$refs.cesiumMap.removeRouteById(route.id);
}
if (this.selectedRouteDetails && this.selectedRouteDetails.id === route.id) {
if (this.activeRouteIds.length > 0) {
const lastId = this.activeRouteIds[this.activeRouteIds.length - 1];
try {
const res = await getRoutes(lastId);
if (res.code === 200 && res.data) {
this.selectedRouteDetails = {
id: res.data.id,
name: res.data.callSign,
waypoints: res.data.waypoints || []
};
if (isRouteExpanded) {
// 线
// RightPanel toggleRoute
return;
} else {
// 线
this.activeRouteIds.splice(index, 1);
if (this.$refs.cesiumMap) {
this.$refs.cesiumMap.removeRouteById(route.id);
}
if (this.selectedRouteDetails && this.selectedRouteDetails.id === route.id) {
if (this.activeRouteIds.length > 0) {
const lastId = this.activeRouteIds[this.activeRouteIds.length - 1];
try {
const res = await getRoutes(lastId);
if (res.code === 200 && res.data) {
this.selectedRouteId = res.data.id;
this.selectedRouteDetails = {
id: res.data.id,
name: res.data.callSign,
waypoints: res.data.waypoints || []
};
}
} catch (e) {
console.error("回显剩余航线失败", e);
}
} catch (e) {
console.error("回显剩余航线失败", e);
} else {
this.selectedRouteId = null;
this.selectedRouteDetails = null;
}
} else {
this.selectedRouteDetails = null;
}
this.$message.info(`已取消航线: ${route.name}`);
return;
}
this.$message.info(`已移除航线: ${route.name}`);
return;
}
// 线
// 线线
try {
const response = await getRoutes(route.id);
if (response.code === 200 && response.data) {
const fullRouteData = response.data;
const waypoints = fullRouteData.waypoints || [];
this.activeRouteIds.push(route.id);
this.selectedRouteId = fullRouteData.id;
this.selectedRouteDetails = {
id: fullRouteData.id,
name: fullRouteData.callSign,
waypoints: waypoints
};
// routes 线 waypoints
const routeIndex = this.routes.findIndex(r => r.id === route.id);
if (routeIndex > -1) {
this.$set(this.routes, routeIndex, {
...this.routes[routeIndex],
waypoints: waypoints
});
}
if (waypoints.length > 0) {
//
if (this.$refs.cesiumMap) {
@ -1218,13 +1292,7 @@ export default {
this.$message.error('无法加载该航线的详细航点数据');
}
},
// 线
selectPlan(plan) {
this.selectedPlanId = plan.id;
this.selectedPlanDetails = plan;
this.selectedRouteId = null;
this.selectedRouteDetails = null;
},
createPlan() {
const newId = Date.now();
const newPlan = {
@ -1249,8 +1317,9 @@ export default {
const count = this.selectedRouteDetails.waypoints.length + 1;
this.selectedRouteDetails.waypoints.push({
name: `WP${count}`,
altitude: 1000,
speed: 250
altitude: 5000,
speed: '800km/h',
eta: `K+01:${(count * 15).toString().padStart(2, '0')}:00`
});
if (this.selectedPlanDetails) {
const route = this.selectedPlanDetails.routes.find(r => r.id === this.selectedRouteId);
@ -1273,6 +1342,44 @@ export default {
this.$message.info('已清空所有选中航线');
},
// 线/
toggleRouteVisibility(route) {
const index = this.activeRouteIds.indexOf(route.id);
if (index > -1) {
// 线
// 使 Vue
this.activeRouteIds = this.activeRouteIds.filter(id => id !== route.id);
if (this.$refs.cesiumMap) {
this.$refs.cesiumMap.removeRouteById(route.id);
}
if (this.selectedRouteDetails && this.selectedRouteDetails.id === route.id) {
if (this.activeRouteIds.length > 0) {
const lastId = this.activeRouteIds[this.activeRouteIds.length - 1];
getRoutes(lastId).then(res => {
if (res.code === 200 && res.data) {
this.selectedRouteId = res.data.id;
this.selectedRouteDetails = {
id: res.data.id,
name: res.data.callSign,
waypoints: res.data.waypoints || []
};
}
}).catch(e => {
console.error("获取航线详情失败", e);
});
} else {
this.selectedRouteId = null;
this.selectedRouteDetails = null;
}
}
this.$message.info(`已隐藏航线: ${route.name}`);
} else {
// 线
this.selectRoute(route);
}
},
//
runConflictCheck() {
this.conflictCount = 2;
@ -1304,7 +1411,6 @@ export default {
</script>
<style scoped>
/* 保持原有样式不变,仅修复背景图语法的注释部分 */
.mission-planning-container {
position: relative;
width: 100vw;
@ -1326,7 +1432,7 @@ export default {
background-position: center;
z-index: 1;
}
/* ...其余样式省略,保持不变... */
.map-overlay-text {
position: absolute;
top: 50%;
@ -1464,6 +1570,7 @@ export default {
box-shadow: 0 0 10px rgba(0, 138, 255, 0.8);
}
/* 蓝色主题标签页 */
.blue-tabs >>> .el-tabs__item {
color: #666;
transition: all 0.3s;

50
ruoyi-ui/src/views/dialogs/PlatformEditDialog.vue

@ -2,21 +2,21 @@
<div v-if="value" class="platform-edit-dialog">
<!-- 遮罩层 -->
<div class="dialog-overlay" @click="closeDialog"></div>
<!-- 弹窗内容 -->
<div class="dialog-content">
<div class="dialog-header">
<h3>平台编辑</h3>
<div class="close-btn" @click="closeDialog">×</div>
</div>
<div class="dialog-body">
<el-form :model="formData" :rules="rules" ref="formRef" label-width="80px" size="small">
<!-- 基本信息 -->
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入平台名称"></el-input>
</el-form-item>
<el-form-item label="位置">
<div class="location-inputs">
<el-input v-model="formData.location.lat" placeholder="纬度" style="width: 120px;"></el-input>
@ -24,54 +24,54 @@
<el-input v-model="formData.location.lng" placeholder="经度" style="width: 120px;"></el-input>
</div>
</el-form-item>
<el-form-item label="速度" prop="speed">
<el-input v-model="formData.speed" placeholder="请输入速度" suffix="km/h"></el-input>
</el-form-item>
<el-form-item label="油耗表" prop="fuelConsumption">
<el-input-number
v-model="formData.fuelConsumption"
:min="0"
:precision="2"
<el-input-number
v-model="formData.fuelConsumption"
:min="0"
:precision="2"
placeholder="请输入油耗"
style="width: 100%;"
suffix="L/km"
></el-input-number>
</el-form-item>
<el-form-item label="高度限制">
<div class="altitude-inputs">
<el-input-number
v-model="formData.altitude.min"
:min="0"
<el-input-number
v-model="formData.altitude.min"
:min="0"
placeholder="最低高度"
style="width: 120px;"
suffix="m"
></el-input-number>
<span class="altitude-separator">~</span>
<el-input-number
v-model="formData.altitude.max"
:min="0"
<el-input-number
v-model="formData.altitude.max"
:min="0"
placeholder="最高高度"
style="width: 120px;"
suffix="m"
></el-input-number>
</div>
</el-form-item>
<el-form-item label="威力区/扇区">
<div class="sector-inputs">
<el-input-number
v-model="formData.sector.radius"
:min="0"
<el-input-number
v-model="formData.sector.radius"
:min="0"
placeholder="半径"
style="width: 100px;"
suffix="km"
></el-input-number>
<el-input-number
v-model="formData.sector.angle"
:min="0"
<el-input-number
v-model="formData.sector.angle"
:min="0"
:max="360"
placeholder="角度"
style="width: 100px;"
@ -81,7 +81,7 @@
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="savePlatform">保存</el-button>
@ -292,4 +292,4 @@ export default {
border-top: 1px solid #e8e8e8;
gap: 10px;
}
</style>
</style>

6
ruoyi-ui/src/views/selectRoom/index.vue

@ -46,7 +46,6 @@
</div>
</div>
</div>
<div v-if="expandedRooms.includes(room.id)" class="child-rooms">
<div
v-for="childRoom in getChildRooms(room.id)"
@ -75,14 +74,12 @@
</div>
</div>
</div>
<div v-if="getParentRooms.length === 0" class="empty-state">
<i class="fa fa-sitemap"></i>
<h3>暂无房间</h3>
<p>点击下方按钮创建您的第一个房间</p>
</div>
</div>
<div class="action-buttons">
<button @click="showAddRoomDialog" class="btn-secondary">
<i class="fa fa-plus"></i> 新增大房间
@ -97,12 +94,10 @@
</button>
</div>
</div>
<div class="footer-info">
<p>© 2026 网络化任务规划系统 | 支持Windows/国产化系统互通</p>
</div>
</div>
<div
v-if="contextMenu.visible"
:style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
@ -117,7 +112,6 @@
<span>删除房间</span>
</div>
</div>
<el-dialog
:title="dialog.mode === 'add' ? '新增房间' : '修改房间'"
:visible.sync="dialog.visible"

2
ruoyi-ui/vue.config.js

@ -10,7 +10,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
const baseUrl = 'http://127.0.0.1:8080' // 后端接口
const baseUrl = 'http://192.168.50.145:8080' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口
// 定义 Cesium 源码路径

Loading…
Cancel
Save