项目bug更改

This commit is contained in:
王兴凯 2026-08-31 14:04:06 +08:00
parent 35db4003a1
commit 6ec994502a
40 changed files with 694 additions and 3896 deletions

View File

@ -405,6 +405,7 @@ const emit = defineEmits<{
(e: 'finish', values: any): void; (e: 'finish', values: any): void;
(e: 'valuesChange', changedValues: any, allValues: any): void; (e: 'valuesChange', changedValues: any, allValues: any): void;
(e: 'reset'): void; (e: 'reset'): void;
(e: 'initDone', values: any): void;
}>(); }>();
const formRef = ref<any>(); const formRef = ref<any>();
@ -427,7 +428,7 @@ const validSearchList = computed(() => {
}); });
// --- --- // --- ---
const initForm = () => { const initForm = async () => {
const initial = JSON.parse(JSON.stringify(props.initialValues || {})); const initial = JSON.parse(JSON.stringify(props.initialValues || {}));
// 1. formData // 1. formData
@ -437,7 +438,7 @@ const initForm = () => {
Object.assign(formData, initial); Object.assign(formData, initial);
// 3. searchList false/null/undefined // 3. searchList false/null/undefined
validSearchList.value.forEach(item => { for (const item of validSearchList.value) {
if (item.type == 'waterStation') { if (item.type == 'waterStation') {
// //
shuJuTianBaoStore.getBaseOption(); shuJuTianBaoStore.getBaseOption();
@ -445,15 +446,23 @@ const initForm = () => {
shuJuTianBaoStore.getEngOption(formData.rvcd,'rvcd'); shuJuTianBaoStore.getEngOption(formData.rvcd,'rvcd');
} }
if (item.type == 'jidiData') { if (item.type == 'jidiData') {
shuJuTianBaoStore.getBaseOption(); // 'all'
shuJuTianBaoStore.getEngOption(formData[item.name] || 'all','baseId'); const initialBaseValue = formData[item.name];
formData[item.name] = null;
await shuJuTianBaoStore.getBaseOption();
const hasBaseValue = shuJuTianBaoStore.baseOption.length > 0;
if (hasBaseValue) {
// null
formData[item.name] = initialBaseValue || 'all';
shuJuTianBaoStore.getEngOption(formData[item.name],'baseId');
}
} }
if (item.fieldProps?.required) { if (item.fieldProps?.required) {
rules[item.name] = [ rules[item.name] = [
{ required: true, message: `${item.label}不能为空`, trigger: 'blur' } { required: true, message: `${item.label}不能为空`, trigger: 'blur' }
]; ];
} }
}); }
}; };
/** /**
@ -501,8 +510,10 @@ const stcdIdChange = (value: any) => {
} }
}; };
onMounted(() => { onMounted(async () => {
initForm(); await initForm();
//
emit('initDone', { ...formData });
}); });
watch( watch(

View File

@ -176,11 +176,11 @@ const columnMetaMap: Record<string, any> = {
addvcdName: { width: 150, sort: true, ellipsis: true }, addvcdName: { width: 150, sort: true, ellipsis: true },
stlc: { width: 200, sort: true, ellipsis: true }, stlc: { width: 200, sort: true, ellipsis: true },
baseName: { width: 120, ellipsis: true }, baseName: { width: 120, ellipsis: true },
jcdt: { width: 120, sort: true, ellipsis: true, customRender: dateRender }, jcdt: { width: 180, sort: true, ellipsis: true, customRender: dateRender },
piodt: { width: 160, sort: true, ellipsis: true, customRender: dateRender }, piodt: { width: 160, sort: true, ellipsis: true, customRender: dateRender },
aiodt: { width: 150, sort: true, ellipsis: true, customRender: dateRender }, aiodt: { width: 150, sort: true, ellipsis: true, customRender: dateRender },
bldsttCcodeName: { width: 100, sort: true, ellipsis: true }, bldsttCcodeName: { width: 100, sort: true, ellipsis: true },
hynm: { width: 150, sort: true, ellipsis: true }, hynm: { width: 240, sort: true, ellipsis: true },
topHynm: { width: 150, sort: true, ellipsis: true }, topHynm: { width: 150, sort: true, ellipsis: true },
nrupar: { width: 180, sort: true }, nrupar: { width: 180, sort: true },
dstcrvr: { width: 150, sort: true }, dstcrvr: { width: 150, sort: true },
@ -243,7 +243,7 @@ const columnMetaMap: Record<string, any> = {
yrge: { width: 200, sort: true }, yrge: { width: 200, sort: true },
ushr: { width: 150, sort: true }, ushr: { width: 150, sort: true },
k: { width: 150, sort: true, ellipsis: true }, k: { width: 150, sort: true, ellipsis: true },
dmtp: { width: 100, sort: true, ellipsis: true }, dmtp: { width: 150, sort: true, ellipsis: true },
dmcrel: { width: 130, sort: true }, dmcrel: { width: 130, sort: true },
mxdmhg: { width: 120, sort: true }, mxdmhg: { width: 120, sort: true },
dmlen: { width: 130, sort: true }, dmlen: { width: 130, sort: true },

View File

@ -103,7 +103,7 @@
style="width: 100%" style="width: 100%"
> >
<a-select-option <a-select-option
v-for="opt in shuJuTianBaoStore.lyOption" v-for="opt in fishLyOption"
:key="opt.rvcd" :key="opt.rvcd"
:value="opt.rvcd" :value="opt.rvcd"
:label="opt.rvnm" :label="opt.rvnm"
@ -307,11 +307,8 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> <a-col :span="12">
<!-- 图片上传 --> <a-form-item label="图片" >
<a-row :gutter="16" class="mt-4">
<a-col :span="24">
<a-form-item label="图片" :label-col="{ span: 3 }" :wrapper-col="{ span: 21 }">
<a-upload <a-upload
v-model:file-list="fileList" v-model:file-list="fileList"
:multiple="true" :multiple="true"
@ -328,6 +325,10 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
<!-- 图片上传 -->
<a-row :gutter="16" class="mt-4">
</a-row>
</a-form> </a-form>
</a-modal> </a-modal>
@ -350,6 +351,11 @@ import { useDraggable } from '@/utils/drag';
import { useShuJuTianBaoStore } from '@/store/modules/shuJuTianBao'; import { useShuJuTianBaoStore } from '@/store/modules/shuJuTianBao';
const shuJuTianBaoStore = useShuJuTianBaoStore(); const shuJuTianBaoStore = useShuJuTianBaoStore();
// ""
const fishLyOption = computed(() =>
shuJuTianBaoStore.lyOption.filter((opt: any) => opt.rvcd !== 'all')
);
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL; const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
const props = defineProps<{ const props = defineProps<{
@ -438,7 +444,7 @@ const fieldLabelMap: Record<string, string> = {
// select // select
const selectOptionsMap: Record<string, () => any[]> = { const selectOptionsMap: Record<string, () => any[]> = {
rvcd: () => shuJuTianBaoStore.lyOption.map((opt: any) => ({ rvcd: () => fishLyOption.value.map((opt: any) => ({
label: opt.rvnm, label: opt.rvnm,
value: opt.rvcd value: opt.rvcd
})), })),

View File

@ -6,6 +6,7 @@
:zhujianfujian="'fu'" :zhujianfujian="'fu'"
@reset="handleReset" @reset="handleReset"
@finish="onSearchFinish" @finish="onSearchFinish"
@init-done="handleInitDone"
> >
<template #actions> <template #actions>
<a-button @click="hideBtn">{{ isHide ? '展开' : '隐藏' }}</a-button> <a-button @click="hideBtn">{{ isHide ? '展开' : '隐藏' }}</a-button>
@ -16,7 +17,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, onMounted } from 'vue'; import { ref, computed } from 'vue';
import BasicSearch from '@/components/BasicSearch/index.vue'; import BasicSearch from '@/components/BasicSearch/index.vue';
const emit = defineEmits<{ const emit = defineEmits<{
@ -78,9 +79,10 @@ const seeEdit = () => {
emit('seeEdit'); emit('seeEdit');
}; };
onMounted(() => { // BasicSearch
emit('search-finish', { ...initSearchData }); const handleInitDone = (values: any) => {
}); emit('search-finish', { ...values });
};
defineExpose({ defineExpose({
basicSearchRef basicSearchRef

View File

@ -182,17 +182,6 @@
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:maxlength="1000"
show-count
:rows="2"
/>
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }"> <a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea <a-textarea
@ -281,7 +270,6 @@ const fieldLabelMap: Record<string, string> = {
dtfrqcy: '监测频次', dtfrqcy: '监测频次',
jbtxcs: '基本特性参数', jbtxcs: '基本特性参数',
blprd: '所属建设阶段', blprd: '所属建设阶段',
introduce: '简介',
remark: '备注' remark: '备注'
}; };

View File

@ -49,7 +49,7 @@
@success="handleEditSuccess" @success="handleEditSuccess"
/> />
<OperationLogModal v-model:open="operationLogVisible" :table-name="'SD_OTTE_B_H'" :record-name-title="'工程名称'" /> <OperationLogModal v-model:open="operationLogVisible" :table-name="'SD_OTWE_B_H'" :record-name-title="'工程名称'" />
</div> </div>
</template> </template>

View File

@ -1,71 +1,168 @@
<template> <template>
<a-modal v-model:open="visible" :title="isAdd ? '新增过鱼设施' : '编辑过鱼设施'" width="80vw" :confirm-loading="confirmLoading" @ok="handleOk" @cancel="handleCancel"> <a-modal
<a-form ref="formRef" :model="formData" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" :rules="formRules" class="max-h-[70vh] overflow-y-auto pr-4"> v-model:open="visible"
:title="isAdd ? '新增过鱼设施' : '编辑过鱼设施'"
width="80vw"
:confirm-loading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
>
<a-form
ref="formRef"
:model="formData"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
:rules="formRules"
class="max-h-[70vh] overflow-y-auto pr-4"
>
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="8"> <a-col :span="8">
<a-form-item label="设施编码" name="stcd"> <a-form-item label="设施编码" name="stcd">
<a-input v-model:value="formData.stcd" placeholder="请输入设施编码" :disabled="!isAdd" style="width: 100%" /> <a-input
v-model:value="formData.stcd"
placeholder="请输入设施编码"
:disabled="!isAdd"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="设施名称" name="stnm"> <a-form-item label="设施名称" name="stnm">
<a-input v-model:value="formData.stnm" placeholder="请输入设施名称" style="width: 100%" /> <a-input
v-model:value="formData.stnm"
placeholder="请输入设施名称"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="设施类型" name="sttp"> <a-form-item label="设施类型" name="sttp">
<a-select v-model:value="formData.sttp" placeholder="请选择设施类型" allow-clear show-search :filter-option="filterOption"> <a-select
<a-select-option v-for="item in sttpOptions" :key="item.value" :label="item.label" :value="item.value">{{ item.label }}</a-select-option> v-model:value="formData.sttp"
placeholder="请选择设施类型"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in sttpOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option
>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="站址/位置" name="stlc"> <a-form-item label="站址/位置" name="stlc">
<a-input v-model:value="formData.stlc" placeholder="请输入站址" style="width: 100%" /> <a-input
v-model:value="formData.stlc"
placeholder="请输入站址"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="水电基地" name="baseId"> <a-form-item label="水电基地" name="baseId">
<a-select v-model:value="formData.baseId" placeholder="请选择水电基地" allow-clear show-search :filter-option="filterOption"> <a-select
<a-select-option v-for="item in baseNameOptions" :key="item.value" :label="item.label" :value="item.value">{{ item.label }}</a-select-option> v-model:value="formData.baseId"
placeholder="请选择水电基地"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in baseNameOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option
>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="所属电站" name="rstcd"> <a-form-item label="所属电站" name="rstcd">
<a-select v-model:value="formData.rstcd" placeholder="请选择所属电站" allow-clear show-search :loading="engLoading" :filter-option="filterOption"> <a-select
<a-select-option v-for="item in engInfoOptions" :key="item.value" :label="item.label" :value="item.value">{{ item.label }}</a-select-option> v-model:value="formData.rstcd"
placeholder="请选择所属电站"
allow-clear
show-search
:loading="engLoading"
:filter-option="filterOption"
>
<a-select-option
v-for="item in engInfoOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option
>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="经度(°)" name="lgtd"> <a-form-item label="经度(°)" name="lgtd">
<a-input-number v-model:value="formData.lgtd" placeholder="请输入" :precision="6" style="width: 100%" /> <a-input-number
v-model:value="formData.lgtd"
placeholder="请输入"
:precision="6"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="纬度(°)" name="lttd"> <a-form-item label="纬度(°)" name="lttd">
<a-input-number v-model:value="formData.lttd" placeholder="请输入" :precision="6" style="width: 100%" /> <a-input-number
v-model:value="formData.lttd"
placeholder="请输入"
:precision="6"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="高程(m)" name="elev"> <a-form-item label="高程(m)" name="elev">
<a-input-number v-model:value="formData.elev" placeholder="请输入" :precision="6" style="width: 100%" /> <a-input-number
v-model:value="formData.elev"
placeholder="请输入"
:precision="6"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="开工日期" name="swdt"> <a-form-item label="开工日期" name="swdt">
<a-date-picker v-model:value="formData.swdt" format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" :disabled-date="disabledSwdtDate" placeholder="请选择开工日期" style="width: 100%" /> <a-date-picker
v-model:value="formData.swdt"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled-date="disabledSwdtDate"
placeholder="请选择开工日期"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="建成日期" name="jcdt"> <a-form-item label="建成日期" name="jcdt">
<a-date-picker v-model:value="formData.jcdt" format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" :disabled-date="disabledJcdtDate" placeholder="请选择建成日期" style="width: 100%" /> <a-date-picker
v-model:value="formData.jcdt"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled-date="disabledJcdtDate"
placeholder="请选择建成日期"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="建设状态" name="bldsttCode"> <a-form-item label="建设状态" name="bldsttCode">
<a-select v-model:value="formData.bldsttCode" placeholder="请选择建设状态" allow-clear> <a-select
v-model:value="formData.bldsttCode"
placeholder="请选择建设状态"
allow-clear
>
<a-select-option :value="0">规划</a-select-option> <a-select-option :value="0">规划</a-select-option>
<a-select-option :value="1">在建</a-select-option> <a-select-option :value="1">在建</a-select-option>
<a-select-option :value="2">已建</a-select-option> <a-select-option :value="2">已建</a-select-option>
@ -74,59 +171,114 @@
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="投资(亿元)" name="inv"> <a-form-item label="投资(亿元)" name="inv">
<a-input-number v-model:value="formData.inv" placeholder="请输入" :precision="4" style="width: 100%" /> <a-input-number
v-model:value="formData.inv"
placeholder="请输入"
:precision="4"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="上游码头位置" name="symtlc"> <a-form-item label="上游码头位置" name="symtlc">
<a-input v-model:value="formData.symtlc" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.symtlc"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="上游码头型式" name="symtxs"> <a-form-item label="上游码头型式" name="symtxs">
<a-input v-model:value="formData.symtxs" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.symtxs"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="下游码头位置" name="xymtlc"> <a-form-item label="下游码头位置" name="xymtlc">
<a-input v-model:value="formData.xymtlc" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.xymtlc"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="下游码头型式" name="xymtxs"> <a-form-item label="下游码头型式" name="xymtxs">
<a-input v-model:value="formData.xymtxs" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.xymtxs"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="集诱鱼方式" name="jyfs"> <a-form-item label="集诱鱼方式" name="jyfs">
<a-input v-model:value="formData.jyfs" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.jyfs"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="运鱼设施方式" name="yyfs"> <a-form-item label="运鱼设施方式" name="yyfs">
<a-input v-model:value="formData.yyfs" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.yyfs"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="过鱼规模(尾)" name="sjgycnt"> <a-form-item label="过鱼规模(尾)" name="sjgycnt">
<a-input v-model:value="formData.sjgycnt" placeholder="请输入" style="width: 100%" /> <a-input
v-model:value="formData.sjgycnt"
placeholder="请输入"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="过鱼月份" name="fpssmn"> <a-form-item label="过鱼月份" name="fpssmn">
<a-select :key="visible" v-model:value="formData.fpssmn" mode="multiple" placeholder="请选择过鱼月份" allow-clear> <a-select
<a-select-option v-for="item in fpssmnOptions" :key="item.value" :label="item.label" :value="item.value">{{ item.label }}</a-select-option> :key="visible"
v-model:value="formData.fpssmn"
mode="multiple"
placeholder="请选择过鱼月份"
allow-clear
:max-tag-count="4"
>
<a-select-option
v-for="item in fpssmnOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option
>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="监测频次(min)" name="dtfrqcy"> <a-form-item label="监测频次(min)" name="dtfrqcy">
<a-input-number v-model:value="formData.dtfrqcy" placeholder="请输入" :precision="0" style="width: 100%" /> <a-input-number
v-model:value="formData.dtfrqcy"
placeholder="请输入"
:precision="0"
style="width: 100%"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-form-item label="监测方式" name="mway"> <a-form-item label="监测方式" name="mway">
<a-select v-model:value="formData.mway" placeholder="请选择监测方式" allow-clear> <a-select
v-model:value="formData.mway"
placeholder="请选择监测方式"
allow-clear
>
<a-select-option :value="1">人工</a-select-option> <a-select-option :value="1">人工</a-select-option>
<a-select-option :value="2">自动</a-select-option> <a-select-option :value="2">自动</a-select-option>
</a-select> </a-select>
@ -136,7 +288,13 @@
</a-form> </a-form>
</a-modal> </a-modal>
<ConfirmModal v-model:open="confirmModalVisible" :diff-list="diffList" :confirm-loading="confirmLoading" @confirm="handleConfirmSubmit" @cancel="handleConfirmCancel" /> <ConfirmModal
v-model:open="confirmModalVisible"
:diff-list="diffList"
:confirm-loading="confirmLoading"
@confirm="handleConfirmSubmit"
@cancel="handleConfirmCancel"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -154,7 +312,10 @@ const props = defineProps<{ open: boolean; record?: any; isAdd?: boolean }>();
const emit = defineEmits(['update:open', 'success']); const emit = defineEmits(['update:open', 'success']);
const jidiSelectEventStore = useJidiSelectEventStore(); const jidiSelectEventStore = useJidiSelectEventStore();
const visible = computed({ get: () => props.open, set: val => emit('update:open', val) }); const visible = computed({
get: () => props.open,
set: val => emit('update:open', val)
});
useDraggable(visible, { boundary: true, resetOnOpen: true }); useDraggable(visible, { boundary: true, resetOnOpen: true });
const formRef = ref(); const formRef = ref();
@ -166,29 +327,53 @@ const confirmModalVisible = ref(false);
const formRules = ref<any>({ const formRules = ref<any>({
stcd: [{ required: true, message: '请输入设施编码', trigger: 'blur' }], stcd: [{ required: true, message: '请输入设施编码', trigger: 'blur' }],
stnm: [{ required: true, message: '请输入设施名称', trigger: 'blur' }] stnm: [{ required: true, message: '请输入设施名称', trigger: 'blur' }],
sttp: [{ required: true, message: '请输入设施名称', trigger: 'blur' }]
}); });
const engInfoOptions = ref<any[]>([]); const engInfoOptions = ref<any[]>([]);
const sttpOptions = ref<any[]>([]); const sttpOptions = ref<any[]>([]);
const baseNameOptions = computed(() => const baseNameOptions = computed(() =>
jidiSelectEventStore.jidiData.filter((item: any) => item.wbsCode !== 'all').map((item: any) => ({ label: item.wbsName, value: item.wbsCode })) jidiSelectEventStore.jidiData
.filter((item: any) => item.wbsCode !== 'all')
.map((item: any) => ({ label: item.wbsName, value: item.wbsCode }))
); );
const engLoading = ref(false); const engLoading = ref(false);
// 1-12 // 1-12
const fpssmnOptions = ref(Array.from({ length: 12 }, (_, i) => ({ label: `${i + 1}`, value: `${i + 1}` }))); const fpssmnOptions = ref(
Array.from({ length: 12 }, (_, i) => ({
label: `${i + 1}`,
value: `${i + 1}`
}))
);
const fieldLabelMap: Record<string, string> = { const fieldLabelMap: Record<string, string> = {
stcd: '设施编码', stnm: '设施名称', sttp: '设施类型', stlc: '站址/位置', stcd: '设施编码',
baseId: '水电基地', rstcd: '所属电站', lgtd: '经度(°)', lttd: '纬度(°)', stnm: '设施名称',
elev: '高程(m)', swdt: '开工日期', jcdt: '建成日期', bldsttCode: '建设状态', sttp: '设施类型',
inv: '投资(亿元)', symtlc: '上游码头位置', symtxs: '上游码头型式', stlc: '站址/位置',
xymtlc: '下游码头位置', xymtxs: '下游码头型式', jyfs: '集诱鱼方式', baseId: '水电基地',
yyfs: '运鱼设施方式', sjgycnt: '过鱼规模(尾)', fpssmn: '过鱼月份', rstcd: '所属电站',
dtfrqcy: '监测频次(min)', mway: '监测方式' lgtd: '经度(°)',
lttd: '纬度(°)',
elev: '高程(m)',
swdt: '开工日期',
jcdt: '建成日期',
bldsttCode: '建设状态',
inv: '投资(亿元)',
symtlc: '上游码头位置',
symtxs: '上游码头型式',
xymtlc: '下游码头位置',
xymtxs: '下游码头型式',
jyfs: '集诱鱼方式',
yyfs: '运鱼设施方式',
sjgycnt: '过鱼规模(尾)',
fpssmn: '过鱼月份',
dtfrqcy: '监测频次(min)',
mway: '监测方式'
}; };
const selectOptionsMap: Record<string, () => any[]> = { const selectOptionsMap: Record<string, () => any[]> = {
@ -207,7 +392,9 @@ const selectOptionsMap: Record<string, () => any[]> = {
fpssmn: () => fpssmnOptions.value fpssmn: () => fpssmnOptions.value
}; };
const changeOrder = ref<{ field: string; label: string; oldValue: string; newValue: string }[]>([]); const changeOrder = ref<
{ field: string; label: string; oldValue: string; newValue: string }[]
>([]);
const diffList = changeOrder; const diffList = changeOrder;
const resolveSelectLabel = (field: string, value: any): string => { const resolveSelectLabel = (field: string, value: any): string => {
@ -215,16 +402,21 @@ const resolveSelectLabel = (field: string, value: any): string => {
// fpssmn label // fpssmn label
if (field === 'fpssmn') { if (field === 'fpssmn') {
const arr = Array.isArray(value) ? value : String(value).split(','); const arr = Array.isArray(value) ? value : String(value).split(',');
return arr.map((v: any) => { return arr
.map((v: any) => {
const trimmed = String(v).trim(); const trimmed = String(v).trim();
if (!trimmed) return ''; if (!trimmed) return '';
const opt = fpssmnOptions.value.find((o) => String(o.value) === trimmed); const opt = fpssmnOptions.value.find(o => String(o.value) === trimmed);
return opt ? opt.label : trimmed; return opt ? opt.label : trimmed;
}).filter(Boolean).join('、'); })
.filter(Boolean)
.join('、');
} }
const getOptions = selectOptionsMap[field]; const getOptions = selectOptionsMap[field];
if (getOptions) { if (getOptions) {
const opt = getOptions().find((o: any) => String(o.value) === String(value)); const opt = getOptions().find(
(o: any) => String(o.value) === String(value)
);
if (opt) return opt.label; if (opt) return opt.label;
} }
return String(value); return String(value);
@ -257,7 +449,9 @@ const disabledJcdtDate = (current: any) => {
return current && current < dayjs(formData.value.swdt).startOf('day'); return current && current < dayjs(formData.value.swdt).startOf('day');
}; };
watch(() => formData.value, newData => { watch(
() => formData.value,
newData => {
const original = originalRecord.value; const original = originalRecord.value;
for (const key in newData) { for (const key in newData) {
const oldVal = original[key]; const oldVal = original[key];
@ -268,30 +462,61 @@ watch(() => formData.value, newData => {
const normalize = (v: any) => { const normalize = (v: any) => {
if (!v) return ''; if (!v) return '';
const arr = Array.isArray(v) ? v : String(v).split(','); const arr = Array.isArray(v) ? v : String(v).split(',');
return arr.map((s: string) => s.trim()).filter(Boolean).sort().join(','); return arr
.map((s: string) => s.trim())
.filter(Boolean)
.sort()
.join(',');
}; };
if (normalize(oldVal) === normalize(newVal)) continue; if (normalize(oldVal) === normalize(newVal)) continue;
} }
const existingIdx = changeOrder.value.findIndex(c => c.field === key); const existingIdx = changeOrder.value.findIndex(c => c.field === key);
const oldNorm = oldVal === null || oldVal === undefined || oldVal === '-' ? null : oldVal; const oldNorm =
oldVal === null || oldVal === undefined || oldVal === '-'
? null
: oldVal;
const newNorm = newVal === null || newVal === undefined ? null : newVal; const newNorm = newVal === null || newVal === undefined ? null : newVal;
if (oldNorm === newNorm) continue; if (oldNorm === newNorm) continue;
if (oldNorm !== null && newNorm !== null && !isNaN(Number(oldNorm)) && !isNaN(Number(newNorm)) && Number(oldNorm) === Number(newNorm)) continue; if (
oldNorm !== null &&
newNorm !== null &&
!isNaN(Number(oldNorm)) &&
!isNaN(Number(newNorm)) &&
Number(oldNorm) === Number(newNorm)
)
continue;
const isSelect = !!selectOptionsMap[key]; const isSelect = !!selectOptionsMap[key];
const oldDisplay = isSelect ? (originalLabels.value[key] ?? resolveSelectLabel(key, oldNorm)) : oldNorm === null ? '空' : String(oldNorm); const oldDisplay = isSelect
const newDisplay = isSelect ? resolveSelectLabel(key, newNorm) : newNorm === null ? '空' : String(newNorm); ? originalLabels.value[key] ?? resolveSelectLabel(key, oldNorm)
const entry = { field: key, label: fieldLabelMap[key] || key, oldValue: oldDisplay, newValue: newDisplay }; : oldNorm === null
? '空'
: String(oldNorm);
const newDisplay = isSelect
? resolveSelectLabel(key, newNorm)
: newNorm === null
? '空'
: String(newNorm);
const entry = {
field: key,
label: fieldLabelMap[key] || key,
oldValue: oldDisplay,
newValue: newDisplay
};
if (existingIdx >= 0) changeOrder.value[existingIdx] = entry; if (existingIdx >= 0) changeOrder.value[existingIdx] = entry;
else changeOrder.value.push(entry); else changeOrder.value.push(entry);
} else { } else {
changeOrder.value = changeOrder.value.filter(c => c.field !== key); changeOrder.value = changeOrder.value.filter(c => c.field !== key);
} }
} }
}, { deep: true }); },
{ deep: true }
);
// record // record
const isInitLoading = ref(false); const isInitLoading = ref(false);
watch(() => props.record, newRecord => { watch(
() => props.record,
newRecord => {
if (newRecord) { if (newRecord) {
isInitLoading.value = true; isInitLoading.value = true;
const converted = { ...newRecord }; const converted = { ...newRecord };
@ -303,8 +528,16 @@ watch(() => props.record, newRecord => {
} }
originalRecord.value = { ...converted }; originalRecord.value = { ...converted };
// fpssmn // fpssmn
const fpssmnArr = converted.fpssmn ? String(converted.fpssmn).split(',').map((s: string) => s.trim()).filter(Boolean) : []; const fpssmnArr = converted.fpssmn
formData.value = { ...converted, fpssmn: fpssmnArr.length > 0 ? fpssmnArr : undefined }; ? String(converted.fpssmn)
.split(',')
.map((s: string) => s.trim())
.filter(Boolean)
: [];
formData.value = {
...converted,
fpssmn: fpssmnArr.length > 0 ? fpssmnArr : undefined
};
changeOrder.value = []; changeOrder.value = [];
// rstcd diff // rstcd diff
loadEngOptions(converted.baseId || undefined); loadEngOptions(converted.baseId || undefined);
@ -321,12 +554,12 @@ watch(() => props.record, newRecord => {
isInitLoading.value = false; isInitLoading.value = false;
}); });
} }
}, { deep: true }); },
{ deep: true }
);
// record code // record code
watch( watch([baseNameOptions, engInfoOptions, sttpOptions], () => {
[baseNameOptions, engInfoOptions, sttpOptions],
() => {
const original = originalRecord.value; const original = originalRecord.value;
if (!original || Object.keys(original).length === 0) return; if (!original || Object.keys(original).length === 0) return;
const labels: Record<string, string> = {}; const labels: Record<string, string> = {};
@ -336,15 +569,17 @@ watch(
} }
} }
originalLabels.value = labels; originalLabels.value = labels;
} });
);
const loadEngOptions = async (baseId?: string) => { const loadEngOptions = async (baseId?: string) => {
engLoading.value = true; engLoading.value = true;
try { try {
const params = baseId ? { baseId } : {}; const params = baseId ? { baseId } : {};
const res = await getEngInfoDropdown(params); const res = await getEngInfoDropdown(params);
engInfoOptions.value = (res.data || []).map((item: any) => ({ label: item.ennm, value: item.stcd })); engInfoOptions.value = (res.data || []).map((item: any) => ({
label: item.ennm,
value: item.stcd
}));
} catch (error) { } catch (error) {
console.error('获取电站列表失败:', error); console.error('获取电站列表失败:', error);
} finally { } finally {
@ -354,24 +589,42 @@ const loadEngOptions = async (baseId?: string) => {
const loadDropdownData = () => { const loadDropdownData = () => {
sttpGetKendoList({ sttpGetKendoList({
filter: { logic: 'and', filters: [{ field: 'sttpCode', operator: 'in', dataType: 'string', value: ['FP', 'FP_1', 'FP_2', 'FP_3', 'FP_4', 'FP_5'] }] } filter: {
logic: 'and',
filters: [
{
field: 'sttpCode',
operator: 'in',
dataType: 'string',
value: ['FP', 'FP_1', 'FP_2', 'FP_3', 'FP_4', 'FP_5']
}
]
}
}).then(res => { }).then(res => {
sttpOptions.value = (res.data?.data || []).map((item: any) => ({ label: item.sttpName, value: item.sttpCode })); sttpOptions.value = (res.data?.data || []).map((item: any) => ({
label: item.sttpName,
value: item.sttpCode
}));
}); });
// store computed // store computed
}; };
// //
watch(() => formData.value?.baseId, (newBaseId) => { watch(
() => formData.value?.baseId,
newBaseId => {
// record record watch // record record watch
if (isInitLoading.value) { if (isInitLoading.value) {
return; return;
} }
formData.value.rstcd = undefined; formData.value.rstcd = undefined;
loadEngOptions(newBaseId || undefined); loadEngOptions(newBaseId || undefined);
}); }
);
watch(() => props.open, val => { watch(
() => props.open,
val => {
if (val) { if (val) {
if (props.isAdd) { if (props.isAdd) {
formData.value = { fpssmn: [] }; formData.value = { fpssmn: [] };
@ -381,14 +634,20 @@ watch(() => props.open, val => {
} }
loadDropdownData(); loadDropdownData();
} }
}); }
);
const handleOk = async () => { const handleOk = async () => {
try { try {
await formRef.value?.validateFields(); await formRef.value?.validateFields();
if (!props.isAdd && changeOrder.value.length === 0) { message.info('未检测到任何修改'); return; } if (!props.isAdd && changeOrder.value.length === 0) {
message.info('未检测到任何修改');
return;
}
confirmModalVisible.value = true; confirmModalVisible.value = true;
} catch (error) { console.error('验证失败:', error); } } catch (error) {
console.error('验证失败:', error);
}
}; };
const handleConfirmSubmit = async (source: string) => { const handleConfirmSubmit = async (source: string) => {
@ -399,7 +658,8 @@ const handleConfirmSubmit = async (source: string) => {
if (props.isAdd) { if (props.isAdd) {
Object.assign(engInfo, formData.value); Object.assign(engInfo, formData.value);
// fpssmn // fpssmn
if (Array.isArray(engInfo.fpssmn)) engInfo.fpssmn = engInfo.fpssmn.join(','); if (Array.isArray(engInfo.fpssmn))
engInfo.fpssmn = engInfo.fpssmn.join(',');
res = await addFpInfo({ engInfo, source: source.trim() || '新增' }); res = await addFpInfo({ engInfo, source: source.trim() || '新增' });
} else { } else {
engInfo.stcd = formData.value.stcd; engInfo.stcd = formData.value.stcd;
@ -412,7 +672,8 @@ const handleConfirmSubmit = async (source: string) => {
engInfo[item.field] = val; engInfo[item.field] = val;
}); });
// fpssmn // fpssmn
if (Array.isArray(engInfo.fpssmn)) engInfo.fpssmn = engInfo.fpssmn.join(','); if (Array.isArray(engInfo.fpssmn))
engInfo.fpssmn = engInfo.fpssmn.join(',');
res = await updateFpInfo({ engInfo, source: source.trim() || '编辑' }); res = await updateFpInfo({ engInfo, source: source.trim() || '编辑' });
} }
if (res?.code == 0 || res?.success) { if (res?.code == 0 || res?.success) {
@ -420,11 +681,22 @@ const handleConfirmSubmit = async (source: string) => {
confirmModalVisible.value = false; confirmModalVisible.value = false;
visible.value = false; visible.value = false;
emit('success'); emit('success');
} else { message.error(res?.msg || (props.isAdd ? '新增失败' : '编辑失败')); } } else {
} catch (error) { message.error('提交失败,请重试'); } message.error(res?.msg || (props.isAdd ? '新增失败' : '编辑失败'));
finally { confirmLoading.value = false; } }
} catch (error) {
message.error('提交失败,请重试');
} finally {
confirmLoading.value = false;
}
}; };
const handleConfirmCancel = () => { confirmModalVisible.value = false; }; const handleConfirmCancel = () => {
const handleCancel = () => { visible.value = false; confirmModalVisible.value = false; formRef.value?.resetFields(); }; confirmModalVisible.value = false;
};
const handleCancel = () => {
visible.value = false;
confirmModalVisible.value = false;
formRef.value?.resetFields();
};
</script> </script>

View File

@ -120,17 +120,6 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:maxlength="1000"
show-count
:rows="3"
/>
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }"> <a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea <a-textarea
@ -213,7 +202,6 @@ const fieldLabelMap: Record<string, string> = {
baseId: '水电基地', baseId: '水电基地',
rstcd: '所属电站', rstcd: '所属电站',
jcdt: '建成日期', jcdt: '建成日期',
introduce: '简介',
remark: '备注', remark: '备注',
lgtd: '经度(°)', lgtd: '经度(°)',
lttd: '纬度(°)' lttd: '纬度(°)'

View File

@ -120,6 +120,7 @@
placeholder="请选择保护对象" placeholder="请选择保护对象"
allow-clear allow-clear
show-search show-search
:max-tag-count="2"
:filter-option="filterOption" :filter-option="filterOption"
> >
<a-select-option <a-select-option

View File

@ -67,10 +67,10 @@ const columns = ref<any[]>([
{ key: 'stcd', title: '栖息地站码', dataIndex: 'stcd', visible: true, width: 320, ellipsis: true }, { key: 'stcd', title: '栖息地站码', dataIndex: 'stcd', visible: true, width: 320, ellipsis: true },
{ key: 'baseName', title: '水电基地', dataIndex: 'baseName', visible: true, width: 120, ellipsis: true }, { key: 'baseName', title: '水电基地', dataIndex: 'baseName', visible: true, width: 120, ellipsis: true },
{ key: 'ennm', title: '所属电站', dataIndex: 'ennm', visible: true, width: 150, ellipsis: true }, { key: 'ennm', title: '所属电站', dataIndex: 'ennm', visible: true, width: 150, ellipsis: true },
{ key: 'bhdxName', title: '保护对象', dataIndex: 'bhdxName', visible: true, width: 240, ellipsis: true }, { key: 'bhdx', title: '保护对象', dataIndex: 'bhdx', visible: true, width: 240, ellipsis: true },
{ key: 'bhhl', title: '保护河流', dataIndex: 'bhhl', visible: true, width: 120, ellipsis: true }, { key: 'bhhl', title: '保护河流', dataIndex: 'bhhl', visible: true, width: 140, ellipsis: true },
{ key: 'bhhd', title: '保护河段', dataIndex: 'bhhd', visible: true, width: 240, ellipsis: true }, { key: 'bhhd', title: '保护河段', dataIndex: 'bhhd', visible: true, width: 240, ellipsis: true },
{ key: 'bhfw', title: '保护范围', dataIndex: 'bhfw', visible: true, width: 120, ellipsis: true }, { key: 'bhfw', title: '保护范围', dataIndex: 'bhfw', visible: true, width: 240, ellipsis: true },
{ key: 'bhhxcd', title: '保护核心长度(km)', dataIndex: 'bhhxcd', visible: true, width: 140 }, { key: 'bhhxcd', title: '保护核心长度(km)', dataIndex: 'bhhxcd', visible: true, width: 140 },
{ key: 'bhcs', title: '保护措施', dataIndex: 'bhcs', visible: true, width: 120, ellipsis: true }, { key: 'bhcs', title: '保护措施', dataIndex: 'bhcs', visible: true, width: 120, ellipsis: true },

View File

@ -130,14 +130,11 @@
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<a-form-item label="保护原因" name="bhyy"> <a-form-item label="保护原因" name="bhyy">
<a-select <a-input
v-model:value="formData.bhyy" v-model:value="formData.bhyy"
placeholder="请选择保护原因" placeholder="请输入保护原因"
allow-clear style="width: 100%"
> />
<a-select-option :value="1"></a-select-option>
<a-select-option :value="0"></a-select-option>
</a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
@ -183,17 +180,6 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:maxlength="1000"
show-count
:rows="2"
/>
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }"> <a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea <a-textarea
@ -295,10 +281,6 @@ const selectOptionsMap: Record<string, () => any[]> = {
{ label: '启用', value: 1 }, { label: '启用', value: 1 },
{ label: '禁用', value: 0 } { label: '禁用', value: 0 }
], ],
bhyy: () => [
{ label: '是', value: 1 },
{ label: '否', value: 0 }
],
baseId: () => baseNameOptions.value, baseId: () => baseNameOptions.value,
rstcd: () => engInfoOptions.value rstcd: () => engInfoOptions.value
}; };

View File

@ -120,17 +120,6 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:maxlength="1000"
show-count
:rows="3"
/>
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }"> <a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea <a-textarea
@ -216,7 +205,6 @@ const fieldLabelMap: Record<string, string> = {
baseId: '水电基地', baseId: '水电基地',
rstcd: '所属电站', rstcd: '所属电站',
jcdt: '建成日期', jcdt: '建成日期',
introduce: '简介',
remark: '备注', remark: '备注',
lgtd: '经度(°)', lgtd: '经度(°)',
lttd: '纬度(°)' lttd: '纬度(°)'

View File

@ -171,17 +171,6 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:maxlength="1000"
show-count
:rows="2"
/>
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }"> <a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea <a-textarea
@ -275,7 +264,6 @@ const fieldLabelMap: Record<string, string> = {
dtfrqcy: '监测频次', dtfrqcy: '监测频次',
fwdx: '服务对象', fwdx: '服务对象',
gcfs: '观察方式', gcfs: '观察方式',
introduce: '简介',
remark: '备注' remark: '备注'
}; };

View File

@ -182,17 +182,6 @@
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:maxlength="1000"
show-count
:rows="2"
/>
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }"> <a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea <a-textarea
@ -283,7 +272,6 @@ const fieldLabelMap: Record<string, string> = {
dtfrqcy: '监测频次', dtfrqcy: '监测频次',
jbtxcs: '基本特性参数', jbtxcs: '基本特性参数',
blprd: '所属建设阶段', blprd: '所属建设阶段',
introduce: '简介',
remark: '备注' remark: '备注'
}; };

View File

@ -49,7 +49,7 @@
@success="handleEditSuccess" @success="handleEditSuccess"
/> />
<OperationLogModal v-model:open="operationLogVisible" :table-name="'SD_OTWE_B_H'" :record-name-title="'工程名称'" /> <OperationLogModal v-model:open="operationLogVisible" :table-name="'SD_OTTE_B_H'" :record-name-title="'工程名称'" />
</div> </div>
</template> </template>

View File

@ -40,13 +40,13 @@ const deleteModalRef = ref();
const operationLogVisible = ref(false); const operationLogVisible = ref(false);
const columns = ref<any[]>([ const columns = ref<any[]>([
{ key: 'stnm', title: '增殖站名称', dataIndex: 'stnm', visible: true, width: 160,fixed: 'left', ellipsis: true }, { key: 'stnm', title: '增殖站名称', dataIndex: 'stnm', visible: true, width: 240,fixed: 'left', ellipsis: true },
{ key: 'stcd', title: '增殖站编码', dataIndex: 'stcd', visible: true, width: 180, ellipsis: true }, { key: 'stcd', title: '增殖站编码', dataIndex: 'stcd', visible: true, width: 180, ellipsis: true },
{ key: 'baseName', title: '水电基地', dataIndex: 'baseName', visible: true, width: 120, ellipsis: true }, { key: 'baseName', title: '水电基地', dataIndex: 'baseName', visible: true, width: 120, ellipsis: true },
{ key: 'ennm', title: '所属电站', dataIndex: 'ennm', visible: true, width: 100, ellipsis: true }, { key: 'ennm', title: '所属电站', dataIndex: 'ennm', visible: true, width: 100, ellipsis: true },
{ key: 'zzfldx', title: '放流对象', dataIndex: 'zzfldx', visible: true, width: 120, ellipsis: true }, { key: 'zzfldx', title: '放流对象', dataIndex: 'zzfldx', visible: true, width: 260, ellipsis: true },
{ key: 'zzflcnt', title: '放流规模(尾)', dataIndex: 'zzflcnt', visible: true, width: 120 }, { key: 'zzflcnt', title: '放流规模(尾)', dataIndex: 'zzflcnt', visible: true, width: 120 },
{ key: 'zzflbjfs', title: '标记方式', dataIndex: 'zzflbjfs', visible: true, width: 100, ellipsis: true }, { key: 'zzflbjfs', title: '标记方式', dataIndex: 'zzflbjfs', visible: true, width: 100, ellipsis: true },
@ -56,7 +56,7 @@ const columns = ref<any[]>([
{ key: 'zzflfllc', title: '放流地点', dataIndex: 'zzflfllc', visible: true, width: 260, ellipsis: true }, { key: 'zzflfllc', title: '放流地点', dataIndex: 'zzflfllc', visible: true, width: 260, ellipsis: true },
{ key: 'zzflyzms', title: '养殖模式', dataIndex: 'zzflyzms', visible: true, width: 220, ellipsis: true }, { key: 'zzflyzms', title: '养殖模式', dataIndex: 'zzflyzms', visible: true, width: 220, ellipsis: true },
{ key: 'zzflgy', title: '生产工艺', dataIndex: 'zzflgy', visible: true, width: 180, ellipsis: true }, { key: 'zzflgy', title: '生产工艺', dataIndex: 'zzflgy', visible: true, width: 240, ellipsis: true },
{ key: 'swdt', title: '开工日期', dataIndex: 'swdt', visible: true, width: 110, customRender: ({ text }) => { if (!text || text === '-') return '-'; const date = dayjs(text); return date.isValid() ? date.format('YYYY-MM-DD') : '-'; } }, { key: 'swdt', title: '开工日期', dataIndex: 'swdt', visible: true, width: 110, customRender: ({ text }) => { if (!text || text === '-') return '-'; const date = dayjs(text); return date.isValid() ? date.format('YYYY-MM-DD') : '-'; } },
{ key: 'jcdt', title: '建成日期', dataIndex: 'jcdt', visible: true, width: 110, customRender: ({ text }) => { if (!text || text === '-') return '-'; const date = dayjs(text); return date.isValid() ? date.format('YYYY-MM-DD') : '-'; } }, { key: 'jcdt', title: '建成日期', dataIndex: 'jcdt', visible: true, width: 110, customRender: ({ text }) => { if (!text || text === '-') return '-'; const date = dayjs(text); return date.isValid() ? date.format('YYYY-MM-DD') : '-'; } },
{ key: 'zzfltm', title: '放流时间', dataIndex: 'zzfltm', visible: true, width: 110, customRender: ({ text }) => { if (!text || text === '-') return '-'; const date = dayjs(text); return date.isValid() ? date.format('YYYY-MM-DD') : '-'; } }, { key: 'zzfltm', title: '放流时间', dataIndex: 'zzfltm', visible: true, width: 110, customRender: ({ text }) => { if (!text || text === '-') return '-'; const date = dayjs(text); return date.isValid() ? date.format('YYYY-MM-DD') : '-'; } },

View File

@ -2,7 +2,8 @@
<div <div
id="map-baselayer" id="map-baselayer"
class="baselayer-switcher" class="baselayer-switcher"
:style="{ right: drawerOpen ? '480px' : '26px' }" :class="{ 'is-dzzt': hasDzztBottom }"
:style="positionStyle"
v-if="uiStore.mapType == '2D'" v-if="uiStore.mapType == '2D'"
> >
<div <div
@ -22,6 +23,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useUiStore } from '@/store/modules/ui'; import { useUiStore } from '@/store/modules/ui';
import { useMapConfigStore } from '@/modules/map/stores/map-config.store'; import { useMapConfigStore } from '@/modules/map/stores/map-config.store';
import { useMapViewStore } from '@/modules/map/stores/map-view.store'; import { useMapViewStore } from '@/modules/map/stores/map-view.store';
@ -39,12 +41,32 @@ const props = defineProps({
} }
}); });
const uiStore = useUiStore(); const uiStore = useUiStore();
const route = useRoute();
const mapConfigStore = useMapConfigStore(); const mapConfigStore = useMapConfigStore();
const mapViewStore = useMapViewStore(); const mapViewStore = useMapViewStore();
// //
const drawerOpen = computed( const drawerOpen = computed(
() => uiStore.drawerOpen || uiStore.globalDrawerOpen () => uiStore.drawerOpen || uiStore.globalDrawerOpen
); );
// /
const isDzzt = computed(() =>
route.path.includes('dianZhanZhuanTi/dianZhanZhuanTi')
);
const hasDzztBottom = computed(
() => isDzzt.value && !!uiStore.mapControlsPosition.baselayerBottom
);
const positionStyle = computed(() => {
const bottom = uiStore.mapControlsPosition.baselayerBottom;
if (hasDzztBottom.value && bottom) {
return {
right:
uiStore.mapControlsPosition.baselayerRight ??
(drawerOpen.value ? '480px' : '26px'),
bottom
};
}
return { right: drawerOpen.value ? '480px' : '26px' };
});
const layers = [ const layers = [
{ key: 's_province_boundaries', name: '矢量', img: shiliangImg }, { key: 's_province_boundaries', name: '矢量', img: shiliangImg },
{ key: 'BASEMAP-white', name: '地形', img: dixingImg }, { key: 'BASEMAP-white', name: '地形', img: dixingImg },
@ -167,5 +189,11 @@ const handleSwitch = (key: string) => {
width: 100px !important; width: 100px !important;
} }
} }
// 沿
&.is-dzzt .nineSectionsImg {
left: 50%;
right: auto;
transform: translateX(-50%);
}
} }
</style> </style>

View File

@ -286,6 +286,7 @@ import EcologicalFlow from './components/EcologicalFlow.vue'; // 生态流量
import Attachment from './components/Attachment.vue'; // / import Attachment from './components/Attachment.vue'; // /
import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; // import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; //
import { useModelStore } from '@/store/modules/model'; import { useModelStore } from '@/store/modules/model';
import { useUiStore } from '@/store/modules/ui';
import { handleTabs } from './setting.config'; import { handleTabs } from './setting.config';
import { import {
getMonitorDataWt, getMonitorDataWt,
@ -304,6 +305,7 @@ import { useDraggable } from '@/utils/drag';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
const modelStore = useModelStore(); const modelStore = useModelStore();
const uiStore = useUiStore();
const tabsConfig = ref([]); const tabsConfig = ref([]);
// tabs // tabs
const isLoading = ref(true); const isLoading = ref(true);
@ -362,6 +364,9 @@ const checkPowerStationTopicData = async (stcd: string) => {
const gotoEngTopic = () => { const gotoEngTopic = () => {
const stcd = modelStore.params?.stcd; const stcd = modelStore.params?.stcd;
if (!stcd) return; if (!stcd) return;
//
uiStore.setIsSearchActive(false);
uiStore.setGlobalDrawerOpen(false);
router.push({ router.push({
path: '/dianZhanZhuanTi/dianZhanZhuanTi', path: '/dianZhanZhuanTi/dianZhanZhuanTi',
query: { stcd } query: { stcd }

View File

@ -11,6 +11,7 @@ import {
offset5 offset5
} from '@/utils/GisUrlList'; } from '@/utils/GisUrlList';
import { LAYOUT_GRID_SKELETONS } from '@/views/dianZhanZhuanTi/layoutGridSkeletons'; import { LAYOUT_GRID_SKELETONS } from '@/views/dianZhanZhuanTi/layoutGridSkeletons';
import { useUiStore } from '@/store/modules/ui';
declare global { declare global {
interface Window { interface Window {
__lyConfigs?: { __lyConfigs?: {
@ -340,9 +341,7 @@ export const setMapLegendPos = (
const legend = document.querySelector('#qgc-legendtl') as HTMLElement; const legend = document.querySelector('#qgc-legendtl') as HTMLElement;
const filter = document.querySelector('#map-filter-container') as HTMLElement; const filter = document.querySelector('#map-filter-container') as HTMLElement;
const compassControl = document.querySelector('#map-compassControl') as HTMLElement; const compassControl = document.querySelector('#map-compassControl') as HTMLElement;
const controller = document.querySelector('#map-controller') as HTMLElement;
const monitor = document.querySelector('#map-monitor') as HTMLElement; const monitor = document.querySelector('#map-monitor') as HTMLElement;
const baselayer = document.querySelector('#map-baselayer') as HTMLElement;
const leftList = getListByPosition(data, 'left'); const leftList = getListByPosition(data, 'left');
const rightList = getListByPosition(data, 'right'); const rightList = getListByPosition(data, 'right');
@ -386,16 +385,29 @@ export const setMapLegendPos = (
if (compassControl) { if (compassControl) {
compassControl.style.left = hasLeft ? l : b; compassControl.style.left = hasLeft ? l : b;
} }
if (controller) {
controller.style.right = hasRight ? w : '0';
controller.style.bottom = hasBottom ? `calc(${bottomOffset} + 10px)` : '0';
}
if (monitor) { if (monitor) {
monitor.style.right = hasRight ? w : '0'; monitor.style.right = hasRight ? w : '0';
} }
if (baselayer) {
baselayer.style.right = hasRight ? `calc(${w} + 60px)` : '60px'; // 地图控制器/底图切换器:通过 store 发布位置覆盖,组件内联样式优先读取,
baselayer.style.bottom = hasBottom ? bottomOffset : '0'; // 避免 JS 直写 el.style 与组件自身 :style 绑定互相覆盖(刷新后重叠问题)。
const uiStore = useUiStore();
if (hasBottom) {
// 有底部模块有右模块时整体左移避让两者同底bottomOffset
uiStore.setMapControlsPosition({
controllerRight: hasRight ? w : null,
controllerBottom: bottomOffset,
baselayerRight: hasRight ? `calc(${w} + 60px)` : null,
baselayerBottom: bottomOffset
});
} else {
// 无底部模块:完全回退组件自身默认样式(与非电站专题页面一致)
uiStore.setMapControlsPosition({
controllerRight: null,
controllerBottom: null,
baselayerRight: null,
baselayerBottom: null
});
} }
}; };

View File

@ -2,7 +2,7 @@
<div <div
id="map-controller" id="map-controller"
class="map-controller" class="map-controller"
:style="{ right: drawerOpen ? '480px' : '26px' }" :style="positionStyle"
> >
<div <div
class="map-controller-group" class="map-controller-group"
@ -60,6 +60,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, toRef, computed, onUnmounted } from 'vue'; import { ref, watch, toRef, computed, onUnmounted } from 'vue';
import { useRoute } from 'vue-router';
import { useUiStore } from '@/store/modules/ui'; import { useUiStore } from '@/store/modules/ui';
import Calculate from './Calculate.vue'; import Calculate from './Calculate.vue';
import LayerController from './LayerController.vue'; import LayerController from './LayerController.vue';
@ -74,10 +75,27 @@ const map = toRef(props, 'map');
// 使 Pinia store // 使 Pinia store
const uiStore = useUiStore(); const uiStore = useUiStore();
const route = useRoute();
// //
const drawerOpen = computed( const drawerOpen = computed(
() => uiStore.drawerOpen || uiStore.globalDrawerOpen () => uiStore.drawerOpen || uiStore.globalDrawerOpen
); );
// /
const isDzzt = computed(() =>
route.path.includes('dianZhanZhuanTi/dianZhanZhuanTi')
);
const positionStyle = computed(() => {
const bottom = uiStore.mapControlsPosition.controllerBottom;
if (isDzzt.value && bottom) {
return {
right:
uiStore.mapControlsPosition.controllerRight ??
(drawerOpen.value ? '480px' : '26px'),
bottom
};
}
return { right: drawerOpen.value ? '480px' : '26px' };
});
const tjVisible = ref(false); const tjVisible = ref(false);
watch( watch(

View File

@ -730,6 +730,8 @@ const handleAnchorPointChange = (value: string) => {
uiStore.setIsSearchActive(true); uiStore.setIsSearchActive(true);
uiStore.setDrawerOpen(false); uiStore.setDrawerOpen(false);
setTimeout(() => { setTimeout(() => {
// 300ms
if (route.path.includes('dianZhanZhuanTi/dianZhanZhuanTi')) return;
uiStore.setGlobalDrawerOpen(true); uiStore.setGlobalDrawerOpen(true);
}, 300); }, 300);
}; };

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onBeforeMount, onMounted } from 'vue'; import { ref, watch, onBeforeMount, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useMapStore } from '@/store/modules/map'; import { useMapStore } from '@/store/modules/map';
@ -23,6 +23,21 @@ const buildPageKeyFromPath = (path?: string) => {
return normalizedPath || '__route-change__'; return normalizedPath || '__route-change__';
}; };
// / path opturl
const syncActiveFromRoute = () => {
permissionStore.routes.forEach((item: any) => {
if (item.meta?.hidden) return;
const matched = (item.children || []).find(
(child: any) => child.path === route.path || child.opturl === route.path
);
if (matched) {
activeKey.value = item.id;
subMenus.value = item.children;
subActiveKey.value = matched.id;
}
});
};
// //
const handleTabChange = (key: string) => { const handleTabChange = (key: string) => {
let data = menus.value.find((item: any) => item.id === key); let data = menus.value.find((item: any) => item.id === key);
@ -61,18 +76,19 @@ onBeforeMount(() => {
} else { } else {
menus.value.push(item); menus.value.push(item);
} }
if (item.children) {
item.children.map((child: any) => {
if (child.path === route.path) {
activeKey.value = item.id;
subMenus.value = item.children;
subActiveKey.value = child.id;
}
});
}
} }
}); });
syncActiveFromRoute();
}); });
//
watch(
() => route.path,
() => {
syncActiveFromRoute();
}
);
onMounted(() => {}); onMounted(() => {});
</script> </script>

View File

@ -192,7 +192,7 @@ const scopeDateConfig = computed(() => ({
value: [dateRange.value[0], dateRange.value[1]] as any, value: [dateRange.value[0], dateRange.value[1]] as any,
picker: (mway.value === '1' ? 'year' : 'date') as const, picker: (mway.value === '1' ? 'year' : 'date') as const,
format: mway.value === '1' ? 'YYYY' : 'YYYY-MM-DD', format: mway.value === '1' ? 'YYYY' : 'YYYY-MM-DD',
width: mway.value === '1' ? '170px' : '215px' width: mway.value === '1' ? '170px' : '220px'
})); }));
// ==================== ==================== // ==================== ====================

View File

@ -2,6 +2,7 @@ import router from '@/router';
import { RouteRecordRaw } from 'vue-router'; import { RouteRecordRaw } from 'vue-router';
import { useUserStoreHook } from '@/store/modules/user'; import { useUserStoreHook } from '@/store/modules/user';
import { usePermissionStoreHook } from '@/store/modules/permission'; import { usePermissionStoreHook } from '@/store/modules/permission';
import { useUiStore } from '@/store/modules/ui';
import NProgress from 'nprogress'; import NProgress from 'nprogress';
import 'nprogress/nprogress.css'; import 'nprogress/nprogress.css';
NProgress.configure({ showSpinner: false }); NProgress.configure({ showSpinner: false });
@ -130,6 +131,10 @@ router.beforeEach(async (to, from, next) => {
} }
}); });
router.afterEach(() => { router.afterEach(to => {
NProgress.done(); NProgress.done();
// 进入非电站专题页时清除地图控件位置覆盖(防止专题页的 store 覆盖值泄漏到其他页面)
if (!to.path.includes('dianZhanZhuanTi')) {
useUiStore().resetMapControlsPosition();
}
}); });

View File

@ -18,6 +18,18 @@ export const useUiStore = defineStore('ui', () => {
const globalDrawerOpen = ref(false); const globalDrawerOpen = ref(false);
// 是否处于锚点搜索状态(选中命中 DRAWER_STTP_CODES 的锚点时 true清空/切页等 false // 是否处于锚点搜索状态(选中命中 DRAWER_STTP_CODES 的锚点时 true清空/切页等 false
const isSearchActive = ref(false); const isSearchActive = ref(false);
// 地图控件(地图控制器/底图切换器位置覆盖值null 表示回退组件自身默认(非电站专题页样式)
const mapControlsPosition = ref<{
controllerRight: string | null;
controllerBottom: string | null;
baselayerRight: string | null;
baselayerBottom: string | null;
}>({
controllerRight: null,
controllerBottom: null,
baselayerRight: null,
baselayerBottom: null
});
// 切换抽屉状态 // 切换抽屉状态
const toggleDrawer = () => { const toggleDrawer = () => {
@ -39,6 +51,26 @@ export const useUiStore = defineStore('ui', () => {
const setIsSearchActive = (active: boolean) => { const setIsSearchActive = (active: boolean) => {
isSearchActive.value = active; isSearchActive.value = active;
}; };
// 部分更新地图控件位置覆盖
const setMapControlsPosition = (
partial: Partial<{
controllerRight: string | null;
controllerBottom: string | null;
baselayerRight: string | null;
baselayerBottom: string | null;
}>
) => {
mapControlsPosition.value = { ...mapControlsPosition.value, ...partial };
};
// 重置地图控件位置覆盖(恢复组件自身默认样式,即非电站专题页样式)
const resetMapControlsPosition = () => {
mapControlsPosition.value = {
controllerRight: null,
controllerBottom: null,
baselayerRight: null,
baselayerBottom: null
};
};
const markMapSwitchCompleted = () => { const markMapSwitchCompleted = () => {
mapSwitchCompletedTick.value += 1; mapSwitchCompletedTick.value += 1;
@ -57,6 +89,9 @@ export const useUiStore = defineStore('ui', () => {
setGlobalDrawerOpen, setGlobalDrawerOpen,
isSearchActive, isSearchActive,
setIsSearchActive, setIsSearchActive,
mapControlsPosition,
setMapControlsPosition,
resetMapControlsPosition,
mapType, mapType,
mapSwitchCompletedTick, mapSwitchCompletedTick,
markMapSwitchCompleted markMapSwitchCompleted

View File

@ -1,115 +0,0 @@
<template>
<!-- 第一步输入修改依据 -->
<a-modal
v-model:open="dataSourceVisible"
:title="title"
ok-text="确定"
cancel-text="取消"
@ok="handleDataSourceConfirm"
>
<div>
<p style="color: red; margin-bottom: 8px">请输入修改依据以继续删除操作</p>
<a-textarea
v-model:value="dataSource"
placeholder="请输入修改依据"
:rows="4"
/>
</div>
</a-modal>
<!-- 第二步确认删除 -->
<a-modal
v-model:open="confirmVisible"
title="确认删除"
ok-text="确认删除"
cancel-text="取消"
:ok-button-props="{ danger: true }"
:confirm-loading="confirmLoading"
@ok="handleFinalDelete"
>
<div>
<p style="color: red; font-weight: bold">请慎重操作</p>
<p>{{ label }}名称{{ deleteRecord?.stnm }}</p>
<p>修改依据{{ dataSource || '无' }}</p>
<p>确定要删除该{{ label }}</p>
</div>
</a-modal>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { message } from 'ant-design-vue';
import { deletePowerInfo } from '@/api/DataQueryMenuModule';
import { useDraggable } from '@/utils/drag';
const props = withDefaults(
defineProps<{
/** 自定义删除函数,接收 (record, reason) 参数 */
deleteFn?: (record: any, reason: string) => Promise<any>;
/** 弹窗标题 */
title?: string;
/** 显示标签(如"电站"、"数据" */
label?: string;
}>(),
{
title: '删除电站',
label: '电站'
}
);
const emit = defineEmits(['success']);
const dataSourceVisible = ref(false);
const confirmVisible = ref(false);
const confirmLoading = ref(false);
const dataSource = ref('');
const deleteRecord = ref<any>(null);
const onSuccess = ref<Function>(() => {});
//
const open = (record: any, callback: Function) => {
deleteRecord.value = record;
dataSource.value = '';
dataSourceVisible.value = true;
onSuccess.value = callback;
};
useDraggable(dataSourceVisible, { boundary: true, resetOnOpen: true });
useDraggable(confirmVisible, { boundary: true, resetOnOpen: true });
//
const handleDataSourceConfirm = () => {
dataSourceVisible.value = false;
confirmVisible.value = true;
};
//
const handleFinalDelete = async () => {
confirmLoading.value = true; //
try {
let res: any;
if (props.deleteFn) {
// 使
res = await props.deleteFn(deleteRecord.value, dataSource.value);
} else {
// 使
const params = {
ids: [deleteRecord.value.stcd],
source: dataSource.value
};
res = await deletePowerInfo(params);
}
if (res?.code == 0 || res?.success) {
message.success('删除成功');
confirmVisible.value = false;
onSuccess.value();
} else {
message.error(res?.msg || '删除失败');
}
} catch (error) {
message.error('删除失败,请重试');
} finally {
confirmLoading.value = false; //
}
};
defineExpose({ open });
</script>

