填报页面修改,沿程配置修改,添加预警和推送页面
This commit is contained in:
parent
46100d8318
commit
549849b479
@ -7,7 +7,7 @@ VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台'
|
|||||||
VITE_APP_PORT = 3000
|
VITE_APP_PORT = 3000
|
||||||
VITE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API = '/dev-api'
|
||||||
# 本地环境
|
# 本地环境
|
||||||
VITE_APP_BASE_URL = 'http://10.84.121.127:8093'
|
VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||||
# 测试环境
|
# 测试环境
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||||
|
|||||||
@ -12,12 +12,9 @@ VITE_APP_BASE_API = '/dev-api'
|
|||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||||
# 汤伟
|
# 汤伟
|
||||||
VITE_APP_BASE_URL = 'http://10.84.121.127:8093'
|
# VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||||
# 李林
|
# 李林
|
||||||
# VITE_APP_BASE_URL = 'http://10.84.121.43:8093'
|
VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||||
# VITE_APP_BASE_URL = 'http://192.168.1.162:8093'
|
|
||||||
# 李林
|
|
||||||
# VITE_APP_BASE_URL = 'http://10.84.121.43:8093'
|
|
||||||
|
|
||||||
# 测试环境线上10.84.121.122:
|
# 测试环境线上10.84.121.122:
|
||||||
VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
||||||
|
|||||||
@ -106,3 +106,11 @@ export function uploadFile(data: any) {
|
|||||||
headers: { 'Content-Type': 'multipart/form-data' }
|
headers: { 'Content-Type': 'multipart/form-data' }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 所在位置下拉列表
|
||||||
|
export function getAddvcdDropdownByRvcd(params: any) {
|
||||||
|
return request({
|
||||||
|
url: '/base/msalongb/noAuth/GetKendoList',
|
||||||
|
method: 'post',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import request from '@/utils/request';
|
|||||||
// 获取所有沿程配置数据
|
// 获取所有沿程配置数据
|
||||||
export function getAllConfigTree(data: any) {
|
export function getAllConfigTree(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msalongb/GetKendoList',
|
url: '/base/msalongb/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -11,7 +11,7 @@ export function getAllConfigTree(data: any) {
|
|||||||
// 保存沿程配置
|
// 保存沿程配置
|
||||||
export function saveBaseWbsb(data: any) {
|
export function saveBaseWbsb(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/wbsb/addOrUpdate',
|
url: '/base/msalongb/save',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -19,8 +19,24 @@ export function saveBaseWbsb(data: any) {
|
|||||||
// 删除沿程配置
|
// 删除沿程配置
|
||||||
export function deleteBaseWbsb(data: any) {
|
export function deleteBaseWbsb(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/wbsb/delete',
|
url: '/base/msalongb/delete',
|
||||||
method: 'get',
|
method: 'post',
|
||||||
params: data
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 保存沿程配置子节点
|
||||||
|
export function saveBaseWbsbChild(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/base/msalongb/save',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveBaseWbsbChildDetail(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/base/msalongdetb/save',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function overviewGetOverviewSecond(data: any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//增殖站介绍 /api/dec-lygk-base-server/base/msstbprpt/GetKendoList
|
//增殖站介绍
|
||||||
export function msstbprptGetKendoList(data: any) {
|
export function msstbprptGetKendoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/fb/msstbprpt/GetKendoList',
|
url: '/fb/msstbprpt/GetKendoList',
|
||||||
|
|||||||
@ -56,6 +56,9 @@ service.interceptors.response.use(
|
|||||||
if (status === 200) {
|
if (status === 200) {
|
||||||
if (response.data.code == 401) {
|
if (response.data.code == 401) {
|
||||||
message.error(response.data.msg || '请求失败');
|
message.error(response.data.msg || '请求失败');
|
||||||
|
setTimeout(() => {
|
||||||
|
router.push('/login');
|
||||||
|
}, 1000);
|
||||||
return;
|
return;
|
||||||
} else if (response.data.code == 1) {
|
} else if (response.data.code == 1) {
|
||||||
message.error(response.data.msg);
|
message.error(response.data.msg);
|
||||||
|
|||||||
@ -0,0 +1,784 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑沿程配置' : '新增沿程配置'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="localLoading"
|
||||||
|
width="1200px"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
ok-text="保存"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
name="edit_form"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="沿程配置名称" name="name">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.name"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入沿程配置名称"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="配置编码" name="code">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.code"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入配置编码"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="所在河段" name="rvnm">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.rvnm"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入所在河段"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="备注" name="description">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.description"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
<div class="config-tree-container">
|
||||||
|
<!-- 新增一级节点区域 -->
|
||||||
|
<div v-if="addingNewNode" class="add-node-row">
|
||||||
|
<a-select
|
||||||
|
v-model:value="newNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveNewNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleCancelAdd" style="margin-left: 8px">
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<a-button v-else class="mb-4" type="primary" @click="handleAdd">
|
||||||
|
<PlusOutlined /> 新增一级节点
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<!-- 树形结构 -->
|
||||||
|
<a-tree
|
||||||
|
v-if="treeData.length > 0"
|
||||||
|
:tree-data="treeData"
|
||||||
|
:default-expand-all="false"
|
||||||
|
:selectable="false"
|
||||||
|
block-node
|
||||||
|
style="width: 300px"
|
||||||
|
>
|
||||||
|
<template #title="{ dataRef }">
|
||||||
|
<!-- 编辑状态:只显示编辑区域 -->
|
||||||
|
<div
|
||||||
|
v-if="editingNode && editingNodeKey === dataRef.key"
|
||||||
|
class="add-child-node-row w-[300px]"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="editNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleEditNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click.stop="handleSaveEditNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
@click.stop="handleCancelEditNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<!-- 非编辑状态:显示正常节点内容 -->
|
||||||
|
<template v-else>
|
||||||
|
<div class="tree-node-wrapper">
|
||||||
|
<span class="tree-node-title"> {{ getNodeTitle(dataRef) }} </span>
|
||||||
|
<div class="tree-node-actions">
|
||||||
|
<!-- 一级节点:支持新增子节点、编辑、排序、删除 -->
|
||||||
|
<template v-if="!dataRef.parentId">
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleAddChild(dataRef)"
|
||||||
|
title="添加子节点"
|
||||||
|
>
|
||||||
|
<PlusOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleEditNode(dataRef)"
|
||||||
|
title="编辑"
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveUp(dataRef)"
|
||||||
|
title="上移"
|
||||||
|
:disabled="isFirstNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowUpOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveDown(dataRef)"
|
||||||
|
title="下移"
|
||||||
|
:disabled="isLastNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowDownOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="handleDeleteNode(dataRef)"
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<!-- 二级节点:只支持编辑、排序、删除 -->
|
||||||
|
<template v-else>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleEditNode(dataRef)"
|
||||||
|
title="编辑"
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveUp(dataRef)"
|
||||||
|
title="上移"
|
||||||
|
:disabled="isFirstNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowUpOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveDown(dataRef)"
|
||||||
|
title="下移"
|
||||||
|
:disabled="isLastNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowDownOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="handleDeleteNode(dataRef)"
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 子节点添加区域 -->
|
||||||
|
<div
|
||||||
|
v-if="addingChildNode && currentParentKey === dataRef.key"
|
||||||
|
class="add-child-node-row"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="childNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleChildNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click.stop="handleSaveChildNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
@click.stop="handleCancelAddChild"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-tree>
|
||||||
|
<a-empty v-else description="暂无数据" style="margin-top: 20px" />
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
PlusOutlined,
|
||||||
|
MinusOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
ArrowUpOutlined,
|
||||||
|
ArrowDownOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
code: undefined,
|
||||||
|
rvnm: undefined,
|
||||||
|
description: undefined
|
||||||
|
});
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
name: [{ required: true, message: '请输入沿程配置名称', trigger: 'blur' }],
|
||||||
|
code: [{ required: true, message: '请输入配置编码', trigger: 'blur' }],
|
||||||
|
rvnm: [{ required: true, message: '请输入所在河段', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
|
||||||
|
// 树形数据
|
||||||
|
const treeData = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 新增节点相关
|
||||||
|
const addingNewNode = ref(false);
|
||||||
|
const newNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加子节点相关
|
||||||
|
const addingChildNode = ref(false);
|
||||||
|
const currentParentKey = ref<string | null>(null);
|
||||||
|
const childNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 编辑节点相关
|
||||||
|
const editingNode = ref(false);
|
||||||
|
const editingNodeKey = ref<string | null>(null);
|
||||||
|
const editNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: '',
|
||||||
|
originalData: null as any
|
||||||
|
});
|
||||||
|
|
||||||
|
// 站点列表(模拟数据,实际应从接口获取)
|
||||||
|
const stationList = ref([
|
||||||
|
{ stcd: '1', stnm: '站点A', sttpName: '类型1' },
|
||||||
|
{ stcd: '2', stnm: '站点B', sttpName: '类型2' },
|
||||||
|
{ stcd: '3', stnm: '站点C', sttpName: '类型1' },
|
||||||
|
{ stcd: '4', stnm: '站点D', sttpName: '类型3' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 生成唯一ID
|
||||||
|
let nodeIdCounter = 0;
|
||||||
|
const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`;
|
||||||
|
|
||||||
|
// 获取节点标题
|
||||||
|
const getNodeTitle = (dataRef: any) => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 一级节点:只显示 stnm
|
||||||
|
return dataRef.stnm || '';
|
||||||
|
} else {
|
||||||
|
// 二级节点:显示 stnm + sttpName
|
||||||
|
return `${dataRef.stnm || ''} ${dataRef.sttpName || ''}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索过滤
|
||||||
|
const filterOption = (input: string, option: any) => {
|
||||||
|
return (
|
||||||
|
option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为第一个节点
|
||||||
|
const isFirstNode = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
return siblings.length > 0 && siblings[0].key === dataRef.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为最后一个节点
|
||||||
|
const isLastNode = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
return (
|
||||||
|
siblings.length > 0 && siblings[siblings.length - 1].key === dataRef.key
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取兄弟节点
|
||||||
|
const getSiblings = (dataRef: any) => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 一级节点
|
||||||
|
return treeData.value;
|
||||||
|
} else {
|
||||||
|
// 二级节点,找到父节点的 children
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
return parent?.children || [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据 key 查找节点
|
||||||
|
const findNodeByKey = (nodes: any[], key: string): any => {
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (node.key === key) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (node.children && node.children.length > 0) {
|
||||||
|
const found = findNodeByKey(node.children, key);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增一级节点
|
||||||
|
const handleAdd = () => {
|
||||||
|
addingNewNode.value = true;
|
||||||
|
newNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择节点
|
||||||
|
const handleNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
newNodeData.value.stnm = station.stnm;
|
||||||
|
newNodeData.value.sttpName = station.sttpName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存新增节点
|
||||||
|
const handleSaveNewNode = () => {
|
||||||
|
if (!newNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newNode = {
|
||||||
|
key: generateNodeId(),
|
||||||
|
stcd: newNodeData.value.stcd,
|
||||||
|
stnm: newNodeData.value.stnm,
|
||||||
|
sttpName: newNodeData.value.sttpName,
|
||||||
|
parentId: null,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
treeData.value.push(newNode);
|
||||||
|
addingNewNode.value = false;
|
||||||
|
message.success('添加成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消新增
|
||||||
|
const handleCancelAdd = () => {
|
||||||
|
addingNewNode.value = false;
|
||||||
|
newNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加子节点(二级节点)
|
||||||
|
const handleAddChild = (parentData: any) => {
|
||||||
|
addingChildNode.value = true;
|
||||||
|
currentParentKey.value = parentData.key;
|
||||||
|
childNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择子节点
|
||||||
|
const handleChildNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
childNodeData.value.stnm = station.stnm;
|
||||||
|
childNodeData.value.sttpName = station.sttpName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存新增子节点
|
||||||
|
const handleSaveChildNode = () => {
|
||||||
|
if (!childNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = findNodeByKey(treeData.value, currentParentKey.value!);
|
||||||
|
if (!parent) {
|
||||||
|
message.error('父节点不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newChild = {
|
||||||
|
key: generateNodeId(),
|
||||||
|
stcd: childNodeData.value.stcd,
|
||||||
|
stnm: childNodeData.value.stnm,
|
||||||
|
sttpName: childNodeData.value.sttpName,
|
||||||
|
parentId: parent.key,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
// 在子节点列表顶部添加
|
||||||
|
parent.children.unshift(newChild);
|
||||||
|
|
||||||
|
addingChildNode.value = false;
|
||||||
|
currentParentKey.value = null;
|
||||||
|
message.success('添加子节点成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消添加子节点
|
||||||
|
const handleCancelAddChild = () => {
|
||||||
|
addingChildNode.value = false;
|
||||||
|
currentParentKey.value = null;
|
||||||
|
childNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑节点
|
||||||
|
const handleEditNode = (dataRef: any) => {
|
||||||
|
editingNode.value = true;
|
||||||
|
editingNodeKey.value = dataRef.key;
|
||||||
|
// 保存原始数据
|
||||||
|
editNodeData.value = {
|
||||||
|
stcd: dataRef.stcd,
|
||||||
|
stnm: dataRef.stnm,
|
||||||
|
sttpName: dataRef.sttpName,
|
||||||
|
originalData: { ...dataRef }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择编辑节点
|
||||||
|
const handleEditNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
editNodeData.value.stnm = station.stnm;
|
||||||
|
editNodeData.value.sttpName = station.sttpName;
|
||||||
|
editNodeData.value.stcd = station.stcd;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存编辑节点
|
||||||
|
const handleSaveEditNode = () => {
|
||||||
|
if (!editNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到要编辑的节点
|
||||||
|
const node = findNodeByKey(treeData.value, editingNodeKey.value!);
|
||||||
|
if (!node) {
|
||||||
|
message.error('节点不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新节点数据
|
||||||
|
node.stcd = editNodeData.value.stcd;
|
||||||
|
node.stnm = editNodeData.value.stnm;
|
||||||
|
node.sttpName = editNodeData.value.sttpName;
|
||||||
|
|
||||||
|
editingNode.value = false;
|
||||||
|
editingNodeKey.value = null;
|
||||||
|
message.success('编辑成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消编辑节点
|
||||||
|
const handleCancelEditNode = () => {
|
||||||
|
editingNode.value = false;
|
||||||
|
editingNodeKey.value = null;
|
||||||
|
editNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: '',
|
||||||
|
originalData: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上移
|
||||||
|
const handleMoveUp = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
// 交换位置
|
||||||
|
[siblings[index - 1], siblings[index]] = [
|
||||||
|
siblings[index],
|
||||||
|
siblings[index - 1]
|
||||||
|
];
|
||||||
|
message.success('上移成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下移
|
||||||
|
const handleMoveDown = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||||
|
|
||||||
|
if (index < siblings.length - 1) {
|
||||||
|
// 交换位置
|
||||||
|
[siblings[index], siblings[index + 1]] = [
|
||||||
|
siblings[index + 1],
|
||||||
|
siblings[index]
|
||||||
|
];
|
||||||
|
message.success('下移成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除节点
|
||||||
|
const handleDeleteNode = (dataRef: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: `确定要删除节点"${dataRef.stnm}"吗?`,
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 删除一级节点
|
||||||
|
const index = treeData.value.findIndex(
|
||||||
|
item => item.key === dataRef.key
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
treeData.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 删除二级节点
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
if (parent && parent.children) {
|
||||||
|
const index = parent.children.findIndex(
|
||||||
|
item => item.key === dataRef.key
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
parent.children.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.success('删除成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
const submitValues = {
|
||||||
|
...formData,
|
||||||
|
captureDate: formData.captureDate
|
||||||
|
? dayjs(formData.captureDate).format('YYYY-MM-DD')
|
||||||
|
: undefined,
|
||||||
|
configNodes: treeData.value // 提交树形数据
|
||||||
|
};
|
||||||
|
emit('ok', submitValues);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initForm = () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
const values = props.initialValues;
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
if (key === 'captureDate' && values[key]) {
|
||||||
|
formData[key] = dayjs(values[key]);
|
||||||
|
} else {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化树形数据
|
||||||
|
if (values.configNodes && Array.isArray(values.configNodes)) {
|
||||||
|
treeData.value = values.configNodes.map((node: any) => ({
|
||||||
|
...node,
|
||||||
|
children:
|
||||||
|
node.children?.map((child: any) => ({
|
||||||
|
...child
|
||||||
|
})) || []
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
treeData.value = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
treeData.value = [];
|
||||||
|
addingNewNode.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
emit('cancel');
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.config-tree-container {
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.add-node-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 8px;
|
||||||
|
|
||||||
|
.tree-node-title {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-actions {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保鼠标悬停时显示操作按钮
|
||||||
|
.tree-node-wrapper:hover {
|
||||||
|
.tree-node-actions {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子节点添加区域样式
|
||||||
|
.add-child-node-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 0 8px 24px;
|
||||||
|
margin-top: 4px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增配置">
|
||||||
|
<a-button @click="props.handleAdd" type="primary"> 新增沿程配置 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from "vue";
|
||||||
|
import BasicSearch from "@/components/BasicSearch/index.vue";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "reset", values: any): void;
|
||||||
|
(e: "searchFinish", values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
configName: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "name",
|
||||||
|
label: "沿程配置名称",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "rvnm",
|
||||||
|
label: "所在河段",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit("searchFinish", values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
emit("reset", initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit("searchFinish", initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
@ -0,0 +1,228 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\ConfigManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
预警配置管理
|
||||||
|
<!-- <ConfigManagementSearch
|
||||||
|
ref="configManagementSearch"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
ref="basicTable"
|
||||||
|
:columns="columns"
|
||||||
|
:list-url="getAllConfigTree"
|
||||||
|
:search-params="searchParams"
|
||||||
|
>
|
||||||
|
<template #action="{ column, record }">
|
||||||
|
<div class="flex gap-[6px]">
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEdit(record)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click="handleDelete(record)"
|
||||||
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<ConfigManagementForm
|
||||||
|
ref="configManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:initial-values="currentRecord"
|
||||||
|
@cancel="editModalCancel"
|
||||||
|
@ok="handleEditSubmit"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick, onMounted } from 'vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import ConfigManagementSearch from './ConfigManagementSearch.vue';
|
||||||
|
import ConfigManagementForm from './ConfigManagementForm.vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
getAllConfigTree,
|
||||||
|
deleteBaseWbsb,
|
||||||
|
saveBaseWbsb
|
||||||
|
} from '@/api/system/map/ConfigManagement';
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const basicTable = ref<any>(null);
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text, record, index }) => index + 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '沿程配置名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '配置编码',
|
||||||
|
key: 'code',
|
||||||
|
dataIndex: 'code',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所在河段',
|
||||||
|
dataIndex: 'rvnm',
|
||||||
|
key: 'rvnm',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
key: 'recordUser',
|
||||||
|
dataIndex: 'recordUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'recordTime',
|
||||||
|
dataIndex: 'recordTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'modifyTime',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
key: 'remark',
|
||||||
|
width: 360
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({});
|
||||||
|
// 编辑弹窗数据
|
||||||
|
const currentRecord = ref<any | null>(null);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
|
||||||
|
// 新增处理
|
||||||
|
const handleAdd = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑处理
|
||||||
|
const handleEdit = (record: any) => {
|
||||||
|
currentRecord.value = { ...record };
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
zIndex: 2002,
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
let res = await deleteBaseWbsb([record.id]);
|
||||||
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索完成处理
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
const params = {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
values.parentId
|
||||||
|
? {
|
||||||
|
field: 'parentId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.parentId
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.name
|
||||||
|
? {
|
||||||
|
field: 'name',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.name
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
].filter(Boolean)
|
||||||
|
};
|
||||||
|
basicTable.value.getList(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
basicTable.value.getList({
|
||||||
|
logic: 'and',
|
||||||
|
filters: []
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单取消
|
||||||
|
const editModalCancel = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单提交
|
||||||
|
const handleEditSubmit = async (values: any) => {
|
||||||
|
try {
|
||||||
|
let res = await saveBaseWbsb({
|
||||||
|
...currentRecord.value,
|
||||||
|
...values
|
||||||
|
});
|
||||||
|
message.success(`保存成功`);
|
||||||
|
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
|
||||||
|
editModalVisible.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initOption = () => {};
|
||||||
|
onMounted(() => {
|
||||||
|
initOption();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.config-management {
|
||||||
|
height: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,260 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑图层' : '新增图层'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="props.loading"
|
||||||
|
width="600px"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
name="edit_form"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
>
|
||||||
|
<a-form-item label="图层名称" name="title">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.title"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入图层名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图层编码" name="code">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.code"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入图层编码"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图层类型" name="type" v-if="isInterface">
|
||||||
|
<a-select
|
||||||
|
:options="typeOpiton"
|
||||||
|
v-model:value="formData.type"
|
||||||
|
:fieldNames="{
|
||||||
|
label: 'dictName',
|
||||||
|
value: 'itemCode'
|
||||||
|
}"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入图层类型"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="标签显示级别" name="treeLevel" v-if="!isInterface">
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="formData.treeLevel"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入标签显示级别"
|
||||||
|
:min="0"
|
||||||
|
:max="24"
|
||||||
|
:step="1"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="锚点接口" name="url" v-if="isInterface">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.url"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入锚点接口"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="接口参数" name="anchorParamJson" v-if="isInterface">
|
||||||
|
<a-textarea
|
||||||
|
:rows="6"
|
||||||
|
v-model:value="formData.anchorParamJson"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入接口参数"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="三维接口"
|
||||||
|
name="urlThd"
|
||||||
|
v-if="isInterface && formData.type === 'geojson'"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.urlThd"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入三维接口"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="gisJson"
|
||||||
|
name="paramJson"
|
||||||
|
v-if="isInterface && formData.type === 'geojson'"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.paramJson"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入gisJson"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="备注"
|
||||||
|
name="description"
|
||||||
|
v-if="!isInterface || formData.type === 'geojson'"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.description"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import { getDictItemsByCode } from '@/api/dict';
|
||||||
|
|
||||||
|
// 定义 Props
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
isInterface?: boolean;
|
||||||
|
}
|
||||||
|
// 加载状态
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false,
|
||||||
|
isInterface: false
|
||||||
|
});
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
// 定义 Emits
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any, type: string): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref();
|
||||||
|
// 1. 新增用于存储手动验证错误信息的响应式变量
|
||||||
|
const bodyLengthError = ref<string>('');
|
||||||
|
const weightError = ref<string>('');
|
||||||
|
|
||||||
|
// 表单数据模型
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
title: undefined,
|
||||||
|
code: undefined,
|
||||||
|
type: undefined,
|
||||||
|
treeLevel: undefined,
|
||||||
|
description: undefined,
|
||||||
|
parentId: undefined,
|
||||||
|
url: undefined,
|
||||||
|
urlThd: undefined,
|
||||||
|
paramJson: undefined,
|
||||||
|
anchorParamJson: undefined
|
||||||
|
});
|
||||||
|
const typeOpiton = ref<any>([]);
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
// 验证规则
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
title: [{ required: true, message: '请输入图层名称', trigger: 'blur' }],
|
||||||
|
code: [{ required: true, message: '请输入图层编码', trigger: 'blur' }],
|
||||||
|
type: [{ required: true, message: '请输入图层类型', trigger: 'change' }],
|
||||||
|
treeLevel: [
|
||||||
|
{ required: true, message: '请输入标签显示级别', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 计算是否为编辑模式
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
// 确认操作
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
// 验证表单
|
||||||
|
await formRef.value.validate();
|
||||||
|
// 准备提交数据
|
||||||
|
const submitValues = {
|
||||||
|
...formData
|
||||||
|
};
|
||||||
|
emit('ok', submitValues, 'form');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const initForm = () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
// --- 编辑模式:回填数据 ---
|
||||||
|
const values = props.initialValues;
|
||||||
|
if (props.isInterface) {
|
||||||
|
initType();
|
||||||
|
}
|
||||||
|
// 回填其他普通字段
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
// 确保字段存在于 initialValues 中再赋值,避免覆盖默认值
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const initType = () => {
|
||||||
|
getDictItemsByCode({ dictCode: 'LayerTypeCode' }).then(res => {
|
||||||
|
typeOpiton.value = res.data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
// 清空手动验证的错误信息
|
||||||
|
bodyLengthError.value = '';
|
||||||
|
weightError.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消操作
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
emit('cancel');
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听图层类型变化,清空相关字段
|
||||||
|
watch(
|
||||||
|
() => formData.type,
|
||||||
|
(newType, oldType) => {
|
||||||
|
if (oldType && newType !== oldType) {
|
||||||
|
// 类型切换时清空相关字段
|
||||||
|
formData.urlThd = undefined;
|
||||||
|
formData.paramJson = undefined;
|
||||||
|
if (oldType === 'geojson') {
|
||||||
|
formData.description = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// 暴露变量
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增图层">
|
||||||
|
<a-button @click="props.handleAdd" type="primary"> 新增图层 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted, watch } from "vue";
|
||||||
|
import BasicSearch from "@/components/BasicSearch/index.vue"; // 确保路径正确
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: (record: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "reset", values: any): void;
|
||||||
|
(e: "searchFinish", values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
title: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "title",
|
||||||
|
label: "图层名称",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
// --- Methods ---
|
||||||
|
|
||||||
|
// 2. 搜索表单逻辑
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit("searchFinish", values);
|
||||||
|
};
|
||||||
|
// 值改变
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
emit("reset", initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit("searchFinish", initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,358 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\LayerManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
预警规则
|
||||||
|
<!-- <LayerManagementSearch
|
||||||
|
ref="layerManagementSearch"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
ref="basicTable"
|
||||||
|
:columns="columns"
|
||||||
|
:list-url="getAllMapLayerTree"
|
||||||
|
:search-params="searchParams"
|
||||||
|
>
|
||||||
|
<template #action="{ record }">
|
||||||
|
<div class="flex gap-[6px]">
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEdit(record)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
v-if="record.children && record.children.length == 0"
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEditInterface(record)"
|
||||||
|
>编辑接口</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleAdd(record)"
|
||||||
|
>新增子图层</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click="handleDelete(record)"
|
||||||
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #enable="{ record }">
|
||||||
|
<a-switch
|
||||||
|
:checked="record.enable === 1"
|
||||||
|
@change="(checked: boolean) => handleEnableChange(record, checked)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #checkable="{ record }">
|
||||||
|
<a-switch
|
||||||
|
:checked="record.checkable === 1"
|
||||||
|
@change="(checked: boolean) => handleCheckableChange(record, checked)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<LayerManagementForm
|
||||||
|
ref="layerManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:initial-values="currentRecord"
|
||||||
|
:is-interface="isInterface"
|
||||||
|
:loading="editLoading"
|
||||||
|
@cancel="editModalCancel"
|
||||||
|
@ok="handleEditSubmit"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick } from 'vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import LayerManagementSearch from './LayerManagementSearch.vue';
|
||||||
|
import LayerManagementForm from './LayerManagementForm.vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
getAllMapLayerTree,
|
||||||
|
saveMapLayer,
|
||||||
|
deleteMapLayer
|
||||||
|
} from '@/api/system/map/LayerManagement';
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
dataIndex: '',
|
||||||
|
key: '',
|
||||||
|
width: 50,
|
||||||
|
customRender: () => {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ record, index }: any) => {
|
||||||
|
// 对于树形结构,计算当前记录在其父节点的 children 中的位置
|
||||||
|
// 如果没有 parentId,说明是根节点,需要计算在所有根节点中的序号
|
||||||
|
if (!record.parentId) {
|
||||||
|
// 根节点:计算在 dataSource 中是第几个根节点
|
||||||
|
let rootIndex = 0;
|
||||||
|
for (let i = 0; i < basicTable.value.tableData.length; i++) {
|
||||||
|
const item = basicTable.value.tableData[i];
|
||||||
|
// 只统计根节点(没有 parentId 的节点)
|
||||||
|
if (!item.parentId) {
|
||||||
|
rootIndex++;
|
||||||
|
// 找到当前记录,返回其序号
|
||||||
|
if (
|
||||||
|
item.id === record.id ||
|
||||||
|
(item.key === record.key && item.id === record.id)
|
||||||
|
) {
|
||||||
|
return rootIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rootIndex;
|
||||||
|
} else {
|
||||||
|
// 子节点:在其父节点的 children 中查找索引
|
||||||
|
const findParentAndIndex = (data: any[], parentId: string): number => {
|
||||||
|
for (const item of data) {
|
||||||
|
if (item.key === parentId || item.id === parentId) {
|
||||||
|
// 找到父节点,在其 children 中查找当前记录的位置
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
const childIndex = item.children.findIndex(
|
||||||
|
(child: any) =>
|
||||||
|
child.key === record.key || child.id === record.id
|
||||||
|
);
|
||||||
|
return childIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 递归查找更深层的父节点
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
const result = findParentAndIndex(item.children, parentId);
|
||||||
|
if (result > 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
return findParentAndIndex(basicTable.value.tableData, record.parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图层名称',
|
||||||
|
dataIndex: 'title',
|
||||||
|
key: 'title',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图层编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '标签显示级别',
|
||||||
|
dataIndex: 'treeLevel',
|
||||||
|
key: 'treeLevel',
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否启用',
|
||||||
|
dataIndex: 'enable',
|
||||||
|
key: 'enable',
|
||||||
|
width: 80,
|
||||||
|
slots: { customRender: 'enable' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否可选',
|
||||||
|
dataIndex: 'checkable',
|
||||||
|
key: 'checkable',
|
||||||
|
width: 80,
|
||||||
|
slots: { customRender: 'checkable' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
key: 'displayRecordUser',
|
||||||
|
dataIndex: 'displayRecordUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'recordTime',
|
||||||
|
dataIndex: 'recordTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'modifyTime',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 220,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
// 表格实例
|
||||||
|
const basicTable = ref<any>(null);
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({});
|
||||||
|
// 编辑弹窗数据
|
||||||
|
const isInterface = ref(false);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
const editLoading = ref(false);
|
||||||
|
const parentId = ref<string | null>(null);
|
||||||
|
const currentRecord = ref<any | null>(null);
|
||||||
|
// 添加处理
|
||||||
|
const handleAdd = (record: any) => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
parentId.value = record.id;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
// 过滤掉值为 '-' 的字段
|
||||||
|
const filterRecord = (record: any) => {
|
||||||
|
const filtered: any = {};
|
||||||
|
const keepKeys = ['code']; // 这些键始终保留
|
||||||
|
Object.keys(record).forEach(key => {
|
||||||
|
if (keepKeys.includes(key) || record[key] !== '-') {
|
||||||
|
filtered[key] = record[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filtered;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑处理
|
||||||
|
const handleEdit = (record: any) => {
|
||||||
|
console.log('handleEdit', record);
|
||||||
|
parentId.value = null;
|
||||||
|
isInterface.value = false;
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
// 编辑接口处理
|
||||||
|
const handleEditInterface = (record: any) => {
|
||||||
|
console.log('handleEdit', record);
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
console.log('handleEdit', currentRecord.value);
|
||||||
|
isInterface.value = true;
|
||||||
|
parentId.value = null;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = async (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
zIndex: 2002,
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
let res = await deleteMapLayer([record.id]);
|
||||||
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 搜索
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
searchParams.value = values;
|
||||||
|
nextTick(() => {
|
||||||
|
basicTable.value.getList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchParams.value = {};
|
||||||
|
nextTick(() => {
|
||||||
|
basicTable.value.refresh();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 是否启用切换处理
|
||||||
|
const handleEnableChange = (record: any, checked: boolean) => {
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
console.log(currentRecord.value);
|
||||||
|
record.enable = checked ? 1 : 0;
|
||||||
|
handleEditSubmit({ enable: checked ? 1 : 0 }, 'switch');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 是否可选切换处理
|
||||||
|
const handleCheckableChange = (record: any, checked: boolean) => {
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
record.checkable = checked ? 1 : 0;
|
||||||
|
handleEditSubmit({ checkable: checked ? 1 : 0 }, 'switch');
|
||||||
|
};
|
||||||
|
// 表单
|
||||||
|
const editModalCancel = () => {
|
||||||
|
isInterface.value = false;
|
||||||
|
parentId.value = null;
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
const handleEditSubmit = async (values: any, type: string) => {
|
||||||
|
editLoading.value = true;
|
||||||
|
try {
|
||||||
|
let res = await saveMapLayer({
|
||||||
|
...currentRecord.value,
|
||||||
|
...values,
|
||||||
|
parentId: parentId.value
|
||||||
|
});
|
||||||
|
if (res.code == 0) {
|
||||||
|
if (type === 'switch') {
|
||||||
|
message.success('修改状态成功');
|
||||||
|
} else {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
}
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} else {
|
||||||
|
if (type === 'switch') {
|
||||||
|
message.success('修改状态成功');
|
||||||
|
} else {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (type === 'switch') {
|
||||||
|
message.error('修改状态失败');
|
||||||
|
} else {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
editLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
:deep(.ant-table-cell-with-append) {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
:deep(.ant-table-row-expand-icon) {
|
||||||
|
width: 17px !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
89
frontend/src/views/system/alertRules/index.vue
Normal file
89
frontend/src/views/system/alertRules/index.vue
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<div class="map-page">
|
||||||
|
<!-- Ant Design Tabs -->
|
||||||
|
<a-tabs v-model:activeKey="activeTab" class="map-tabs">
|
||||||
|
<a-tab-pane v-for="tab in tabs" :key="tab.value" :tab="tab.name">
|
||||||
|
<!-- 动态加载对应的组件 -->
|
||||||
|
<component :is="getComponent(tab.value)" />
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, defineAsyncComponent } from 'vue';
|
||||||
|
|
||||||
|
// Tab 配置
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
name: '预警规则',
|
||||||
|
value: 'rules'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '预警配置管理',
|
||||||
|
value: 'config'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 当前激活的 tab
|
||||||
|
const activeTab = ref('rules');
|
||||||
|
|
||||||
|
// 获取对应组件的方法
|
||||||
|
const getComponent = (value: string) => {
|
||||||
|
const componentMap: Record<string, any> = {
|
||||||
|
rules: defineAsyncComponent(
|
||||||
|
() => import('./components/RulesManagement/index.vue')
|
||||||
|
),
|
||||||
|
config: defineAsyncComponent(
|
||||||
|
() => import('./components/ConfigManagement/index.vue')
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
return componentMap[value] || null;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.map-page {
|
||||||
|
position: relative;
|
||||||
|
z-index: 900;
|
||||||
|
pointer-events: all;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 2px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 900;
|
||||||
|
pointer-events: all;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
:deep(.ant-form-item) {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs) {
|
||||||
|
height: 100%; // 减去 tabs header 的高度
|
||||||
|
padding: 0 13px;
|
||||||
|
}
|
||||||
|
.map-tabs {
|
||||||
|
:deep(.ant-tabs-content) {
|
||||||
|
height: 100%; // 减去 tabs header 的高度
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs-tabpane) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -26,32 +26,40 @@
|
|||||||
/> </a-form-item
|
/> </a-form-item
|
||||||
></a-col>
|
></a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="配置编码" name="code">
|
<a-form-item label="沿程配置编码" name="code">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="formData.code"
|
v-model:value="formData.code"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入配置编码"
|
placeholder="请输入沿程配置编码"
|
||||||
/> </a-form-item
|
/>
|
||||||
></a-col>
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="所在河段" name="rvnm">
|
<a-form-item label="所在河段" name="rvcd">
|
||||||
<a-input
|
<a-select
|
||||||
v-model:value="formData.rvnm"
|
v-model:value="formData.rvcd"
|
||||||
|
show-search
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入所在河段"
|
placeholder="请选择所在河段"
|
||||||
/> </a-form-item
|
:options="riverOptions"
|
||||||
></a-col>
|
:filter-option="filterOption"
|
||||||
|
@change="handleRiverSelect"
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="备注" name="description">
|
<a-form-item label="备注" name="remark">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
:rows="4"
|
:rows="4"
|
||||||
v-model:value="formData.description"
|
v-model:value="formData.remark"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入备注"
|
placeholder="请输入备注"
|
||||||
/> </a-form-item
|
/>
|
||||||
></a-col>
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
<div class="config-tree-container">
|
<div class="config-tree-container">
|
||||||
@ -70,7 +78,7 @@
|
|||||||
:key="item.stcd"
|
:key="item.stcd"
|
||||||
:value="item.stcd"
|
:value="item.stcd"
|
||||||
>
|
>
|
||||||
{{ item.stnm }}
|
{{ item.ennm }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-button
|
<a-button
|
||||||
@ -109,14 +117,16 @@
|
|||||||
placeholder="请选择站点"
|
placeholder="请选择站点"
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
@change="handleEditNodeSelect"
|
@change="() => handleEditNodeSelect(dataRef)"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="item in stationList"
|
v-for="item in dataRef.parentId
|
||||||
|
? childStationList
|
||||||
|
: stationList"
|
||||||
:key="item.stcd"
|
:key="item.stcd"
|
||||||
:value="item.stcd"
|
:value="item.stcd"
|
||||||
>
|
>
|
||||||
{{ item.stnm }}
|
{{ dataRef.parentId ? item.stnm : item.ennm }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-button
|
<a-button
|
||||||
@ -238,7 +248,7 @@
|
|||||||
@change="handleChildNodeSelect"
|
@change="handleChildNodeSelect"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="item in stationList"
|
v-for="item in childStationList"
|
||||||
:key="item.stcd"
|
:key="item.stcd"
|
||||||
:value="item.stcd"
|
:value="item.stcd"
|
||||||
>
|
>
|
||||||
@ -280,18 +290,21 @@ import {
|
|||||||
ArrowUpOutlined,
|
ArrowUpOutlined,
|
||||||
ArrowDownOutlined
|
ArrowDownOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
|
import { getEngInfoDropdown, getAddvcdDropdownByRvcd } from '@/api/select';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
initialValues?: any | null;
|
initialValues?: any | null;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
|
riverOptions?: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const localLoading = ref(false);
|
const localLoading = ref(false);
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
visible: false,
|
visible: false,
|
||||||
initialValues: null,
|
initialValues: null,
|
||||||
loading: false
|
loading: false,
|
||||||
|
riverOptions: () => []
|
||||||
});
|
});
|
||||||
|
|
||||||
const modalVisible = computed({
|
const modalVisible = computed({
|
||||||
@ -311,15 +324,20 @@ const defaultFormData = reactive({
|
|||||||
id: undefined,
|
id: undefined,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
code: undefined,
|
code: undefined,
|
||||||
rvnm: undefined,
|
rvcd: undefined,
|
||||||
description: undefined
|
remark: undefined
|
||||||
});
|
});
|
||||||
const formData: any = reactive({ ...defaultFormData });
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
|
||||||
const rules: Record<string, Rule[]> = {
|
const rules: Record<string, Rule[]> = {
|
||||||
name: [{ required: true, message: '请输入沿程配置名称', trigger: 'blur' }],
|
name: [{ required: true, message: '请输入沿程配置名称', trigger: 'blur' }],
|
||||||
code: [{ required: true, message: '请输入配置编码', trigger: 'blur' }],
|
code: [{ required: true, message: '请输入配置编码', trigger: 'blur' }],
|
||||||
rvnm: [{ required: true, message: '请输入所在河段', trigger: 'blur' }]
|
rvcd: [{ required: true, message: '请选择所在河段', trigger: 'change' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRiverSelect = async (value: string) => {
|
||||||
|
const res = await getEngInfoDropdown({ rvcd: value });
|
||||||
|
stationList.value = res.data || [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const isEdit = computed(() => !!props.initialValues);
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
@ -331,7 +349,7 @@ const treeData = ref<any[]>([]);
|
|||||||
const addingNewNode = ref(false);
|
const addingNewNode = ref(false);
|
||||||
const newNodeData = ref({
|
const newNodeData = ref({
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: ''
|
sttpName: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -340,7 +358,7 @@ const addingChildNode = ref(false);
|
|||||||
const currentParentKey = ref<string | null>(null);
|
const currentParentKey = ref<string | null>(null);
|
||||||
const childNodeData = ref({
|
const childNodeData = ref({
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: ''
|
sttpName: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -349,18 +367,13 @@ const editingNode = ref(false);
|
|||||||
const editingNodeKey = ref<string | null>(null);
|
const editingNodeKey = ref<string | null>(null);
|
||||||
const editNodeData = ref({
|
const editNodeData = ref({
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: '',
|
sttpName: '',
|
||||||
originalData: null as any
|
originalData: null as any
|
||||||
});
|
});
|
||||||
|
|
||||||
// 站点列表(模拟数据,实际应从接口获取)
|
const stationList = ref([]);
|
||||||
const stationList = ref([
|
const childStationList = ref([]);
|
||||||
{ stcd: '1', stnm: '站点A', sttpName: '类型1' },
|
|
||||||
{ stcd: '2', stnm: '站点B', sttpName: '类型2' },
|
|
||||||
{ stcd: '3', stnm: '站点C', sttpName: '类型1' },
|
|
||||||
{ stcd: '4', stnm: '站点D', sttpName: '类型3' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 生成唯一ID
|
// 生成唯一ID
|
||||||
let nodeIdCounter = 0;
|
let nodeIdCounter = 0;
|
||||||
@ -369,19 +382,19 @@ const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`;
|
|||||||
// 获取节点标题
|
// 获取节点标题
|
||||||
const getNodeTitle = (dataRef: any) => {
|
const getNodeTitle = (dataRef: any) => {
|
||||||
if (!dataRef.parentId) {
|
if (!dataRef.parentId) {
|
||||||
// 一级节点:只显示 stnm
|
return dataRef.ennm || '';
|
||||||
return dataRef.stnm || '';
|
|
||||||
} else {
|
} else {
|
||||||
// 二级节点:显示 stnm + sttpName
|
return `${dataRef.ennm || ''} ${dataRef.sttpName || ''}`;
|
||||||
return `${dataRef.stnm || ''} ${dataRef.sttpName || ''}`;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 搜索过滤
|
// 搜索过滤
|
||||||
const filterOption = (input: string, option: any) => {
|
const filterOption = (inputValue: string, option: any) => {
|
||||||
return (
|
const label = option.label || option.name || '';
|
||||||
option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
const reachcdName = option.reachcdName || '';
|
||||||
);
|
const keyword = inputValue || '';
|
||||||
|
|
||||||
|
return label.indexOf(keyword) !== -1 || reachcdName.indexOf(keyword) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 判断是否为第一个节点
|
// 判断是否为第一个节点
|
||||||
@ -426,10 +439,14 @@ const findNodeByKey = (nodes: any[], key: string): any => {
|
|||||||
|
|
||||||
// 新增一级节点
|
// 新增一级节点
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
if (!formData.rvcd) {
|
||||||
|
message.warning('请先选择所在河段');
|
||||||
|
return;
|
||||||
|
}
|
||||||
addingNewNode.value = true;
|
addingNewNode.value = true;
|
||||||
newNodeData.value = {
|
newNodeData.value = {
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: ''
|
sttpName: ''
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -438,7 +455,7 @@ const handleAdd = () => {
|
|||||||
const handleNodeSelect = (value: string) => {
|
const handleNodeSelect = (value: string) => {
|
||||||
const station = stationList.value.find(item => item.stcd === value);
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
if (station) {
|
if (station) {
|
||||||
newNodeData.value.stnm = station.stnm;
|
newNodeData.value.ennm = station.ennm;
|
||||||
newNodeData.value.sttpName = station.sttpName;
|
newNodeData.value.sttpName = station.sttpName;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -453,7 +470,7 @@ const handleSaveNewNode = () => {
|
|||||||
const newNode = {
|
const newNode = {
|
||||||
key: generateNodeId(),
|
key: generateNodeId(),
|
||||||
stcd: newNodeData.value.stcd,
|
stcd: newNodeData.value.stcd,
|
||||||
stnm: newNodeData.value.stnm,
|
ennm: newNodeData.value.ennm,
|
||||||
sttpName: newNodeData.value.sttpName,
|
sttpName: newNodeData.value.sttpName,
|
||||||
parentId: null,
|
parentId: null,
|
||||||
children: []
|
children: []
|
||||||
@ -469,27 +486,29 @@ const handleCancelAdd = () => {
|
|||||||
addingNewNode.value = false;
|
addingNewNode.value = false;
|
||||||
newNodeData.value = {
|
newNodeData.value = {
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: ''
|
sttpName: ''
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加子节点(二级节点)
|
// 添加子节点(二级节点)
|
||||||
const handleAddChild = (parentData: any) => {
|
const handleAddChild = async (parentData: any) => {
|
||||||
addingChildNode.value = true;
|
addingChildNode.value = true;
|
||||||
currentParentKey.value = parentData.key;
|
currentParentKey.value = parentData.key;
|
||||||
childNodeData.value = {
|
childNodeData.value = {
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: ''
|
sttpName: ''
|
||||||
};
|
};
|
||||||
|
const res = await getAddvcdDropdownByRvcd({ stcd: parentData.stcd });
|
||||||
|
childStationList.value = res.data || [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 选择子节点
|
// 选择子节点
|
||||||
const handleChildNodeSelect = (value: string) => {
|
const handleChildNodeSelect = (value: string) => {
|
||||||
const station = stationList.value.find(item => item.stcd === value);
|
const station = childStationList.value.find(item => item.stcd === value);
|
||||||
if (station) {
|
if (station) {
|
||||||
childNodeData.value.stnm = station.stnm;
|
childNodeData.value.ennm = station.stnm;
|
||||||
childNodeData.value.sttpName = station.sttpName;
|
childNodeData.value.sttpName = station.sttpName;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -510,7 +529,7 @@ const handleSaveChildNode = () => {
|
|||||||
const newChild = {
|
const newChild = {
|
||||||
key: generateNodeId(),
|
key: generateNodeId(),
|
||||||
stcd: childNodeData.value.stcd,
|
stcd: childNodeData.value.stcd,
|
||||||
stnm: childNodeData.value.stnm,
|
ennm: childNodeData.value.ennm,
|
||||||
sttpName: childNodeData.value.sttpName,
|
sttpName: childNodeData.value.sttpName,
|
||||||
parentId: parent.key,
|
parentId: parent.key,
|
||||||
children: []
|
children: []
|
||||||
@ -533,29 +552,38 @@ const handleCancelAddChild = () => {
|
|||||||
currentParentKey.value = null;
|
currentParentKey.value = null;
|
||||||
childNodeData.value = {
|
childNodeData.value = {
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: ''
|
sttpName: ''
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 编辑节点
|
// 编辑节点
|
||||||
const handleEditNode = (dataRef: any) => {
|
const handleEditNode = async (dataRef: any) => {
|
||||||
editingNode.value = true;
|
editingNode.value = true;
|
||||||
editingNodeKey.value = dataRef.key;
|
editingNodeKey.value = dataRef.key;
|
||||||
// 保存原始数据
|
// 保存原始数据
|
||||||
editNodeData.value = {
|
editNodeData.value = {
|
||||||
stcd: dataRef.stcd,
|
stcd: dataRef.stcd,
|
||||||
stnm: dataRef.stnm,
|
ennm: dataRef.ennm,
|
||||||
sttpName: dataRef.sttpName,
|
sttpName: dataRef.sttpName,
|
||||||
originalData: { ...dataRef }
|
originalData: { ...dataRef }
|
||||||
};
|
};
|
||||||
|
if (dataRef.parentId) {
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
if (parent) {
|
||||||
|
const res = await getAddvcdDropdownByRvcd({ stcd: parent.stcd });
|
||||||
|
childStationList.value = res.data || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 选择编辑节点
|
// 选择编辑节点
|
||||||
const handleEditNodeSelect = (value: string) => {
|
const handleEditNodeSelect = (dataRef: any) => {
|
||||||
const station = stationList.value.find(item => item.stcd === value);
|
const value = editNodeData.value.stcd;
|
||||||
|
const list = dataRef.parentId ? childStationList.value : stationList.value;
|
||||||
|
const station = list.find(item => item.stcd === value);
|
||||||
if (station) {
|
if (station) {
|
||||||
editNodeData.value.stnm = station.stnm;
|
editNodeData.value.ennm = dataRef.parentId ? station.stnm : station.ennm;
|
||||||
editNodeData.value.sttpName = station.sttpName;
|
editNodeData.value.sttpName = station.sttpName;
|
||||||
editNodeData.value.stcd = station.stcd;
|
editNodeData.value.stcd = station.stcd;
|
||||||
}
|
}
|
||||||
@ -577,7 +605,7 @@ const handleSaveEditNode = () => {
|
|||||||
|
|
||||||
// 更新节点数据
|
// 更新节点数据
|
||||||
node.stcd = editNodeData.value.stcd;
|
node.stcd = editNodeData.value.stcd;
|
||||||
node.stnm = editNodeData.value.stnm;
|
node.ennm = editNodeData.value.ennm;
|
||||||
node.sttpName = editNodeData.value.sttpName;
|
node.sttpName = editNodeData.value.sttpName;
|
||||||
|
|
||||||
editingNode.value = false;
|
editingNode.value = false;
|
||||||
@ -591,7 +619,7 @@ const handleCancelEditNode = () => {
|
|||||||
editingNodeKey.value = null;
|
editingNodeKey.value = null;
|
||||||
editNodeData.value = {
|
editNodeData.value = {
|
||||||
stcd: undefined,
|
stcd: undefined,
|
||||||
stnm: '',
|
ennm: '',
|
||||||
sttpName: '',
|
sttpName: '',
|
||||||
originalData: null
|
originalData: null
|
||||||
};
|
};
|
||||||
@ -631,7 +659,7 @@ const handleMoveDown = (dataRef: any) => {
|
|||||||
const handleDeleteNode = (dataRef: any) => {
|
const handleDeleteNode = (dataRef: any) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '确认删除',
|
title: '确认删除',
|
||||||
content: `确定要删除节点"${dataRef.stnm}"吗?`,
|
content: `确定要删除节点"${dataRef.ennm}"吗?`,
|
||||||
okText: '确定',
|
okText: '确定',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
@ -677,7 +705,7 @@ const handleOk = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const initForm = () => {
|
const initForm = async () => {
|
||||||
if (props.initialValues) {
|
if (props.initialValues) {
|
||||||
const values = props.initialValues;
|
const values = props.initialValues;
|
||||||
Object.keys(formData).forEach(key => {
|
Object.keys(formData).forEach(key => {
|
||||||
@ -702,6 +730,12 @@ const initForm = () => {
|
|||||||
} else {
|
} else {
|
||||||
treeData.value = [];
|
treeData.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 编辑时调用接口获取一级站点列表
|
||||||
|
if (formData.rvcd) {
|
||||||
|
const res = await getEngInfoDropdown({ rvcd: formData.rvcd });
|
||||||
|
stationList.value = res.data || [];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
resetForm();
|
resetForm();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,9 @@
|
|||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<a-tooltip title="新增配置">
|
<a-tooltip title="新增配置">
|
||||||
<a-button @click="props.handleAdd" type="primary"> 新增沿程配置 </a-button>
|
<a-button @click="props.handleAdd" type="primary">
|
||||||
|
新增沿程配置
|
||||||
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</BasicSearch>
|
</BasicSearch>
|
||||||
@ -18,46 +20,52 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import BasicSearch from "@/components/BasicSearch/index.vue";
|
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
handleAdd: () => void;
|
handleAdd: () => void;
|
||||||
|
riverOptions: any[];
|
||||||
|
riverOptionsLoad: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "reset", values: any): void;
|
(e: 'reset', values: any): void;
|
||||||
(e: "searchFinish", values: any): void;
|
(e: 'searchFinish', values: any): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const initSearchData = {
|
const initSearchData = {
|
||||||
configName: "",
|
name: null,
|
||||||
|
rvcd: null
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchData = ref<any>({ ...initSearchData });
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
const searchList: any = computed(() => [
|
const searchList: any = computed(() => [
|
||||||
{
|
{
|
||||||
type: "Input",
|
type: 'Input',
|
||||||
name: "name",
|
name: 'name',
|
||||||
label: "沿程配置名称",
|
label: '沿程配置名称',
|
||||||
fieldProps: {
|
fieldProps: {
|
||||||
allowClear: true,
|
allowClear: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "Input",
|
type: 'Select',
|
||||||
name: "rvnm",
|
name: 'rvcd',
|
||||||
label: "所在河段",
|
label: '所在河段',
|
||||||
|
width: 300,
|
||||||
fieldProps: {
|
fieldProps: {
|
||||||
allowClear: true,
|
allowClear: true
|
||||||
},
|
},
|
||||||
},
|
options: props.riverOptions,
|
||||||
|
loading: props.riverOptionsLoad
|
||||||
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onSearchFinish = (values: any) => {
|
const onSearchFinish = (values: any) => {
|
||||||
emit("searchFinish", values);
|
emit('searchFinish', values);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
@ -65,11 +73,11 @@ const onValuesChange = (changedValues: any, allValues: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
emit("reset", initSearchData);
|
emit('reset', initSearchData);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
emit("searchFinish", initSearchData);
|
emit('searchFinish', initSearchData);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss"></style>
|
<style lang="scss"></style>
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
<ConfigManagementSearch
|
<ConfigManagementSearch
|
||||||
ref="configManagementSearch"
|
ref="configManagementSearch"
|
||||||
:handle-add="handleAdd"
|
:handle-add="handleAdd"
|
||||||
|
:river-options="riverOptions"
|
||||||
|
:river-options-load="riverOptionsLoad"
|
||||||
@reset="handleReset"
|
@reset="handleReset"
|
||||||
@search-finish="onSearchFinish"
|
@search-finish="onSearchFinish"
|
||||||
/>
|
/>
|
||||||
@ -37,6 +39,8 @@
|
|||||||
ref="configManagementForm"
|
ref="configManagementForm"
|
||||||
v-model:visible="editModalVisible"
|
v-model:visible="editModalVisible"
|
||||||
:initial-values="currentRecord"
|
:initial-values="currentRecord"
|
||||||
|
:river-options="riverOptions"
|
||||||
|
:river-options-load="riverOptionsLoad"
|
||||||
@cancel="editModalCancel"
|
@cancel="editModalCancel"
|
||||||
@ok="handleEditSubmit"
|
@ok="handleEditSubmit"
|
||||||
/>
|
/>
|
||||||
@ -52,8 +56,10 @@ import { message, Modal } from 'ant-design-vue';
|
|||||||
import {
|
import {
|
||||||
getAllConfigTree,
|
getAllConfigTree,
|
||||||
deleteBaseWbsb,
|
deleteBaseWbsb,
|
||||||
saveBaseWbsb
|
saveBaseWbsbChild,
|
||||||
|
saveBaseWbsbChildDetail
|
||||||
} from '@/api/system/map/ConfigManagement';
|
} from '@/api/system/map/ConfigManagement';
|
||||||
|
import { getRvcdDropdown } from '@/api/select';
|
||||||
|
|
||||||
// 表格实例
|
// 表格实例
|
||||||
const basicTable = ref<any>(null);
|
const basicTable = ref<any>(null);
|
||||||
@ -129,9 +135,20 @@ const handleAdd = () => {
|
|||||||
editModalVisible.value = true;
|
editModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 过滤掉值为 '-' 的字段
|
||||||
|
const filterRecord = (record: any) => {
|
||||||
|
const filtered: any = {};
|
||||||
|
Object.keys(record).forEach(key => {
|
||||||
|
if (record[key] !== '-') {
|
||||||
|
filtered[key] = record[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filtered;
|
||||||
|
};
|
||||||
|
|
||||||
// 编辑处理
|
// 编辑处理
|
||||||
const handleEdit = (record: any) => {
|
const handleEdit = (record: any) => {
|
||||||
currentRecord.value = { ...record };
|
currentRecord.value = filterRecord(record);
|
||||||
editModalVisible.value = true;
|
editModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,8 +161,12 @@ const handleDelete = (record: any) => {
|
|||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
let res = await deleteBaseWbsb([record.id]);
|
let res = await deleteBaseWbsb([record.id]);
|
||||||
message.success('删除成功');
|
if (res.code == 0) {
|
||||||
basicTable.value.refresh();
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} else {
|
||||||
|
message.error('删除失败');
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error('删除失败');
|
message.error('删除失败');
|
||||||
return;
|
return;
|
||||||
@ -159,12 +180,12 @@ const onSearchFinish = (values: any) => {
|
|||||||
const params = {
|
const params = {
|
||||||
logic: 'and',
|
logic: 'and',
|
||||||
filters: [
|
filters: [
|
||||||
values.parentId
|
values.rvcd
|
||||||
? {
|
? {
|
||||||
field: 'parentId',
|
field: 'rvcd',
|
||||||
operator: 'eq',
|
operator: 'eq',
|
||||||
dataType: 'string',
|
dataType: 'string',
|
||||||
value: values.parentId
|
value: values.rvcd
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
values.name
|
values.name
|
||||||
@ -197,23 +218,79 @@ const editModalCancel = () => {
|
|||||||
// 表单提交
|
// 表单提交
|
||||||
const handleEditSubmit = async (values: any) => {
|
const handleEditSubmit = async (values: any) => {
|
||||||
try {
|
try {
|
||||||
let res = await saveBaseWbsb({
|
const formData = {
|
||||||
...currentRecord.value,
|
...currentRecord.value,
|
||||||
...values
|
...values
|
||||||
});
|
};
|
||||||
message.success(`保存成功`);
|
delete formData.configNodes;
|
||||||
|
|
||||||
editModalVisible.value = false;
|
Object.keys(formData).forEach(key => {
|
||||||
basicTable.value.refresh();
|
if (key.includes('-')) {
|
||||||
|
delete formData[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let res = await saveBaseWbsbChild(formData);
|
||||||
|
if (res.code == 0) {
|
||||||
|
const alongId = res.data;
|
||||||
|
const treeData = values.configNodes || [];
|
||||||
|
|
||||||
|
if (treeData.length > 0) {
|
||||||
|
const formatTreeData = (
|
||||||
|
nodes: any[],
|
||||||
|
parentId: string | null = null
|
||||||
|
) => {
|
||||||
|
return nodes.map(node => ({
|
||||||
|
alongId,
|
||||||
|
stcd: node.stcd,
|
||||||
|
stnm: node.ennm,
|
||||||
|
sttpName: node.sttpName,
|
||||||
|
parentId: parentId ? parentId : null,
|
||||||
|
children:
|
||||||
|
node.children && node.children.length > 0
|
||||||
|
? formatTreeData(node.children, node.key)
|
||||||
|
: []
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const detailData = formatTreeData(treeData);
|
||||||
|
|
||||||
|
const detailRes = await saveBaseWbsbChildDetail(detailData);
|
||||||
|
if (detailRes.code == 0) {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} else {
|
||||||
|
message.error(`保存子节点失败`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error(`保存失败`);
|
message.error(`保存失败`);
|
||||||
|
|
||||||
editModalVisible.value = false;
|
editModalVisible.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const riverOptions = ref<any>([]);
|
||||||
const initOption = () => {};
|
const riverOptionsLoad = ref(false);
|
||||||
|
const initOption = () => {
|
||||||
|
const params = {};
|
||||||
|
riverOptionsLoad.value = true;
|
||||||
|
getRvcdDropdown(params).then((res: any) => {
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
item.value = item.rvcd;
|
||||||
|
item.label = item.rvnm;
|
||||||
|
});
|
||||||
|
riverOptions.value = res.data || [];
|
||||||
|
riverOptionsLoad.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initOption();
|
initOption();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<a-modal
|
<a-modal
|
||||||
:title="isEdit ? '编辑图例数据' : '新增图例数据'"
|
:title="isEdit ? '编辑图例数据' : '新增图例数据'"
|
||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
:confirm-loading="localLoading"
|
:confirm-loading="confirmLoading"
|
||||||
width="600px"
|
width="600px"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
@ -194,6 +194,10 @@ const modalVisible = computed({
|
|||||||
set: val => emit('update:visible', val)
|
set: val => emit('update:visible', val)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const confirmLoading = computed(() => {
|
||||||
|
return localLoading.value || props.loading;
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:visible', value: boolean): void;
|
(e: 'update:visible', value: boolean): void;
|
||||||
(e: 'cancel'): void;
|
(e: 'cancel'): void;
|
||||||
@ -276,6 +280,7 @@ const handleLayerSelect = (value: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
|
localLoading.value = true;
|
||||||
try {
|
try {
|
||||||
await formRef.value.validate();
|
await formRef.value.validate();
|
||||||
// 过滤掉 undefined 的字段,不提交空值
|
// 过滤掉 undefined 的字段,不提交空值
|
||||||
@ -329,6 +334,7 @@ const handleOk = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Validate Failed:', error);
|
console.error('Validate Failed:', error);
|
||||||
message.error('请检查表单填写是否正确');
|
message.error('请检查表单填写是否正确');
|
||||||
|
localLoading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -350,6 +356,7 @@ const resetForm = () => {
|
|||||||
formRef.value.resetFields();
|
formRef.value.resetFields();
|
||||||
}
|
}
|
||||||
Object.assign(formData, defaultFormData);
|
Object.assign(formData, defaultFormData);
|
||||||
|
localLoading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
@ -358,11 +365,22 @@ const handleCancel = () => {
|
|||||||
resetForm();
|
resetForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.loading,
|
||||||
|
newLoading => {
|
||||||
|
if (newLoading) {
|
||||||
|
localLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
newVisible => {
|
newVisible => {
|
||||||
if (newVisible) {
|
if (newVisible) {
|
||||||
initForm();
|
initForm();
|
||||||
|
} else {
|
||||||
|
localLoading.value = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: false }
|
{ immediate: false }
|
||||||
|
|||||||
@ -66,6 +66,7 @@
|
|||||||
:LayerOptions="LayerOptions"
|
:LayerOptions="LayerOptions"
|
||||||
v-model:visible="editModalVisible"
|
v-model:visible="editModalVisible"
|
||||||
:initial-values="currentRecord"
|
:initial-values="currentRecord"
|
||||||
|
:loading="editLoading"
|
||||||
@cancel="editModalCancel"
|
@cancel="editModalCancel"
|
||||||
@ok="handleEditSubmit"
|
@ok="handleEditSubmit"
|
||||||
/>
|
/>
|
||||||
@ -249,6 +250,7 @@ const LegendOptions = ref<any[]>([]);
|
|||||||
const LayerOptions = ref<any[]>([]);
|
const LayerOptions = ref<any[]>([]);
|
||||||
const currentRecord = ref<any | null>(null);
|
const currentRecord = ref<any | null>(null);
|
||||||
const editModalVisible = ref(false);
|
const editModalVisible = ref(false);
|
||||||
|
const editLoading = ref(false);
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
currentRecord.value = null;
|
currentRecord.value = null;
|
||||||
ensureOptionsLoaded().then(() => {
|
ensureOptionsLoaded().then(() => {
|
||||||
@ -401,11 +403,16 @@ const editModalCancel = () => {
|
|||||||
|
|
||||||
// 表单提交
|
// 表单提交
|
||||||
const handleEditSubmit = async (values: any, type: string) => {
|
const handleEditSubmit = async (values: any, type: string) => {
|
||||||
|
editLoading.value = true;
|
||||||
try {
|
try {
|
||||||
let res = await saveMapLegend({
|
let res = await saveMapLegend({
|
||||||
...currentRecord.value,
|
...currentRecord.value,
|
||||||
...values
|
...values
|
||||||
});
|
});
|
||||||
|
if (res.code == 1) {
|
||||||
|
message.error('保存失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (type === 'switch') {
|
if (type === 'switch') {
|
||||||
message.success('修改状态成功');
|
message.success('修改状态成功');
|
||||||
} else {
|
} else {
|
||||||
@ -421,6 +428,8 @@ const handleEditSubmit = async (values: any, type: string) => {
|
|||||||
}
|
}
|
||||||
editModalVisible.value = false;
|
editModalVisible.value = false;
|
||||||
return;
|
return;
|
||||||
|
} finally {
|
||||||
|
editLoading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const initOption = () => {
|
const initOption = () => {
|
||||||
|
|||||||
@ -0,0 +1,784 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑沿程配置' : '新增沿程配置'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="localLoading"
|
||||||
|
width="1200px"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
ok-text="保存"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
name="edit_form"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="沿程配置名称" name="name">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.name"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入沿程配置名称"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="配置编码" name="code">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.code"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入配置编码"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="所在河段" name="rvnm">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.rvnm"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入所在河段"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="备注" name="description">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.description"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
<div class="config-tree-container">
|
||||||
|
<!-- 新增一级节点区域 -->
|
||||||
|
<div v-if="addingNewNode" class="add-node-row">
|
||||||
|
<a-select
|
||||||
|
v-model:value="newNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveNewNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleCancelAdd" style="margin-left: 8px">
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<a-button v-else class="mb-4" type="primary" @click="handleAdd">
|
||||||
|
<PlusOutlined /> 新增一级节点
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<!-- 树形结构 -->
|
||||||
|
<a-tree
|
||||||
|
v-if="treeData.length > 0"
|
||||||
|
:tree-data="treeData"
|
||||||
|
:default-expand-all="false"
|
||||||
|
:selectable="false"
|
||||||
|
block-node
|
||||||
|
style="width: 300px"
|
||||||
|
>
|
||||||
|
<template #title="{ dataRef }">
|
||||||
|
<!-- 编辑状态:只显示编辑区域 -->
|
||||||
|
<div
|
||||||
|
v-if="editingNode && editingNodeKey === dataRef.key"
|
||||||
|
class="add-child-node-row w-[300px]"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="editNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleEditNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click.stop="handleSaveEditNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
@click.stop="handleCancelEditNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<!-- 非编辑状态:显示正常节点内容 -->
|
||||||
|
<template v-else>
|
||||||
|
<div class="tree-node-wrapper">
|
||||||
|
<span class="tree-node-title"> {{ getNodeTitle(dataRef) }} </span>
|
||||||
|
<div class="tree-node-actions">
|
||||||
|
<!-- 一级节点:支持新增子节点、编辑、排序、删除 -->
|
||||||
|
<template v-if="!dataRef.parentId">
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleAddChild(dataRef)"
|
||||||
|
title="添加子节点"
|
||||||
|
>
|
||||||
|
<PlusOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleEditNode(dataRef)"
|
||||||
|
title="编辑"
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveUp(dataRef)"
|
||||||
|
title="上移"
|
||||||
|
:disabled="isFirstNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowUpOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveDown(dataRef)"
|
||||||
|
title="下移"
|
||||||
|
:disabled="isLastNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowDownOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="handleDeleteNode(dataRef)"
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<!-- 二级节点:只支持编辑、排序、删除 -->
|
||||||
|
<template v-else>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleEditNode(dataRef)"
|
||||||
|
title="编辑"
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveUp(dataRef)"
|
||||||
|
title="上移"
|
||||||
|
:disabled="isFirstNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowUpOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveDown(dataRef)"
|
||||||
|
title="下移"
|
||||||
|
:disabled="isLastNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowDownOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="handleDeleteNode(dataRef)"
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 子节点添加区域 -->
|
||||||
|
<div
|
||||||
|
v-if="addingChildNode && currentParentKey === dataRef.key"
|
||||||
|
class="add-child-node-row"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="childNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleChildNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click.stop="handleSaveChildNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
@click.stop="handleCancelAddChild"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-tree>
|
||||||
|
<a-empty v-else description="暂无数据" style="margin-top: 20px" />
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
PlusOutlined,
|
||||||
|
MinusOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
ArrowUpOutlined,
|
||||||
|
ArrowDownOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
code: undefined,
|
||||||
|
rvnm: undefined,
|
||||||
|
description: undefined
|
||||||
|
});
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
name: [{ required: true, message: '请输入沿程配置名称', trigger: 'blur' }],
|
||||||
|
code: [{ required: true, message: '请输入配置编码', trigger: 'blur' }],
|
||||||
|
rvnm: [{ required: true, message: '请输入所在河段', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
|
||||||
|
// 树形数据
|
||||||
|
const treeData = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 新增节点相关
|
||||||
|
const addingNewNode = ref(false);
|
||||||
|
const newNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加子节点相关
|
||||||
|
const addingChildNode = ref(false);
|
||||||
|
const currentParentKey = ref<string | null>(null);
|
||||||
|
const childNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 编辑节点相关
|
||||||
|
const editingNode = ref(false);
|
||||||
|
const editingNodeKey = ref<string | null>(null);
|
||||||
|
const editNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: '',
|
||||||
|
originalData: null as any
|
||||||
|
});
|
||||||
|
|
||||||
|
// 站点列表(模拟数据,实际应从接口获取)
|
||||||
|
const stationList = ref([
|
||||||
|
{ stcd: '1', stnm: '站点A', sttpName: '类型1' },
|
||||||
|
{ stcd: '2', stnm: '站点B', sttpName: '类型2' },
|
||||||
|
{ stcd: '3', stnm: '站点C', sttpName: '类型1' },
|
||||||
|
{ stcd: '4', stnm: '站点D', sttpName: '类型3' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 生成唯一ID
|
||||||
|
let nodeIdCounter = 0;
|
||||||
|
const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`;
|
||||||
|
|
||||||
|
// 获取节点标题
|
||||||
|
const getNodeTitle = (dataRef: any) => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 一级节点:只显示 stnm
|
||||||
|
return dataRef.stnm || '';
|
||||||
|
} else {
|
||||||
|
// 二级节点:显示 stnm + sttpName
|
||||||
|
return `${dataRef.stnm || ''} ${dataRef.sttpName || ''}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索过滤
|
||||||
|
const filterOption = (input: string, option: any) => {
|
||||||
|
return (
|
||||||
|
option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为第一个节点
|
||||||
|
const isFirstNode = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
return siblings.length > 0 && siblings[0].key === dataRef.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为最后一个节点
|
||||||
|
const isLastNode = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
return (
|
||||||
|
siblings.length > 0 && siblings[siblings.length - 1].key === dataRef.key
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取兄弟节点
|
||||||
|
const getSiblings = (dataRef: any) => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 一级节点
|
||||||
|
return treeData.value;
|
||||||
|
} else {
|
||||||
|
// 二级节点,找到父节点的 children
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
return parent?.children || [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据 key 查找节点
|
||||||
|
const findNodeByKey = (nodes: any[], key: string): any => {
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (node.key === key) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (node.children && node.children.length > 0) {
|
||||||
|
const found = findNodeByKey(node.children, key);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增一级节点
|
||||||
|
const handleAdd = () => {
|
||||||
|
addingNewNode.value = true;
|
||||||
|
newNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择节点
|
||||||
|
const handleNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
newNodeData.value.stnm = station.stnm;
|
||||||
|
newNodeData.value.sttpName = station.sttpName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存新增节点
|
||||||
|
const handleSaveNewNode = () => {
|
||||||
|
if (!newNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newNode = {
|
||||||
|
key: generateNodeId(),
|
||||||
|
stcd: newNodeData.value.stcd,
|
||||||
|
stnm: newNodeData.value.stnm,
|
||||||
|
sttpName: newNodeData.value.sttpName,
|
||||||
|
parentId: null,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
treeData.value.push(newNode);
|
||||||
|
addingNewNode.value = false;
|
||||||
|
message.success('添加成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消新增
|
||||||
|
const handleCancelAdd = () => {
|
||||||
|
addingNewNode.value = false;
|
||||||
|
newNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加子节点(二级节点)
|
||||||
|
const handleAddChild = (parentData: any) => {
|
||||||
|
addingChildNode.value = true;
|
||||||
|
currentParentKey.value = parentData.key;
|
||||||
|
childNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择子节点
|
||||||
|
const handleChildNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
childNodeData.value.stnm = station.stnm;
|
||||||
|
childNodeData.value.sttpName = station.sttpName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存新增子节点
|
||||||
|
const handleSaveChildNode = () => {
|
||||||
|
if (!childNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = findNodeByKey(treeData.value, currentParentKey.value!);
|
||||||
|
if (!parent) {
|
||||||
|
message.error('父节点不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newChild = {
|
||||||
|
key: generateNodeId(),
|
||||||
|
stcd: childNodeData.value.stcd,
|
||||||
|
stnm: childNodeData.value.stnm,
|
||||||
|
sttpName: childNodeData.value.sttpName,
|
||||||
|
parentId: parent.key,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
// 在子节点列表顶部添加
|
||||||
|
parent.children.unshift(newChild);
|
||||||
|
|
||||||
|
addingChildNode.value = false;
|
||||||
|
currentParentKey.value = null;
|
||||||
|
message.success('添加子节点成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消添加子节点
|
||||||
|
const handleCancelAddChild = () => {
|
||||||
|
addingChildNode.value = false;
|
||||||
|
currentParentKey.value = null;
|
||||||
|
childNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑节点
|
||||||
|
const handleEditNode = (dataRef: any) => {
|
||||||
|
editingNode.value = true;
|
||||||
|
editingNodeKey.value = dataRef.key;
|
||||||
|
// 保存原始数据
|
||||||
|
editNodeData.value = {
|
||||||
|
stcd: dataRef.stcd,
|
||||||
|
stnm: dataRef.stnm,
|
||||||
|
sttpName: dataRef.sttpName,
|
||||||
|
originalData: { ...dataRef }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择编辑节点
|
||||||
|
const handleEditNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
editNodeData.value.stnm = station.stnm;
|
||||||
|
editNodeData.value.sttpName = station.sttpName;
|
||||||
|
editNodeData.value.stcd = station.stcd;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存编辑节点
|
||||||
|
const handleSaveEditNode = () => {
|
||||||
|
if (!editNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到要编辑的节点
|
||||||
|
const node = findNodeByKey(treeData.value, editingNodeKey.value!);
|
||||||
|
if (!node) {
|
||||||
|
message.error('节点不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新节点数据
|
||||||
|
node.stcd = editNodeData.value.stcd;
|
||||||
|
node.stnm = editNodeData.value.stnm;
|
||||||
|
node.sttpName = editNodeData.value.sttpName;
|
||||||
|
|
||||||
|
editingNode.value = false;
|
||||||
|
editingNodeKey.value = null;
|
||||||
|
message.success('编辑成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消编辑节点
|
||||||
|
const handleCancelEditNode = () => {
|
||||||
|
editingNode.value = false;
|
||||||
|
editingNodeKey.value = null;
|
||||||
|
editNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
stnm: '',
|
||||||
|
sttpName: '',
|
||||||
|
originalData: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上移
|
||||||
|
const handleMoveUp = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
// 交换位置
|
||||||
|
[siblings[index - 1], siblings[index]] = [
|
||||||
|
siblings[index],
|
||||||
|
siblings[index - 1]
|
||||||
|
];
|
||||||
|
message.success('上移成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下移
|
||||||
|
const handleMoveDown = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||||
|
|
||||||
|
if (index < siblings.length - 1) {
|
||||||
|
// 交换位置
|
||||||
|
[siblings[index], siblings[index + 1]] = [
|
||||||
|
siblings[index + 1],
|
||||||
|
siblings[index]
|
||||||
|
];
|
||||||
|
message.success('下移成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除节点
|
||||||
|
const handleDeleteNode = (dataRef: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: `确定要删除节点"${dataRef.stnm}"吗?`,
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 删除一级节点
|
||||||
|
const index = treeData.value.findIndex(
|
||||||
|
item => item.key === dataRef.key
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
treeData.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 删除二级节点
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
if (parent && parent.children) {
|
||||||
|
const index = parent.children.findIndex(
|
||||||
|
item => item.key === dataRef.key
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
parent.children.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.success('删除成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
const submitValues = {
|
||||||
|
...formData,
|
||||||
|
captureDate: formData.captureDate
|
||||||
|
? dayjs(formData.captureDate).format('YYYY-MM-DD')
|
||||||
|
: undefined,
|
||||||
|
configNodes: treeData.value // 提交树形数据
|
||||||
|
};
|
||||||
|
emit('ok', submitValues);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initForm = () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
const values = props.initialValues;
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
if (key === 'captureDate' && values[key]) {
|
||||||
|
formData[key] = dayjs(values[key]);
|
||||||
|
} else {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化树形数据
|
||||||
|
if (values.configNodes && Array.isArray(values.configNodes)) {
|
||||||
|
treeData.value = values.configNodes.map((node: any) => ({
|
||||||
|
...node,
|
||||||
|
children:
|
||||||
|
node.children?.map((child: any) => ({
|
||||||
|
...child
|
||||||
|
})) || []
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
treeData.value = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
treeData.value = [];
|
||||||
|
addingNewNode.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
emit('cancel');
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.config-tree-container {
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.add-node-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 8px;
|
||||||
|
|
||||||
|
.tree-node-title {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-actions {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保鼠标悬停时显示操作按钮
|
||||||
|
.tree-node-wrapper:hover {
|
||||||
|
.tree-node-actions {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子节点添加区域样式
|
||||||
|
.add-child-node-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 0 8px 24px;
|
||||||
|
margin-top: 4px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增配置">
|
||||||
|
<a-button @click="props.handleAdd" type="primary"> 新增沿程配置 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from "vue";
|
||||||
|
import BasicSearch from "@/components/BasicSearch/index.vue";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "reset", values: any): void;
|
||||||
|
(e: "searchFinish", values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
configName: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "name",
|
||||||
|
label: "沿程配置名称",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "rvnm",
|
||||||
|
label: "所在河段",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit("searchFinish", values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
emit("reset", initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit("searchFinish", initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
@ -0,0 +1,228 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\ConfigManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
推送配置
|
||||||
|
<!-- <ConfigManagementSearch
|
||||||
|
ref="configManagementSearch"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
ref="basicTable"
|
||||||
|
:columns="columns"
|
||||||
|
:list-url="getAllConfigTree"
|
||||||
|
:search-params="searchParams"
|
||||||
|
>
|
||||||
|
<template #action="{ column, record }">
|
||||||
|
<div class="flex gap-[6px]">
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEdit(record)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click="handleDelete(record)"
|
||||||
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<ConfigManagementForm
|
||||||
|
ref="configManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:initial-values="currentRecord"
|
||||||
|
@cancel="editModalCancel"
|
||||||
|
@ok="handleEditSubmit"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick, onMounted } from 'vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import ConfigManagementSearch from './ConfigManagementSearch.vue';
|
||||||
|
import ConfigManagementForm from './ConfigManagementForm.vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
getAllConfigTree,
|
||||||
|
deleteBaseWbsb,
|
||||||
|
saveBaseWbsb
|
||||||
|
} from '@/api/system/map/ConfigManagement';
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const basicTable = ref<any>(null);
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text, record, index }) => index + 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '沿程配置名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '配置编码',
|
||||||
|
key: 'code',
|
||||||
|
dataIndex: 'code',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所在河段',
|
||||||
|
dataIndex: 'rvnm',
|
||||||
|
key: 'rvnm',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
key: 'recordUser',
|
||||||
|
dataIndex: 'recordUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'recordTime',
|
||||||
|
dataIndex: 'recordTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'modifyTime',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
key: 'remark',
|
||||||
|
width: 360
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({});
|
||||||
|
// 编辑弹窗数据
|
||||||
|
const currentRecord = ref<any | null>(null);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
|
||||||
|
// 新增处理
|
||||||
|
const handleAdd = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑处理
|
||||||
|
const handleEdit = (record: any) => {
|
||||||
|
currentRecord.value = { ...record };
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
zIndex: 2002,
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
let res = await deleteBaseWbsb([record.id]);
|
||||||
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索完成处理
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
const params = {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
values.parentId
|
||||||
|
? {
|
||||||
|
field: 'parentId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.parentId
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.name
|
||||||
|
? {
|
||||||
|
field: 'name',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.name
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
].filter(Boolean)
|
||||||
|
};
|
||||||
|
basicTable.value.getList(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
basicTable.value.getList({
|
||||||
|
logic: 'and',
|
||||||
|
filters: []
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单取消
|
||||||
|
const editModalCancel = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单提交
|
||||||
|
const handleEditSubmit = async (values: any) => {
|
||||||
|
try {
|
||||||
|
let res = await saveBaseWbsb({
|
||||||
|
...currentRecord.value,
|
||||||
|
...values
|
||||||
|
});
|
||||||
|
message.success(`保存成功`);
|
||||||
|
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
|
||||||
|
editModalVisible.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initOption = () => {};
|
||||||
|
onMounted(() => {
|
||||||
|
initOption();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.config-management {
|
||||||
|
height: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,260 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑图层' : '新增图层'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="props.loading"
|
||||||
|
width="600px"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
name="edit_form"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
>
|
||||||
|
<a-form-item label="图层名称" name="title">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.title"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入图层名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图层编码" name="code">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.code"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入图层编码"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="图层类型" name="type" v-if="isInterface">
|
||||||
|
<a-select
|
||||||
|
:options="typeOpiton"
|
||||||
|
v-model:value="formData.type"
|
||||||
|
:fieldNames="{
|
||||||
|
label: 'dictName',
|
||||||
|
value: 'itemCode'
|
||||||
|
}"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入图层类型"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="标签显示级别" name="treeLevel" v-if="!isInterface">
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="formData.treeLevel"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入标签显示级别"
|
||||||
|
:min="0"
|
||||||
|
:max="24"
|
||||||
|
:step="1"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="锚点接口" name="url" v-if="isInterface">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.url"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入锚点接口"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="接口参数" name="anchorParamJson" v-if="isInterface">
|
||||||
|
<a-textarea
|
||||||
|
:rows="6"
|
||||||
|
v-model:value="formData.anchorParamJson"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入接口参数"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="三维接口"
|
||||||
|
name="urlThd"
|
||||||
|
v-if="isInterface && formData.type === 'geojson'"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.urlThd"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入三维接口"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="gisJson"
|
||||||
|
name="paramJson"
|
||||||
|
v-if="isInterface && formData.type === 'geojson'"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.paramJson"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入gisJson"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="备注"
|
||||||
|
name="description"
|
||||||
|
v-if="!isInterface || formData.type === 'geojson'"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.description"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import { getDictItemsByCode } from '@/api/dict';
|
||||||
|
|
||||||
|
// 定义 Props
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
isInterface?: boolean;
|
||||||
|
}
|
||||||
|
// 加载状态
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false,
|
||||||
|
isInterface: false
|
||||||
|
});
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
// 定义 Emits
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any, type: string): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref();
|
||||||
|
// 1. 新增用于存储手动验证错误信息的响应式变量
|
||||||
|
const bodyLengthError = ref<string>('');
|
||||||
|
const weightError = ref<string>('');
|
||||||
|
|
||||||
|
// 表单数据模型
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
title: undefined,
|
||||||
|
code: undefined,
|
||||||
|
type: undefined,
|
||||||
|
treeLevel: undefined,
|
||||||
|
description: undefined,
|
||||||
|
parentId: undefined,
|
||||||
|
url: undefined,
|
||||||
|
urlThd: undefined,
|
||||||
|
paramJson: undefined,
|
||||||
|
anchorParamJson: undefined
|
||||||
|
});
|
||||||
|
const typeOpiton = ref<any>([]);
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
// 验证规则
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
title: [{ required: true, message: '请输入图层名称', trigger: 'blur' }],
|
||||||
|
code: [{ required: true, message: '请输入图层编码', trigger: 'blur' }],
|
||||||
|
type: [{ required: true, message: '请输入图层类型', trigger: 'change' }],
|
||||||
|
treeLevel: [
|
||||||
|
{ required: true, message: '请输入标签显示级别', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 计算是否为编辑模式
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
// 确认操作
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
// 验证表单
|
||||||
|
await formRef.value.validate();
|
||||||
|
// 准备提交数据
|
||||||
|
const submitValues = {
|
||||||
|
...formData
|
||||||
|
};
|
||||||
|
emit('ok', submitValues, 'form');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const initForm = () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
// --- 编辑模式:回填数据 ---
|
||||||
|
const values = props.initialValues;
|
||||||
|
if (props.isInterface) {
|
||||||
|
initType();
|
||||||
|
}
|
||||||
|
// 回填其他普通字段
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
// 确保字段存在于 initialValues 中再赋值,避免覆盖默认值
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const initType = () => {
|
||||||
|
getDictItemsByCode({ dictCode: 'LayerTypeCode' }).then(res => {
|
||||||
|
typeOpiton.value = res.data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
// 清空手动验证的错误信息
|
||||||
|
bodyLengthError.value = '';
|
||||||
|
weightError.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消操作
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
emit('cancel');
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听图层类型变化,清空相关字段
|
||||||
|
watch(
|
||||||
|
() => formData.type,
|
||||||
|
(newType, oldType) => {
|
||||||
|
if (oldType && newType !== oldType) {
|
||||||
|
// 类型切换时清空相关字段
|
||||||
|
formData.urlThd = undefined;
|
||||||
|
formData.paramJson = undefined;
|
||||||
|
if (oldType === 'geojson') {
|
||||||
|
formData.description = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// 暴露变量
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增图层">
|
||||||
|
<a-button @click="props.handleAdd" type="primary"> 新增图层 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted, watch } from "vue";
|
||||||
|
import BasicSearch from "@/components/BasicSearch/index.vue"; // 确保路径正确
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: (record: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "reset", values: any): void;
|
||||||
|
(e: "searchFinish", values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
title: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "title",
|
||||||
|
label: "图层名称",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
// --- Methods ---
|
||||||
|
|
||||||
|
// 2. 搜索表单逻辑
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit("searchFinish", values);
|
||||||
|
};
|
||||||
|
// 值改变
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
emit("reset", initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit("searchFinish", initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,358 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\LayerManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
推送历史
|
||||||
|
<!-- <LayerManagementSearch
|
||||||
|
ref="layerManagementSearch"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
ref="basicTable"
|
||||||
|
:columns="columns"
|
||||||
|
:list-url="getAllMapLayerTree"
|
||||||
|
:search-params="searchParams"
|
||||||
|
>
|
||||||
|
<template #action="{ record }">
|
||||||
|
<div class="flex gap-[6px]">
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEdit(record)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
v-if="record.children && record.children.length == 0"
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEditInterface(record)"
|
||||||
|
>编辑接口</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleAdd(record)"
|
||||||
|
>新增子图层</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click="handleDelete(record)"
|
||||||
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #enable="{ record }">
|
||||||
|
<a-switch
|
||||||
|
:checked="record.enable === 1"
|
||||||
|
@change="(checked: boolean) => handleEnableChange(record, checked)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #checkable="{ record }">
|
||||||
|
<a-switch
|
||||||
|
:checked="record.checkable === 1"
|
||||||
|
@change="(checked: boolean) => handleCheckableChange(record, checked)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<LayerManagementForm
|
||||||
|
ref="layerManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:initial-values="currentRecord"
|
||||||
|
:is-interface="isInterface"
|
||||||
|
:loading="editLoading"
|
||||||
|
@cancel="editModalCancel"
|
||||||
|
@ok="handleEditSubmit"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick } from 'vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import LayerManagementSearch from './LayerManagementSearch.vue';
|
||||||
|
import LayerManagementForm from './LayerManagementForm.vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
getAllMapLayerTree,
|
||||||
|
saveMapLayer,
|
||||||
|
deleteMapLayer
|
||||||
|
} from '@/api/system/map/LayerManagement';
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
dataIndex: '',
|
||||||
|
key: '',
|
||||||
|
width: 50,
|
||||||
|
customRender: () => {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ record, index }: any) => {
|
||||||
|
// 对于树形结构,计算当前记录在其父节点的 children 中的位置
|
||||||
|
// 如果没有 parentId,说明是根节点,需要计算在所有根节点中的序号
|
||||||
|
if (!record.parentId) {
|
||||||
|
// 根节点:计算在 dataSource 中是第几个根节点
|
||||||
|
let rootIndex = 0;
|
||||||
|
for (let i = 0; i < basicTable.value.tableData.length; i++) {
|
||||||
|
const item = basicTable.value.tableData[i];
|
||||||
|
// 只统计根节点(没有 parentId 的节点)
|
||||||
|
if (!item.parentId) {
|
||||||
|
rootIndex++;
|
||||||
|
// 找到当前记录,返回其序号
|
||||||
|
if (
|
||||||
|
item.id === record.id ||
|
||||||
|
(item.key === record.key && item.id === record.id)
|
||||||
|
) {
|
||||||
|
return rootIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rootIndex;
|
||||||
|
} else {
|
||||||
|
// 子节点:在其父节点的 children 中查找索引
|
||||||
|
const findParentAndIndex = (data: any[], parentId: string): number => {
|
||||||
|
for (const item of data) {
|
||||||
|
if (item.key === parentId || item.id === parentId) {
|
||||||
|
// 找到父节点,在其 children 中查找当前记录的位置
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
const childIndex = item.children.findIndex(
|
||||||
|
(child: any) =>
|
||||||
|
child.key === record.key || child.id === record.id
|
||||||
|
);
|
||||||
|
return childIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 递归查找更深层的父节点
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
const result = findParentAndIndex(item.children, parentId);
|
||||||
|
if (result > 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
return findParentAndIndex(basicTable.value.tableData, record.parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图层名称',
|
||||||
|
dataIndex: 'title',
|
||||||
|
key: 'title',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '图层编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '标签显示级别',
|
||||||
|
dataIndex: 'treeLevel',
|
||||||
|
key: 'treeLevel',
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否启用',
|
||||||
|
dataIndex: 'enable',
|
||||||
|
key: 'enable',
|
||||||
|
width: 80,
|
||||||
|
slots: { customRender: 'enable' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否可选',
|
||||||
|
dataIndex: 'checkable',
|
||||||
|
key: 'checkable',
|
||||||
|
width: 80,
|
||||||
|
slots: { customRender: 'checkable' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
key: 'displayRecordUser',
|
||||||
|
dataIndex: 'displayRecordUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'recordTime',
|
||||||
|
dataIndex: 'recordTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'modifyTime',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 220,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
// 表格实例
|
||||||
|
const basicTable = ref<any>(null);
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({});
|
||||||
|
// 编辑弹窗数据
|
||||||
|
const isInterface = ref(false);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
const editLoading = ref(false);
|
||||||
|
const parentId = ref<string | null>(null);
|
||||||
|
const currentRecord = ref<any | null>(null);
|
||||||
|
// 添加处理
|
||||||
|
const handleAdd = (record: any) => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
parentId.value = record.id;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
// 过滤掉值为 '-' 的字段
|
||||||
|
const filterRecord = (record: any) => {
|
||||||
|
const filtered: any = {};
|
||||||
|
const keepKeys = ['code']; // 这些键始终保留
|
||||||
|
Object.keys(record).forEach(key => {
|
||||||
|
if (keepKeys.includes(key) || record[key] !== '-') {
|
||||||
|
filtered[key] = record[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filtered;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑处理
|
||||||
|
const handleEdit = (record: any) => {
|
||||||
|
console.log('handleEdit', record);
|
||||||
|
parentId.value = null;
|
||||||
|
isInterface.value = false;
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
// 编辑接口处理
|
||||||
|
const handleEditInterface = (record: any) => {
|
||||||
|
console.log('handleEdit', record);
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
console.log('handleEdit', currentRecord.value);
|
||||||
|
isInterface.value = true;
|
||||||
|
parentId.value = null;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = async (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
zIndex: 2002,
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
let res = await deleteMapLayer([record.id]);
|
||||||
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 搜索
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
searchParams.value = values;
|
||||||
|
nextTick(() => {
|
||||||
|
basicTable.value.getList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
searchParams.value = {};
|
||||||
|
nextTick(() => {
|
||||||
|
basicTable.value.refresh();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 是否启用切换处理
|
||||||
|
const handleEnableChange = (record: any, checked: boolean) => {
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
console.log(currentRecord.value);
|
||||||
|
record.enable = checked ? 1 : 0;
|
||||||
|
handleEditSubmit({ enable: checked ? 1 : 0 }, 'switch');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 是否可选切换处理
|
||||||
|
const handleCheckableChange = (record: any, checked: boolean) => {
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
record.checkable = checked ? 1 : 0;
|
||||||
|
handleEditSubmit({ checkable: checked ? 1 : 0 }, 'switch');
|
||||||
|
};
|
||||||
|
// 表单
|
||||||
|
const editModalCancel = () => {
|
||||||
|
isInterface.value = false;
|
||||||
|
parentId.value = null;
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
const handleEditSubmit = async (values: any, type: string) => {
|
||||||
|
editLoading.value = true;
|
||||||
|
try {
|
||||||
|
let res = await saveMapLayer({
|
||||||
|
...currentRecord.value,
|
||||||
|
...values,
|
||||||
|
parentId: parentId.value
|
||||||
|
});
|
||||||
|
if (res.code == 0) {
|
||||||
|
if (type === 'switch') {
|
||||||
|
message.success('修改状态成功');
|
||||||
|
} else {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
}
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} else {
|
||||||
|
if (type === 'switch') {
|
||||||
|
message.success('修改状态成功');
|
||||||
|
} else {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (type === 'switch') {
|
||||||
|
message.error('修改状态失败');
|
||||||
|
} else {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
editLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
:deep(.ant-table-cell-with-append) {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
:deep(.ant-table-row-expand-icon) {
|
||||||
|
width: 17px !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
89
frontend/src/views/system/pushManagement/index.vue
Normal file
89
frontend/src/views/system/pushManagement/index.vue
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<div class="map-page">
|
||||||
|
<!-- Ant Design Tabs -->
|
||||||
|
<a-tabs v-model:activeKey="activeTab" class="map-tabs">
|
||||||
|
<a-tab-pane v-for="tab in tabs" :key="tab.value" :tab="tab.name">
|
||||||
|
<!-- 动态加载对应的组件 -->
|
||||||
|
<component :is="getComponent(tab.value)" />
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, defineAsyncComponent } from 'vue';
|
||||||
|
|
||||||
|
// Tab 配置
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
name: '推送配置',
|
||||||
|
value: 'config'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '推送历史',
|
||||||
|
value: 'history'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 当前激活的 tab
|
||||||
|
const activeTab = ref('config');
|
||||||
|
|
||||||
|
// 获取对应组件的方法
|
||||||
|
const getComponent = (value: string) => {
|
||||||
|
const componentMap: Record<string, any> = {
|
||||||
|
config: defineAsyncComponent(
|
||||||
|
() => import('./components/ConfigManagement/index.vue')
|
||||||
|
),
|
||||||
|
history: defineAsyncComponent(
|
||||||
|
() => import('./components/HistoryManagement/index.vue')
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
return componentMap[value] || null;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.map-page {
|
||||||
|
position: relative;
|
||||||
|
z-index: 900;
|
||||||
|
pointer-events: all;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 2px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 900;
|
||||||
|
pointer-events: all;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
:deep(.ant-form-item) {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs) {
|
||||||
|
height: 100%; // 减去 tabs header 的高度
|
||||||
|
padding: 0 13px;
|
||||||
|
}
|
||||||
|
.map-tabs {
|
||||||
|
:deep(.ant-tabs-content) {
|
||||||
|
height: 100%; // 减去 tabs header 的高度
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs-tabpane) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user