553 lines
15 KiB
Vue
553 lines
15 KiB
Vue
<template>
|
|
<div class="w-full h-full flex flex-col pt-[20px] pl-[20px] body_one">
|
|
<!-- 搜索组件 -->
|
|
<BasicDataSearch
|
|
:topHynmList="topHynmList"
|
|
:hycdList="hycdList"
|
|
:topHynmLoading="topHynmLoading"
|
|
:hycdLoading="hycdLoading"
|
|
:dvtpList="dvtpList"
|
|
@add="handleAdd"
|
|
@export-btn="exportBtn"
|
|
@custom-filter-btn="customFilterBtn"
|
|
@search-finish="onSearchFinish"
|
|
@reset="onReset"
|
|
ref="searchRef"
|
|
/>
|
|
|
|
<!-- 表格组件 -->
|
|
<BasicTable
|
|
v-if="columnLoaded"
|
|
ref="tableRef"
|
|
:enableEllipsis="true"
|
|
:scrollX="tableScrollX"
|
|
:scrollY="tableScrollY"
|
|
:columns="columns"
|
|
:searchParams="{
|
|
sort: sort
|
|
}"
|
|
:list-url="getPowerTableList"
|
|
>
|
|
<template #action="{ record }">
|
|
<a-button
|
|
type="link"
|
|
class="text-[#2f6b98]"
|
|
size="small"
|
|
@click="handleDetail(record)"
|
|
>查看详情</a-button
|
|
>
|
|
<a-button
|
|
type="link"
|
|
class="text-[#2f6b98]"
|
|
size="small"
|
|
@click="handleEdit(record)"
|
|
>编辑</a-button
|
|
>
|
|
<a-button type="link" danger size="small" @click="handleDelete(record)"
|
|
>删除</a-button
|
|
>
|
|
</template>
|
|
</BasicTable>
|
|
|
|
<!-- 自定义数据列 Modal -->
|
|
<CustomColumnModal
|
|
v-if="columnLoaded"
|
|
v-model:visible="customColumnVisible"
|
|
:user-column-list="userColumnList"
|
|
@confirm="handleColumnConfirm"
|
|
/>
|
|
|
|
<!-- 编辑电站 Modal -->
|
|
<EditPowerModal
|
|
v-model:open="editVisible"
|
|
:is-add="isAdd"
|
|
:dvtp-list="dvtpList"
|
|
:record="editRecord"
|
|
:top-hynm-list="topHynmList"
|
|
:hycd-list="hycdList"
|
|
@success="handleEditSuccess"
|
|
/>
|
|
|
|
<!-- 删除确认 Modal -->
|
|
<DeleteConfirmModal ref="deleteModalRef" @success="handleEditSuccess" />
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import { ref, computed, onMounted, nextTick } from 'vue';
|
|
import dayjs from 'dayjs';
|
|
import BasicDataSearch from './BasicDataSearch.vue';
|
|
import BasicTable from '@/components/BasicTable/index.vue';
|
|
import CustomColumnModal from './CustomColumnModal.vue';
|
|
import EditPowerModal from './EditPowerModal.vue';
|
|
import DeleteConfirmModal from './DeleteConfirmModal.vue';
|
|
import {
|
|
getCompanyList,
|
|
getPowerTableList,
|
|
addPowerInfo,
|
|
updatePowerInfo,
|
|
deletePowerInfo,
|
|
getUserColumnData,
|
|
batchSaveUserColumn
|
|
} from '@/api/DataQueryMenuModule';
|
|
import { getEngInfoById } from '@/api/select';
|
|
import { calcTableScrollY } from '@/utils/index';
|
|
import { useModelStore } from '@/store/modules/model';
|
|
import { useUserStore } from "@/store/modules/user";
|
|
|
|
|
|
const modelStore = useModelStore();
|
|
const userStore = useUserStore();
|
|
|
|
const sort = ref<any>([
|
|
{
|
|
field: 'baseStepSort',
|
|
dir: 'asc'
|
|
},
|
|
{
|
|
field: 'rvcdStepSort',
|
|
dir: 'asc'
|
|
},
|
|
{
|
|
field: 'rstcdStepSort',
|
|
dir: 'asc'
|
|
},
|
|
{
|
|
field: 'ttpwr',
|
|
dir: 'asc'
|
|
}
|
|
]);
|
|
|
|
const tableRef = ref();
|
|
const searchRef = ref();
|
|
const tableScrollY = ref<string | number>(0);
|
|
const currentSearchParams = ref<any>({});
|
|
const exportLoading = ref(false);
|
|
const customColumnVisible = ref(false);
|
|
const userColumnList = ref<any[]>([]);
|
|
const columnLoaded = ref(false);
|
|
|
|
// 编辑相关
|
|
const editVisible = ref(false);
|
|
const editRecord = ref<any>(null);
|
|
const isAdd = ref(false);
|
|
const deleteModalRef = ref();
|
|
|
|
// 集团和公司数据
|
|
const topHynmList = ref<any>([]);
|
|
const hycdList = ref<any>([]);
|
|
const topHynmLoading = ref(false);
|
|
const hycdLoading = ref(false);
|
|
|
|
const isEdit = ref(true);
|
|
|
|
const dvtpList = ref<any[]>([
|
|
{ label: '堤坝式', value: '0' },
|
|
{ label: '引水式', value: '1' },
|
|
{ label: '混合式', value: '2' }
|
|
]);
|
|
// 日期列渲染函数
|
|
const dateRender = ({ text }: { text: string }) => {
|
|
if (!text || text === '-') return '-';
|
|
const date = dayjs(text);
|
|
return date.isValid() ? date.format('YYYY-MM-DD') : '-';
|
|
};
|
|
|
|
// 表格列元数据映射(列宽、排序、固定列、自定义渲染等)
|
|
const columnMetaMap: Record<string, any> = {
|
|
stnm: { width: 150, fixed: 'left', sort: true, ellipsis: true },
|
|
addvcdName: { width: 150, sort: true, ellipsis: true },
|
|
stlc: { width: 200, sort: true, ellipsis: true },
|
|
baseName: { width: 120, ellipsis: true },
|
|
jcdt: { width: 120, sort: true, ellipsis: true, customRender: dateRender },
|
|
piodt: { width: 160, sort: true, ellipsis: true, customRender: dateRender },
|
|
aiodt: { width: 150, sort: true, ellipsis: true, customRender: dateRender },
|
|
bldsttCcodeName: { width: 100, sort: true, ellipsis: true },
|
|
hynm: { width: 150, sort: true, ellipsis: true },
|
|
topHynm: { width: 150, sort: true, ellipsis: true },
|
|
nrupar: { width: 180, sort: true },
|
|
dstcrvr: { width: 150, sort: true },
|
|
avyrp: { width: 170, sort: true },
|
|
avw: { width: 190, sort: true },
|
|
avq: { width: 160, sort: true },
|
|
avq01: { width: 180, sort: true },
|
|
avq02: { width: 180, sort: true },
|
|
avq03: { width: 180, sort: true },
|
|
avq04: { width: 180, sort: true },
|
|
avq05: { width: 180, sort: true },
|
|
avq06: { width: 180, sort: true },
|
|
avq07: { width: 180, sort: true },
|
|
avq08: { width: 180, sort: true },
|
|
avq09: { width: 180, sort: true },
|
|
avq10: { width: 190, sort: true },
|
|
avq11: { width: 190, sort: true },
|
|
avq12: { width: 190, sort: true },
|
|
obmxq: { width: 170, sort: true },
|
|
obmnq: { width: 170, sort: true },
|
|
hmxq: { width: 190, sort: true },
|
|
dsnfqfrq: { width: 190, sort: true },
|
|
dsrcin: { width: 160, sort: true },
|
|
ckfqfqr: { width: 190, sort: true },
|
|
chrcin: { width: 160, sort: true },
|
|
obmxw3: { width: 220, sort: true },
|
|
dsw3: { width: 190, sort: true },
|
|
ckw3: { width: 190, sort: true },
|
|
avsd: { width: 180 },
|
|
avs: { width: 180, sort: true },
|
|
obmxs: { width: 180, sort: true },
|
|
ckflz: { width: 140, sort: true },
|
|
dsflz: { width: 140, sort: true },
|
|
normz: { width: 140, sort: true },
|
|
uzfc: { width: 140, sort: true },
|
|
fsltdz: { width: 150, sort: true },
|
|
ydownz: { width: 140, sort: true },
|
|
ddz: { width: 120, sort: true },
|
|
nrzar: { width: 200, sort: true },
|
|
bcklen: { width: 130, sort: true },
|
|
ttcp: { width: 130, sort: true },
|
|
nmzcp: { width: 200, sort: true },
|
|
fldcpStr: { width: 140, sort: true },
|
|
actcp: { width: 140, sort: true },
|
|
ddcp: { width: 130, sort: true },
|
|
cpsc: { width: 120, sort: true },
|
|
rgcpName: { width: 120, sort: true, ellipsis: true },
|
|
dsflzmxq: { width: 250, sort: true },
|
|
dsflzxyz: { width: 320, sort: true },
|
|
ckflzmxq: { width: 250, sort: true },
|
|
ckflzxyz: { width: 320, sort: true },
|
|
ksqadjq: { width: 170, sort: true },
|
|
ksqxyz: { width: 250, sort: true },
|
|
gemaxrq: { width: 190, sort: true },
|
|
mxgeqxyz: { width: 260, sort: true },
|
|
ttpwr: { width: 120, sort: true, ellipsis: true },
|
|
gncnt: { width: 130, sort: true, ellipsis: true },
|
|
gntp: { width: 150, sort: true, ellipsis: true },
|
|
grntpwr: { width: 130, sort: true, ellipsis: true },
|
|
yrge: { width: 200, sort: true },
|
|
ushr: { width: 150, sort: true },
|
|
k: { width: 150, sort: true, ellipsis: true },
|
|
dmtp: { width: 100, sort: true, ellipsis: true },
|
|
dmcrel: { width: 130, sort: true },
|
|
mxdmhg: { width: 120, sort: true },
|
|
dmlen: { width: 130, sort: true },
|
|
sgyge: { width: 180, sort: true },
|
|
unyge: { width: 180, sort: true },
|
|
gap: { width: 120, sort: true },
|
|
dvtpName: { width: 120, sort: true },
|
|
dtinName: { width: 120, sort: true, ellipsis: true }
|
|
};
|
|
|
|
// API columnEn 到表格 dataIndex 的映射(处理字段名不一致的情况)
|
|
const apiToDataIndexMap: Record<string, string> = {
|
|
hbrvcdName: 'reachcdName'
|
|
};
|
|
|
|
const columns = ref<any[]>([]);
|
|
|
|
const tableScrollX = computed(() =>
|
|
Math.max(
|
|
columns.value.reduce(
|
|
(sum: number, col: any) => sum + (col.width || 180),
|
|
0
|
|
),
|
|
600
|
|
)
|
|
);
|
|
|
|
const onSearchFinish = (values: any) => {
|
|
currentSearchParams.value = values;
|
|
initTable(values);
|
|
};
|
|
|
|
const onReset = (values: any) => {
|
|
currentSearchParams.value = values;
|
|
initTable(values);
|
|
};
|
|
|
|
// 导出
|
|
const exportBtn = () => {
|
|
if (exportLoading.value) return;
|
|
|
|
exportLoading.value = true;
|
|
searchRef.value.btnLoading = true;
|
|
|
|
tableRef.value
|
|
.exportTable({
|
|
fileName: `基础数据_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
|
|
})
|
|
.finally(() => {
|
|
exportLoading.value = false;
|
|
searchRef.value.btnLoading = false;
|
|
});
|
|
};
|
|
// 自定义筛选列
|
|
const customFilterBtn = () => {
|
|
customColumnVisible.value = true;
|
|
};
|
|
|
|
// 确认自定义列选择
|
|
const handleColumnConfirm = (selectedFiledKeys: string[]) => {
|
|
console.log('选中的 columnEn keys:', selectedFiledKeys);
|
|
|
|
// 1. 构建保存数据(更新 checked 字段)
|
|
const updatedList = userColumnList.value.map((item: any) => ({
|
|
...item,
|
|
checked: selectedFiledKeys.includes(item.columnEn) ? 1 : 0
|
|
}));
|
|
|
|
// 2. 按接口要求包装为 { recordUser, cfgId, list }
|
|
const saveParams = {
|
|
recordUser: userStore.userid,
|
|
cfgId: 'cgsdbase',
|
|
list: updatedList
|
|
};
|
|
batchSaveUserColumn(saveParams).then(() => {
|
|
// 3. 保存成功后重新请求表头配置和表格数据
|
|
fetchColumnConfig();
|
|
initTable(currentSearchParams.value);
|
|
});
|
|
};
|
|
const buildSearchParams = (values: any) => {
|
|
console.log(values);
|
|
return {
|
|
logic: 'and',
|
|
filters: [
|
|
values.rvcd && values.rvcd !== 'all'
|
|
? {
|
|
field: 'rvcd',
|
|
operator: 'contains',
|
|
dataType: 'string',
|
|
value: values.rvcd
|
|
}
|
|
: null,
|
|
|
|
values.rstcd
|
|
? {
|
|
field: 'stcd',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.rstcd
|
|
}
|
|
: null,
|
|
values.baseId
|
|
? {
|
|
field: 'baseId',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.baseId
|
|
}
|
|
: null,
|
|
values.hbrvcd
|
|
? {
|
|
field: 'hbrvcd',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.hbrvcd
|
|
}
|
|
: null,
|
|
values.bldsttCcode != undefined && values.bldsttCcode != ''
|
|
? {
|
|
field: 'bldsttCcode',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.bldsttCcode
|
|
}
|
|
: null,
|
|
values.hycd
|
|
? {
|
|
field: 'hycd',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.hycd
|
|
}
|
|
: null,
|
|
values.topHynm
|
|
? {
|
|
field: 'topHynm',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.topHynm
|
|
}
|
|
: null,
|
|
values.ttpwr && values.ttpwr.min
|
|
? {
|
|
field: 'ttpwr',
|
|
operator: 'gte',
|
|
dataType: 'string',
|
|
value: values.ttpwr.min * 10
|
|
}
|
|
: null,
|
|
values.ttpwr && values.ttpwr.max
|
|
? {
|
|
field: 'ttpwr',
|
|
operator: 'lte',
|
|
dataType: 'string',
|
|
value: values.ttpwr.max * 10
|
|
}
|
|
: null,
|
|
values.jcdt && values.jcdt.min
|
|
? {
|
|
field: 'jcdt',
|
|
operator: 'gte',
|
|
dataType: 'date',
|
|
value: values.jcdt.min
|
|
}
|
|
: null,
|
|
values.jcdt && values.jcdt.max
|
|
? {
|
|
field: 'jcdt',
|
|
operator: 'lte',
|
|
dataType: 'date',
|
|
value: values.jcdt.max
|
|
}
|
|
: null,
|
|
values.dtin && values.dtin !== 'all'
|
|
? {
|
|
field: 'dtin',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.dtin
|
|
}
|
|
: null,
|
|
values.dvtp && values.dvtp.length > 0
|
|
? {
|
|
logic: 'or',
|
|
filters: [
|
|
...values.dvtp.map((item: any) => ({
|
|
field: 'dvtp',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: item
|
|
}))
|
|
]
|
|
}
|
|
: null
|
|
].filter(Boolean)
|
|
};
|
|
};
|
|
|
|
const initTable = (values: any) => {
|
|
if (!tableRef.value) return;
|
|
const params = buildSearchParams(values);
|
|
tableRef.value.getList(params);
|
|
};
|
|
|
|
const init = () => {
|
|
topHynmLoading.value = true;
|
|
hycdLoading.value = true;
|
|
|
|
// 获取集团列表 (lx=1)
|
|
getCompanyList({ lx: 1 }).then(res => {
|
|
topHynmList.value = res?.data || [];
|
|
topHynmLoading.value = false;
|
|
});
|
|
|
|
// 获取公司列表 (lx=2)
|
|
getCompanyList({ lx: 2 }).then(res => {
|
|
hycdList.value = res?.data || [];
|
|
hycdLoading.value = false;
|
|
});
|
|
};
|
|
// 查看详情
|
|
const handleDetail = (record: any) => {
|
|
modelStore.modalVisible = true;
|
|
modelStore.params.sttp = record.sttp || record.sttpCode;
|
|
modelStore.params.stcd = record.stcd;
|
|
modelStore.title = record.stnm;
|
|
};
|
|
// 新增
|
|
const handleAdd = () => {
|
|
isAdd.value = true;
|
|
editRecord.value = null;
|
|
editVisible.value = true;
|
|
};
|
|
// 编辑
|
|
const handleEdit = (record: any) => {
|
|
isAdd.value = false;
|
|
getEngInfoById({ stcd: record.stcd }).then(res => {
|
|
console.log(res);
|
|
editRecord.value = { ...res.data };
|
|
});
|
|
editVisible.value = true;
|
|
};
|
|
|
|
// 编辑成功回调
|
|
const handleEditSuccess = () => {
|
|
initTable(currentSearchParams.value);
|
|
};
|
|
|
|
// 删除
|
|
const handleDelete = (record: any) => {
|
|
deleteModalRef.value?.open(record, () => {
|
|
initTable(currentSearchParams.value);
|
|
});
|
|
};
|
|
// 获取用户自定义列配置,构建表格列
|
|
const fetchColumnConfig = () => {
|
|
getUserColumnData({
|
|
recordUser: userStore.userid,
|
|
cfgId: 'cgsdbase'
|
|
}).then((res: any) => {
|
|
const list = res?.data || [];
|
|
userColumnList.value = list;
|
|
|
|
// 根据 API 数据动态构建表格列,按 orderIndex 排序,只保留 checked 为 1 的列
|
|
const sorted = [...list]
|
|
.filter((item: any) => item.checked === 1 && item.enable == 1)
|
|
.sort((a: any, b: any) => a.orderIndex - b.orderIndex);
|
|
|
|
const cols = sorted.map((item: any) => {
|
|
const dataIndex = apiToDataIndexMap[item.columnEn] || item.columnEn;
|
|
const meta = columnMetaMap[item.columnEn] || {};
|
|
return {
|
|
key: item.columnEn,
|
|
title: item.columnName,
|
|
dataIndex,
|
|
...meta
|
|
};
|
|
});
|
|
|
|
// 添加操作列
|
|
cols.push({
|
|
key: 'action',
|
|
title: '操作',
|
|
dataIndex: 'action',
|
|
fixed: 'right',
|
|
width: isEdit.value ? 180 : 100
|
|
});
|
|
|
|
columns.value = cols;
|
|
}).catch(() => {
|
|
// API 失败时,至少显示操作列
|
|
columns.value = [{
|
|
key: 'action',
|
|
title: '操作',
|
|
dataIndex: 'action',
|
|
fixed: 'right',
|
|
width: isEdit.value ? 180 : 100
|
|
}];
|
|
}).finally(() => {
|
|
columnLoaded.value = true;
|
|
// 等待表格渲染完成后再请求数据
|
|
nextTick(() => {
|
|
initTable(currentSearchParams.value);
|
|
});
|
|
});
|
|
};
|
|
|
|
onMounted(() => {
|
|
init();
|
|
fetchColumnConfig();
|
|
nextTick(() => {
|
|
tableScrollY.value = calcTableScrollY();
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.body_one{
|
|
position: relative;
|
|
z-index: 900;
|
|
pointer-events: all;
|
|
}
|
|
</style>
|