View File

@ -26,7 +26,16 @@
sort: sort sort: sort
}" }"
:list-url="getPowerTableList" :list-url="getPowerTableList"
><template #action="{ record }">
<a-button
type="link"
class="text-[#2f6b98]"
size="small"
@click="handleDetail(record)"
>查看详情</a-button
> >
</template>
</BasicTable> </BasicTable>
<!-- 自定义数据列 Modal --> <!-- 自定义数据列 Modal -->
@ -36,19 +45,6 @@
:user-column-list="userColumnList" :user-column-list="userColumnList"
@confirm="handleColumnConfirm" @confirm="handleColumnConfirm"
/> />
<!-- 编辑电站 Modal -->
<EditPowerModal
v-model:open="editVisible"
:dvtp-list="dvtpList"
:record="editRecord"
:top-hynm-list="topHynmList"
:hycd-list="hycdList"
@success="handleEditSuccess"
/>
<!-- 删除确认 Modal -->
<DeleteConfirmModal ref="deleteModalRef" @success="handleEditSuccess" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -57,13 +53,9 @@ import dayjs from 'dayjs';
import BasicDataSearch from './BasicDataSearch.vue'; import BasicDataSearch from './BasicDataSearch.vue';
import BasicTable from '@/components/BasicTable/index.vue'; import BasicTable from '@/components/BasicTable/index.vue';
import CustomColumnModal from './CustomColumnModal.vue'; import CustomColumnModal from './CustomColumnModal.vue';
import EditPowerModal from './EditPowerModal.vue';
import DeleteConfirmModal from './DeleteConfirmModal.vue';
import { import {
getCompanyList, getCompanyList,
getPowerTableList, getPowerTableList,
updatePowerInfo,
deletePowerInfo,
getUserColumnData, getUserColumnData,
batchSaveUserColumn batchSaveUserColumn
} from '@/api/DataQueryMenuModule'; } from '@/api/DataQueryMenuModule';
@ -435,26 +427,6 @@ const handleDetail = (record: any) => {
modelStore.params.stcd = record.stcd; modelStore.params.stcd = record.stcd;
modelStore.title = record.stnm; modelStore.title = record.stnm;
}; };
//
const handleEdit = (record: any) => {
getEngInfoById({ stcd: record.stcd }).then(res => {
console.log(res);
editRecord.value = { ...res.data };
});
editVisible.value = true;
};
//
const handleEditSuccess = () => {
initTable(currentSearchParams.value);
};
//
const handleDelete = (record: any) => {
deleteModalRef.value?.open(record, () => {
initTable(currentSearchParams.value);
});
};
// //
const fetchColumnConfig = () => { const fetchColumnConfig = () => {
@ -482,7 +454,13 @@ const fetchColumnConfig = () => {
}); });
// //
cols.push({
key: 'action',
title: '操作',
dataIndex: 'action',
fixed: 'right',
width: isEdit.value ? 180 : 100
});
columns.value = cols; columns.value = cols;
}).catch(() => { }).catch(() => {

View File

@ -1,121 +0,0 @@
<!-- <template>
<BasicSearch
ref="basicSearchRef"
:searchList="searchList"
:initial-values="initSearchData"
:zhujianfujian="'fu'"
@reset="handleReset"
@finish="onSearchFinish"
>
<template #actions>
<a-button @click="hideBtn">{{ isHide ? '展开' : '隐藏' }}</a-button>
<a-button type="primary" @click="handleAdd">新增</a-button>
</template>
</BasicSearch>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import BasicSearch from '@/components/BasicSearch/index.vue';
import { sttpGetKendoList } from '@/api/system/map/ConfigManagement';
const emit = defineEmits<{
(e: 'search-finish', values: any): void;
(e: 'reset', values: any): void;
(e: 'add'): void;
}>();
const basicSearchRef = ref();
const isHide = ref<boolean>(false);
const sttpOption = ref([]);
const initSearchData = {
baseId: 'all',
rstcd: null,
stnm: null,
sttp: null
};
const searchList: any = computed(() => [
{
type: 'jidiData',
name: 'baseId',
label: '水电基地',
placeholder: '请输入水电基地名称',
fieldProps: {
allowClear: true
},
options: []
},
{
type: 'Input',
name: 'stnm',
label: '站点名称',
placeholder: '请输入站点名称',
width: 160,
fieldProps: {
allowClear: true
}
},
{
col: isHide.value ? 0 : null,
type: 'Select',
name: 'sttp',
label: '测站类型',
width: 160,
fieldProps: {
allowClear: true,
placeholder: '请选择测站类型'
},
options: sttpOption.value
}
]);
const getBaseList = async () => {
let params = {
"filter": {
"logic": "and",
"filters": [
{
"field": "sttpCode",
"operator": "in",
"dataType": "string",
"value": ["OSGB"]
}
]
}
};
const res = await sttpGetKendoList(params);
sttpOption.value = res.data.data.map(item => {
return {
label: item.sttpName,
value: item.sttpCode
};
});
};
const onSearchFinish = (values: any) => {
emit('search-finish', { ...values });
};
const hideBtn = () => {
isHide.value = !isHide.value;
};
const handleReset = () => {
emit('reset', initSearchData);
};
const handleAdd = () => {
emit('add');
};
onMounted(() => {
getBaseList();
emit('search-finish', { ...initSearchData });
});
defineExpose({
basicSearchRef
});
</script> -->

View File

@ -1,275 +0,0 @@
<!-- <template>
<div class="w-full h-full flex flex-col pt-[20px] pl-[20px] body_one">
<PhotoSearch
@search-finish="onSearchFinish"
@reset="onReset"
@add="handleAdd"
ref="searchRef"
/>
<BasicTable
ref="tableRef"
:enableEllipsis="true"
:scrollX="tableScrollX"
:scrollY="tableScrollY"
:columns="columns"
:list-url="getOpPageList"
>
<template #action="{ record }">
<a-button
type="link"
class="text-[#2f6b98]"
size="small"
@click="handleEdit(record)"
>编辑</a-button
>
<a-button type="link" danger size="small" @click="handleDelete(record)"
>删除</a-button
>
</template>
</BasicTable>
<EditPhotoModal
v-model:open="editVisible"
:record="editRecord"
:is-add="isAdd"
@success="handleEditSuccess"
/>
<DeleteConfirmModal
ref="deleteModalRef"
:delete-fn="deleteOpFn"
:label="'倾斜摄影站点'"
title="删除倾斜摄影站点"
@success="handleEditSuccess"
/>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from 'vue';
import dayjs from 'dayjs';
import PhotoSearch from './PhotoSearch.vue';
import BasicTable from '@/components/BasicTable/index.vue';
import EditPhotoModal from './EditPhotoModal.vue';
import DeleteConfirmModal from '@/views/conventionalHydropower/BasicData/DeleteConfirmModal.vue';
import { getOpPageList, deleteOpInfo } from '@/api/DataQueryMenuModule';
import { calcTableScrollY } from '@/utils/index';
const tableRef = ref();
const searchRef = ref();
const tableScrollY = ref<string | number>(0);
const currentSearchParams = ref<any>({});
//
const editVisible = ref(false);
const editRecord = ref<any>(null);
const isAdd = ref(false);
const deleteModalRef = ref();
const columns = ref<any[]>([
{
key: 'stnm',
title: '站点名称',
dataIndex: 'stnm',
visible: true,
width: 200,
fixed: 'left',
ellipsis: true
},
{
key: 'stcd',
title: '站点编码',
dataIndex: 'stcd',
visible: true,
width: 160,
ellipsis: true
},
{
key: 'sttpName',
title: '测站类型',
dataIndex: 'sttpName',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'stlc',
title: '位置',
dataIndex: 'stlc',
visible: true,
width: 160,
ellipsis: true
},
{
key: 'baseName',
title: '水电基地',
dataIndex: 'baseName',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'url',
title: '在线地址',
dataIndex: 'url',
visible: true,
width: 200,
ellipsis: true
},
{
key: 'usflName',
title: '是否启用',
dataIndex: 'usflName',
visible: true,
width: 80,
ellipsis: true
},
{
key: 'jcdt',
title: '建成日期',
dataIndex: 'jcdt',
visible: true,
width: 110,
customRender: ({ text }) => {
if (!text || text === '-') return '-';
const date = dayjs(text);
return date.isValid() ? date.format('YYYY-MM-DD') : '-';
}
},
{
key: 'remark',
title: '备注',
dataIndex: 'remark',
visible: true,
ellipsis: true
},
{
key: 'action',
title: '操作',
dataIndex: 'action',
fixed: 'right',
width: 120
}
]);
const tableScrollX = computed(() =>
Math.max(
columns.value.reduce(
(sum: number, col: any) => sum + (col.width || 180),
0
),
600
)
);
const buildSearchParams = (values: any) => {
return {
logic: 'and',
filters: [
values.rstcd
? {
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: values.rstcd
}
: null,
values.baseId !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: values.baseId
}
: null,
values.stnm
? {
field: 'stnm',
operator: 'contains',
dataType: 'string',
value: values.stnm
}
: null,
values.sttp
? {
field: 'sttp',
operator: 'eq',
dataType: 'string',
value: values.sttp
}
: null
].filter(Boolean)
};
};
const onSearchFinish = (values: any) => {
currentSearchParams.value = values;
initTable(values);
};
const onReset = (values: any) => {
currentSearchParams.value = values;
initTable(values);
};
const initTable = (values: any) => {
const params = buildSearchParams(values);
tableRef.value.getList(params);
};
//
const handleAdd = () => {
isAdd.value = true;
editRecord.value = null;
editVisible.value = true;
};
//
const handleEdit = (record: any) => {
isAdd.value = false;
editRecord.value = { ...record };
editVisible.value = true;
};
//
const handleEditSuccess = () => {
initTable(currentSearchParams.value);
};
//
const deleteOpFn = async (record: any, reason: string) => {
return deleteOpInfo({
ids: [record.stcd],
source: reason
});
};
const handleDelete = (record: any) => {
deleteModalRef.value?.open(record, () => {
initTable(currentSearchParams.value);
});
};
onMounted(() => {
nextTick(() => {
tableScrollY.value = calcTableScrollY();
});
});
</script>
<style scoped lang="scss">
.body_one {
position: relative;
z-index: 900;
pointer-events: all;
}
</style> -->

View File

@ -1,506 +0,0 @@
<template>
<a-modal
v-model:open="visible"
:title="isAdd ? '新增人工产卵场' : '编辑人工产卵场'"
width="60vw"
:confirm-loading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
>
<a-form
ref="formRef"
:model="formData"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
:rules="formRules"
class="max-h-[70vh] overflow-y-auto pr-4"
>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="产卵场编码" name="stcd">
<a-input
v-model:value="formData.stcd"
placeholder="请输入产卵场编码"
:disabled="!isAdd"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="产卵场名称" name="stnm">
<a-input
v-model:value="formData.stnm"
placeholder="请输入产卵场名称"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="测站类型" name="sttp">
<a-select
v-model:value="formData.sttp"
placeholder="请选择测站类型"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in sttpOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="站址" name="stlc">
<a-input
v-model:value="formData.stlc"
placeholder="请输入站址"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="水电基地" name="baseId">
<a-select
v-model:value="formData.baseId"
placeholder="请选择水电基地"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in baseNameOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="所属电站" name="rstcd">
<a-select
v-model:value="formData.rstcd"
placeholder="请选择所属电站"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in engInfoOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="保护对象" name="prtcts">
<a-input
v-model:value="formData.prtcts"
placeholder="请输入保护对象"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="产卵场数量(个)" name="cnt">
<a-input-number
v-model:value="formData.cnt"
placeholder="请输入数量"
style="width: 100%"
:min="0"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="面积(km²)" name="ar">
<a-input-number
v-model:value="formData.ar"
placeholder="请输入面积"
style="width: 100%"
:min="0"
:precision="2"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="营造型式" name="tp">
<a-input
v-model:value="formData.tp"
placeholder="请输入营造型式"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="实施时间" name="attm">
<a-date-picker
v-model:value="formData.attm"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择实施时间"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="建成日期" name="jcdt">
<a-date-picker
v-model:value="formData.jcdt"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择建成日期"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="是否启用" name="usfl">
<a-select
v-model:value="formData.usfl"
placeholder="请选择是否启用"
allow-clear
>
<a-select-option :value="1">启用</a-select-option>
<a-select-option :value="0">禁用</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="投资(亿元)" name="inv">
<a-input-number
v-model:value="formData.inv"
placeholder="请输入投资"
style="width: 100%"
:min="0"
:precision="4"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="监测频次(min)" name="dtfrqcy">
<a-input-number
v-model:value="formData.dtfrqcy"
placeholder="请输入监测频次"
style="width: 100%"
:min="0"
/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="简介" name="introduce" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.introduce"
placeholder="请输入简介"
:rows="2"
/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="备注" name="remark" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.remark"
placeholder="请输入备注"
:rows="2"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-modal>
<ConfirmModal
v-model:open="confirmModalVisible"
:diff-list="diffList"
:confirm-loading="confirmLoading"
@confirm="handleConfirmSubmit"
@cancel="handleConfirmCancel"
/>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { message } from 'ant-design-vue';
import { addSgInfo, updateSgInfo } from '@/api/DataQueryMenuModule';
import { getEngInfoDropdown } from '@/api/select';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { sttpGetKendoList } from '@/api/system/map/ConfigManagement';
import ConfirmModal from '@/components/ConfirmModal/index.vue';
import { useDraggable } from '@/utils/drag';
const props = defineProps<{
open: boolean;
record?: any;
isAdd?: boolean;
}>();
const emit = defineEmits(['update:open', 'success']);
const jidiSelectEventStore = useJidiSelectEventStore();
const visible = computed({
get: () => props.open,
set: val => emit('update:open', val)
});
useDraggable(visible, { boundary: true, resetOnOpen: true });
const formRef = ref();
const confirmLoading = ref(false);
const formData = ref<any>({});
const originalRecord = ref<any>({});
const confirmModalVisible = ref(false);
const formRules = ref<any>({
stcd: [{ required: true, message: '请输入产卵场编码', trigger: 'blur' }],
stnm: [{ required: true, message: '请输入产卵场名称', trigger: 'blur' }]
});
//
const engInfoOptions = ref<any[]>([]);
const sttpOptions = ref<any[]>([]);
const baseNameOptions = ref<any[]>(
jidiSelectEventStore.jidiData
.filter((item: any) => item.wbsCode !== 'all')
.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}))
);
//
const fieldLabelMap: Record<string, string> = {
stcd: '产卵场编码',
stnm: '产卵场名称',
sttp: '测站类型',
stlc: '站址',
baseId: '水电基地',
rstcd: '所属电站',
prtcts: '保护对象',
cnt: '产卵场数量',
ar: '面积',
tp: '营造型式',
attm: '实施时间',
jcdt: '建成日期',
usfl: '是否启用',
inv: '投资',
dtfrqcy: '监测频次',
introduce: '简介',
remark: '备注'
};
// select
const selectOptionsMap: Record<string, () => any[]> = {
sttp: () => sttpOptions.value,
usfl: () => [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 }
],
baseId: () => baseNameOptions.value,
rstcd: () => engInfoOptions.value
};
//
const changeOrder = ref<
{ field: string; label: string; oldValue: string; newValue: string }[]
>([]);
const diffList = changeOrder;
const resolveSelectLabel = (field: string, value: any): string => {
if (value === null || value === undefined || value === '') return '空';
const getOptions = selectOptionsMap[field];
if (getOptions) {
const opt = getOptions().find(
(o: any) => String(o.value) === String(value)
);
if (opt) return opt.label;
}
return String(value);
};
const filterOption = (inputValue: string, option: any) => {
const label = option.label || option.value;
const keyword = inputValue || '';
return label.includes(keyword);
};
// formData
watch(
() => formData.value,
newData => {
const original = originalRecord.value;
for (const key in newData) {
const oldVal = original[key];
const newVal = newData[key];
if (oldVal !== newVal) {
const existingIdx = changeOrder.value.findIndex(c => c.field === key);
const oldNorm =
oldVal === null || oldVal === undefined || oldVal === '-'
? null
: oldVal;
const newNorm = newVal === null || newVal === undefined ? null : newVal;
if (oldNorm === newNorm) continue;
if (
oldNorm !== null &&
newNorm !== null &&
!isNaN(Number(oldNorm)) &&
!isNaN(Number(newNorm)) &&
Number(oldNorm) === Number(newNorm)
)
continue;
const isSelect = !!selectOptionsMap[key];
const oldDisplay = isSelect
? resolveSelectLabel(key, oldNorm)
: oldNorm === null
? '空'
: String(oldNorm);
const newDisplay = isSelect
? resolveSelectLabel(key, newNorm)
: newNorm === null
? '空'
: String(newNorm);
const entry = {
field: key,
label: fieldLabelMap[key] || key,
oldValue: oldDisplay,
newValue: newDisplay
};
if (existingIdx >= 0) {
changeOrder.value[existingIdx] = entry;
} else {
changeOrder.value.push(entry);
}
} else {
changeOrder.value = changeOrder.value.filter(c => c.field !== key);
}
}
},
{ deep: true }
);
// record
watch(
() => props.record,
newRecord => {
if (newRecord) {
const converted = { ...newRecord };
originalRecord.value = { ...converted };
formData.value = { ...converted };
changeOrder.value = [];
}
},
{ deep: true }
);
//
const loadDropdownData = () => {
//
sttpGetKendoList({
filter: {
logic: 'and',
filters: [
{
field: 'sttpCode',
operator: 'in',
dataType: 'string',
value: ['SG']
}
]
}
}).then(res => {
sttpOptions.value = (res.data?.data || []).map((item: any) => ({
label: item.sttpName,
value: item.sttpCode
}));
});
baseNameOptions.value = jidiSelectEventStore.jidiData
.filter((item: any) => item.wbsCode !== 'all')
.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}));
getEngInfoDropdown({}).then(res => {
engInfoOptions.value = (res.data || []).map((item: any) => ({
label: item.ennm,
value: item.stcd
}));
});
};
watch(
() => props.open,
val => {
if (val) {
loadDropdownData();
if (props.isAdd) {
formData.value = {};
originalRecord.value = {};
changeOrder.value = [];
}
}
}
);
const handleOk = async () => {
try {
await formRef.value?.validateFields();
if (!props.isAdd && changeOrder.value.length === 0) {
message.info('未检测到任何修改');
return;
}
confirmModalVisible.value = true;
} catch (error) {
console.error('验证失败:', error);
}
};
const handleConfirmSubmit = async (source: string) => {
confirmLoading.value = true;
try {
const engInfo: Record<string, any> = {};
let res: any;
if (props.isAdd) {
Object.assign(engInfo, formData.value);
res = await addSgInfo({
engInfo,
source: source.trim() || '新增'
});
} else {
engInfo.stcd = formData.value.stcd;
changeOrder.value.forEach(item => {
engInfo[item.field] = formData.value[item.field];
});
res = await updateSgInfo({
engInfo,
source: source.trim() || '编辑'
});
}
if (res?.code == 0 || res?.success) {
message.success(props.isAdd ? '新增成功' : '编辑成功');
confirmModalVisible.value = false;
visible.value = false;
emit('success');
} else {
message.error(res?.msg || (props.isAdd ? '新增失败' : '编辑失败'));
}
} catch (error) {
message.error('提交失败,请重试');
} finally {
confirmLoading.value = false;
}
};
const handleConfirmCancel = () => {
confirmModalVisible.value = false;
};
const handleCancel = () => {
visible.value = false;
confirmModalVisible.value = false;
formRef.value?.resetFields();
};
</script>

