feat(screen): 添加可编辑的计划步骤和基于站点的调度计划
- 使用el-input将静态计划步骤和后续文本转换为可编辑输入框 - 使清场步骤和调度计划具有响应性,支持动态站点分配 - 添加用于添加和删除调度计划的UI元素(当前已禁用) - 为新的交互组件更新样式并改善布局 - 从父组件集成stations属性以实现站点名称的自动分配
This commit is contained in:
parent
93295fd420
commit
677a5fa9ac
@ -144,7 +144,12 @@
|
|||||||
<div class="plan-steps">
|
<div class="plan-steps">
|
||||||
<div v-for="step in clearanceSteps" :key="step.id" class="step-item">
|
<div v-for="step in clearanceSteps" :key="step.id" class="step-item">
|
||||||
<label class="step-label">{{ step.number }}{{ step.title }}</label>
|
<label class="step-label">{{ step.number }}{{ step.title }}</label>
|
||||||
<div class="step-content">{{ step.content }}</div>
|
<el-input
|
||||||
|
v-model="step.content"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
|
class="step-content-input"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -159,7 +164,10 @@
|
|||||||
class="title-icon"
|
class="title-icon"
|
||||||
/>
|
/>
|
||||||
<h3 class="section-title">力量调派方案</h3>
|
<h3 class="section-title">力量调派方案</h3>
|
||||||
<button class="add-btn" @click="handleAddPlan">新增</button>
|
<button class="add-btn" @click="handleAddPlan">
|
||||||
|
<span class="add-icon">+</span>
|
||||||
|
<span>新增</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="section-body">
|
<div class="section-body">
|
||||||
<div class="dispatch-plans">
|
<div class="dispatch-plans">
|
||||||
@ -168,9 +176,10 @@
|
|||||||
:key="plan.id"
|
:key="plan.id"
|
||||||
class="dispatch-card"
|
class="dispatch-card"
|
||||||
>
|
>
|
||||||
|
<button class="close-btn" @click="handleDeletePlan(plan.id)" title="删除">×</button>
|
||||||
<h4 class="plan-name">
|
<h4 class="plan-name">
|
||||||
<span class="plan-icon"></span>
|
<span class="plan-icon"></span>
|
||||||
{{ plan.name }}
|
基地{{ plan.id }}:{{ plan.stationName || 'xxxxx名称' }}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="resource-grid">
|
<div class="resource-grid">
|
||||||
<div
|
<div
|
||||||
@ -198,16 +207,34 @@
|
|||||||
<h3 class="section-title">后续处治</h3>
|
<h3 class="section-title">后续处治</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="section-body">
|
<div class="section-body">
|
||||||
<p class="follow-up-text">{{ followUpText }}</p>
|
<el-input
|
||||||
|
v-model="followUpText"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||||
|
class="follow-up-textarea"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive } from "vue";
|
import { ref, reactive, computed, watch } from "vue";
|
||||||
// 导入 Element Plus 组件(如果项目已全局注册则可省略)
|
|
||||||
// import { ElSelect, ElOption } from 'element-plus'
|
/**
|
||||||
|
* Props 定义
|
||||||
|
*/
|
||||||
|
const props = defineProps({
|
||||||
|
stations: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可用站点列表(从快速匹配传入)
|
||||||
|
*/
|
||||||
|
const availableStations = computed(() => props.stations);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表单数据
|
* 表单数据
|
||||||
@ -226,7 +253,7 @@ const formData = reactive({
|
|||||||
/**
|
/**
|
||||||
* 公路抢通方案步骤
|
* 公路抢通方案步骤
|
||||||
*/
|
*/
|
||||||
const clearanceSteps = [
|
const clearanceSteps = reactive([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
number: "①",
|
number: "①",
|
||||||
@ -268,17 +295,17 @@ const clearanceSteps = [
|
|||||||
title: "全断面抢通",
|
title: "全断面抢通",
|
||||||
content: "将剩余集聚废弃物的清理清除,恢复道路原貌状。",
|
content: "将剩余集聚废弃物的清理清除,恢复道路原貌状。",
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 力量调派预案
|
* 力量调派预案
|
||||||
*/
|
*/
|
||||||
const dispatchPlans = [
|
const dispatchPlans = ref([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "基地1:xxxxx名称",
|
stationName: "", // 站点名称,从 stations 自动赋值
|
||||||
resources: [
|
resources: [
|
||||||
{ label: "装载机挖掘机", value: "1台" },
|
{ label: "轮播挖掘机挖掘机", value: "1台" },
|
||||||
{ label: "平板拖车", value: "1台" },
|
{ label: "平板拖车", value: "1台" },
|
||||||
{ label: "自卸货车", value: "4台" },
|
{ label: "自卸货车", value: "4台" },
|
||||||
{ label: "工程车", value: "1台" },
|
{ label: "工程车", value: "1台" },
|
||||||
@ -291,9 +318,9 @@ const dispatchPlans = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "基地2:xxxxx名称",
|
stationName: "",
|
||||||
resources: [
|
resources: [
|
||||||
{ label: "装载机挖掘机", value: "1台" },
|
{ label: "轮播挖掘机挖掘机", value: "1台" },
|
||||||
{ label: "平板拖车", value: "1台" },
|
{ label: "平板拖车", value: "1台" },
|
||||||
{ label: "自卸货车", value: "4台" },
|
{ label: "自卸货车", value: "4台" },
|
||||||
{ label: "工程车", value: "1台" },
|
{ label: "工程车", value: "1台" },
|
||||||
@ -304,20 +331,94 @@ const dispatchPlans = [
|
|||||||
{ label: "麻袋、砂石袋等", value: "若干" },
|
{ label: "麻袋、砂石袋等", value: "若干" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后续处治文本
|
* 后续处治文本
|
||||||
*/
|
*/
|
||||||
const followUpText =
|
const followUpText = ref(
|
||||||
'将该处于方案大部分障碍清点,设置"注意落石"等标志牌,进行巡逻管控,进行巡逻处理信号监测统设备。';
|
'将该处于方案大部分障碍清点,设置"注意落石"等标志牌,进行巡逻管控,进行巡逻处理信号监测统设备。'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据站点索引获取站点名称
|
||||||
|
* @param {number} index - 站点索引(从0开始)
|
||||||
|
* @returns {string} 站点名称
|
||||||
|
*/
|
||||||
|
const getStationNameByIndex = (index) => {
|
||||||
|
if (availableStations.value && availableStations.value.length > index) {
|
||||||
|
return availableStations.value[index].name;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动为所有基地分配站点名称
|
||||||
|
*/
|
||||||
|
const assignStationNames = () => {
|
||||||
|
dispatchPlans.value.forEach((plan, index) => {
|
||||||
|
plan.stationName = getStationNameByIndex(index);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听站点数据变化,自动分配站点名称
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => props.stations,
|
||||||
|
(newStations) => {
|
||||||
|
console.log("[EmergencyPlanContent] 站点数据变化检测:", newStations);
|
||||||
|
if (newStations && newStations.length > 0) {
|
||||||
|
assignStationNames();
|
||||||
|
console.log("[EmergencyPlanContent] 站点数据更新,自动分配站点名称");
|
||||||
|
console.log("[EmergencyPlanContent] 当前基地列表:", dispatchPlans.value);
|
||||||
|
} else {
|
||||||
|
console.log("[EmergencyPlanContent] 站点数据为空或未定义");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理新增预案按钮点击
|
* 处理新增预案按钮点击
|
||||||
*/
|
*/
|
||||||
const handleAddPlan = () => {
|
const handleAddPlan = () => {
|
||||||
|
// 暂时禁止新增预案
|
||||||
|
return
|
||||||
console.log("[EmergencyPlanContent] 点击新增预案");
|
console.log("[EmergencyPlanContent] 点击新增预案");
|
||||||
// TODO: 后续可以打开新增预案弹窗或添加新预案
|
const newId = Math.max(...dispatchPlans.value.map((p) => p.id)) + 1;
|
||||||
|
const newIndex = dispatchPlans.value.length;
|
||||||
|
|
||||||
|
dispatchPlans.value.push({
|
||||||
|
id: newId,
|
||||||
|
stationName: getStationNameByIndex(newIndex),
|
||||||
|
resources: [
|
||||||
|
{ label: "轮播挖掘机挖掘机", value: "1台" },
|
||||||
|
{ label: "平板拖车", value: "1台" },
|
||||||
|
{ label: "自卸货车", value: "4台" },
|
||||||
|
{ label: "工程车", value: "1台" },
|
||||||
|
{ label: "人员", value: "15人" },
|
||||||
|
{ label: "标志标牌", value: "5块" },
|
||||||
|
{ label: "铁锹", value: "30件" },
|
||||||
|
{ label: "铁镐", value: "10件" },
|
||||||
|
{ label: "麻袋、砂石袋等", value: "若干" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理删除预案
|
||||||
|
*/
|
||||||
|
const handleDeletePlan = (id) => {
|
||||||
|
// 暂时禁止删除预案
|
||||||
|
return
|
||||||
|
console.log("[EmergencyPlanContent] 删除预案", id);
|
||||||
|
const index = dispatchPlans.value.findIndex((p) => p.id === id);
|
||||||
|
if (index > -1) {
|
||||||
|
dispatchPlans.value.splice(index, 1);
|
||||||
|
// 删除后重新分配站点名称,保持顺序
|
||||||
|
assignStationNames();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -374,6 +475,15 @@ const handleAddPlan = () => {
|
|||||||
font-family: SourceHanSansCN-Medium, sans-serif;
|
font-family: SourceHanSansCN-Medium, sans-serif;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: vw(6);
|
||||||
|
|
||||||
|
.add-icon {
|
||||||
|
font-size: fs(18);
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--primary-light);
|
background: var(--primary-light);
|
||||||
@ -591,6 +701,35 @@ const handleAddPlan = () => {
|
|||||||
background: #052044;
|
background: #052044;
|
||||||
border-radius: vw(4);
|
border-radius: vw(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.step-content-input {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
:deep(.el-textarea__inner) {
|
||||||
|
background: #052044 !important;
|
||||||
|
border: 1px solid rgba(28, 161, 255, 0.3) !important;
|
||||||
|
border-radius: vw(4);
|
||||||
|
color: var(--text-white);
|
||||||
|
font-size: fs(13);
|
||||||
|
font-family: SourceHanSansCN-Regular, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
padding: vh(8) vw(12);
|
||||||
|
transition: border-color 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--primary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--primary-color) !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 调派预案 */
|
/* 调派预案 */
|
||||||
@ -605,13 +744,45 @@ const handleAddPlan = () => {
|
|||||||
border: 1px solid rgba(28, 161, 255, 0.2);
|
border: 1px solid rgba(28, 161, 255, 0.2);
|
||||||
border-radius: vw(8);
|
border-radius: vw(8);
|
||||||
padding: vh(12) vw(14);
|
padding: vh(12) vw(14);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: vh(12);
|
||||||
|
right: vw(14);
|
||||||
|
width: vw(24);
|
||||||
|
height: vw(24);
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
background: transparent;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
font-size: fs(20);
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 77, 79, 0.2);
|
||||||
|
border-color: #ff4d4f;
|
||||||
|
color: #ff4d4f;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: rotate(90deg) scale(0.95);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.plan-name {
|
.plan-name {
|
||||||
font-size: fs(15);
|
font-size: fs(15);
|
||||||
font-family: SourceHanSansCN-Bold, sans-serif;
|
font-family: SourceHanSansCN-Bold, sans-serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--text-white);
|
color: var(--text-white);
|
||||||
margin: 0 0 vh(10) 0;
|
margin: 0 vw(30) vh(10) 0;
|
||||||
|
|
||||||
.plan-icon {
|
.plan-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 9px;
|
width: 9px;
|
||||||
@ -660,6 +831,33 @@ const handleAddPlan = () => {
|
|||||||
background: #052044;
|
background: #052044;
|
||||||
border-radius: vw(4);
|
border-radius: vw(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.follow-up-textarea {
|
||||||
|
:deep(.el-textarea__inner) {
|
||||||
|
background: #052044 !important;
|
||||||
|
border: 1px solid rgba(28, 161, 255, 0.3) !important;
|
||||||
|
border-radius: vw(4);
|
||||||
|
color: var(--text-white);
|
||||||
|
font-size: fs(13);
|
||||||
|
font-family: SourceHanSansCN-Regular, sans-serif;
|
||||||
|
line-height: 1.8;
|
||||||
|
padding: vh(10) vw(14);
|
||||||
|
transition: border-color 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--primary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--primary-color) !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@ -178,7 +178,7 @@
|
|||||||
width="clamp(100px, 50vw, 1400px)"
|
width="clamp(100px, 50vw, 1400px)"
|
||||||
>
|
>
|
||||||
<!-- 使用应急方案内容组件 -->
|
<!-- 使用应急方案内容组件 -->
|
||||||
<EmergencyPlanContent />
|
<EmergencyPlanContent :stations="disasterData.forcePreset.value.stations" />
|
||||||
|
|
||||||
<!-- 底部一键启动按钮 -->
|
<!-- 底部一键启动按钮 -->
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user