飞行路径管理,沿程bug修改

This commit is contained in:
王兴凯 2026-07-15 18:24:58 +08:00
commit 87781537f9
20 changed files with 1645 additions and 1015 deletions

View File

@ -115,10 +115,18 @@ export function uploadFile(data: any) {
}); });
} }
// 所在位置下拉列表 // 所在位置下拉列表
export function getAddvcdDropdownByRvcd(params: any) { export function getAddvcdDropdownByRvcd(data: any = {}) {
return request({ return request({
url: '/base/msalongb/noAuth/GetKendoList', url: '/base/msalongb/noAuth/GetKendoList',
method: 'post', method: 'post',
params data
});
}
//沿程配置下拉列表
export function noAuthGetKendoPage(data: any = {}) {
return request({
url: '/base/msalongb/noAuth/GetKendoPage',
method: 'post',
data
}); });
} }

View File

@ -39,6 +39,14 @@ export function vmsstbprptGetKendoList(queryParams: any) {
data: queryParams data: queryParams
}); });
} }
//获取电站
export function overviewvmsstbprptGetKendoList(queryParams: any) {
return request({
url: '/eq/vmsstbprpt/GetKendoList',
method: 'post',
data: queryParams
});
}
export function vmsstbprptGetKendoList1(queryParams: any) { export function vmsstbprptGetKendoList1(queryParams: any) {
return request({ return request({
url: '/eq/vmsstbprpt/GetKendoList', url: '/eq/vmsstbprpt/GetKendoList',

View File

@ -42,7 +42,7 @@ export function getCxswList(data: any) {
//获取出入库水温下拉选则树 //获取出入库水温下拉选则树
export function getVmsstbprpt(data: any) { export function getVmsstbprpt(data: any) {
return request({ return request({
url: '/wt/vmsstbprpt/GetKendoList', url: '/eq/vmsstbprpt/GetKendoList',
method: 'post', method: 'post',
data data
}); });

View File

@ -0,0 +1,50 @@
import request from '@/utils/request';
// 获取所有沿程配置数据
export function threedroambGetKendoListCust(data: any) {
return request({
url: '/api/wmp-sys-server/sys/threedroamb/GetKendoListCust',
method: 'post',
data: data
});
}
export function threedroambsave(data: any) {
return request({
url: '/api/wmp-sys-server/sys/threedroamb/save',
method: 'post',
data: data
});
}
export function threedroambdelete(data: any) {
return request({
url: '/api/wmp-sys-server/sys/threedroamb/delete',
method: 'get',
params: data
});
}
//根据id查询弹窗
export function threedroambGetKendoById(data: any) {
return request({
url: '/api/wmp-sys-server/sys/threedroamb/getThreedRoamDetails',
method: 'get',
params: data
});
}
// 导入接口
export function threedroambimport(data: FormData) {
return request({
url: '/api/wmp-sys-server/sys/threedroamb/import',
method: 'post',
data: data,
headers: { 'Content-Type': 'multipart/form-data' }
});
}
// 导出模板
export function threedroambexport(data: any) {
return request({
url: '/api/wmp-sys-server/sys/threedroamb/export',
method: 'post',
data: data,
responseType: 'blob'
});
}

View File

@ -34,7 +34,7 @@
<Yanchengyulei <Yanchengyulei
v-if="modalVisible && JidiSelectEventStore.jidiData.length > 0" v-if="modalVisible && JidiSelectEventStore.jidiData.length > 0"
:tm="modalYear" :tm="modalYear"
:dataDimensionVal="baseid" :dataDimensionVal="moreSelect.value.value"
:hbrvcd="modalHbrvcd" :hbrvcd="modalHbrvcd"
:jdList="JidiSelectEventStore.jidiData" :jdList="JidiSelectEventStore.jidiData"
:stateName="modalStateName" :stateName="modalStateName"
@ -52,7 +52,7 @@ import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import Yanchengyulei from './TwoLayers/Yanchengyulei.vue'; import Yanchengyulei from './TwoLayers/Yanchengyulei.vue';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { wbsbGetKendoList, getDftYear, fishChanges2 } from '@/api/stdc'; import { getDftYear, fishChanges2 } from '@/api/stdc';
import moment from 'moment'; import moment from 'moment';
import { useDraggable } from '@/utils/drag'; import { useDraggable } from '@/utils/drag';
@ -64,8 +64,6 @@ defineOptions({
const JidiSelectEventStore = useJidiSelectEventStore(); const JidiSelectEventStore = useJidiSelectEventStore();
// ==================== ==================== // ==================== ====================
/** 当前选中的基地ID来自 JidiSelectEventStore.selectedItem */
const baseid = ref('');
/** 图表数据加载状态 */ /** 图表数据加载状态 */
const dataLoading = ref(false); const dataLoading = ref(false);
/** 初始化标志位:初始化期间不响应控件变化触发数据请求 */ /** 初始化标志位:初始化期间不响应控件变化触发数据请求 */
@ -253,8 +251,8 @@ const handleResize = () => {
const getYearData = async () => { const getYearData = async () => {
try { try {
const filter: any = {}; const filter: any = {};
if (baseid.value && baseid.value !== 'all') { if (moreSelect.value.value) {
filter.baseId = baseid.value; filter.baseId = moreSelect.value.value;
} }
const params = { const params = {
@ -285,7 +283,7 @@ const getYearData = async () => {
); );
const latestYear = uniqueYears[0]; const latestYear = uniqueYears[0];
// baseid all //
const firstWbsCode = Object.keys(data)[0]; const firstWbsCode = Object.keys(data)[0];
select.value.options = objYear[firstWbsCode] || []; select.value.options = objYear[firstWbsCode] || [];
select.value.value = latestYear select.value.value = latestYear
@ -326,70 +324,6 @@ const updateYearOptionsByBase = async (wbsCode: string) => {
* 获取流域树形选择器数据 + 年份数据 + 图表数据 * 获取流域树形选择器数据 + 年份数据 + 图表数据
* 在基地变化时调用是整个模块数据加载的入口 * 在基地变化时调用是整个模块数据加载的入口
*/ */
const getMoreSelectData = async () => {
if (!baseid.value) return;
isInitializing.value = true;
try {
const params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
},
baseid.value !== 'all'
? {
field: 'objid',
operator: 'eq',
value: baseid.value
}
: null
].filter(Boolean)
},
group: [
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' }
],
groupResultFlat: true
};
const res = await wbsbGetKendoList(params);
const data = res?.data?.data || [];
if (data.length > 0) {
const treeData = buildTreeData(data);
const filteredData = filterSelectOptions(treeData);
//
moreSelect.value.options = filteredData;
moreSelect.value.value = treeData?.[0]?.children?.[0]?.value;
// yearOptions
await getYearData();
if (moreSelect.value.value) {
await updateYearOptionsByBase(moreSelect.value.value);
}
await getChartData();
} else {
moreSelect.value.options = [];
moreSelect.value.value = undefined;
await getYearData();
}
} catch (error) {
console.error('获取树形选择器数据失败:', error);
moreSelect.value.options = [];
moreSelect.value.value = undefined;
} finally {
isInitializing.value = false;
}
};
/** /**
* 获取图表数据 * 获取图表数据
* 根据当前选中的流域(hbrvcd)年份(yr)基地(baseId)调用 fishChanges2 API * 根据当前选中的流域(hbrvcd)年份(yr)基地(baseId)调用 fishChanges2 API
@ -404,28 +338,18 @@ const getChartData = async () => {
filter: { filter: {
logic: 'and', logic: 'and',
filters: [ filters: [
moreSelect.value.value {
? { field: 'baseId',
field: 'hbrvcd', operator: 'eq',
operator: 'eq', dataType: 'string',
dataType: 'string', value: moreSelect.value.value
value: moreSelect.value.value },
}
: null,
{ {
field: 'yr', field: 'yr',
operator: 'eq', operator: 'eq',
dataType: 'string', dataType: 'string',
value: moment(select.value.value).format('YYYY') value: moment(select.value.value).format('YYYY')
}, }
baseid.value !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: baseid.value
}
: null
].filter(Boolean) ].filter(Boolean)
}, },
group: [ group: [
@ -452,73 +376,6 @@ const getChartData = async () => {
} }
}; };
// ==================== ====================
/**
* API 返回的扁平数据转换为树形结构
* objid基地分组每个基地下包含其流域列表
* @param data 扁平的流域数据数组
*/
const buildTreeData = (data: any[]) => {
if (!data || data.length === 0) return [];
//
const jiDiListMap: Record<string, string> = {};
JidiSelectEventStore.jidiData.forEach((item: any) => {
jiDiListMap[item.wbsCode] = item.wbsName;
});
// objid
const dataMapNameMap: Record<string, any[]> = {};
data.forEach(item => {
const objId = item.objid || item.objId;
if (!dataMapNameMap[objId]) {
dataMapNameMap[objId] = [];
}
const exists = dataMapNameMap[objId].some(
existing => existing.wbsCode === item.wbsCode
);
if (!exists) {
dataMapNameMap[objId].push(item);
}
});
const treeData = Object.keys(dataMapNameMap).map(objId => ({
title: jiDiListMap[objId] || '---',
value: objId,
selectable: false,
children: dataMapNameMap[objId].map((item: any) => ({
title: item.wbsName,
value: item.wbsCode
}))
}));
//
treeData.sort((a, b) => {
const numA = Number(a.value);
const numB = Number(b.value);
const aIsNum = !isNaN(numA);
const bIsNum = !isNaN(numB);
if (aIsNum && bIsNum) return numA - numB;
if (aIsNum) return -1;
if (bIsNum) return 1;
return a.value.localeCompare(b.value);
});
return treeData;
};
/**
* 过滤树形选择器数据
* 当只有一个基地且只有一个流域时直接返回流域列表跳过基地层级
*/
const filterSelectOptions = (options: any[]) => {
if (options?.length === 1 && options?.[0]?.children?.length === 1) {
return options[0].children;
}
return options;
};
// ==================== ==================== // ==================== ====================
/** /**
@ -581,8 +438,32 @@ watch(
() => JidiSelectEventStore.selectedItem, () => JidiSelectEventStore.selectedItem,
async newVal => { async newVal => {
if (newVal && newVal.wbsCode) { if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode; if (newVal.wbsCode === 'all') {
await getMoreSelectData(); moreSelect.value.value = moreSelect.value.options[0]?.value;
} else {
moreSelect.value.value = newVal.wbsCode;
}
await getYearData();
if (moreSelect.value.value) {
await updateYearOptionsByBase(moreSelect.value.value);
}
await getChartData();
}
},
{ deep: true, immediate: true }
);
// JidiSelectEventStore.jidiData moreSelect
watch(
() => JidiSelectEventStore.jidiData,
newVal => {
const filtered = newVal.filter(item => item.wbsCode !== 'all');
moreSelect.value.options = filtered.map(item => ({
value: item.wbsCode,
title: item.wbsName
}));
if (!moreSelect.value.value && filtered.length > 0) {
moreSelect.value.value = filtered[0].wbsCode;
} }
}, },
{ deep: true, immediate: true } { deep: true, immediate: true }

View File

@ -37,7 +37,7 @@
<churukushuiwen <churukushuiwen
v-if="clickDataInfo" v-if="clickDataInfo"
:tm="[clickDataInfo.date, clickDataInfo.date]" :tm="[clickDataInfo.date, clickDataInfo.date]"
:stcd="paramsOne.value" :stcd="select.value"
/> />
</div> </div>
</a-modal> </a-modal>
@ -49,7 +49,7 @@ import { ref, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { getVmsstbprpt, inOutOneGetKendoListCust } from '@/api/sw'; import { inOutOneGetKendoListCust } from '@/api/sw';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import churukushuiwen from './churukushuiwen.vue'; import churukushuiwen from './churukushuiwen.vue';
import { MapClass } from '@/components/gis/map.class'; import { MapClass } from '@/components/gis/map.class';
@ -93,7 +93,6 @@ const scopeDate = ref({
}); });
// ==================== ==================== // ==================== ====================
const baseid = ref(''); // ID
const modalVisible = ref(false); // const modalVisible = ref(false); //
const clickDataInfo = ref<any>(null); // const clickDataInfo = ref<any>(null); //
const stationName = ref(''); // const stationName = ref(''); //
@ -169,7 +168,6 @@ function calculateXAxisInterval(dateCount: number): number {
return Math.ceil(dateCount / 4) - 1; // ,4 return Math.ceil(dateCount / 4) - 1; // ,4
} }
const paramsOne: any = ref({ const paramsOne: any = ref({
value: '',
tm: [currentMonth, currentMonth] tm: [currentMonth, currentMonth]
}); });
/** /**
@ -194,20 +192,10 @@ async function fetchChartData() {
logic: 'and', logic: 'and',
filters: [ filters: [
{ {
// OR: field: 'baseId',
logic: 'or', operator: 'eq',
filters: [ dataType: 'string',
{ value: select.value.value
field: 'engDwtCode',
operator: 'eq',
value: paramsOne.value.value
}, //
{
field: 'engIwtCode',
operator: 'eq',
value: paramsOne.value.value
} //
]
}, },
// //
{ field: 'dt', operator: 'gte', dataType: 'date', value: startDate }, { field: 'dt', operator: 'gte', dataType: 'date', value: startDate },
@ -584,12 +572,10 @@ const handleChartClick = (params: any) => {
dataIndex: dataIndex // dataIndex: dataIndex //
}; };
// //
// console.log(':', select.value.options, paramsOne.value.value); stationName.value = select.value.options?.find(
const selectedStation = select.value.options (item: any) => item.value === select.value.value
.flatMap((base: any) => base.children || []) )?.title || '未知站点';
.find((station: any) => station.stcd === paramsOne.value.value);
stationName.value = selectedStation?.title || '未知站点';
// //
modalVisible.value = true; modalVisible.value = true;
@ -612,7 +598,7 @@ const handleModalClose = () => {
const handlePanelChange1 = (data: any, type: string) => { const handlePanelChange1 = (data: any, type: string) => {
// TODO: // TODO:
if (data.moreSelect && data.scopeDate) { if (data.moreSelect && data.scopeDate) {
paramsOne.value.value = data.moreSelect; select.value.value = data.moreSelect;
paramsOne.value.tm = data.scopeDate; paramsOne.value.tm = data.scopeDate;
fetchChartData(); fetchChartData();
} }
@ -628,143 +614,31 @@ const handlePanelChange1 = (data: any, type: string) => {
} }
}; };
/**
* 获取站点下拉选项数据
* 根据选中的基地ID查询对应的站点列表
*/
const getselsectData = async () => {
loading.value = true; //
try {
let params = {
filter: {
logic: 'and',
filters: [
// baseid'all',
baseid.value != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: baseid.value
}
: null,
// :ENG
{
field: 'sttpCode',
operator: 'contains',
dataType: 'string',
value: 'ENG'
},
// (dtin=1)
{
field: 'dtin',
operator: 'eq',
dataType: 'string',
value: 1
}
].filter(Boolean) // null
},
sort: [
// 'all',;
baseid.value == 'all'
? {
field: 'baseStepSort',
dir: 'asc'
}
: null,
{
field: 'rvcdStepSort',
dir: 'asc'
},
{
field: 'siteStepSort',
dir: 'asc'
}
].filter(Boolean), // null
select: [
'stcd', //
'stnm', //
'lgtd', //
'lttd', //
'siteStepSort', //
'baseId', // ID
'baseName' //
]
};
// API
const res = await getVmsstbprpt(params);
console.log('res', res);
const data = res?.data?.data || res?.data;
const obj: any = {};
if (data) {
// ()
data.map(e => {
if (obj[e.baseId]) {
// ,
obj[e.baseId] = {
...obj[e.baseId],
children: [
...obj[e.baseId].children,
{ ...e, value: e.stcd, title: e.stnm }
]
};
} else {
//
obj[e.baseId] = {
value: e.baseId,
title: e.baseName,
selectable: false,
key: e.baseId,
children: [{ ...e, value: e.stcd, title: e.stnm }]
};
}
});
// jiDiList
let treeData: any = [];
const dataMapNameArr: any = Object.entries(obj).map(([, v]) => v);
treeData = dataMapNameArr?.sort((a: any, b: any) => {
const indexA = JidiSelectEventStore.jidiData.findIndex(
item => item.wbsCode === a.value
);
const indexB = JidiSelectEventStore.jidiData.findIndex(
item => item.wbsCode === b.value
);
return indexA - indexB;
});
console.log('treeData', treeData);
//
select.value.options = treeData;
//
if (baseid.value == 'all') {
select.value.value = '008640203800000001'; //
} else {
select.value.value = treeData?.[0]?.children[0]?.value; //
}
}
} catch (error) {
console.error('获取站点数据失败:', error);
} finally {
loading.value = false; // loading
}
};
// ==================== Watch ==================== // ==================== Watch ====================
/**
* 监听基地选择变化
* 当用户切换基地时,重新加载站点下拉选项
*/
watch( watch(
() => JidiSelectEventStore.selectedItem, // Store () => JidiSelectEventStore.selectedItem,
newVal => { newVal => {
baseid.value = newVal.wbsCode; // ID select.value.value = newVal.wbsCode;
getselsectData(); // fetchChartData();
}, },
{ deep: true, immediate: true } // , { deep: true, immediate: true }
);
// JidiSelectEventStore.jidiData
watch(
() => JidiSelectEventStore.jidiData,
newVal => {
select.value.options = newVal.map(item => ({
value: item.wbsCode,
title: item.wbsName
}));
//
if (!select.value.value && newVal.length > 0) {
select.value.value = newVal[0].wbsCode;
}
},
{ deep: true, immediate: true }
); );
</script> </script>

View File

@ -33,7 +33,7 @@
import { ref, onMounted, onBeforeUnmount, watch } from 'vue' import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { wbsbGetKendoList, avgMonGetKendoListCust } from "@/api/sw"; import { avgMonGetKendoListCust } from "@/api/sw";
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent"; import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
import MonthlyAverage from './monthlyAverage.vue' import MonthlyAverage from './monthlyAverage.vue'
import MonthlyAverageMaxModal from './TwoLayers/monthlyAverageMaxModal.vue' import MonthlyAverageMaxModal from './TwoLayers/monthlyAverageMaxModal.vue'
@ -55,7 +55,6 @@ const searchParams = ref({
dateValue: '' // string Dayjs dateValue: '' // string Dayjs
}); });
const unit = '°C' const unit = '°C'
const baseid: any = ref(null);
const loading = ref(false); const loading = ref(false);
const showemit = ref(true); const showemit = ref(true);
@ -94,123 +93,6 @@ const datetimePicker = ref({
options: [], options: [],
}); });
const filterSelectOptions = (selectOptions: any) => {
if (selectOptions?.length === 1 && selectOptions?.[0]?.children?.length === 1) {
return [{ ...selectOptions?.[0]?.children?.[0], isLeaf: true }]
} else if (selectOptions.length) {
return selectOptions.map((e) => {
if (e?.children?.length > 1) {
return { ...e, isLeaf: false, selectable: true, children: e.children.map((item) => ({ ...item, isLeaf: true })) }
} else {
return { ...e.children[0], isLeaf: true }
}
})
}
return []
}
//
const getSelectConfig = async () => {
loading.value = true;
try {
let obj: any = {}
if (baseid.value === 'all') {
obj = { rstcdStepSort: 'asc', siteStepSort: 'asc' }
} else {
obj = { siteStepSort: 'asc' }
}
const filters = [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
}
]
if (baseid.value && baseid.value !== 'all') {
filters.push({
field: 'objId',
operator: 'eq',
value: baseid.value
})
}
let data: any = {
filter: {
logic: 'and',
filters
}
}
if (obj) {
data.sort = [obj]
} else {
data = {
...data,
group: [
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' },
],
groupResultFlat: true
}
}
let res = await wbsbGetKendoList(data)
let dataOne = res?.data?.data || res?.data
if (dataOne.length > 0) {
let dataMapNameMap: any = {}
let jiDiListMap: any = {}
JidiSelectEventStore.jidiData.forEach((item: any) => {
jiDiListMap[item.wbsCode] = item.wbsName
})
dataOne.map((item: any, index: number) => {
const { stcd, stnm, objId } = item
if (dataMapNameMap[objId]) {
dataMapNameMap[objId].push({ ...item, baseName: jiDiListMap[objId], baseId: objId })
} else {
dataMapNameMap[objId] = [{ ...item, baseName: jiDiListMap[objId], baseId: objId }]
}
return { label: item.wbsName, value: item.wbsCode, baseId: objId, baseName: jiDiListMap[objId] }
})
let dataMapNameArr: any = []
Object.keys(dataMapNameMap).forEach((item: any) => {
dataMapNameArr.push({
title: dataMapNameMap[item]?.[0]?.baseName,
value: item,
selectable: false,
children: dataMapNameMap[item].map((item2: any) => {
return {
title: item2.wbsName,
value: item2.wbsCode
}
})
})
})
dataMapNameArr = dataMapNameArr.sort((a: any, b: any) => {
const indexA = JidiSelectEventStore.jidiData.findIndex(item => item.wbsCode === a.value);
const indexB = JidiSelectEventStore.jidiData.findIndex(item => item.wbsCode === b.value);
return indexA - indexB;
})
select.value.options = filterSelectOptions(dataMapNameArr)
if (filterSelectOptions(dataMapNameArr)[0]?.children) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value
} else if (filterSelectOptions(dataMapNameArr)[0]?.value) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.value
} else {
select.value.value = ''
}
}
getEchartsData()
} catch (error) {
console.error('选择器配置加载失败:', error);
} finally {
loading.value = false;
}
}
// //
const getEchartsData = async () => { const getEchartsData = async () => {
if (loading.value) return; // if (loading.value) return; //
@ -238,7 +120,7 @@ const getEchartsData = async () => {
"logic": "and", "logic": "and",
"filters": [ "filters": [
{ {
"field": "rvcd", "field": "baseId",
"operator": "eq", "operator": "eq",
"dataType": "string", "dataType": "string",
"value": select.value.value "value": select.value.value
@ -527,7 +409,7 @@ const initChart = (newXData: any[], actualData: any[], lastData: any[], naturalD
// //
stationName.value = stnm; stationName.value = stnm;
modalData.value = { modalData.value = {
baseid: baseid.value, baseid: select.value.value,
rvcd: select.value.value, rvcd: select.value.value,
date: datetimePicker.value.value, date: datetimePicker.value.value,
stcd: stcd, stcd: stcd,
@ -575,8 +457,24 @@ const handlePanelChange1 = (data) => {
watch( watch(
() => JidiSelectEventStore.selectedItem, () => JidiSelectEventStore.selectedItem,
(newVal) => { (newVal) => {
baseid.value = newVal.wbsCode; select.value.value = newVal.wbsCode;
getSelectConfig() getEchartsData()
},
{ deep: true, immediate: true }
);
// JidiSelectEventStore.jidiData
watch(
() => JidiSelectEventStore.jidiData,
newVal => {
select.value.options = newVal.map(item => ({
value: item.wbsCode,
title: item.wbsName
}));
//
if (!select.value.value && newVal.length > 0) {
select.value.value = newVal[0].wbsCode;
}
}, },
{ deep: true, immediate: true } { deep: true, immediate: true }
); );

View File

@ -38,12 +38,20 @@
class="tab-style" class="tab-style"
@change="fetchTableData" @change="fetchTableData"
> >
<a-tab-pane v-for="item in tabList" :key="item.key" :tab="item.label" /> <a-tab-pane
v-for="item in tabList"
:key="item.key"
:tab="item.label"
/>
</a-tabs> </a-tabs>
<div class="body_zhengti"> <div class="body_zhengti">
<div class="echarts"> <div class="echarts">
<a-spin :spinning="dataLoading"> <a-spin :spinning="dataLoading">
<div v-if="pieData.length > 0" ref="chartRef" class="pie-chart"></div> <div
v-if="pieData.length > 0"
ref="chartRef"
class="pie-chart"
></div>
<a-empty <a-empty
v-if="!dataLoading && pieData.length === 0" v-if="!dataLoading && pieData.length === 0"
description="暂无数据" description="暂无数据"
@ -55,7 +63,6 @@
ref="tableRef" ref="tableRef"
:columns="columns" :columns="columns"
:scrollY="380" :scrollY="380"
:list-url="vmsstbprptGetKendoList" :list-url="vmsstbprptGetKendoList"
:search-params="searchParams" :search-params="searchParams"
:transform-data="customTransform" :transform-data="customTransform"
@ -80,10 +87,7 @@
</div> </div>
</div> </div>
</template> </template>
<a-empty <a-empty v-else-if="!bodyLoading" description="暂无数据" />
v-else-if="!bodyLoading"
description="暂无数据"
/>
</a-spin> </a-spin>
</div> </div>
</template> </template>
@ -96,6 +100,7 @@ import dayjs from 'dayjs';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { import {
dayGetKendoListCust, dayGetKendoListCust,
overviewvmsstbprptGetKendoList,
vmsstbprptGetKendoList, vmsstbprptGetKendoList,
msstbprptGetKendoList msstbprptGetKendoList
} from '@/api/stll'; } from '@/api/stll';
@ -745,7 +750,7 @@ watch(ecoFlowType, () => {
// tabList // tabList
watch( watch(
() => tabList.value.length, () => tabList.value.length,
(newLen) => { newLen => {
if (newLen === 0 && chartInstance) { if (newLen === 0 && chartInstance) {
chartInstance.dispose(); chartInstance.dispose();
chartInstance = null; chartInstance = null;
@ -766,12 +771,18 @@ const rstcdOption = async () => {
filters: [ filters: [
params.value.qid != 'all' params.value.qid != 'all'
? { ? {
field: 'sttpCode', field: 'baseId',
operator: 'eq', operator: 'contains',
dataType: 'string', dataType: 'string',
value: 'ENG' value: params.value.qid
} }
: null : null,
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'ENG'
}
].filter(Boolean) ].filter(Boolean)
}, },
sort: [ sort: [
@ -782,7 +793,34 @@ const rstcdOption = async () => {
], ],
select: ['stcd', 'stnm'] select: ['stcd', 'stnm']
}; };
let res = await vmsstbprptGetKendoList(obj); if (params.value.qid == 'all') {
obj.sort = [
{
field: 'ttpwr',
dir: 'desc'
}
];
} else {
obj.sort = [
{
field: 'baseId',
dir: 'asc'
},
{
field: 'rvcdStepSort',
dir: 'asc'
},
{
field: 'rstcdStepSort',
dir: 'asc'
},
{
field: 'siteStepSort',
dir: 'asc'
}
];
}
let res = await overviewvmsstbprptGetKendoList(obj);
rstcdOptions.value = res.data.data.map((item: any) => { rstcdOptions.value = res.data.data.map((item: any) => {
return { return {
value: item.stcd, value: item.stcd,
@ -834,7 +872,7 @@ const handleResize = () => {
width: 35%; width: 35%;
height: 482px; height: 482px;
// position: relative; // position: relative;
.pie-chart { .pie-chart {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -30,7 +30,7 @@ import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts'; import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { wbsbGetKendoList, getDftYear, getFishListStat } from '@/api/stdc'; import { getDftYear, getFishListStat } from '@/api/stdc';
import moment from 'moment'; import moment from 'moment';
defineOptions({ defineOptions({
@ -41,7 +41,6 @@ defineOptions({
const JidiSelectEventStore = useJidiSelectEventStore(); const JidiSelectEventStore = useJidiSelectEventStore();
// ==================== ==================== // ==================== ====================
const baseid = ref('');
const isInitializing = ref(false); const isInitializing = ref(false);
const dataLoading = ref(false); const dataLoading = ref(false);
@ -174,8 +173,8 @@ const handleResize = () => {
const getYearData = async () => { const getYearData = async () => {
try { try {
const filter: any = {}; const filter: any = {};
if (baseid.value && baseid.value !== 'all') { if (moreSelect.value.value) {
filter.baseId = baseid.value; filter.baseId = moreSelect.value.value;
} }
const params = { const params = {
@ -236,69 +235,6 @@ const updateYearOptionsByBase = async (wbsCode: string) => {
} }
}; };
const getMoreSelectData = async () => {
if (!baseid.value) return;
isInitializing.value = true;
try {
const params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
},
baseid.value !== 'all'
? {
field: 'objid',
operator: 'eq',
value: baseid.value
}
: null
].filter(Boolean)
},
group: [
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' }
],
groupResultFlat: true
};
const res = await wbsbGetKendoList(params);
const data = res?.data?.data || [];
// debugger
if (data.length > 0) {
const treeData = buildTreeData(data);
const filteredData = filterSelectOptions(treeData);
moreSelect.value.options = filteredData;
moreSelect.value.value = treeData?.[0]?.children?.[0]?.value;
await getYearData();
if (moreSelect.value.value) {
await updateYearOptionsByBase(moreSelect.value.value);
}
await getChartData();
} else {
moreSelect.value.options = [];
moreSelect.value.value = undefined;
await getYearData();
}
} catch (error) {
console.error('获取树形选择器数据失败:', error);
moreSelect.value.options = [];
moreSelect.value.value = undefined;
} finally {
isInitializing.value = false;
}
};
/** /**
* 获取图表数据 * 获取图表数据
* 根据当前选中的流域(hbrvcd)调用 getFishListStat API * 根据当前选中的流域(hbrvcd)调用 getFishListStat API
@ -314,7 +250,7 @@ const getChartData = async () => {
logic: 'and', logic: 'and',
filters: [ filters: [
{ {
field: 'hbrvcd', field: 'baseId',
operator: 'eq', operator: 'eq',
dataType: 'string', dataType: 'string',
value: moreSelect.value.value value: moreSelect.value.value
@ -340,61 +276,6 @@ const getChartData = async () => {
} }
}; };
// ==================== ====================
const buildTreeData = (data: any[]) => {
if (!data || data.length === 0) return [];
const jiDiListMap: Record<string, string> = {};
JidiSelectEventStore.jidiData.forEach((item: any) => {
jiDiListMap[item.wbsCode] = item.wbsName;
});
const dataMapNameMap: Record<string, any[]> = {};
data.forEach(item => {
const objId = item.objid || item.objId;
if (!dataMapNameMap[objId]) {
dataMapNameMap[objId] = [];
}
const exists = dataMapNameMap[objId].some(
existing => existing.wbsCode === item.wbsCode
);
if (!exists) {
dataMapNameMap[objId].push(item);
}
});
const treeData = Object.keys(dataMapNameMap).map(objId => ({
title: jiDiListMap[objId] || '---',
value: objId,
selectable: false,
children: dataMapNameMap[objId].map((item: any) => ({
title: item.wbsName,
value: item.wbsCode
}))
}));
treeData.sort((a, b) => {
const numA = Number(a.value);
const numB = Number(b.value);
const aIsNum = !isNaN(numA);
const bIsNum = !isNaN(numB);
if (aIsNum && bIsNum) return numA - numB;
if (aIsNum) return -1;
if (bIsNum) return 1;
return a.value.localeCompare(b.value);
});
return treeData;
};
const filterSelectOptions = (options: any[]) => {
if (options?.length === 1 && options?.[0]?.children?.length === 1) {
return options[0].children;
}
return options;
};
// ==================== ==================== // ==================== ====================
const handlePanelChange = async (data: any) => { const handlePanelChange = async (data: any) => {
@ -421,8 +302,32 @@ watch(
() => JidiSelectEventStore.selectedItem, () => JidiSelectEventStore.selectedItem,
async newVal => { async newVal => {
if (newVal && newVal.wbsCode) { if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode; if (newVal.wbsCode === 'all') {
await getMoreSelectData(); moreSelect.value.value = moreSelect.value.options[0]?.value;
} else {
moreSelect.value.value = newVal.wbsCode;
}
await getYearData();
if (moreSelect.value.value) {
await updateYearOptionsByBase(moreSelect.value.value);
}
await getChartData();
}
},
{ deep: true, immediate: true }
);
// JidiSelectEventStore.jidiData moreSelect
watch(
() => JidiSelectEventStore.jidiData,
newVal => {
const filtered = newVal.filter(item => item.wbsCode !== 'all');
moreSelect.value.options = filtered.map(item => ({
value: item.wbsCode,
title: item.wbsName
}));
if (!moreSelect.value.value && filtered.length > 0) {
moreSelect.value.value = filtered[0].wbsCode;
} }
}, },
{ deep: true, immediate: true } { deep: true, immediate: true }

View File

@ -26,7 +26,7 @@ import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts'; import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { qgcGetKendoListCust, wbsbGetKendoList } from '@/api/sz'; import { qgcGetKendoListCust } from '@/api/sz';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { useModelStore } from '@/store/modules/model'; import { useModelStore } from '@/store/modules/model';
import { import {
@ -835,12 +835,6 @@ const getecharts = async () => {
field: 'baseId', field: 'baseId',
operator: 'eq', operator: 'eq',
dataType: 'string', dataType: 'string',
value: wbsCode.value
},
{
field: 'rvcd',
operator: 'eq',
dataType: 'string',
value: select.value.value value: select.value.value
}, },
{ {
@ -1154,93 +1148,6 @@ onBeforeUnmount(() => {
} }
}); });
//
const getSelect = async () => {
if (!wbsCode.value) {
console.warn('wbsCode 为空,无法获取河段数据');
return;
}
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'objId',
operator: 'eq',
dataType: 'string',
value: wbsCode.value
},
{
field: 'wbsType',
operator: 'eq',
dataType: 'string',
value: 'PSB_RVCD'
}
]
},
group: [
{
dir: 'asc',
field: 'orderIndex'
},
{
dir: 'des',
field: 'wbsCode'
},
{
dir: 'des',
field: 'wbsName'
}
],
groupResultFlat: 'true'
};
try {
let res = await wbsbGetKendoList(params);
// -
let data;
if (res && res.data && res.data.data) {
// res.data.data 使
if (Array.isArray(res.data.data)) {
data = res.data.data;
}
// res.data.data data 使 res.data.data.data
else if (res.data.data.data && Array.isArray(res.data.data.data)) {
data = res.data.data.data;
} else {
console.warn('无法解析河段数据:', res);
return;
}
} else {
console.warn('未获取到河段数据');
return;
}
if (data && data.length > 0) {
select.value.value = data[0].wbsCode;
select.value.options = data.map(item => {
return {
value: item.wbsCode,
label: item.wbsName
};
});
//
await nextTick();
getecharts();
} else {
console.warn('河段数据为空');
select.value.value = '';
select.value.options = [];
hasData.value = false;
}
} catch (error) {
console.error('获取河段数据失败:', error);
}
};
// //
const handlePanelChange1 = async data => { const handlePanelChange1 = async data => {
console.log('当前所有控件状态:', data); console.log('当前所有控件状态:', data);
@ -1269,7 +1176,21 @@ watch(
newVal => { newVal => {
console.log(newVal); console.log(newVal);
wbsCode.value = newVal.wbsCode; wbsCode.value = newVal.wbsCode;
getSelect(); select.value.value = newVal.wbsCode;
getecharts();
},
{ deep: true, immediate: true }
);
// JidiSelectEventStore.jidiData ""
watch(
() => JidiSelectEventStore.jidiData,
newVal => {
const filtered = newVal.filter(item => item.wbsCode !== 'all');
select.value.options = filtered.map(item => ({
value: item.wbsCode,
label: item.wbsName
}));
}, },
{ deep: true, immediate: true } { deep: true, immediate: true }
); );

View File

@ -25,11 +25,9 @@ import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import type { ECharts } from 'echarts'; import type { ECharts } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { getKendoListCust, wbsbGetKendoList } from '@/api/sw'; import { getKendoListCust } from '@/api/sw';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { da } from 'element-plus/es/locale/index.mjs';
import { f } from 'vue-router/dist/router-CWoNjPRp.mjs';
import { useModelStore } from '@/store/modules/model'; import { useModelStore } from '@/store/modules/model';
const modelStore = useModelStore(); const modelStore = useModelStore();
@ -50,9 +48,7 @@ const getCurrentHourTime = () => {
return `${year}-${month}-${day} ${hour}`; return `${year}-${month}-${day} ${hour}`;
}; };
const JidiSelectEventStore = useJidiSelectEventStore(); const JidiSelectEventStore = useJidiSelectEventStore();
const baseid: any = ref(null);
const paramsOne = { const paramsOne = {
rvcd: '',
tm: [] tm: []
}; };
const dataOne = ref(''); const dataOne = ref('');
@ -300,10 +296,10 @@ const init = async () => {
logic: 'and', logic: 'and',
filters: [ filters: [
{ {
field: 'rvcd', field: 'baseId',
operator: 'eq', operator: 'eq',
dataType: 'string', dataType: 'string',
value: paramsOne.rvcd value: select.value.value
}, },
{ {
field: 'tm', field: 'tm',
@ -378,151 +374,11 @@ const init = async () => {
loading.value = false; loading.value = false;
} }
}; };
//
const getSelectConfig = async () => {
loading.value = true;
try {
let obj: any = {};
if (baseid.value === 'all') {
obj = { rstcdStepSort: 'asc', siteStepSort: 'asc' };
} else {
obj = { siteStepSort: 'asc' };
}
const filters = [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
}
];
if (baseid.value && baseid.value !== 'all') {
filters.push({
field: 'objId',
operator: 'eq', // contains
value: baseid.value
});
}
let data: any = {
filter: {
logic: 'and',
filters
}
// select: ['WBS_CODE', 'WBS_NAME']
};
if (obj) {
data.sort = [obj];
} else {
data = {
...data,
group: [
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' }
],
groupResultFlat: true
};
}
let res = await wbsbGetKendoList(data);
let dataOne = res?.data?.data || res?.data;
if (dataOne.length > 0) {
let dataMapNameMap: any = {};
let jiDiListMap: any = {};
JidiSelectEventStore.jidiData.forEach((item: any) => {
jiDiListMap[item.wbsCode] = item.wbsName;
});
dataOne.map((item: any, index: number) => {
const { stcd, stnm, objId } = item;
if (dataMapNameMap[objId]) {
dataMapNameMap[objId].push({
...item,
baseName: jiDiListMap[objId],
baseId: objId
});
} else {
dataMapNameMap[objId] = [
{ ...item, baseName: jiDiListMap[objId], baseId: objId }
];
}
return {
label: item.wbsName,
value: item.wbsCode,
baseId: objId,
baseName: jiDiListMap[objId]
};
});
let dataMapNameArr: any = [];
Object.keys(dataMapNameMap).forEach((item: any) => {
dataMapNameArr.push({
title: dataMapNameMap[item]?.[0]?.baseName,
value: item,
selectable: false,
// baseId:dataMapNameMap[item]?.[0]?.baseId,
children: dataMapNameMap[item].map((item2: any) => {
return {
title: item2.wbsName,
value: item2.wbsCode
};
})
});
});
dataMapNameArr = dataMapNameArr.sort((a: any, b: any) => {
const indexA = JidiSelectEventStore.jidiData.findIndex(
item => item.wbsCode === a.value
);
const indexB = JidiSelectEventStore.jidiData.findIndex(
item => item.wbsCode === b.value
);
return indexA - indexB;
});
select.value.options = filterSelectOptions(dataMapNameArr);
if (filterSelectOptions(dataMapNameArr)[0]?.children) {
select.value.value =
filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value;
} else if (filterSelectOptions(dataMapNameArr)[0]?.value) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.value;
} else {
select.value.value = '';
}
}
} catch (error) {
console.error('选择器配置加载失败:', error);
} finally {
loading.value = false;
}
};
const filterSelectOptions = (selectOptions: any) => {
if (
selectOptions?.length === 1 &&
selectOptions?.[0]?.children?.length === 1
) {
return [{ ...selectOptions?.[0]?.children?.[0], isLeaf: true }];
} else if (selectOptions.length) {
return selectOptions.map(e => {
if (e?.children?.length > 1) {
return {
...e,
isLeaf: false,
selectable: true,
children: e.children.map(item => ({ ...item, isLeaf: true }))
};
} else {
return { ...e.children[0], isLeaf: true };
}
});
}
return [];
};
// //
const handlePanelChange1 = data => { const handlePanelChange1 = data => {
console.log('当前所有控件状态:', data); console.log('当前所有控件状态:', data);
if (data.moreSelect) { if (data.moreSelect) {
paramsOne.rvcd = data.moreSelect; select.value.value = data.moreSelect;
} }
if (data.datetime) { if (data.datetime) {
@ -565,7 +421,7 @@ const handlePanelChange1 = data => {
paramsOne.tm = result; paramsOne.tm = result;
console.log(paramsOne.tm, 'paramsOne.tm'); console.log(paramsOne.tm, 'paramsOne.tm');
} }
if (paramsOne.rvcd || paramsOne.tm.length > 0) { if (select.value.value || paramsOne.tm.length > 0) {
init(); init();
} }
}; };
@ -573,8 +429,26 @@ const handlePanelChange1 = data => {
watch( watch(
() => JidiSelectEventStore.selectedItem, () => JidiSelectEventStore.selectedItem,
newVal => { newVal => {
baseid.value = newVal.wbsCode; // if (newVal.baseId) {
getSelectConfig(); select.value.value = newVal.wbsCode;
init();
// }
},
{ deep: true, immediate: true }
);
// JidiSelectEventStore.jidiData ""
watch(
() => JidiSelectEventStore.jidiData,
newVal => {
select.value.options = newVal.map(item => ({
value: item.wbsCode,
title: item.wbsName
}));
//
if (!select.value.value && newVal.length > 0) {
select.value.value = newVal[0].baseId || newVal[0].wbsCode;
}
}, },
{ deep: true, immediate: true } { deep: true, immediate: true }
); );

View File

@ -47,7 +47,7 @@ export const useJidiSelectEventStore = defineStore('jidiSelectEvent', () => {
dir: 'asc' dir: 'asc'
} }
], ],
select: ['wbsCode', 'wbsName'] select: ['wbsCode', 'wbsName', 'baseId']
}; };
const res = await wbsbGetKendoList(params); const res = await wbsbGetKendoList(params);
const data = res?.data?.data || [ const data = res?.data?.data || [

View File

@ -34,7 +34,7 @@ service.interceptors.request.use(
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9'; config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
config.headers.authorization = config.headers.authorization =
'bearer 223f63a2-0b13-4757-8e15-f342098e63ca'; 'bearer b142d8ee-7e9d-4704-97c9-da935615bac3';
config.baseURL = '/'; config.baseURL = '/';
} else { } else {
const user = useUserStoreHook(); const user = useUserStoreHook();

View File

@ -37,13 +37,13 @@
</a-row> </a-row>
<a-row> <a-row>
<a-col :span="12"> <a-col :span="12">
<a-form-item label="所在河段" name="rvcd"> <a-form-item label="水电基地" name="baseId">
<a-select <a-select
v-model:value="formData.rvcd" v-model:value="formData.baseId"
show-search show-search
style="width: 100%" style="width: 100%"
placeholder="请选择所在河段" placeholder="请选择水电基地"
:options="riverOptions" :options="filteredRiverOptions"
:filter-option="filterOption" :filter-option="filterOption"
@change="handleRiverSelect" @change="handleRiverSelect"
:disabled="isEdit" :disabled="isEdit"
@ -108,7 +108,9 @@
<template #title="{ dataRef }"> <template #title="{ dataRef }">
<!-- 编辑状态只显示编辑区域 --> <!-- 编辑状态只显示编辑区域 -->
<div <div
v-if="editingNode && editingNodeKey === dataRef.key" v-if="
editingNode && editingNodeKey === dataRef.key && !dataRef.parentId
"
class="add-child-node-row w-[300px]" class="add-child-node-row w-[300px]"
> >
<a-select <a-select
@ -155,8 +157,8 @@
size="small" size="small"
@click.stop="handleAddChild(dataRef)" @click.stop="handleAddChild(dataRef)"
:title=" :title="
dataRef.sttpName dataRef.stnm
? `子级添加-${dataRef.sttpName}` ? `子级添加-${dataRef.stnm}`
: '子级添加' : '子级添加'
" "
> >
@ -238,47 +240,19 @@
</template> </template>
</div> </div>
</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 childStationList"
:key="item.stcd"
:value="item.stcd"
>
{{ item.stnm }}-{{ item.sttpName }}
</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>
</template> </template>
</a-tree> </a-tree>
<a-empty v-else description="暂无数据" style="margin-top: 20px" /> <a-empty v-else description="暂无数据" style="margin-top: 20px" />
</div> </div>
</a-modal> </a-modal>
<!-- 测站选择弹窗子节点新增/编辑用 -->
<StationSelectModal
:baseId="formData.baseId"
v-model:visible="stationSelectVisible"
@confirm="handleStationSelectConfirm"
/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -294,8 +268,9 @@ import {
ArrowUpOutlined, ArrowUpOutlined,
ArrowDownOutlined ArrowDownOutlined
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import { getEngInfoDropdown, getAddvcdDropdownByRvcd } from '@/api/select'; import { getEngInfoDropdown } from '@/api/select';
import StationSelectModal from './StationSelectModal.vue';
import { useDraggable } from '@/utils/drag';
interface Props { interface Props {
visible: boolean; visible: boolean;
initialValues?: any | null; initialValues?: any | null;
@ -315,7 +290,7 @@ const modalVisible = computed({
get: () => props.visible, get: () => props.visible,
set: val => emit('update:visible', val) set: val => emit('update:visible', val)
}); });
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:visible', value: boolean): void; (e: 'update:visible', value: boolean): void;
(e: 'cancel'): void; (e: 'cancel'): void;
@ -328,7 +303,7 @@ const defaultFormData = reactive({
id: undefined, id: undefined,
name: undefined, name: undefined,
code: undefined, code: undefined,
rvcd: undefined, baseId: undefined,
remark: undefined remark: undefined
}); });
const formData: any = reactive({ ...defaultFormData }); const formData: any = reactive({ ...defaultFormData });
@ -336,19 +311,16 @@ 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' }],
rvcd: [{ required: true, message: '请选择所在河段', trigger: 'change' }] baseId: [{ required: true, message: '请选择水电基地', trigger: 'change' }]
};
const handleRiverSelect = async (value: string) => {
const res = await getEngInfoDropdown({ rvcd: value });
stationList.value = (res.data || []).map((item: any) => ({
...item,
stnm: item.ennm
}));
}; };
const isEdit = computed(() => !!props.initialValues); const isEdit = computed(() => !!props.initialValues);
// ""wbsCode === 'all'
const filteredRiverOptions = computed(() =>
props.riverOptions.filter((item: any) => item.value !== 'all')
);
// //
const treeData = ref<any[]>([]); const treeData = ref<any[]>([]);
@ -357,17 +329,12 @@ const addingNewNode = ref(false);
const newNodeData = ref({ const newNodeData = ref({
stcd: undefined, stcd: undefined,
ennm: '', ennm: '',
sttpName: '' stnm: ''
}); });
// // /
const addingChildNode = ref(false); const stationSelectVisible = ref(false);
const currentParentKey = ref<string | null>(null); const currentParentKey = ref<string | null>(null);
const childNodeData = ref({
stcd: undefined,
ennm: '',
sttpName: ''
});
// //
const editingNode = ref(false); const editingNode = ref(false);
@ -375,7 +342,7 @@ const editingNodeKey = ref<string | null>(null);
const editNodeData = ref({ const editNodeData = ref({
stcd: undefined, stcd: undefined,
ennm: '', ennm: '',
sttpName: '', stnm: '',
originalData: null as any originalData: null as any
}); });
@ -386,12 +353,30 @@ const childStationList = ref([]);
let nodeIdCounter = 0; let nodeIdCounter = 0;
const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`; const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`;
// sort
const refreshNodeSort = (nodes: any[]) => {
nodes.forEach((node, index) => {
node.sort = index;
});
};
// stcd
const checkDuplicateStcd = (stcd: string, siblings: any[], excludeKey?: string): boolean => {
return siblings.some(node => node.stcd === stcd && node.key !== excludeKey);
};
const handleRiverSelect = async (value: string) => {
const res = await getEngInfoDropdown({ baseId: value });
stationList.value = (res.data || []).map((item: any) => ({
...item,
stnm: item.ennm
}));
};
// //
const getNodeTitle = (dataRef: any) => { const getNodeTitle = (dataRef: any) => {
if (!dataRef.parentId) { if (!dataRef.parentId) {
return dataRef.ennm || ''; return dataRef.ennm || '';
} else { } else {
return `${dataRef.ennm || ''} ${dataRef.sttpName || ''}`; return `${dataRef.stnm ||dataRef.ennm || ''}-${dataRef.type == 1 || dataRef.ioDirection == 1 ? '出库' : '入库'}`;
} }
}; };
@ -446,15 +431,15 @@ const findNodeByKey = (nodes: any[], key: string): any => {
// //
const handleAdd = () => { const handleAdd = () => {
if (!formData.rvcd) { if (!formData.baseId) {
message.warning('请先选择所在河段'); message.warning('请先选择水电基地');
return; return;
} }
addingNewNode.value = true; addingNewNode.value = true;
newNodeData.value = { newNodeData.value = {
stcd: undefined, stcd: undefined,
ennm: '', ennm: '',
sttpName: '' stnm: ''
}; };
}; };
@ -463,7 +448,7 @@ 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.ennm = station.stnm; newNodeData.value.ennm = station.stnm;
newNodeData.value.sttpName = station.sttpName; newNodeData.value.stnm = station.stnm;
} }
}; };
@ -474,16 +459,22 @@ const handleSaveNewNode = () => {
return; return;
} }
if (checkDuplicateStcd(newNodeData.value.stcd, treeData.value)) {
message.warning('该站点已存在,请勿重复添加');
return;
}
const newNode = { const newNode = {
key: generateNodeId(), key: generateNodeId(),
stcd: newNodeData.value.stcd, stcd: newNodeData.value.stcd,
ennm: newNodeData.value.ennm, ennm: newNodeData.value.ennm,
sttpName: newNodeData.value.sttpName, stnm: newNodeData.value.stnm,
parentId: null, parentId: null,
children: [] children: []
}; };
treeData.value.push(newNode); treeData.value.push(newNode);
refreshNodeSort(treeData.value);
addingNewNode.value = false; addingNewNode.value = false;
message.success('添加成功'); message.success('添加成功');
}; };
@ -494,93 +485,34 @@ const handleCancelAdd = () => {
newNodeData.value = { newNodeData.value = {
stcd: undefined, stcd: undefined,
ennm: '', ennm: '',
sttpName: '' stnm: ''
}; };
}; };
// // -
const handleAddChild = async (parentData: any) => { const handleAddChild = (parentData: any) => {
addingChildNode.value = true;
currentParentKey.value = parentData.key; currentParentKey.value = parentData.key;
childNodeData.value = { editingNodeKey.value = null; //
stcd: undefined, stationSelectVisible.value = true;
ennm: '',
sttpName: ''
};
const res = await getAddvcdDropdownByRvcd({ stcd: parentData.stcd });
childStationList.value = res.data || [];
};
//
const handleChildNodeSelect = (value: string) => {
const station = childStationList.value.find(item => item.stcd === value);
if (station) {
childNodeData.value.ennm = 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,
ennm: childNodeData.value.ennm,
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,
ennm: '',
sttpName: ''
};
}; };
// //
const handleEditNode = async (dataRef: any) => { const handleEditNode = async (dataRef: any) => {
editingNode.value = true;
editingNodeKey.value = dataRef.key;
//
editNodeData.value = {
stcd: dataRef.stcd,
ennm: dataRef.ennm,
sttpName: dataRef.sttpName,
originalData: { ...dataRef }
};
if (dataRef.parentId) { if (dataRef.parentId) {
const parent = findNodeByKey(treeData.value, dataRef.parentId); //
if (parent) { editingNodeKey.value = dataRef.key;
const res = await getAddvcdDropdownByRvcd({ stcd: parent.stcd }); currentParentKey.value = null; //
childStationList.value = res.data || []; stationSelectVisible.value = true;
} } else {
//
editingNode.value = true;
editingNodeKey.value = dataRef.key;
editNodeData.value = {
stcd: dataRef.stcd,
ennm: dataRef.ennm,
stnm: dataRef.stnm,
originalData: { ...dataRef }
};
} }
}; };
@ -591,7 +523,7 @@ const handleEditNodeSelect = (dataRef: any) => {
const station = list.find(item => item.stcd === value); const station = list.find(item => item.stcd === value);
if (station) { if (station) {
editNodeData.value.ennm = station.stnm; editNodeData.value.ennm = station.stnm;
editNodeData.value.sttpName = station.sttpName; editNodeData.value.stnm = station.stnm;
editNodeData.value.stcd = station.stcd; editNodeData.value.stcd = station.stcd;
} }
}; };
@ -610,10 +542,16 @@ const handleSaveEditNode = () => {
return; return;
} }
//
if (checkDuplicateStcd(editNodeData.value.stcd, treeData.value, editingNodeKey.value!)) {
message.warning('该站点在当前层级已存在,请重新选择');
return;
}
// //
node.stcd = editNodeData.value.stcd; node.stcd = editNodeData.value.stcd;
node.ennm = editNodeData.value.ennm; node.ennm = editNodeData.value.ennm;
node.sttpName = editNodeData.value.sttpName; node.stnm = editNodeData.value.stnm;
editingNode.value = false; editingNode.value = false;
editingNodeKey.value = null; editingNodeKey.value = null;
@ -627,11 +565,66 @@ const handleCancelEditNode = () => {
editNodeData.value = { editNodeData.value = {
stcd: undefined, stcd: undefined,
ennm: '', ennm: '',
sttpName: '', stnm: '',
originalData: null originalData: null
}; };
}; };
// /
const handleStationSelectConfirm = (data: { record: any; type: number }) => {
if (editingNodeKey.value && currentParentKey.value === null) {
// -
const node = findNodeByKey(treeData.value, editingNodeKey.value);
if (node) {
//
const siblings = node.parentId
? findNodeByKey(treeData.value, node.parentId)?.children || []
: treeData.value;
if (checkDuplicateStcd(data.record.stcd, siblings, editingNodeKey.value!)) {
message.warning('该站点在当前层级已存在,请重新选择');
return;
}
node.stcd = data.record.stcd;
node.ennm = data.record.ennm;
node.sttpName = data.record.sttpName;
node.baseName = data.record.baseName;
node.type = data.type;
node.stnm = data.record.stnm;
message.success('编辑成功');
}
editingNodeKey.value = null;
} else {
// -
const parent = findNodeByKey(treeData.value, currentParentKey.value!);
if (!parent) {
message.error('父节点不存在');
return;
}
if (checkDuplicateStcd(data.record.stcd, parent.children || [])) {
message.warning('该站点在当前层级已存在,请勿重复添加');
return;
}
const newChild = {
key: generateNodeId(),
stcd: data.record.stcd,
ennm: data.record.ennm,
sttpName: data.record.sttpName,
baseName: data.record.baseName,
stnm: data.record.stnm,
type: data.type,
parentId: parent.key,
children: []
};
if (!parent.children) parent.children = [];
parent.children.unshift(newChild);
refreshNodeSort(parent.children);
message.success('添加子节点成功');
}
currentParentKey.value = null;
stationSelectVisible.value = false;
};
// //
const handleMoveUp = (dataRef: any) => { const handleMoveUp = (dataRef: any) => {
const siblings = getSiblings(dataRef); const siblings = getSiblings(dataRef);
@ -643,6 +636,7 @@ const handleMoveUp = (dataRef: any) => {
siblings[index], siblings[index],
siblings[index - 1] siblings[index - 1]
]; ];
refreshNodeSort(siblings);
message.success('上移成功'); message.success('上移成功');
} }
}; };
@ -658,6 +652,7 @@ const handleMoveDown = (dataRef: any) => {
siblings[index + 1], siblings[index + 1],
siblings[index] siblings[index]
]; ];
refreshNodeSort(siblings);
message.success('下移成功'); message.success('下移成功');
} }
}; };
@ -739,15 +734,21 @@ const initForm = async () => {
} }
// //
if (formData.rvcd) { if (formData.baseId) {
const res = await getEngInfoDropdown({ rvcd: formData.rvcd }); const res = await getEngInfoDropdown({ baseId: formData.baseId });
stationList.value = (res.data || []).map((item: any) => ({ stationList.value = (res.data || []).map((item: any) => ({
...item, ...item,
stnm: item.ennm stnm: item.ennm
})); }));
} }
} else { } else {
resetForm(); resetForm();
const res = await getEngInfoDropdown({});
stationList.value = (res.data || []).map((item: any) => ({
...item,
stnm: item.ennm
}));
} }
}; };
@ -776,6 +777,14 @@ watch(
{ immediate: false } { immediate: false }
); );
//
watch(stationSelectVisible, visible => {
if (!visible) {
editingNodeKey.value = null;
currentParentKey.value = null;
}
});
defineExpose({ defineExpose({
localLoading localLoading
}); });

View File

@ -38,7 +38,7 @@ const emit = defineEmits<{
const initSearchData = { const initSearchData = {
name: null, name: null,
rvcd: null baseId: 'all'
}; };
const searchData = ref<any>({ ...initSearchData }); const searchData = ref<any>({ ...initSearchData });
@ -53,12 +53,10 @@ const searchList: any = computed(() => [
}, },
{ {
type: 'Select', type: 'Select',
name: 'rvcd', name: 'baseId',
label: '所在河段', label: '水电基地',
width: 300, width: 300,
fieldProps: {
allowClear: true
},
options: props.riverOptions, options: props.riverOptions,
loading: props.riverOptionsLoad loading: props.riverOptionsLoad
} }

View File

@ -0,0 +1,218 @@
<template>
<a-modal
:open="visible"
title="选择测站"
width="1536px"
:footer="null"
:body-style="{ height: '700px', padding: '16px' }"
:destroy-on-close="true"
@cancel="handleClose"
>
<!-- 搜索表单 -->
<a-form layout="inline" class="search-form">
<a-form-item label="名称">
<a-input
v-model:value="searchName"
placeholder="请输入测站名称"
style="width: 180px"
allow-clear
@press-enter="handleSearch"
/>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSearch">查询</a-button>
</a-form-item>
</a-form>
<!-- 表格 -->
<div class="table-wrapper">
<BasicTable
ref="tableRef"
:columns="columns"
:scrollY="460"
:list-url="noAuthGetKendoPage"
:search-params="searchParams"
:transform-data="transformData"
:enable-row-selection="true"
row-key="stcd"
@selection-change="onSelectionChange"
/>
</div>
<!-- 底部按钮 -->
<div class="footer-actions">
<a-button type="primary" :disabled="!selectedRow" @click="handleConfirm">
确认选择
</a-button>
</div>
</a-modal>
<!-- 出库/入库选择弹窗 -->
<a-modal
:open="typeModalVisible"
title="选择类型"
width="400px"
:z-index="2000"
ok-text="确认"
:ok-button-props="{ disabled: selectedType === null }"
@ok="handleTypeConfirm"
@cancel="handleTypeCancel"
>
<a-radio-group v-model:value="selectedType">
<a-radio :value="1">出库</a-radio>
<a-radio :value="2">入库</a-radio>
</a-radio-group>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { noAuthGetKendoPage } from '@/api/select';
import BasicTable from '@/components/BasicTable/index.vue';
interface Props {
visible: boolean;
baseId: string;
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
baseId: ''
});
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void;
(e: 'confirm', data: { record: any; type: number }): void;
}>();
//
const searchName = ref('');
//
const tableRef = ref();
const selectedRow = ref<any>(null);
//
const typeModalVisible = ref(false);
const selectedType = ref<number | null>(null);
const columns = [
{ title: '测站名称', key: 'stnm', dataIndex: 'stnm', width: 200 },
{ title: '测站类型', key: 'sttpName', dataIndex: 'sttpName', width: 200 },
{ title: '水电基地', key: 'baseName', dataIndex: 'baseName', width: 200 },
{ title: '电站名称', key: 'ennm', dataIndex: 'ennm', width: 200 }
];
const searchParams = computed(() => ({
sort: [
{
field: 'ORDER_INDEX',
dir: 'asc'
}
]
}));
const transformData = (res: any) => {
return {
records: res?.data?.data || res?.data || [],
total: res?.data?.total || res?.data?.length || 0
};
};
//
const onSelectionChange = (keys: string[], rows: any[]) => {
if (keys.length > 1) {
//
const lastKey = keys[keys.length - 1];
const lastRow = rows[rows.length - 1];
tableRef.value.setSelectedRowKeys([lastKey]);
selectedRow.value = lastRow;
} else {
selectedRow.value = rows.length > 0 ? rows[0] : null;
}
};
//
const handleSearch = () => {
const filters: any[] = [
props.baseId != 'all'
? {
field: 'BASE_ID',
operator: 'eq',
dataType: 'string',
value: props.baseId
}
: null
].filter(Boolean);
if (searchName.value) {
filters.push({
field: 'STNM',
operator: 'contains',
value: searchName.value
});
}
const filter = {
logic: 'and',
filters
};
tableRef.value?.getList(filter);
};
//
watch(
() => props.visible,
visible => {
if (visible) {
searchName.value = '';
// DOM
setTimeout(() => handleSearch(), 0);
}
}
);
//
const handleConfirm = () => {
if (!selectedRow.value) return;
selectedType.value = null;
typeModalVisible.value = true;
};
//
const handleTypeConfirm = () => {
if (selectedType.value === null) return;
emit('confirm', {
record: selectedRow.value,
type: selectedType.value
});
typeModalVisible.value = false;
handleClose();
};
//
const handleTypeCancel = () => {
typeModalVisible.value = false;
};
//
const handleClose = () => {
emit('update:visible', false);
};
</script>
<style scoped lang="scss">
.search-form {
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0;
}
.table-wrapper {
flex: 1;
overflow: hidden;
}
.footer-actions {
margin-top: 16px;
text-align: right;
}
</style>

View File

@ -48,7 +48,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick, onMounted } from 'vue'; import { ref, nextTick, onMounted, computed } from 'vue';
import BasicTable from '@/components/BasicTable/index.vue'; import BasicTable from '@/components/BasicTable/index.vue';
import ConfigManagementSearch from './ConfigManagementSearch.vue'; import ConfigManagementSearch from './ConfigManagementSearch.vue';
import ConfigManagementForm from './ConfigManagementForm.vue'; import ConfigManagementForm from './ConfigManagementForm.vue';
@ -62,7 +62,8 @@ import {
} from '@/api/system/map/ConfigManagement'; } from '@/api/system/map/ConfigManagement';
import { getRvcdDropdown } from '@/api/select'; import { getRvcdDropdown } from '@/api/select';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
const JidiSelectEventStore = useJidiSelectEventStore();
// //
const basicTable = ref<any>(null); const basicTable = ref<any>(null);
// //
@ -88,9 +89,9 @@ const columns = [
width: 120 width: 120
}, },
{ {
title: '所在河段', title: '水电基地',
dataIndex: 'rvnm', dataIndex: 'baseName',
key: 'rvnm', key: 'baseName',
width: 300, width: 300,
ellipsis: true ellipsis: true
}, },
@ -129,12 +130,12 @@ const columns = [
// //
const searchParams = ref({ const searchParams = ref({
"sort": [ sort: [
{ {
"field": "recordTime", field: 'recordTime',
"dir": "desc" dir: 'desc'
} }
], ]
}); });
// //
const currentRecord = ref<any | null>(null); const currentRecord = ref<any | null>(null);
@ -181,9 +182,10 @@ const handleEdit = async (record: any) => {
const res = await getChildConfigTree(params); const res = await getChildConfigTree(params);
if (res.code == 0) { if (res.code == 0) {
const data = res.data.data || []; const data = res.data.data || [];
const firstLevelNodes = data.filter((item: any) => !item.rstcd); const firstLevelNodes = data.filter((item: any) => !item.rstcd);
const secondLevelNodes = data.filter((item: any) => item.rstcd); const secondLevelNodes = data.filter((item: any) => item.rstcd);
// debugger
const configNodes = firstLevelNodes.map((node: any, index: number) => { const configNodes = firstLevelNodes.map((node: any, index: number) => {
const children = secondLevelNodes.filter( const children = secondLevelNodes.filter(
(child: any) => child.rstcd === node.stcd (child: any) => child.rstcd === node.stcd
@ -194,19 +196,23 @@ const handleEdit = async (record: any) => {
stcd: node.stcd, stcd: node.stcd,
ennm: node.stnm, ennm: node.stnm,
sttpName: node.sttpName, sttpName: node.sttpName,
sort: node.sort,
parentId: null, parentId: null,
children: children.map((child: any, childIndex: number) => ({ children: children.map((child: any, childIndex: number) => ({
key: `child-${index}-${childIndex}`, key: `child-${index}-${childIndex}`,
stcd: child.stcd, stcd: child.stcd,
ennm: child.stnm, ennm: child.stnm,
sttpName: child.sttpName, sttpName: child.sttpName,
sort: child.sort,
parentId: `parent-${index}`, parentId: `parent-${index}`,
ioDirection: child.ioDirection,
children: [] children: []
})) }))
}; };
}); });
currentRecord.value.configNodes = configNodes; currentRecord.value.configNodes = configNodes;
// debugger
} }
editModalVisible.value = true; editModalVisible.value = true;
}; };
@ -239,12 +245,12 @@ const onSearchFinish = (values: any) => {
const params = { const params = {
logic: 'and', logic: 'and',
filters: [ filters: [
values.rvcd values.baseId != 'all'
? { ? {
field: 'rvcd', field: 'baseId',
operator: 'eq', operator: 'eq',
dataType: 'string', dataType: 'string',
value: values.rvcd value: values.baseId
} }
: null, : null,
values.name values.name
@ -280,6 +286,7 @@ const handleEditSubmit = async (values: any) => {
const formData = { const formData = {
...currentRecord.value, ...currentRecord.value,
...values, ...values,
baseName: (JidiSelectEventStore.jidiData.find(element => element.wbsCode === values.baseId) || {}).wbsName,
modifyTime: dayjs().format('YYYY-MM-DD HH:mm:ss') modifyTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
}; };
delete formData.configNodes; delete formData.configNodes;
@ -299,7 +306,8 @@ const handleEditSubmit = async (values: any) => {
const formatTreeData = ( const formatTreeData = (
nodes: any[], nodes: any[],
parentId: string | null = null, parentId: string | null = null,
parentStcd: string | null = null parentStcd: string | null = null,
type: string | null = null
) => { ) => {
return nodes.map(node => ({ return nodes.map(node => ({
alongId, alongId,
@ -308,15 +316,15 @@ const handleEditSubmit = async (values: any) => {
sttpName: node.sttpName, sttpName: node.sttpName,
parentId: parentId ? parentId : null, parentId: parentId ? parentId : null,
rstcd: parentStcd || null, rstcd: parentStcd || null,
ioDirection: node.type ||node.ioDirection || null,
children: children:
node.children && node.children.length > 0 node.children && node.children.length > 0
? formatTreeData(node.children, node.key, node.stcd) ? formatTreeData(node.children, node.key, node.stcd, node.type)
: [] : []
})); }));
}; };
const detailData = formatTreeData(treeData); const detailData = formatTreeData(treeData);
const detailRes = await saveBaseWbsbChildDetail(detailData); const detailRes = await saveBaseWbsbChildDetail(detailData);
if (detailRes.code == 0) { if (detailRes.code == 0) {
message.success(`保存成功`); message.success(`保存成功`);
@ -339,19 +347,29 @@ const handleEditSubmit = async (values: any) => {
return; return;
} }
}; };
const riverOptions = ref<any>([]); // const riverOptions = ref<any>([]);
const riverOptions = computed(() => {
return JidiSelectEventStore.jidiData.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}));
});
const riverOptionsLoad = ref(false); const riverOptionsLoad = ref(false);
const initOption = () => { const initOption = () => {
const params = {}; // const params = {};
riverOptionsLoad.value = true; // riverOptionsLoad.value = true;
getRvcdDropdown(params).then((res: any) => { // riverOptions.value = JidiSelectEventStore.jidiData.map((item:any)=>{
res.data.forEach((item: any) => { // return{
item.value = item.rvcd; // }
item.label = item.rvnm; // })
}); // getRvcdDropdown(params).then((res: any) => {
riverOptions.value = res.data || []; // res.data.forEach((item: any) => {
riverOptionsLoad.value = false; // item.value = item.rvcd;
}); // item.label = item.rvnm;
// });
// riverOptions.value = res.data || [];
// riverOptionsLoad.value = false;
// });
}; };
onMounted(() => { onMounted(() => {
initOption(); initOption();

View File

@ -0,0 +1,567 @@
<template>
<a-modal
:title="isEdit ? '编辑飞行路径' : '新增飞行路径'"
v-model:open="modalVisible"
:confirm-loading="localLoading"
width="1536px"
: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="飞行路径Code" name="code">
<a-input
v-model:value="formData.code"
style="width: 100%"
placeholder="请输入飞行路径Code"
/>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-form-item label="备注" name="remark">
<a-textarea
v-model:value="formData.remark"
:rows="4"
style="width: 100%"
placeholder="请输入备注"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="水电基地" name="baseId">
<a-select
v-model:value="formData.baseId"
show-search
style="width: 100%"
placeholder="请选择水电基地"
:options="ennmOptions"
:filter-option="filterOption"
:disabled="isEdit"
@change="getdianzha"
/>
</a-form-item>
</a-col>
</a-row>
<a-divider />
<div class="flex justify-between items-center mb-2">
<a-button type="primary" @click="handleAddRow"> 新增行</a-button>
</div>
<div ref="tableWrapperRef">
<a-table
:data-source="currentPageData"
:columns="columns"
:pagination="false"
row-key="id"
size="small"
:scroll="{ x: 950 }"
:custom-row="customRow"
>
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'drag'">
<UnorderedListOutlined
v-if="editingRowId !== record.id"
class="drag-handle cursor-move text-gray-400"
/>
</template>
<template v-else-if="column.key === 'index'">
{{ (currentPage - 1) * pageSize + index + 1 }}
</template>
<template v-else-if="column.key === 'time'">
<template v-if="editingRowId === record.id">
<a-input-number
v-model:value="record.time"
style="width: 100%"
placeholder="时间(s)"
/>
</template>
<template v-else>
{{ record.time ?? '-' }}
</template>
</template>
<template v-else-if="column.key === 'lgtd'">
<template v-if="editingRowId === record.id">
<a-input-number
v-model:value="record.lgtd"
style="width: 100%"
placeholder="经度"
/>
</template>
<template v-else>
{{ record.lgtd ?? '-' }}
</template>
</template>
<template v-else-if="column.key === 'lttd'">
<template v-if="editingRowId === record.id">
<a-input-number
v-model:value="record.lttd"
style="width: 100%"
placeholder="纬度"
/>
</template>
<template v-else>
{{ record.lttd ?? '-' }}
</template>
</template>
<template v-else-if="column.key === 'dtmel'">
<template v-if="editingRowId === record.id">
<a-input-number
v-model:value="record.dtmel"
style="width: 100%"
placeholder="高程(m)"
/>
</template>
<template v-else>
{{ record.dtmel ?? '-' }}
</template>
</template>
<template v-else-if="column.key === 'stnm'">
<template v-if="editingRowId === record.id">
<a-select
v-model:value="record.stcd"
style="width: 100%"
placeholder="请选择电站"
:options="stationOptions"
allow-clear
@change="(val) => handleStnmChange(record, val)"
/>
</template>
<template v-else>
{{ getStationLabel(record.stcd) || '-' }}
</template>
</template>
<template v-else-if="column.key === 'action'">
<template v-if="editingRowId === record.id">
<a-button
type="link"
size="small"
@click="handleSaveRow(record)"
>保存</a-button
>
</template>
<template v-else>
<a-button
type="link"
size="small"
@click="handleStartEdit(record)"
>编辑</a-button
>
</template>
<a-popconfirm
title="确定删除该航点?"
@confirm="handleDeleteRow(record)"
>
<a-button type="link" danger size="small">删除</a-button>
</a-popconfirm>
</template>
</template>
</a-table>
</div>
<div v-if="formData.list.length > pageSize" class="flex justify-end mt-2">
<a-pagination
v-model:current="currentPage"
:total="formData.list.length"
:page-size="pageSize"
size="small"
show-size-changer
:page-size-options="['5', '10', '20', '50']"
show-total
@change="handlePageChange"
/>
</div>
</a-form>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch, nextTick, onBeforeUnmount } from 'vue';
import { message } from 'ant-design-vue';
import type { Rule } from 'ant-design-vue/es/form';
import { UnorderedListOutlined } from '@ant-design/icons-vue';
import Sortable from 'sortablejs';
import dayjs from 'dayjs';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { getEngInfoDropdown } from '@/api/select';
import { useDraggable } from '@/utils/drag';
const JidiSelectEventStore = useJidiSelectEventStore();
//
const stationOptions = ref([]);
//
const columns = [
{ title: '排序', key: 'drag', width: 60, align: 'center' as const },
{ title: '序号', key: 'index', width: 60, align: 'center' as const },
{ title: '时间(s)', key: 'time', width: 130 },
{ title: '经度°', key: 'lgtd', width: 150 },
{ title: '纬度°', key: 'lttd', width: 150 },
{ title: '高程(m)', key: 'dtmel', width: 120 },
{ title: '电站名称', key: 'stnm', width: 160 },
{ title: '操作', key: 'action', width: 120, align: 'center' as const }
];
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)
});
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void;
(e: 'cancel'): void;
(e: 'ok', values: any): void;
}>();
const formRef = ref();
const tableWrapperRef = ref<HTMLElement | null>(null);
let sortableInstance: Sortable | null = null;
// ID
const editingRowId = ref<string | null>(null);
// data-row-key
const customRow = (record: any) => {
return {
attrs: {
'data-row-key': record?.id
}
};
};
//
const currentPage = ref(1);
const pageSize = ref(5);
const currentPageData = computed(() => {
const start = (currentPage.value - 1) * pageSize.value;
return formData.list.slice(start, start + pageSize.value);
});
const defaultFormData = reactive({
id: undefined,
name: undefined,
baseId: undefined,
code: undefined,
remark: undefined,
list: [] as any[]
});
const formData: any = reactive({ ...defaultFormData });
const rules: Record<string, Rule[]> = {
name: [{ required: true, message: '请输入飞行路径名称', trigger: 'blur' }],
code: [{ required: true, message: '请输入飞行路径Code', trigger: 'blur' }]
};
const isEdit = computed(() => !!props.initialValues);
// ID
const generateId = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = (Math.random() * 16) | 0;
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16).toUpperCase();
});
};
//
const handleStartEdit = (record: any) => {
editingRowId.value = record.id;
};
// 退
const handleSaveRow = (record: any) => {
editingRowId.value = null;
};
//
const handleAddRow = () => {
if(!formData.baseId){
message.warning('请先选择水电基地');
return;
}
//
if (editingRowId.value) {
message.warning('请先保存当前编辑的行');
return;
}
const newRow = {
_tls: {},
id: generateId(),
recordUser: null,
recordTime: null,
modifyTime: null,
displayRecordUser: null,
roamId: null,
code: formData.code || null,
name: formData.name || null,
lgtd: undefined,
lttd: undefined,
dtmel: undefined,
time: undefined,
orderIndex: formData.list.length,
stcd: null,
stnm: undefined,
departmentId: null,
displayDepartment: null
};
formData.list.push(newRow);
//
editingRowId.value = newRow.id;
//
const lastPage = Math.ceil(formData.list.length / pageSize.value);
currentPage.value = lastPage;
nextTick(() => initSortable());
};
//
const handleDeleteRow = (record: any) => {
// 退
if (editingRowId.value === record.id) {
editingRowId.value = null;
}
const idx = formData.list.findIndex((item: any) => item.id === record.id);
if (idx !== -1) {
formData.list.splice(idx, 1);
//
if (currentPageData.value.length === 0 && currentPage.value > 1) {
currentPage.value--;
}
nextTick(() => initSortable());
}
};
//
const handlePageChange = () => {
editingRowId.value = null; // 退
nextTick(() => initSortable());
};
// Sortable DOM data-row-key oldIndex/newIndex
const initSortable = () => {
destroySortable();
if (!tableWrapperRef.value) return;
const tbody = tableWrapperRef.value.querySelector('.ant-table-tbody');
if (!tbody) return;
sortableInstance = new Sortable(tbody as HTMLElement, {
handle: '.drag-handle',
animation: 150,
onEnd: evt => {
if (!tbody) return;
// DOM
const rows = tbody.querySelectorAll<HTMLElement>('tr.ant-table-row');
const domIds: (string | null)[] = [];
rows.forEach(row => {
const id = row.getAttribute('data-row-key');
if (id) domIds.push(id);
});
if (domIds.length === 0) return;
const page = currentPage.value;
const size = pageSize.value;
const start = (page - 1) * size;
const end = start + size;
// DOM
const pageItems = domIds
.map(id => formData.list.find((item: any) => item.id === id))
.filter(Boolean);
if (pageItems.length === 0) return;
// + +
const before = formData.list.slice(0, start);
const after = formData.list.slice(end);
formData.list.splice(
0,
formData.list.length,
...before,
...pageItems,
...after
);
}
});
};
const destroySortable = () => {
if (sortableInstance) {
sortableInstance.destroy();
sortableInstance = null;
}
};
//
const handleOk = async () => {
//
if (editingRowId.value) {
message.warning('请先保存当前编辑的行');
return;
}
try {
await formRef.value.validate();
// baseId rvcd orderIndex
const submitValues = {
name: formData.name,
code: formData.code,
remark: formData.remark || null,
baseId: formData.baseId,
id: formData.id || undefined,
list: formData.list.map((item: any, index: number) => ({
...item,
orderIndex: index,
time: item.time ?? null,
lgtd: item.lgtd ?? null,
lttd: item.lttd ?? null,
dtmel: item.dtmel ?? null
}))
};
emit('ok', submitValues);
} catch (error) {
console.error('Validate Failed:', error);
message.error('请检查表单填写是否正确');
}
};
//
const initForm = () => {
currentPage.value = 1;
editingRowId.value = null;
if (props.initialValues) {
const values = props.initialValues;
// formData
Object.keys(formData).forEach(key => {
if (key === 'list') return; // list
if (values.hasOwnProperty(key)) {
if (key === 'captureDate' && values[key]) {
formData[key] = dayjs(values[key]);
} else {
formData[key] = values[key];
}
}
});
// rvcd baseId
if (values.baseId) {
formData.baseId = values.baseId;
}
// list
formData.list = values.list
? values.list.map((item: any) => ({ ...item }))
: [];
} else {
resetForm();
}
nextTick(() => initSortable());
};
const resetForm = () => {
if (formRef.value) {
formRef.value.resetFields();
}
Object.assign(formData, defaultFormData);
formData.list = [];
};
const handleCancel = () => {
emit('update:visible', false);
emit('cancel');
resetForm();
};
//
const filterOption = (inputValue: string, option: any) => {
const label = option.label || option.name || '';
const reachcdName = option.reachcdName || '';
const keyword = inputValue || '';
return label.indexOf(keyword) !== -1 || reachcdName.indexOf(keyword) !== -1;
};
const ennmOptions = computed(() => {
return JidiSelectEventStore.jidiData.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}));
});
const getdianzha = async (data: any) => {
//
if (!isEdit.value && formData.list.length > 0) {
formData.list = [];
currentPage.value = 1;
editingRowId.value = null;
nextTick(() => initSortable());
}
const res = await getEngInfoDropdown({ baseId: data });
stationOptions.value = res.data.map((item: any) => ({
label: item.ennm,
value: item.stcd
}));
};
// select stcd stnm使
const handleStnmChange = (record: any, stcd: string | undefined) => {
const option = stationOptions.value.find((opt: any) => opt.value === stcd);
record.stnm = option ? option.label : null;
};
// stcd label
const getStationLabel = (stcd: string | undefined) => {
const option = stationOptions.value.find((opt: any) => opt.value === stcd);
return option ? option.label : stcd;
};
watch(
() => props.visible,
newVisible => {
if (newVisible) {
initForm();
} else {
destroySortable();
}
},
{ immediate: false }
);
onBeforeUnmount(() => {
destroySortable();
});
defineExpose({
localLoading
});
</script>
<style scoped lang="scss">
.drag-handle {
cursor: grab;
&:active {
cursor: grabbing;
}
}
</style>

View File

@ -0,0 +1,70 @@
<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>
<a-button @click="props.handleImport">导入</a-button>
<a-button @click="props.handleExport">导出模板</a-button>
</template>
</BasicSearch>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from "vue";
import BasicSearch from "@/components/BasicSearch/index.vue";
interface Props {
handleAdd: () => void;
handleImport: () => void;
handleExport: () => void;
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "reset", values: any): void;
(e: "searchFinish", values: any): void;
}>();
const initSearchData = {
name: "",
};
const searchData = ref<any>({ ...initSearchData });
const searchList: any = computed(() => [
{
type: "Input",
name: "name",
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
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,293 @@
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\disposeManage\index.vue -->
<template>
<div class="content">
<disposeManageSearch
ref="disposeManageSearchRef"
:handle-add="handleAdd"
:handle-import="handleImport"
:handle-export="handleExport"
@reset="handleReset"
@search-finish="onSearchFinish"
/>
<BasicTable
ref="basicTable"
:columns="columns"
:list-url="threedroambGetKendoListCust"
: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>
<disposeManageForm
ref="disposeManageFormRef"
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 disposeManageSearch from './disposeManageSearch.vue';
import disposeManageForm from './disposeManageForm.vue';
import { message, Modal } from 'ant-design-vue';
import {
threedroambGetKendoListCust,
threedroambsave,
threedroambdelete,
threedroambGetKendoById,
threedroambimport,
threedroambexport
} from '@/api/system/disposeManage';
import { downloadFile } from '@/utils/index';
//
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: '飞行路径Code',
dataIndex: 'code',
key: 'code',
width: 150
},
{
title: '创建人',
key: 'recordUser',
dataIndex: 'recordUser',
width: 350
},
{
title: '创建时间',
key: 'recordTime',
dataIndex: 'recordTime',
width: 150
},
{
title: '更新时间',
key: 'modifyTime',
dataIndex: 'modifyTime',
width: 150
},
{
title: '备注',
key: 'remark',
dataIndex: 'remark',
},
{
title: '操作',
key: 'action',
width: 120,
fixed: 'right',
slots: { customRender: 'action' }
}
];
//
const basicTable = ref<any>(null);
//
const searchParams = ref({});
//
const currentRecord = ref<any | null>(null);
const editModalVisible = ref(false);
//
const handleAdd = () => {
currentRecord.value = null;
editModalVisible.value = true;
};
//
const handleImport = () => {
//
const input = document.createElement('input');
input.type = 'file';
input.accept = '.xlsx,.xls,.csv';
input.onchange = async (e: any) => {
const file = e.target.files?.[0];
if (!file) return;
const formData = new FormData();
formData.append('file', file);
try {
await threedroambimport(formData);
message.success('导入成功');
basicTable.value.refresh();
} catch (error) {
message.error('导入失败');
}
};
input.click();
};
//
const handleExport = async () => {
try {
const res = await threedroambexport({});
downloadFile(res, '飞行路径模板', 'xlsx');
} catch (error) {
message.error('导出失败');
}
};
// -
const handleEdit = async (record: any) => {
try {
const res = await threedroambGetKendoById({ id: record.id });
currentRecord.value = res?.data || res;
editModalVisible.value = true;
} catch (error) {
message.error('获取数据失败');
}
};
//
const handleDelete = (record: any) => {
Modal.confirm({
title: '确认删除',
content: '确定要删除选中的记录吗?',
zIndex: 2002,
onOk: async () => {
try {
let res = await threedroambdelete({ id: record.id });
message.success('删除成功');
basicTable.value.refresh();
} catch (error) {
message.error('删除失败');
return;
}
}
});
};
//
const onSearchFinish = (values: any) => {
const params = {
logic: 'and',
filters: [
values.name? {
field: 'name',
operator: 'contains',
dataType: 'string',
value: values.name
}:null,
{
field: 'isDeleted',
operator: 'eq',
dataType: 'string',
value: '0'
}
].filter(Boolean)
};
basicTable.value.getList(params);
};
//
const handleReset = () => {
nextTick(() => {
basicTable.value.getList({
logic: 'and',
filters: [ {
field: 'isDeleted',
operator: 'eq',
dataType: 'string',
value: '0'
}]
});
});
};
//
const editModalCancel = () => {
currentRecord.value = null;
editModalVisible.value = false;
};
//
const handleEditSubmit = async (values: any) => {
try {
// let res = await threedroambsave({
// ...currentRecord.value,
// ...values,
// });
let res = await threedroambsave(values);
message.success(`保存成功`);
editModalVisible.value = false;
basicTable.value.refresh();
} catch (error) {
message.error(`保存失败`);
editModalVisible.value = false;
return;
}
};
const initOption = () => {
//
nextTick(() => {
basicTable.value?.getList({
logic: 'and',
filters: [{
field: 'isDeleted',
operator: 'eq',
dataType: 'string',
value: '0'
}]
});
});
};
onMounted(() => {
initOption();
});
</script>
<style scoped lang="scss">
.tilt-photo-management {
height: 100%;
padding: 16px;
}
.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;
padding: 16px;
}
</style>