View File

@ -1,121 +0,0 @@
<template>
<BasicSearch
ref="basicSearchRef"
:searchList="searchList"
:initial-values="initSearchData"
:zhujianfujian="'fu'"
@reset="handleReset"
@finish="onSearchFinish"
>
<template #actions>
<a-button @click="hideBtn">{{ isHide ? '展开' : '隐藏' }}</a-button>
<a-button type="primary" @click="handleAdd">新增</a-button>
</template>
</BasicSearch>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import BasicSearch from '@/components/BasicSearch/index.vue';
import { sttpGetKendoList } from '@/api/system/map/ConfigManagement';
const emit = defineEmits<{
(e: 'search-finish', values: any): void;
(e: 'reset', values: any): void;
(e: 'add'): void;
}>();
const basicSearchRef = ref();
const isHide = ref<boolean>(false);
const sttpOption = ref([]);
const initSearchData = {
baseId: 'all',
rstcd: null,
stnm: null,
sttp: null
};
const searchList: any = computed(() => [
{
type: 'jidiData',
name: 'baseId',
label: '水电基地',
placeholder: '请输入水电基地名称',
fieldProps: {
allowClear: true
},
options: []
},
{
type: 'Input',
name: 'stnm',
label: '产卵场名称',
placeholder: '请输入产卵场名称',
width: 160,
fieldProps: {
allowClear: true
}
},
{
col: isHide.value ? 0 : null,
type: 'Select',
name: 'sttp',
label: '测站类型',
width: 160,
fieldProps: {
allowClear: true,
placeholder: '请选择测站类型'
},
options: sttpOption.value
}
]);
const getBaseList = async () => {
let params = {
"filter": {
"logic": "and",
"filters": [
{
"field": "sttpCode",
"operator": "in",
"dataType": "string",
"value": ["SG"]
}
]
}
};
const res = await sttpGetKendoList(params);
sttpOption.value = res.data.data.map(item => {
return {
label: item.sttpName,
value: item.sttpCode
};
});
};
const onSearchFinish = (values: any) => {
emit('search-finish', { ...values });
};
const hideBtn = () => {
isHide.value = !isHide.value;
};
const handleReset = () => {
emit('reset', initSearchData);
};
const handleAdd = () => {
emit('add');
};
onMounted(() => {
getBaseList();
emit('search-finish', { ...initSearchData });
});
defineExpose({
basicSearchRef
});
</script>

