WholeProcessPlatform/frontend/src/views/system/map/components/LegendStructure/index.vue

384 lines
9.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\LegendStructure\index.vue -->
<template>
<div class="content">
<LegendStructureSearch
ref="legendStructureSearch"
:handle-add="handleAdd"
@reset="handleReset"
@search-finish="onSearchFinish"
/>
<BasicTable
ref="basicTable"
:isPage="false"
:columns="columns"
:transformData="transformData"
:list-url="getAllMapLegendTree"
>
<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
v-if="record.parentId == null"
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="{ column, record }">
<a-switch
:checked="record.enable === 1"
@change="(checked: boolean) => handleEnableChange(record, checked)"
/>
</template>
<template #internal="{ column, record }">
<a-switch
:checked="record.internal === 1"
@change="(checked: boolean) => handleInternalChange(record, checked)"
/>
</template>
<template #ifShow="{ column, record }">
<a-switch
:checked="record.ifShow === 1"
@change="(checked: boolean) => handleIfShowChange(record, checked)"
/>
</template>
</BasicTable>
<LegendStructureForm
ref="legendStructureForm"
v-model:visible="editModalVisible"
:initial-values="currentRecord"
@cancel="editModalCancel"
@ok="handleEditSubmit"
/>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue';
import BasicTable from '@/components/BasicTable/index.vue';
import LegendStructureSearch from './LegendStructureSearch.vue';
import LegendStructureForm from './LegendStructureForm.vue';
import { message, Modal } from 'ant-design-vue';
import {
getAllMapLegendTree,
saveMapLegend,
deleteMapLegend
} from '@/api/system/map/LegendStructure';
// 表格列配置
const columns = [
{
title: '',
dataIndex: '',
key: '',
width: 20
},
{
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: 'name',
key: 'name',
width: 170
},
{
title: '图例编码',
dataIndex: 'nameEn',
key: 'nameEn',
width: 120
},
{
title: '是否启用',
dataIndex: 'enable',
key: 'enable',
width: 80,
slots: { customRender: 'enable' }
},
{
title: '系统内置项',
dataIndex: 'internal',
key: 'internal',
width: 100,
slots: { customRender: 'internal' }
},
{
title: '是否显示',
dataIndex: 'ifShow',
key: 'ifShow',
width: 80,
slots: { customRender: 'ifShow' }
},
{
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: 160,
fixed: 'right',
slots: { customRender: 'action' }
}
];
// 表格实例
const basicTable = ref<any>(null);
// 编辑弹窗数据
const editModalVisible = 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 handleEdit = (record: any) => {
parentId.value = null;
currentRecord.value = { ...record };
editModalVisible.value = true;
};
// 删除处理
const handleDelete = (record: any) => {
Modal.confirm({
title: '确认删除',
content: '确定要删除选中的记录吗?',
zIndex: 2002,
onOk: async () => {
try {
let res = await deleteMapLegend([record.id]);
message.success('删除成功');
basicTable.value.refresh();
} catch (error) {
message.error('删除失败');
return;
}
}
});
};
// ... existing code ...
const transformData = (res: any) => {
const flatData = res.data.data || [];
// 构建树形结构
const buildTree = (data: any[]) => {
const map = new Map();
const tree: any[] = [];
// 第一步:将所有节点放入 map 中,并初始化 children
data.forEach(item => {
map.set(item.id, { ...item, children: [] });
});
// 第二步:根据 parentId 建立父子关系
data.forEach(item => {
const node = map.get(item.id);
if (!item.parentId) {
// 根节点
tree.push(node);
} else {
// 子节点,找到父节点并添加
const parent = map.get(item.parentId);
if (parent) {
parent.children.push(node);
} else {
// 如果找不到父节点,也作为根节点处理
tree.push(node);
}
}
});
// 第三步:清理没有子节点的 children 数组
const cleanEmptyChildren = (nodes: any[]) => {
nodes.forEach(node => {
if (node.children && node.children.length === 0) {
delete node.children;
} else if (node.children && node.children.length > 0) {
cleanEmptyChildren(node.children);
}
});
};
cleanEmptyChildren(tree);
return tree;
};
const treeData = buildTree(flatData);
return {
records: treeData,
total: null
};
};
// ... existing code ...
// 搜索完成处理
const onSearchFinish = (values: any) => {
const params = {
logic: 'and',
filters: [
{ field: 'dataType', operator: 'eq', dataType: 'string', value: '1' },
{
field: 'name',
operator: 'contains',
dataType: 'string',
value: values.name
}
]
};
basicTable.value.getList(params);
};
// 重置
const handleReset = () => {
nextTick(() => {
basicTable.value.getList({
logic: 'and',
filters: [
{ field: 'dataType', operator: 'eq', dataType: 'string', value: '1' }
]
});
});
};
// 是否启用切换处理
const handleEnableChange = (record: any, checked: boolean) => {
currentRecord.value = { ...record };
handleEditSubmit({ enable: checked ? 1 : 0 }, 'switch');
};
// 是否内部切换处理
const handleInternalChange = (record: any, checked: boolean) => {
currentRecord.value = { ...record };
handleEditSubmit({ internal: checked ? 1 : 0 }, 'switch');
};
// 是否显示处理
const handleIfShowChange = (record: any, checked: boolean) => {
currentRecord.value = { ...record };
handleEditSubmit({ ifShow: checked ? 1 : 0 }, 'switch');
};
// 表单取消
const editModalCancel = () => {
parentId.value = null;
currentRecord.value = null;
editModalVisible.value = false;
};
// 表单提交
const handleEditSubmit = async (values: any, type: string) => {
try {
let res = await saveMapLegend({
...currentRecord.value,
...values,
parentId: parentId.value
});
if (type === 'switch') {
message.success('修改状态成功');
} else {
message.success(`保存成功`);
}
editModalVisible.value = false;
basicTable.value.refresh();
} catch (error) {
if (type === 'switch') {
message.error('修改状态失败');
} else {
message.error(`保存失败`);
}
editModalVisible.value = false;
return;
}
};
</script>
<style scoped lang="scss"></style>