View File

@ -1,295 +0,0 @@
<template>
<div class="w-full h-full flex flex-col pt-[20px] pl-[20px] body_one">
<!-- 搜索组件 -->
<SpawnSearch
@search-finish="onSearchFinish"
@reset="onReset"
@add="handleAdd"
ref="searchRef"
/>
<!-- 表格组件 -->
<BasicTable
ref="tableRef"
:enableEllipsis="true"
:scrollX="tableScrollX"
:scrollY="tableScrollY"
:columns="columns"
:list-url="getSgPageList"
>
<template #action="{ record }">
<a-button
type="link"
class="text-[#2f6b98]"
size="small"
@click="handleEdit(record)"
>编辑</a-button
>
<a-button type="link" danger size="small" @click="handleDelete(record)"
>删除</a-button
>
</template>
</BasicTable>
<!-- 编辑/新增 Modal -->
<EditSpawnModal
v-model:open="editVisible"
:record="editRecord"
:is-add="isAdd"
@success="handleEditSuccess"
/>
<!-- 删除确认 Modal -->
<DeleteConfirmModal
ref="deleteModalRef"
:delete-fn="deleteSgFn"
:label="'人工产卵场'"
title="删除人工产卵场"
@success="handleEditSuccess"
/>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from 'vue';
import dayjs from 'dayjs';
import SpawnSearch from './SpawnSearch.vue';
import BasicTable from '@/components/BasicTable/index.vue';
import EditSpawnModal from './EditSpawnModal.vue';
import DeleteConfirmModal from '@/views/conventionalHydropower/BasicData/DeleteConfirmModal.vue';
import { getSgPageList, deleteSgInfo } from '@/api/DataQueryMenuModule';
import { calcTableScrollY } from '@/utils/index';
const tableRef = ref();
const searchRef = ref();
const tableScrollY = ref<string | number>(0);
const currentSearchParams = ref<any>({});
//
const editVisible = ref(false);
const editRecord = ref<any>(null);
const isAdd = ref(false);
const deleteModalRef = ref();
const columns = ref<any[]>([
{
key: 'stnm',
title: '产卵场名称',
dataIndex: 'stnm',
visible: true,
width: 200,
fixed: 'left',
ellipsis: true
},
{
key: 'stcd',
title: '产卵场编码',
dataIndex: 'stcd',
visible: true,
width: 200,
ellipsis: true
},
{
key: 'sttpName',
title: '测站类型',
dataIndex: 'sttpName',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'stlc',
title: '站址',
dataIndex: 'stlc',
visible: true,
width: 160,
ellipsis: true
},
{
key: 'baseName',
title: '水电基地',
dataIndex: 'baseName',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'prtcts',
title: '保护对象',
dataIndex: 'prtcts',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'cnt',
title: '数量(个)',
dataIndex: 'cnt',
visible: true,
width: 80,
ellipsis: true
},
{
key: 'ar',
title: '面积(km²)',
dataIndex: 'ar',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'jcdt',
title: '建成日期',
dataIndex: 'jcdt',
visible: true,
width: 110,
customRender: ({ text }) => {
if (!text || text === '-') return '-';
const date = dayjs(text);
return date.isValid() ? date.format('YYYY-MM-DD') : '-';
}
},
{
key: 'usflName',
title: '是否启用',
dataIndex: 'usflName',
visible: true,
width: 80,
ellipsis: true
},
{
key: 'remark',
title: '备注',
dataIndex: 'remark',
visible: true,
ellipsis: true
},
{
key: 'action',
title: '操作',
dataIndex: 'action',
fixed: 'right',
width: 120
}
]);
const tableScrollX = computed(() =>
Math.max(
columns.value.reduce(
(sum: number, col: any) => sum + (col.width || 180),
0
),
600
)
);
const buildSearchParams = (values: any) => {
return {
logic: 'and',
filters: [
values.rstcd
? {
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: values.rstcd
}
: null,
values.baseId !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: values.baseId
}
: null,
values.stnm
? {
field: 'stnm',
operator: 'contains',
dataType: 'string',
value: values.stnm
}
: null,
values.sttp
? {
field: 'sttp',
operator: 'eq',
dataType: 'string',
value: values.sttp
}
: null
].filter(Boolean)
};
};
const onSearchFinish = (values: any) => {
currentSearchParams.value = values;
initTable(values);
};
const onReset = (values: any) => {
currentSearchParams.value = values;
initTable(values);
};
const initTable = (values: any) => {
const params = buildSearchParams(values);
tableRef.value.getList(params);
};
//
const handleAdd = () => {
isAdd.value = true;
editRecord.value = null;
editVisible.value = true;
};
//
const handleEdit = (record: any) => {
isAdd.value = false;
editRecord.value = { ...record };
editVisible.value = true;
};
//
const handleEditSuccess = () => {
initTable(currentSearchParams.value);
};
//
const deleteSgFn = async (record: any, reason: string) => {
return deleteSgInfo({
ids: [record.stcd],
source: reason
});
};
const handleDelete = (record: any) => {
deleteModalRef.value?.open(record, () => {
initTable(currentSearchParams.value);
});
};
onMounted(() => {
nextTick(() => {
tableScrollY.value = calcTableScrollY();
});
});
</script>
<style scoped lang="scss">
.body_one {
position: relative;
z-index: 900;
pointer-events: all;
}
</style>

View File

@ -1,394 +0,0 @@
<template>
<a-modal
v-model:open="visible"
:title="isAdd ? '新增智能告警' : '编辑智能告警'"
width="60vw"
:confirm-loading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
>
<a-form
ref="formRef"
:model="formData"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
:rules="formRules"
class="max-h-[70vh] overflow-y-auto pr-4"
>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="预警规则名称" name="ruleName">
<a-input
v-model:value="formData.ruleName"
placeholder="请输入预警规则名称"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="预警规则类型" name="ruleType">
<a-select
v-model:value="formData.ruleType"
placeholder="请选择预警规则类型"
allow-clear
>
<a-select-option value="WQLVL">水质预警</a-select-option>
<a-select-option value="EQMN">电站生态流量(环保部)</a-select-option>
<a-select-option value="EQMNMWR">电站生态流量(水利部)</a-select-option>
<a-select-option value="RSVRFSR">水位预警</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="规则编码" name="ruleCode">
<a-select
v-model:value="formData.ruleCode"
placeholder="请选择规则编码"
allow-clear
>
<a-select-option value="global">全局规则</a-select-option>
<a-select-option value="common">通用告警规则</a-select-option>
<a-select-option value="custom">自定义告警规则</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="所属测站" name="stcd">
<a-input
v-model:value="formData.stcd"
placeholder="请输入所属测站"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="水电基地" name="baseId">
<a-select
v-model:value="formData.baseId"
placeholder="请选择水电基地"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in baseNameOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="所属电站" name="rstcd">
<a-select
v-model:value="formData.rstcd"
placeholder="请选择所属电站"
allow-clear
show-search
:filter-option="filterOption"
>
<a-select-option
v-for="item in engInfoOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>{{ item.label }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="是否展示告警等级" name="isShow">
<a-select
v-model:value="formData.isShow"
placeholder="请选择"
allow-clear
>
<a-select-option :value="1">展示</a-select-option>
<a-select-option :value="0">不展示</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="备注" name="description" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-textarea
v-model:value="formData.description"
placeholder="请输入备注"
:rows="3"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-modal>
<ConfirmModal
v-model:open="confirmModalVisible"
:diff-list="diffList"
:confirm-loading="confirmLoading"
@confirm="handleConfirmSubmit"
@cancel="handleConfirmCancel"
/>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { message } from 'ant-design-vue';
import { addWarnInfo, updateWarnInfo } from '@/api/DataQueryMenuModule';
import { getEngInfoDropdown } from '@/api/select';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import ConfirmModal from '@/components/ConfirmModal/index.vue';
import { useDraggable } from '@/utils/drag';
const props = defineProps<{
open: boolean;
record?: any;
isAdd?: boolean;
}>();
const emit = defineEmits(['update:open', 'success']);
const jidiSelectEventStore = useJidiSelectEventStore();
const visible = computed({
get: () => props.open,
set: val => emit('update:open', val)
});
useDraggable(visible, { boundary: true, resetOnOpen: true });
const formRef = ref();
const confirmLoading = ref(false);
const formData = ref<any>({});
const originalRecord = ref<any>({});
const confirmModalVisible = ref(false);
const formRules = ref<any>({
ruleName: [{ required: true, message: '请输入预警规则名称', trigger: 'blur' }],
ruleType: [{ required: true, message: '请选择预警规则类型', trigger: 'change' }]
});
//
const engInfoOptions = ref<any[]>([]);
const baseNameOptions = ref<any[]>(
jidiSelectEventStore.jidiData
.filter((item: any) => item.wbsCode !== 'all')
.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}))
);
//
const fieldLabelMap: Record<string, string> = {
ruleName: '预警规则名称',
ruleType: '预警规则类型',
ruleCode: '规则编码',
stcd: '所属测站',
baseId: '水电基地',
rstcd: '所属电站',
isShow: '是否展示告警等级',
description: '备注'
};
// select
const selectOptionsMap: Record<string, () => any[]> = {
ruleType: () => [
{ label: '水质预警', value: 'WQLVL' },
{ label: '电站生态流量(环保部)', value: 'EQMN' },
{ label: '电站生态流量(水利部)', value: 'EQMNMWR' },
{ label: '水位预警', value: 'RSVRFSR' }
],
ruleCode: () => [
{ label: '全局规则', value: 'global' },
{ label: '通用告警规则', value: 'common' },
{ label: '自定义告警规则', value: 'custom' }
],
isShow: () => [
{ label: '展示', value: 1 },
{ label: '不展示', value: 0 }
],
baseId: () => baseNameOptions.value,
rstcd: () => engInfoOptions.value
};
//
const changeOrder = ref<
{ field: string; label: string; oldValue: string; newValue: string }[]
>([]);
const diffList = changeOrder;
const resolveSelectLabel = (field: string, value: any): string => {
if (value === null || value === undefined || value === '') return '空';
const getOptions = selectOptionsMap[field];
if (getOptions) {
const opt = getOptions().find(
(o: any) => String(o.value) === String(value)
);
if (opt) return opt.label;
}
return String(value);
};
const filterOption = (inputValue: string, option: any) => {
const label = option.label || option.value;
const keyword = inputValue || '';
return label.includes(keyword);
};
// formData
watch(
() => formData.value,
newData => {
const original = originalRecord.value;
for (const key in newData) {
const oldVal = original[key];
const newVal = newData[key];
if (oldVal !== newVal) {
const existingIdx = changeOrder.value.findIndex(c => c.field === key);
const oldNorm =
oldVal === null || oldVal === undefined || oldVal === '-'
? null
: oldVal;
const newNorm = newVal === null || newVal === undefined ? null : newVal;
if (oldNorm === newNorm) continue;
if (
oldNorm !== null &&
newNorm !== null &&
!isNaN(Number(oldNorm)) &&
!isNaN(Number(newNorm)) &&
Number(oldNorm) === Number(newNorm)
)
continue;
const isSelect = !!selectOptionsMap[key];
const oldDisplay = isSelect
? resolveSelectLabel(key, oldNorm)
: oldNorm === null
? '空'
: String(oldNorm);
const newDisplay = isSelect
? resolveSelectLabel(key, newNorm)
: newNorm === null
? '空'
: String(newNorm);
const entry = {
field: key,
label: fieldLabelMap[key] || key,
oldValue: oldDisplay,
newValue: newDisplay
};
if (existingIdx >= 0) {
changeOrder.value[existingIdx] = entry;
} else {
changeOrder.value.push(entry);
}
} else {
changeOrder.value = changeOrder.value.filter(c => c.field !== key);
}
}
},
{ deep: true }
);
// record
watch(
() => props.record,
newRecord => {
if (newRecord) {
const converted = { ...newRecord };
originalRecord.value = { ...converted };
formData.value = { ...converted };
changeOrder.value = [];
}
},
{ deep: true }
);
//
const loadDropdownData = () => {
baseNameOptions.value = jidiSelectEventStore.jidiData
.filter((item: any) => item.wbsCode !== 'all')
.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}));
getEngInfoDropdown({}).then(res => {
engInfoOptions.value = (res.data || []).map((item: any) => ({
label: item.ennm,
value: item.stcd
}));
});
};
watch(
() => props.open,
val => {
if (val) {
loadDropdownData();
if (props.isAdd) {
formData.value = {};
originalRecord.value = {};
changeOrder.value = [];
}
}
}
);
const handleOk = async () => {
try {
await formRef.value?.validateFields();
if (!props.isAdd && changeOrder.value.length === 0) {
message.info('未检测到任何修改');
return;
}
confirmModalVisible.value = true;
} catch (error) {
console.error('验证失败:', error);
}
};
const handleConfirmSubmit = async (source: string) => {
confirmLoading.value = true;
try {
const engInfo: Record<string, any> = {};
let res: any;
if (props.isAdd) {
Object.assign(engInfo, formData.value);
res = await addWarnInfo({
engInfo,
source: source.trim() || '新增'
});
} else {
engInfo.id = formData.value.id;
changeOrder.value.forEach(item => {
engInfo[item.field] = formData.value[item.field];
});
res = await updateWarnInfo({
engInfo,
source: source.trim() || '编辑'
});
}
if (res?.code == 0 || res?.success) {
message.success(props.isAdd ? '新增成功' : '编辑成功');
confirmModalVisible.value = false;
visible.value = false;
emit('success');
} else {
message.error(res?.msg || (props.isAdd ? '新增失败' : '编辑失败'));
}
} catch (error) {
message.error('提交失败,请重试');
} finally {
confirmLoading.value = false;
}
};
const handleConfirmCancel = () => {
confirmModalVisible.value = false;
};
const handleCancel = () => {
visible.value = false;
confirmModalVisible.value = false;
formRef.value?.resetFields();
};
</script>

View File

@ -1,82 +0,0 @@
<template>
<BasicSearch
ref="basicSearchRef"
:searchList="searchList"
:initial-values="initSearchData"
:zhujianfujian="'fu'"
@reset="handleReset"
@finish="onSearchFinish"
>
<template #actions>
<a-button @click="hideBtn">{{ isHide ? '展开' : '隐藏' }}</a-button>
<a-button type="primary" @click="handleAdd">新增</a-button>
</template>
</BasicSearch>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import BasicSearch from '@/components/BasicSearch/index.vue';
const emit = defineEmits<{
(e: 'search-finish', values: any): void;
(e: 'reset', values: any): void;
(e: 'add'): void;
}>();
const basicSearchRef = ref();
const isHide = ref<boolean>(false);
const initSearchData = {
baseId: 'all',
rstcd: null,
ruleName: null
};
const searchList: any = computed(() => [
{
type: 'jidiData',
name: 'baseId',
label: '水电基地',
placeholder: '请输入水电基地名称',
fieldProps: {
allowClear: true
},
options: []
},
{
type: 'Input',
name: 'ruleName',
label: '规则名称',
placeholder: '请输入规则名称',
width: 160,
fieldProps: {
allowClear: true
}
}
]);
const onSearchFinish = (values: any) => {
emit('search-finish', { ...values });
};
const hideBtn = () => {
isHide.value = !isHide.value;
};
const handleReset = () => {
emit('reset', initSearchData);
};
const handleAdd = () => {
emit('add');
};
onMounted(() => {
emit('search-finish', { ...initSearchData });
});
defineExpose({
basicSearchRef
});
</script>

View File

@ -1,255 +0,0 @@
<template>
<div class="w-full h-full flex flex-col pt-[20px] pl-[20px] body_one">
<!-- 搜索组件 -->
<WarnSearch
@search-finish="onSearchFinish"
@reset="onReset"
@add="handleAdd"
ref="searchRef"
/>
<!-- 表格组件 -->
<BasicTable
ref="tableRef"
:enableEllipsis="true"
:scrollX="tableScrollX"
:scrollY="tableScrollY"
:columns="columns"
:list-url="getWarnPageList"
>
<template #action="{ record }">
<a-button
type="link"
class="text-[#2f6b98]"
size="small"
@click="handleEdit(record)"
>编辑</a-button
>
<a-button type="link" danger size="small" @click="handleDelete(record)"
>删除</a-button
>
</template>
</BasicTable>
<!-- 编辑/新增 Modal -->
<EditWarnModal
v-model:open="editVisible"
:record="editRecord"
:is-add="isAdd"
@success="handleEditSuccess"
/>
<!-- 删除确认 Modal -->
<DeleteConfirmModal
ref="deleteModalRef"
:delete-fn="deleteWarnFn"
:label="'智能告警'"
title="删除智能告警"
@success="handleEditSuccess"
/>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from 'vue';
import dayjs from 'dayjs';
import WarnSearch from './WarnSearch.vue';
import BasicTable from '@/components/BasicTable/index.vue';
import EditWarnModal from './EditWarnModal.vue';
import DeleteConfirmModal from '@/views/conventionalHydropower/BasicData/DeleteConfirmModal.vue';
import { getWarnPageList, deleteWarnInfo } from '@/api/DataQueryMenuModule';
import { calcTableScrollY } from '@/utils/index';
const tableRef = ref();
const searchRef = ref();
const tableScrollY = ref<string | number>(0);
const currentSearchParams = ref<any>({});
//
const editVisible = ref(false);
const editRecord = ref<any>(null);
const isAdd = ref(false);
const deleteModalRef = ref();
const columns = ref<any[]>([
{
key: 'ruleName',
title: '预警规则名称',
dataIndex: 'ruleName',
visible: true,
width: 200,
fixed: 'left',
ellipsis: true
},
{
key: 'ruleType',
title: '预警规则类型',
dataIndex: 'ruleType',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'ruleCode',
title: '规则编码',
dataIndex: 'ruleCode',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'stcd',
title: '所属测站',
dataIndex: 'stcd',
visible: true,
width: 160,
ellipsis: true
},
{
key: 'baseName',
title: '水电基地',
dataIndex: 'baseName',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'ennm',
title: '所属电站',
dataIndex: 'ennm',
visible: true,
width: 100,
ellipsis: true
},
{
key: 'isShow',
title: '展示告警等级',
dataIndex: 'isShow',
visible: true,
width: 100,
customRender: ({ text }) => {
if (text === 1) return '展示';
if (text === 0) return '不展示';
return '-';
}
},
{
key: 'description',
title: '备注',
dataIndex: 'description',
visible: true,
ellipsis: true
},
{
key: 'action',
title: '操作',
dataIndex: 'action',
fixed: 'right',
width: 120
}
]);
const tableScrollX = computed(() =>
Math.max(
columns.value.reduce(
(sum: number, col: any) => sum + (col.width || 180),
0
),
600
)
);
const buildSearchParams = (values: any) => {
return {
logic: 'and',
filters: [
values.rstcd
? {
field: 'rstcd',
operator: 'eq',
dataType: 'string',
value: values.rstcd
}
: null,
values.baseId !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: values.baseId
}
: null,
values.ruleName
? {
field: 'ruleName',
operator: 'contains',
dataType: 'string',
value: values.ruleName
}
: null
].filter(Boolean)
};
};
const onSearchFinish = (values: any) => {
currentSearchParams.value = values;
initTable(values);
};
const onReset = (values: any) => {
currentSearchParams.value = values;
initTable(values);
};
const initTable = (values: any) => {
const params = buildSearchParams(values);
tableRef.value.getList(params);
};
//
const handleAdd = () => {
isAdd.value = true;
editRecord.value = null;
editVisible.value = true;
};
//
const handleEdit = (record: any) => {
isAdd.value = false;
editRecord.value = { ...record };
editVisible.value = true;
};
//
const handleEditSuccess = () => {
initTable(currentSearchParams.value);
};
// 使 id
const deleteWarnFn = async (record: any, reason: string) => {
return deleteWarnInfo({
ids: [record.id],
source: reason
});
};
const handleDelete = (record: any) => {
deleteModalRef.value?.open(record, () => {
initTable(currentSearchParams.value);
});
};
onMounted(() => {
nextTick(() => {
tableScrollY.value = calcTableScrollY();
});
});
</script>
<style scoped lang="scss">
.body_one {
position: relative;
z-index: 900;
pointer-events: all;
}
</style>

View File

@ -34,7 +34,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick, provide,defineAsyncComponent } from 'vue'; import { ref, computed, onMounted, onUnmounted, onActivated, onDeactivated, watch, nextTick, provide,defineAsyncComponent } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { getTreeConfiguredps, getPowerSubjectLayout } from '@/api/dianZhanZhuanTi'; import { getTreeConfiguredps, getPowerSubjectLayout } from '@/api/dianZhanZhuanTi';
@ -193,7 +193,7 @@ function onTreeSelect(value: any, item: any) {
waitForMapReady(() => { waitForMapReady(() => {
setTimeout(() => { setTimeout(() => {
if ((window as any).mapClass) { if ((window as any).mapClass) {
(window as any).mapClass.flyTopanto([Number(item.lgtd), Number(item.lttd)], 12); (window as any).mapClass.flyTopanto([Number(item.lgtd), Number(item.lttd)], 15);
} }
}, 0); }, 0);
}); });
@ -327,6 +327,9 @@ watch(
const rows = sk?.gridTemplateRows?.split(' ') || []; const rows = sk?.gridTemplateRows?.split(' ') || [];
const bottomRowHeight = rows[rows.length - 1]; const bottomRowHeight = rows[rows.length - 1];
nextTick(() => setMapLegendPos(val.type, val, 460, bottomRowHeight)); nextTick(() => setMapLegendPos(val.type, val, 460, bottomRowHeight));
} else {
// / 3D
uiStore.resetMapControlsPosition();
} }
}, },
{ deep: true } { deep: true }
@ -348,12 +351,10 @@ watch(
// ==================== ==================== // ==================== ====================
function resetMapControlPositions() { function resetMapControlPositions() {
// / store
uiStore.resetMapControlsPosition();
const legend = document.querySelector('#qgc-legendtl') as HTMLElement; const legend = document.querySelector('#qgc-legendtl') as HTMLElement;
const controller = document.querySelector('#map-controller') as HTMLElement;
const baselayer = document.querySelector('#map-baselayer') as HTMLElement;
if (legend) { legend.style.left = '0px'; legend.style.bottom = '0px'; } if (legend) { legend.style.left = '0px'; legend.style.bottom = '0px'; }
if (controller) { controller.style.right = '12px'; controller.style.bottom = '114px'; }
if (baselayer) { baselayer.style.right = '60px'; baselayer.style.bottom = '0px'; }
['#map-filter-container', '#map-compassControl', '#map-monitor'].forEach(sel => { ['#map-filter-container', '#map-compassControl', '#map-monitor'].forEach(sel => {
const el = document.querySelector(sel) as HTMLElement; const el = document.querySelector(sel) as HTMLElement;
if (el) { el.style.left = ''; el.style.right = ''; el.style.bottom = ''; } if (el) { el.style.left = ''; el.style.right = ''; el.style.bottom = ''; }
@ -366,6 +367,39 @@ function collapseLegend() {
icon?.parentElement?.click(); icon?.parentElement?.click();
} }
//
let legendOpTimer: ReturnType<typeof setTimeout> | null = null;
const clearLegendOpTimer = () => {
if (legendOpTimer !== null) {
clearTimeout(legendOpTimer);
legendOpTimer = null;
}
};
/** 进入专题页时收缩图例:图例尚未渲染则轮询等待,仅展开态才点击收起 */
function collapseLegendOnEnter(retry = 0) {
const btn = document.querySelector('.legendBtn') as HTMLElement | null;
if (!btn) {
if (retry < 30) {
legendOpTimer = setTimeout(() => collapseLegendOnEnter(retry + 1), 200);
}
return;
}
if (btn.querySelector('.icon-fold')) btn.click();
}
/** 离开专题页时展开图例:仅收起态才点击展开 */
function expandLegendOnLeave(retry = 0) {
const btn = document.querySelector('.legendBtn') as HTMLElement | null;
if (!btn) {
if (retry < 30) {
legendOpTimer = setTimeout(() => expandLegendOnLeave(retry + 1), 200);
}
return;
}
if (btn.querySelector('.icon-unFold')) btn.click();
}
// ==================== 3D/2D ==================== // ==================== 3D/2D ====================
watch( watch(
() => uiStore.mapType, () => uiStore.mapType,
@ -411,6 +445,10 @@ watch(
// ==================== ==================== // ==================== ====================
onMounted(() => { onMounted(() => {
// /
uiStore.setIsSearchActive(false);
uiStore.setGlobalDrawerOpen(false);
getTreeConfiguredps() getTreeConfiguredps()
.then((res: any) => { .then((res: any) => {
const result = res?.data ?? []; const result = res?.data ?? [];
@ -432,13 +470,30 @@ onMounted(() => {
}); });
switchToSatellite(); switchToSatellite();
//
collapseLegendOnEnter();
}); });
onUnmounted(() => { onUnmounted(() => {
clearLegendOpTimer();
//
expandLegendOnLeave();
switchToVector(); switchToVector();
layoutData.value = null; layoutData.value = null;
resetMapControlPositions(); resetMapControlPositions();
}); });
// keep-alive mounted/activated
onActivated(() => {
collapseLegendOnEnter();
});
onDeactivated(() => {
clearLegendOpTimer();
expandLegendOnLeave();
// keep-alive
uiStore.resetMapControlsPosition();
});
</script> </script>
<style lang="scss"> <style lang="scss">