BUG更改
This commit is contained in:
parent
d7c33850b5
commit
3623a47546
@ -79,6 +79,16 @@ export function vmsstbprptGetKendoList(data: any) {
|
|||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 环保自动监测工作开展情弹窗
|
||||||
|
export function overviewvmsstbprptGetKendoList(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/overview/vmsstbprpt/GetKendoList',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 获取基本信息
|
// 获取基本信息
|
||||||
export function baseMsstbprptGetKendoList(data: any) {
|
export function baseMsstbprptGetKendoList(data: any) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import request from '@/utils/request';
|
|||||||
// 获取所有倾斜摄影
|
// 获取所有倾斜摄影
|
||||||
export function getAllTiltPhotoTree(data: any) {
|
export function getAllTiltPhotoTree(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-sys-server/sys/oblique/GetKendoListCust',
|
url: '/sys/oblique/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -11,7 +11,7 @@ export function getAllTiltPhotoTree(data: any) {
|
|||||||
// 保存倾斜摄影
|
// 保存倾斜摄影
|
||||||
export function saveTiltPhoto(data: any) {
|
export function saveTiltPhoto(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-sys-server/sys/oblique/addOrUpdate',
|
url: '/sys/oblique/addOrUpdate',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -19,7 +19,7 @@ export function saveTiltPhoto(data: any) {
|
|||||||
// 删除倾斜摄影
|
// 删除倾斜摄影
|
||||||
export function deleteTiltPhoto(data: any) {
|
export function deleteTiltPhoto(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-sys-server/sys/oblique/delete',
|
url: '/sys/oblique/delete',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
|
|||||||
@ -468,7 +468,7 @@ const triggerManualValuesChange = (changedKey: string, newValue: any) => {
|
|||||||
emit('valuesChange', changedValues, { ...formData });
|
emit('valuesChange', changedValues, { ...formData });
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataDimensionDataChange = (value: any, fieldName: string = 'baseId') => {
|
const dataDimensionDataChange = (value: any, fieldName = 'baseId') => {
|
||||||
formData[fieldName] = value;
|
formData[fieldName] = value;
|
||||||
formData.rstcd = "";
|
formData.rstcd = "";
|
||||||
shuJuTianBaoStore.getEngOption(value,'baseId');
|
shuJuTianBaoStore.getEngOption(value,'baseId');
|
||||||
|
|||||||
@ -192,6 +192,7 @@ const getList = async (filter?: Record<string, any>) => {
|
|||||||
total.value = 0;
|
total.value = 0;
|
||||||
if (filter !== undefined) {
|
if (filter !== undefined) {
|
||||||
lastFilter.value = filter;
|
lastFilter.value = filter;
|
||||||
|
page.value = 1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 合并排序参数:优先使用用户手动排序,否则使用 searchParams 中的默认排序
|
// 合并排序参数:优先使用用户手动排序,否则使用 searchParams 中的默认排序
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<div class="card_left">
|
<div class="card_left">
|
||||||
<div class="card_img">
|
<div class="card_img">
|
||||||
<div class="carousel-wrapper">
|
<div class="carousel-wrapper">
|
||||||
<div class="carousel-inner">
|
<div class="carousel-inner" ref="carouselInnerRef">
|
||||||
<div class="carousel-track" :style="trackStyle">
|
<div class="carousel-track" :style="trackStyle">
|
||||||
<div v-for="(item, index) in originalMediaData" :key="index" class="carousel-item">
|
<div v-for="(item, index) in originalMediaData" :key="index" class="carousel-item">
|
||||||
<a-image :src="item.url" />
|
<a-image :src="item.url" />
|
||||||
@ -43,7 +43,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted, watch } from 'vue';
|
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
|
||||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -67,6 +67,15 @@ interface MediaItem {
|
|||||||
|
|
||||||
const originalMediaData = ref<MediaItem[]>([]);
|
const originalMediaData = ref<MediaItem[]>([]);
|
||||||
const currentIndex = ref(0);
|
const currentIndex = ref(0);
|
||||||
|
const carouselInnerRef = ref<HTMLElement | null>(null);
|
||||||
|
const itemWidth = ref(0);
|
||||||
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
|
|
||||||
|
const updateItemWidth = () => {
|
||||||
|
if (carouselInnerRef.value) {
|
||||||
|
itemWidth.value = carouselInnerRef.value.clientWidth;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
const initOriginalData = () => {
|
const initOriginalData = () => {
|
||||||
@ -89,10 +98,9 @@ const setCurrentIndexFromProps = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 计算轨道样式 - 完全按照 React 版本的逻辑
|
|
||||||
const trackStyle = computed(() => {
|
const trackStyle = computed(() => {
|
||||||
return {
|
return {
|
||||||
transform: `translateX(calc((68.8px - 48vw) * ${currentIndex.value}))`
|
transform: `translateX(-${itemWidth.value * currentIndex.value}px)`
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -122,12 +130,23 @@ const currentDescription = computed(() => {
|
|||||||
const currentTitle = computed(() => {
|
const currentTitle = computed(() => {
|
||||||
return originalMediaData.value[currentIndex.value]?.title || '';
|
return originalMediaData.value[currentIndex.value]?.title || '';
|
||||||
});
|
});
|
||||||
// 页面加载时执行
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log('ArtsDetail mounted - props.index:', props.index, 'props.dataSource.length:', props.dataSource?.length);
|
|
||||||
initOriginalData();
|
initOriginalData();
|
||||||
setCurrentIndexFromProps();
|
setCurrentIndexFromProps();
|
||||||
console.log('After setCurrentIndexFromProps - currentIndex.value:', currentIndex.value);
|
updateItemWidth();
|
||||||
|
if (carouselInnerRef.value) {
|
||||||
|
resizeObserver = new ResizeObserver(() => {
|
||||||
|
updateItemWidth();
|
||||||
|
});
|
||||||
|
resizeObserver.observe(carouselInnerRef.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (resizeObserver) {
|
||||||
|
resizeObserver.disconnect();
|
||||||
|
resizeObserver = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 只监听 dataSource 变化,不监听 index 变化
|
// 只监听 dataSource 变化,不监听 index 变化
|
||||||
@ -196,10 +215,9 @@ watch(
|
|||||||
transition: transform 0.3s ease-in-out;
|
transition: transform 0.3s ease-in-out;
|
||||||
|
|
||||||
.carousel-item {
|
.carousel-item {
|
||||||
width: calc(48vw - 80.8px);
|
width: 100%;
|
||||||
flex: 0 0 calc(48vw - 80.8px);
|
flex: 0 0 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-right: 12px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import { PointLayerManager } from './ol/point-layer-manager';
|
|||||||
import { PopupManager } from './ol/popup-manager';
|
import { PopupManager } from './ol/popup-manager';
|
||||||
import { RegionMaskManager } from './ol/region-mask-manager';
|
import { RegionMaskManager } from './ol/region-mask-manager';
|
||||||
import { getNearbyPointDensityDisplayRules } from '@/modules/map/domain/nearby-point-rules';
|
import { getNearbyPointDensityDisplayRules } from '@/modules/map/domain/nearby-point-rules';
|
||||||
|
import router from '@/router';
|
||||||
|
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
const VITE_APP_MAP_URL = import.meta.env.VITE_APP_MAP_URL;
|
const VITE_APP_MAP_URL = import.meta.env.VITE_APP_MAP_URL;
|
||||||
@ -167,6 +168,13 @@ export class MapOl implements MapInterface {
|
|||||||
this.handleZoomChange();
|
this.handleZoomChange();
|
||||||
});
|
});
|
||||||
this.map.on('click', evt => {
|
this.map.on('click', evt => {
|
||||||
|
if (
|
||||||
|
router.currentRoute.value.path.includes(
|
||||||
|
'shengTaiLiuLiangManZuQingKuangJiangJu'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.popupManager.showPopup(undefined, undefined);
|
this.popupManager.showPopup(undefined, undefined);
|
||||||
this.popupManager.handleMapClick(evt.pixel, detectedFeature => {
|
this.popupManager.handleMapClick(evt.pixel, detectedFeature => {
|
||||||
if (detectedFeature.values_.sttpMap == 'ylfb') {
|
if (detectedFeature.values_.sttpMap == 'ylfb') {
|
||||||
|
|||||||
@ -318,7 +318,7 @@ export class PointLayerManager {
|
|||||||
layerKey: string,
|
layerKey: string,
|
||||||
matchValue: string,
|
matchValue: string,
|
||||||
checked: boolean,
|
checked: boolean,
|
||||||
fieldKey: string = 'anchoPointState'
|
fieldKey = 'anchoPointState'
|
||||||
): void {
|
): void {
|
||||||
const vectorLayer = this.layerRegistry.get(layerKey);
|
const vectorLayer = this.layerRegistry.get(layerKey);
|
||||||
if (!vectorLayer) return;
|
if (!vectorLayer) return;
|
||||||
|
|||||||
@ -209,7 +209,7 @@ export class RegionMaskManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 备注:清除当前底图遮罩并按需恢复默认视野,供切换基地和异常兜底复用。
|
// 备注:清除当前底图遮罩并按需恢复默认视野,供切换基地和异常兜底复用。
|
||||||
clearMapMask(resetView: boolean = true): void {
|
clearMapMask(resetView = true): void {
|
||||||
const maskedLayers = this.maskBindings.map(binding => binding.layer);
|
const maskedLayers = this.maskBindings.map(binding => binding.layer);
|
||||||
this.clearMaskEvents();
|
this.clearMaskEvents();
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<a-form ref="formRef" :model="formState" layout="inline" class="search-form">
|
<a-form ref="formRef" :model="formState" layout="inline" class="search-form">
|
||||||
<a-space wrap>
|
<a-space wrap>
|
||||||
<a-form-item label="所属基地" name="dataDimensionVal">
|
<a-form-item label="所属基地" name="dataDimensionVal">
|
||||||
<a-select v-model:value="formState.dataDimensionVal" placeholder="请选择" style="width: 120px"
|
<a-select v-model:value="formState.dataDimensionVal" placeholder="请选择" style="width: 140px"
|
||||||
show-search :filter-option="filterBaseOption" option-filter-prop="label"
|
show-search :filter-option="filterBaseOption" option-filter-prop="label"
|
||||||
@change="handleBaseChange">
|
@change="handleBaseChange">
|
||||||
<a-select-option v-for="item in baseList" :key="item.wbsCode" :value="item.wbsCode"
|
<a-select-option v-for="item in baseList" :key="item.wbsCode" :value="item.wbsCode"
|
||||||
@ -32,7 +32,7 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="达标状态" name="sfdb">
|
<a-form-item label="达标状态" name="sfdb">
|
||||||
<a-select v-model:value="formState.sfdb" placeholder="请选择" style="width: 100px" show-search
|
<a-select v-model:value="formState.sfdb" placeholder="请选择" style="width: 160px" show-search
|
||||||
:filter-option="filterOption" option-filter-prop="label">
|
:filter-option="filterOption" option-filter-prop="label">
|
||||||
<a-select-option value="" label="全部">全部</a-select-option>
|
<a-select-option value="" label="全部">全部</a-select-option>
|
||||||
<a-select-option value="0" label="不达标">不达标</a-select-option>
|
<a-select-option value="0" label="不达标">不达标</a-select-option>
|
||||||
@ -44,12 +44,12 @@
|
|||||||
<a-form-item label="时间" name="dateValues">
|
<a-form-item label="时间" name="dateValues">
|
||||||
<a-date-picker v-model:value="formState.dateValues"
|
<a-date-picker v-model:value="formState.dateValues"
|
||||||
:format="formState.types === 'month' ? 'YYYY-MM' : 'YYYY'" :picker="formState.types"
|
:format="formState.types === 'month' ? 'YYYY-MM' : 'YYYY'" :picker="formState.types"
|
||||||
placeholder="请选择月份" style="width: 140px" :disabled-date="disabledMonthDate" />
|
placeholder="请选择月份" style="width: 100px" :disabled-date="disabledMonthDate" />
|
||||||
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="断面名称" name="stnm">
|
<a-form-item label="断面名称" name="stnm">
|
||||||
<a-input v-model:value="formState.stnm" placeholder="请输入断面名称" style="width: 200px" allow-clear />
|
<a-input v-model:value="formState.stnm" placeholder="请输入断面名称" style="width: 180px" allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
@ -90,7 +90,7 @@
|
|||||||
<!-- 详情弹窗 -->
|
<!-- 详情弹窗 -->
|
||||||
<a-modal v-model:open="detailModalVisible" :title="`${detailData.stnm || ''} 详细信息`" width="1536px" :footer="null"
|
<a-modal v-model:open="detailModalVisible" :title="`${detailData.stnm || ''} 详细信息`" width="1536px" :footer="null"
|
||||||
@cancel="handleDetailModalClose">
|
@cancel="handleDetailModalClose">
|
||||||
<HJMZDTwoLays :tc="{
|
<HJMZDTwoLays v-if="detailModalVisible" :tc="{
|
||||||
stcd: detailData.stcd || '',
|
stcd: detailData.stcd || '',
|
||||||
startTime: detailData.tm,
|
startTime: detailData.tm,
|
||||||
endTime: (typeof detailData.tm === 'string' ? detailData.tm.split(' ')[0] : dayjs(detailData.tm).format('YYYY-MM-DD')) + ' 23:59:59',
|
endTime: (typeof detailData.tm === 'string' ? detailData.tm.split(' ')[0] : dayjs(detailData.tm).format('YYYY-MM-DD')) + ' 23:59:59',
|
||||||
@ -231,7 +231,7 @@ const columns = [
|
|||||||
title: '断面名称',
|
title: '断面名称',
|
||||||
dataIndex: 'stnm',
|
dataIndex: 'stnm',
|
||||||
key: 'stnm',
|
key: 'stnm',
|
||||||
width: 180,
|
width: 200,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customCell: (record: any, rowIndex: number) => {
|
customCell: (record: any, rowIndex: number) => {
|
||||||
const tableData = tableRef.value?.tableData || []
|
const tableData = tableRef.value?.tableData || []
|
||||||
@ -243,13 +243,13 @@ const columns = [
|
|||||||
title: '测站类型',
|
title: '测站类型',
|
||||||
dataIndex: 'sttypeName',
|
dataIndex: 'sttypeName',
|
||||||
key: 'sttypeName',
|
key: 'sttypeName',
|
||||||
width: 120
|
width: 80
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '达标状态',
|
title: '达标状态',
|
||||||
dataIndex: 'sfdbName',
|
dataIndex: 'sfdbName',
|
||||||
key: 'sfdbName',
|
key: 'sfdbName',
|
||||||
width: 120,
|
width: 80,
|
||||||
customRender: ({ record }: any) => {
|
customRender: ({ record }: any) => {
|
||||||
const sfdb = record.sfdbName
|
const sfdb = record.sfdbName
|
||||||
let color = '#000000'
|
let color = '#000000'
|
||||||
@ -267,19 +267,19 @@ const columns = [
|
|||||||
title: '水质要求',
|
title: '水质要求',
|
||||||
dataIndex: 'wwqtgName',
|
dataIndex: 'wwqtgName',
|
||||||
key: 'wwqtgName',
|
key: 'wwqtgName',
|
||||||
width: 120
|
width: 80
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '当前水质',
|
title: '当前水质',
|
||||||
dataIndex: 'wqGrdName',
|
dataIndex: 'wqGrdName',
|
||||||
key: 'wqGrdName',
|
key: 'wqGrdName',
|
||||||
width: 120
|
width: 80
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '去年同期水质',
|
title: '去年同期水质',
|
||||||
dataIndex: 'beforeWqGrdName',
|
dataIndex: 'beforeWqGrdName',
|
||||||
key: 'beforeWqGrdName',
|
key: 'beforeWqGrdName',
|
||||||
width: 150
|
width: 140
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@ -674,7 +674,7 @@ const handleReset = () => {
|
|||||||
formState.dtinType = ''
|
formState.dtinType = ''
|
||||||
formState.types = props.type || 'month'
|
formState.types = props.type || 'month'
|
||||||
formState.sfdb = ''
|
formState.sfdb = ''
|
||||||
formState.dateValues = dayjs()
|
formState.dateValues =props.dateValue ? (typeof props.dateValue === 'string' ? dayjs(props.dateValue, props.type === 'month' ? 'YYYY-MM' : 'YYYY') : props.dateValue) : dayjs(),
|
||||||
formState.stnm = ''
|
formState.stnm = ''
|
||||||
pieCode.value = []
|
pieCode.value = []
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
v-model:value="formState.sfdb"
|
v-model:value="formState.sfdb"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
allow-clear
|
allow-clear
|
||||||
style="width: 150px"
|
style="width: 160px"
|
||||||
>
|
>
|
||||||
<a-select-option value="">全部</a-select-option>
|
<a-select-option value="">全部</a-select-option>
|
||||||
<a-select-option :value="'0'">不达标</a-select-option>
|
<a-select-option :value="'0'">不达标</a-select-option>
|
||||||
@ -114,7 +114,8 @@ const columnList = [
|
|||||||
elementCode: '',
|
elementCode: '',
|
||||||
disabledDate: true,
|
disabledDate: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
multiLink: false
|
multiLink: false,
|
||||||
|
width: 160
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndexRaw: '',
|
dataIndexRaw: '',
|
||||||
@ -558,18 +559,18 @@ const transUnit = (value: any, tbCode: string, ys: string) => {
|
|||||||
// ==================== 监听器 ====================
|
// ==================== 监听器 ====================
|
||||||
|
|
||||||
// 监听 tc 和 formState.sfdb 变化,重新获取列配置
|
// 监听 tc 和 formState.sfdb 变化,重新获取列配置
|
||||||
watch(
|
// watch(
|
||||||
() => [props.tc.stcd, props.tc.startTime, props.tc.endTime, formState.sfdb],
|
// () => [props.tc.stcd, props.tc.startTime, props.tc.endTime, formState.sfdb],
|
||||||
([stcd, startTime, endTime]) => {
|
// ([stcd, startTime, endTime]) => {
|
||||||
if (!stcd) {
|
// if (!stcd) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
//
|
// //
|
||||||
tableRef.value.tableData = [];
|
// tableRef.value.tableData = [];
|
||||||
getCol({ stcd, startTime, endTime });
|
// getCol({ stcd, startTime, endTime });
|
||||||
},
|
// },
|
||||||
{ immediate: false } // 不在初始化时立即执行,由 onMounted 处理
|
// { immediate: false } // 不在初始化时立即执行,由 onMounted 处理
|
||||||
);
|
// );
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@ -167,6 +167,7 @@ const columns = [
|
|||||||
dataIndex: 'dtinTm',
|
dataIndex: 'dtinTm',
|
||||||
key: 'dtinTm',
|
key: 'dtinTm',
|
||||||
width: 120,
|
width: 120,
|
||||||
|
sort: true, // 启用排序
|
||||||
customRender: ({ record }: any) => {
|
customRender: ({ record }: any) => {
|
||||||
const date = record.dtinTm
|
const date = record.dtinTm
|
||||||
if (!date) return '-'
|
if (!date) return '-'
|
||||||
@ -192,6 +193,7 @@ const columns = [
|
|||||||
dataIndex: 'ststdt',
|
dataIndex: 'ststdt',
|
||||||
key: 'ststdt',
|
key: 'ststdt',
|
||||||
width: 120,
|
width: 120,
|
||||||
|
sort: true, // 启用排序
|
||||||
customRender: ({ record }: any) => {
|
customRender: ({ record }: any) => {
|
||||||
const date = record.ststdt
|
const date = record.ststdt
|
||||||
if (!date) return '-'
|
if (!date) return '-'
|
||||||
@ -211,6 +213,7 @@ const columns = [
|
|||||||
dataIndex: 'jcdt',
|
dataIndex: 'jcdt',
|
||||||
key: 'jcdt',
|
key: 'jcdt',
|
||||||
width: 120,
|
width: 120,
|
||||||
|
sort: true, // 启用排序
|
||||||
customRender: ({ record }: any) => {
|
customRender: ({ record }: any) => {
|
||||||
const date = record.jcdt
|
const date = record.jcdt
|
||||||
if (!date) return '-'
|
if (!date) return '-'
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:scrollY="400"
|
:scrollY="400"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:list-url="vmsstbprptGetKendoList"
|
:list-url="overviewvmsstbprptGetKendoList"
|
||||||
:search-params="searchParams"
|
:search-params="searchParams"
|
||||||
:transform-data="customTransform"
|
:transform-data="customTransform"
|
||||||
>
|
>
|
||||||
@ -73,8 +73,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed, onMounted, h } from 'vue';
|
||||||
import { vmsstbprptGetKendoList } from '@/api/home';
|
import { Tooltip } from 'ant-design-vue';
|
||||||
|
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { vmsstbprptGetKendoList,overviewvmsstbprptGetKendoList } from '@/api/home';
|
||||||
import BasicTable from '@/components/BasicTable/index.vue';
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
import { useModelStore } from '@/store/modules/model';
|
import { useModelStore } from '@/store/modules/model';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
@ -144,10 +146,9 @@ const columns = computed(() => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'coenvwState',
|
key: 'coenvwState',
|
||||||
title: '监测状态',
|
title: h(Tooltip, { title: '最近1天有监测数据为在线,否则为离线' }, { default: () => h('span', null, ['监测状态', h(QuestionCircleOutlined, { style: { marginLeft: '4px', color: '#000' } })]) }),
|
||||||
dataIndex: 'coenvwState',
|
dataIndex: 'coenvwState',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
|
|
||||||
slots: { customRender: 'coenvwState' }
|
slots: { customRender: 'coenvwState' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -203,7 +204,7 @@ const columns = computed(() => {
|
|||||||
if (tabIndex.value !== '4') {
|
if (tabIndex.value !== '4') {
|
||||||
baseColumns.push({
|
baseColumns.push({
|
||||||
key: 'coenvwState',
|
key: 'coenvwState',
|
||||||
title: '监测状态',
|
title: h(Tooltip, { title: '最近1天有监测数据为在线,否则为离线' }, { default: () => h('span', null, ['监测状态', h(QuestionCircleOutlined, { style: { marginLeft: '4px', color: '#999' } })]) }),
|
||||||
dataIndex: 'coenvwState',
|
dataIndex: 'coenvwState',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
slots: { customRender: 'coenvwState' }
|
slots: { customRender: 'coenvwState' }
|
||||||
@ -313,7 +314,7 @@ const getRstcdData = async () => {
|
|||||||
],
|
],
|
||||||
select: ['stcd', 'stnm']
|
select: ['stcd', 'stnm']
|
||||||
};
|
};
|
||||||
const res = await vmsstbprptGetKendoList(parmas);
|
const res = await overviewvmsstbprptGetKendoList(parmas);
|
||||||
rstcdOptions.value = res.data.data.map((item) => {
|
rstcdOptions.value = res.data.data.map((item) => {
|
||||||
return {
|
return {
|
||||||
value: item.stcd,
|
value: item.stcd,
|
||||||
|
|||||||
@ -317,7 +317,7 @@ import dayjs from 'dayjs';
|
|||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import videoCover from '@/assets/images/videFm.jpg';
|
import videoCover from '@/assets/images/videFm.jpg';
|
||||||
import { useDraggable } from '@/utils/drag';
|
import { useDraggable } from '@/utils/drag';
|
||||||
;
|
|
||||||
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
|
|
||||||
// ==================== Props ====================
|
// ==================== Props ====================
|
||||||
|
|||||||
@ -33,9 +33,12 @@
|
|||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button type="primary" @click="handleSearch">查询</a-button>
|
<a-button type="primary" @click="handleSearch">查询</a-button>
|
||||||
<!-- <a-button style="margin-left: 8px" @click="handleReset">重置</a-button> -->
|
<!-- <a-button style="margin-left: 8px" @click="handleReset">重置</a-button> -->
|
||||||
<a-tooltip title="导出(暂未实现)">
|
<a-button
|
||||||
<a-button style="margin-left: 8px">导出</a-button>
|
style="margin-left: 8px"
|
||||||
</a-tooltip>
|
@click="handleExport"
|
||||||
|
:loading="exportLoading"
|
||||||
|
>导出</a-button
|
||||||
|
>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
@ -71,6 +74,7 @@ import BasicTable from '@/components/BasicTable/index.vue';
|
|||||||
import { getStllGaojingDetail } from '@/api/zngj';
|
import { getStllGaojingDetail } from '@/api/zngj';
|
||||||
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 dayjs, { Dayjs } from 'dayjs';
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ModeGaoJing'
|
name: 'ModeGaoJing'
|
||||||
});
|
});
|
||||||
@ -262,6 +266,19 @@ const opentan = (record: any) => {
|
|||||||
modelStore.title = record.ennm;
|
modelStore.title = record.ennm;
|
||||||
modelStore.params.stcd = record.rstcd;
|
modelStore.params.stcd = record.rstcd;
|
||||||
};
|
};
|
||||||
|
/* 导出逻辑 */
|
||||||
|
const exportLoading = ref(false);
|
||||||
|
const handleExport = () => {
|
||||||
|
exportLoading.value = true;
|
||||||
|
|
||||||
|
tableRef.value
|
||||||
|
.exportTable({
|
||||||
|
fileName: `生态流量低于限值告警统计_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
exportLoading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
// 初始化加载数据
|
// 初始化加载数据
|
||||||
// handleSearch();
|
// handleSearch();
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -283,7 +300,6 @@ onMounted(() => {
|
|||||||
|
|
||||||
.table-wrapper {
|
.table-wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -32,6 +32,12 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button type="primary" @click="handleSearch">查询</a-button>
|
<a-button type="primary" @click="handleSearch">查询</a-button>
|
||||||
|
<a-button
|
||||||
|
style="margin-left: 8px"
|
||||||
|
@click="handleExport"
|
||||||
|
:loading="exportLoading"
|
||||||
|
>导出</a-button
|
||||||
|
>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
@ -67,7 +73,7 @@ import BasicTable from '@/components/BasicTable/index.vue';
|
|||||||
import { getStllGaojingDetail } from '@/api/zngj';
|
import { getStllGaojingDetail } from '@/api/zngj';
|
||||||
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 dayjs, { Dayjs } from 'dayjs';
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ModeGaoJing'
|
name: 'ModeGaoJing'
|
||||||
});
|
});
|
||||||
@ -266,6 +272,19 @@ const opentan = (record: any) => {
|
|||||||
modelStore.title = record.ennm;
|
modelStore.title = record.ennm;
|
||||||
modelStore.params.stcd = record.rstcd;
|
modelStore.params.stcd = record.rstcd;
|
||||||
};
|
};
|
||||||
|
/* 导出逻辑 */
|
||||||
|
const exportLoading = ref(false);
|
||||||
|
const handleExport = () => {
|
||||||
|
exportLoading.value = true;
|
||||||
|
|
||||||
|
tableRef.value
|
||||||
|
.exportTable({
|
||||||
|
fileName: `生态流量低于限值告警统计_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
exportLoading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
handleSearch();
|
handleSearch();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,15 +1,31 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SidePanelItem title="水质监测数据告警情况" :select="select" @update-values="handlePanelChange">
|
<SidePanelItem
|
||||||
|
title="水质监测数据告警情况"
|
||||||
|
:select="select"
|
||||||
|
@update-values="handlePanelChange"
|
||||||
|
>
|
||||||
<a-spin :spinning="dataLoading" tip="加载中...">
|
<a-spin :spinning="dataLoading" tip="加载中...">
|
||||||
<div class="body_box">
|
<div class="body_box">
|
||||||
<div class="box" v-for="(item, index) in data" :key="index" @click="handleCardClick(item.warnState)" style="cursor: pointer;">
|
<div
|
||||||
|
class="box"
|
||||||
|
v-for="(item, index) in data"
|
||||||
|
:key="index"
|
||||||
|
@click="handleCardClick(item.warnState)"
|
||||||
|
style="cursor: pointer"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<div :class="item.icon" :style="{background:item.background}"></div>
|
<div
|
||||||
|
:class="item.icon"
|
||||||
|
:style="{ background: item.background }"
|
||||||
|
></div>
|
||||||
<div class="title_text">{{ item.name }}</div>
|
<div class="title_text">{{ item.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div><span class="text_num">{{ item.num }}</span><span>座</span></div>
|
<div>
|
||||||
|
<span class="text_num">{{ item.num }}</span
|
||||||
|
><span>座</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
@ -33,15 +49,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from 'vue';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import SidePanelItem from "@/components/SidePanelItem/index.vue";
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { getShuizhiGaojingList } from '@/api/zngj';
|
import { getShuizhiGaojingList } from '@/api/zngj';
|
||||||
import ModeGaoJing from './ModeGaoJing.vue';
|
import ModeGaoJing from './ModeGaoJing.vue';
|
||||||
import { useDraggable } from '@/utils/drag';
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "shuizhijianceshuju",
|
name: 'shuizhijianceshuju'
|
||||||
});
|
});
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
@ -68,10 +84,10 @@ const select = ref({
|
|||||||
options: [
|
options: [
|
||||||
{ label: '全部', value: '' },
|
{ label: '全部', value: '' },
|
||||||
{ label: '国家站', value: '1' },
|
{ label: '国家站', value: '1' },
|
||||||
{ label: '自建站', value: '0' },
|
{ label: '自建站', value: '0' }
|
||||||
],
|
],
|
||||||
width: '140px',
|
width: '140px',
|
||||||
minWidth: '140px',
|
minWidth: '140px'
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = ref([
|
const data = ref([
|
||||||
@ -80,22 +96,22 @@ const data = ref([
|
|||||||
num: '0',
|
num: '0',
|
||||||
warnState: '1',
|
warnState: '1',
|
||||||
icon: 'iconfont icon-map-rgszzDabiao zhuangji',
|
icon: 'iconfont icon-map-rgszzDabiao zhuangji',
|
||||||
background: '#78c300',
|
background: '#78c300'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '告警',
|
name: '告警',
|
||||||
num: '0',
|
num: '0',
|
||||||
warnState: '2',
|
warnState: '2',
|
||||||
icon: 'iconfont icon-map-rgszzDabiao shebeiZhengchang',
|
icon: 'iconfont icon-map-rgszzDabiao shebeiZhengchang',
|
||||||
background: '#e55555',
|
background: '#e55555'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '无数据',
|
name: '无数据',
|
||||||
num: '0',
|
num: '0',
|
||||||
warnState: '0',
|
warnState: '0',
|
||||||
icon: 'iconfont icon-map-rgszzDabiao shebeiLixian',
|
icon: 'iconfont icon-map-rgszzDabiao shebeiLixian',
|
||||||
background: '#8d8d8d',
|
background: '#8d8d8d'
|
||||||
},
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handlePanelChange = (payload: any) => {
|
const handlePanelChange = (payload: any) => {
|
||||||
@ -117,26 +133,28 @@ const getCardData = async () => {
|
|||||||
field: 'sttpCode',
|
field: 'sttpCode',
|
||||||
operator: 'in',
|
operator: 'in',
|
||||||
dataType: 'string',
|
dataType: 'string',
|
||||||
value: ['WQ'],
|
value: ['WQ']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'mway',
|
field: 'mway',
|
||||||
operator: 'eq',
|
operator: 'eq',
|
||||||
dataType: 'number',
|
dataType: 'number',
|
||||||
value: 2,
|
value: 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'usfl',
|
field: 'usfl',
|
||||||
operator: 'eq',
|
operator: 'eq',
|
||||||
dataType: 'string',
|
dataType: 'string',
|
||||||
value: '1',
|
value: '1'
|
||||||
},
|
},
|
||||||
baseid.value !='all'? {
|
baseid.value != 'all'
|
||||||
|
? {
|
||||||
field: 'baseId',
|
field: 'baseId',
|
||||||
operator: 'eq',
|
operator: 'eq',
|
||||||
dataType: 'string',
|
dataType: 'string',
|
||||||
value: baseid.value,
|
value: baseid.value
|
||||||
}: null,
|
}
|
||||||
|
: null
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
if (defaultValue.value === '') {
|
if (defaultValue.value === '') {
|
||||||
@ -144,21 +162,21 @@ const getCardData = async () => {
|
|||||||
field: 'dtinType',
|
field: 'dtinType',
|
||||||
operator: 'in',
|
operator: 'in',
|
||||||
dataType: 'number',
|
dataType: 'number',
|
||||||
value: [0, 1],
|
value: [0, 1]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
filters.push({
|
filters.push({
|
||||||
field: 'dtinType',
|
field: 'dtinType',
|
||||||
operator: 'eq',
|
operator: 'eq',
|
||||||
dataType: 'number',
|
dataType: 'number',
|
||||||
value: Number(defaultValue.value),
|
value: Number(defaultValue.value)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
filter: {
|
filter: {
|
||||||
logic: 'and',
|
logic: 'and',
|
||||||
filters,
|
filters
|
||||||
},
|
},
|
||||||
group: [
|
group: [
|
||||||
{
|
{
|
||||||
@ -167,12 +185,12 @@ const getCardData = async () => {
|
|||||||
aggregates: [
|
aggregates: [
|
||||||
{
|
{
|
||||||
field: 'stcd',
|
field: 'stcd',
|
||||||
aggregate: 'count',
|
aggregate: 'count'
|
||||||
},
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
},
|
select: []
|
||||||
],
|
|
||||||
select: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await getShuizhiGaojingList(params);
|
const res = await getShuizhiGaojingList(params);
|
||||||
@ -181,7 +199,7 @@ const getCardData = async () => {
|
|||||||
const result = {
|
const result = {
|
||||||
normal: 0,
|
normal: 0,
|
||||||
abnormal: 0,
|
abnormal: 0,
|
||||||
noData: 0,
|
noData: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
list.forEach((item: any) => {
|
list.forEach((item: any) => {
|
||||||
@ -195,25 +213,25 @@ const getCardData = async () => {
|
|||||||
data.value = [
|
data.value = [
|
||||||
{
|
{
|
||||||
name: '正常',
|
name: '正常',
|
||||||
num: result.normal.toString(),
|
num: '0',
|
||||||
warnState: '1',
|
warnState: '1',
|
||||||
icon: 'iconfont icon-shuidianzhan1 zhuangji',
|
icon: 'iconfont icon-map-rgszzDabiao zhuangji',
|
||||||
background: '#78c300',
|
background: '#78c300'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '告警',
|
name: '告警',
|
||||||
num: result.abnormal.toString(),
|
num: '0',
|
||||||
warnState: '2',
|
warnState: '2',
|
||||||
icon: 'iconfont icon-shuidianzhanGaojing shebeiZhengchang',
|
icon: 'iconfont icon-map-rgszzDabiao shebeiZhengchang',
|
||||||
background: '#e55555',
|
background: '#e55555'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '无数据',
|
name: '无数据',
|
||||||
num: result.noData.toString(),
|
num: '0',
|
||||||
warnState: '0',
|
warnState: '0',
|
||||||
icon: 'iconfont icon-shuidianzhanWushujv shebeiLixian',
|
icon: 'iconfont icon-map-rgszzDabiao shebeiLixian',
|
||||||
background: '#8d8d8d',
|
background: '#8d8d8d'
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取水质监测告警数据失败:', error);
|
console.error('获取水质监测告警数据失败:', error);
|
||||||
|
|||||||
@ -63,7 +63,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, onUnmounted, nextTick,watch } from 'vue';
|
import { ref, onMounted, onUnmounted, nextTick,watch } from 'vue';
|
||||||
import { ref, watch } from 'vue';
|
// import { ref, watch } from 'vue';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import LsstjkTk from './LsstjkTk.vue';
|
import LsstjkTk from './LsstjkTk.vue';
|
||||||
|
|||||||
@ -55,7 +55,9 @@ const select = ref({
|
|||||||
value: 'all',
|
value: 'all',
|
||||||
options: jiDiList.value,
|
options: jiDiList.value,
|
||||||
picker: undefined,
|
picker: undefined,
|
||||||
format: undefined
|
format: undefined,
|
||||||
|
width: '160px',
|
||||||
|
minWidth:'160px'
|
||||||
});
|
});
|
||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
// 加载状态
|
// 加载状态
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const baseid = ref('');
|
|||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
|
|
||||||
// Loading 状态和数据状态
|
// Loading 状态和数据状态
|
||||||
const loading = ref(false);
|
const loading = ref(true);
|
||||||
const hasData = ref(true); // 初始化为 true,因为 initChart 时会渲染
|
const hasData = ref(true); // 初始化为 true,因为 initChart 时会渲染
|
||||||
const select = ref({
|
const select = ref({
|
||||||
show: true,
|
show: true,
|
||||||
@ -844,4 +844,7 @@ watch(
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
:deep(.ant-spin-nested-loading >div>.ant-spin){
|
||||||
|
background: rgba(255, 255, 255) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -41,7 +41,7 @@ let chartInstance: echarts.ECharts | null = null;
|
|||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
|
|
||||||
// Loading 状态和数据状态
|
// Loading 状态和数据状态
|
||||||
const loading = ref(false);
|
const loading = ref(true);
|
||||||
const hasData = ref(true); // 初始化为 true,因为 initChart 时会渲染
|
const hasData = ref(true); // 初始化为 true,因为 initChart 时会渲染
|
||||||
|
|
||||||
// 选择器配置
|
// 选择器配置
|
||||||
@ -732,4 +732,7 @@ onUnmounted(() => {
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
:deep(.ant-spin-nested-loading >div>.ant-spin){
|
||||||
|
background: rgba(255, 255, 255) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -587,12 +587,12 @@ const fetchTableData = async () => {
|
|||||||
{
|
{
|
||||||
field: 'stnm',
|
field: 'stnm',
|
||||||
operator: 'contains',
|
operator: 'contains',
|
||||||
value: '12'
|
value: params.value.stnm
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'ennm',
|
field: 'ennm',
|
||||||
operator: 'contains',
|
operator: 'contains',
|
||||||
value: '12'
|
value: params.value.stnm
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -501,7 +501,7 @@ const updateChart = () => {
|
|||||||
center: ['35%', '50%'],
|
center: ['35%', '50%'],
|
||||||
avoidLabelOverlap: false,
|
avoidLabelOverlap: false,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: 10,
|
borderRadius: 5,
|
||||||
borderColor: '#fff',
|
borderColor: '#fff',
|
||||||
borderWidth: 2
|
borderWidth: 2
|
||||||
},
|
},
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import {
|
|||||||
getMsstbprptKendoList
|
getMsstbprptKendoList
|
||||||
} from '@/api/home';
|
} from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
dataDimensionVal?: string;
|
dataDimensionVal?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -337,17 +337,27 @@ const customTransform = (res: any) => ({
|
|||||||
total: res?.data?.total || 0
|
total: res?.data?.total || 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const exportLoading = ref(false);
|
||||||
function handleExport() {
|
function handleExport() {
|
||||||
|
if (exportLoading.value) return;
|
||||||
|
|
||||||
|
exportLoading.value = true;
|
||||||
|
|
||||||
const currentTab = tabKey.value;
|
const currentTab = tabKey.value;
|
||||||
if (
|
if (
|
||||||
tableRefs.value[currentTab] &&
|
tableRefs.value[currentTab] &&
|
||||||
typeof tableRefs.value[currentTab].exportTable === 'function'
|
typeof tableRefs.value[currentTab].exportTable === 'function'
|
||||||
) {
|
) {
|
||||||
tableRefs.value[currentTab].exportTable({
|
tableRefs.value[currentTab]
|
||||||
fileName: '环境监测数据接入情况'
|
.exportTable({
|
||||||
|
fileName: `水电开发情况_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
exportLoading.value = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
message.info('导出功能待实现');
|
message.info('当前Tab暂无导出数据');
|
||||||
|
exportLoading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,6 +650,7 @@ const searchList = computed(() => [
|
|||||||
type: 'Input',
|
type: 'Input',
|
||||||
name: 'stnm',
|
name: 'stnm',
|
||||||
label: '',
|
label: '',
|
||||||
|
placeholder:'请输入电站名称',
|
||||||
fieldProps: {
|
fieldProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
placeholder: '请输入电站名称'
|
placeholder: '请输入电站名称'
|
||||||
@ -866,7 +877,7 @@ onUnmounted(() => {
|
|||||||
@reset="handleReset"
|
@reset="handleReset"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<a-button @click="handleExport">
|
<a-button @click="handleExport" :loading ="exportLoading" >
|
||||||
<template #icon><DownloadOutlined /></template>
|
<template #icon><DownloadOutlined /></template>
|
||||||
导出
|
导出
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
getBaseWbsb
|
getBaseWbsb
|
||||||
} from '@/api/home';
|
} from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
defaultJidiInfo?: Record<string, string | number | boolean>;
|
defaultJidiInfo?: Record<string, string | number | boolean>;
|
||||||
seriesName?: string;
|
seriesName?: string;
|
||||||
@ -300,12 +300,27 @@ const customTransform = (res: any) => ({
|
|||||||
records: res?.data?.data || res?.data?.items || [],
|
records: res?.data?.data || res?.data?.items || [],
|
||||||
total: res?.data?.total || 0
|
total: res?.data?.total || 0
|
||||||
});
|
});
|
||||||
|
const exportLoading = ref(false);
|
||||||
function handleExport() {
|
function handleExport() {
|
||||||
if (tableRef.value && typeof tableRef.value.export === 'function') {
|
if (exportLoading.value) return;
|
||||||
tableRef.value.export();
|
|
||||||
|
exportLoading.value = true;
|
||||||
|
|
||||||
|
const currentTab = tabKey.value;
|
||||||
|
if (
|
||||||
|
tableRefs.value[currentTab] &&
|
||||||
|
typeof tableRefs.value[currentTab].exportTable === 'function'
|
||||||
|
) {
|
||||||
|
tableRefs.value[currentTab]
|
||||||
|
.exportTable({
|
||||||
|
fileName: `水电开发情况_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
exportLoading.value = false;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
message.info('导出功能待实现');
|
message.info('当前Tab暂无导出数据');
|
||||||
|
exportLoading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,6 +590,7 @@ const searchList = computed(() => [
|
|||||||
type: 'Input',
|
type: 'Input',
|
||||||
name: 'stnm',
|
name: 'stnm',
|
||||||
label: '',
|
label: '',
|
||||||
|
placeholder: '请输入电站名称',
|
||||||
fieldProps: {
|
fieldProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
placeholder: '请输入电站名称'
|
placeholder: '请输入电站名称'
|
||||||
@ -946,7 +962,7 @@ onUnmounted(() => {
|
|||||||
@reset="handleReset"
|
@reset="handleReset"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<a-button @click="handleExport">
|
<a-button @click="handleExport" :loading ="exportLoading" >
|
||||||
<template #icon><DownloadOutlined /></template>
|
<template #icon><DownloadOutlined /></template>
|
||||||
导出
|
导出
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|||||||
@ -404,7 +404,7 @@ const getselectTwo = async (code: any) => {
|
|||||||
"filters": [
|
"filters": [
|
||||||
code != 'all' ? {
|
code != 'all' ? {
|
||||||
"field": "baseId",
|
"field": "baseId",
|
||||||
"operator": "contains",
|
"operator": "eq",
|
||||||
"dataType": "string",
|
"dataType": "string",
|
||||||
"value": code
|
"value": code
|
||||||
} : null,
|
} : null,
|
||||||
|
|||||||
@ -56,11 +56,28 @@ const paramsOne = {
|
|||||||
tm: []
|
tm: []
|
||||||
};
|
};
|
||||||
const dataOne = ref('');
|
const dataOne = ref('');
|
||||||
// 使用 computed 使 prompts 响应 dataOne.value 的变化
|
// 保存原始表格数据,用于提取 minTm
|
||||||
const prompts = computed(() => ({
|
const rawTableData = ref<any[]>([]);
|
||||||
|
// 使用 computed 使 prompts 基于原始数据的 minTm 字段
|
||||||
|
const prompts = computed(() => {
|
||||||
|
// 如果没有数据或数据为空,不显示提示
|
||||||
|
if (!rawTableData.value || rawTableData.value.length === 0) {
|
||||||
|
return { show: true, value: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取第一条数据的 minTm 字段
|
||||||
|
const minTm = rawTableData.value[0]?.minTm;
|
||||||
|
|
||||||
|
// 如果 minTm 为空,也不显示提示
|
||||||
|
if (!minTm) {
|
||||||
|
return { show: true, value: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
value: `注:最新数据时间为${dataOne.value || getCurrentHourTime()}`
|
value: `注:最新数据时间为${minTm}`
|
||||||
}));
|
};
|
||||||
|
});
|
||||||
const showemit = ref(false);
|
const showemit = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
// const selectOptions: any = ref([])
|
// const selectOptions: any = ref([])
|
||||||
@ -308,6 +325,9 @@ const init = async () => {
|
|||||||
let res = await getKendoListCust(params);
|
let res = await getKendoListCust(params);
|
||||||
let data = res.data.data || res.data;
|
let data = res.data.data || res.data;
|
||||||
|
|
||||||
|
// 保存原始数据,用于提取 minTm
|
||||||
|
rawTableData.value = data;
|
||||||
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
showemit.value = true;
|
showemit.value = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export const useJidiSelectEventStore = defineStore('jidiSelectEvent', () => {
|
|||||||
};
|
};
|
||||||
const getJidiData = async () => {
|
const getJidiData = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
let params = {
|
const params = {
|
||||||
filter: {
|
filter: {
|
||||||
logic: 'and',
|
logic: 'and',
|
||||||
filters: [
|
filters: [
|
||||||
@ -50,7 +50,7 @@ export const useJidiSelectEventStore = defineStore('jidiSelectEvent', () => {
|
|||||||
select: ['wbsCode', 'wbsName']
|
select: ['wbsCode', 'wbsName']
|
||||||
};
|
};
|
||||||
const res = await wbsbGetKendoList(params);
|
const res = await wbsbGetKendoList(params);
|
||||||
let data = res?.data?.data || [
|
const data = res?.data?.data || [
|
||||||
{
|
{
|
||||||
wbsCode: 'all',
|
wbsCode: 'all',
|
||||||
wbsName: '当前全部',
|
wbsName: '当前全部',
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export const useShuJuTianBaoStore = defineStore('shuJuTianBao', () => {
|
|||||||
if (type == 'baseId') {
|
if (type == 'baseId') {
|
||||||
param = rvcd === 'all' ? {} : { baseId: rvcd };
|
param = rvcd === 'all' ? {} : { baseId: rvcd };
|
||||||
} else {
|
} else {
|
||||||
param = rvcd === 'all' ? {} : { reachcd: rvcd };
|
param = rvcd === 'all' ? {} : { rvcd: rvcd };
|
||||||
}
|
}
|
||||||
const res = await getEngInfoDropdown(param);
|
const res = await getEngInfoDropdown(param);
|
||||||
if (res.data && Array.isArray(res.data)) {
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
|||||||
@ -2451,10 +2451,10 @@ const themecc_list = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
const getThemee = (fieldName?: string) => {
|
const getThemee = (fieldName?: string) => {
|
||||||
let themeecList = themecc_list;
|
const themeecList = themecc_list;
|
||||||
let getitem: any = {};
|
let getitem: any = {};
|
||||||
if (fieldName && themeecList.length > 0) {
|
if (fieldName && themeecList.length > 0) {
|
||||||
let getitemList = themeecList.filter(
|
const getitemList = themeecList.filter(
|
||||||
(i: any) => i.fieldName.toUpperCase() == fieldName.toUpperCase()
|
(i: any) => i.fieldName.toUpperCase() == fieldName.toUpperCase()
|
||||||
);
|
);
|
||||||
if (getitemList.length > 0) {
|
if (getitemList.length > 0) {
|
||||||
|
|||||||
@ -246,6 +246,23 @@ const buildSearchParams = (values: any) => {
|
|||||||
return {
|
return {
|
||||||
logic: 'and',
|
logic: 'and',
|
||||||
filters: [
|
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.basin
|
values.basin
|
||||||
? {
|
? {
|
||||||
field: 'basin',
|
field: 'basin',
|
||||||
|
|||||||
@ -510,6 +510,23 @@ const buildSearchParams = (values: any) => {
|
|||||||
return {
|
return {
|
||||||
logic: 'and',
|
logic: 'and',
|
||||||
filters: [
|
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.ptype && values.ptype !== 'all'
|
values.ptype && values.ptype !== 'all'
|
||||||
? {
|
? {
|
||||||
field: 'ptype',
|
field: 'ptype',
|
||||||
|
|||||||
@ -22,7 +22,7 @@ let initialLeft = 0;
|
|||||||
let initialTop = 0;
|
let initialTop = 0;
|
||||||
|
|
||||||
const onMouseDown = (e: MouseEvent) => {
|
const onMouseDown = (e: MouseEvent) => {
|
||||||
;
|
|
||||||
isDragging = true;
|
isDragging = true;
|
||||||
startX = e.clientX;
|
startX = e.clientX;
|
||||||
startY = e.clientY;
|
startY = e.clientY;
|
||||||
|
|||||||
@ -238,6 +238,9 @@ const statusFilter = ref<"online" | "offline">("online");
|
|||||||
// 视频列表
|
// 视频列表
|
||||||
const videoList = ref<any[]>(Array(9).fill(null));
|
const videoList = ref<any[]>(Array(9).fill(null));
|
||||||
|
|
||||||
|
// 等待队列(存放超出布局限制的视频)
|
||||||
|
const pendingVideoQueue = ref<any[]>([]);
|
||||||
|
|
||||||
// 移除视频
|
// 移除视频
|
||||||
const removeVideo = (index: number, nodeKey?: string) => {
|
const removeVideo = (index: number, nodeKey?: string) => {
|
||||||
const videoData = videoList.value[index];
|
const videoData = videoList.value[index];
|
||||||
@ -255,6 +258,19 @@ const removeVideo = (index: number, nodeKey?: string) => {
|
|||||||
}
|
}
|
||||||
// 移除视频
|
// 移除视频
|
||||||
videoList.value[index] = null;
|
videoList.value[index] = null;
|
||||||
|
|
||||||
|
// 尝试从队列补位
|
||||||
|
fillEmptySlot(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 填充空位(从队列中取第一个视频)
|
||||||
|
const fillEmptySlot = (emptyIndex: number) => {
|
||||||
|
if (pendingVideoQueue.value.length > 0) {
|
||||||
|
const nextVideo = pendingVideoQueue.value.shift();
|
||||||
|
if (nextVideo) {
|
||||||
|
videoList.value[emptyIndex] = nextVideo;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加视频到列表
|
// 添加视频到列表
|
||||||
@ -269,18 +285,49 @@ const addVideo = (videoData: any) => {
|
|||||||
} else if (videoList.value.filter((v, i) => i < maxCount).length < maxCount) {
|
} else if (videoList.value.filter((v, i) => i < maxCount).length < maxCount) {
|
||||||
videoList.value.push(videoData);
|
videoList.value.push(videoData);
|
||||||
} else {
|
} else {
|
||||||
// 如果满了,替换第一个
|
// 如果满了,加入等待队列
|
||||||
videoList.value[0] = videoData;
|
if (!pendingVideoQueue.value.find((v) => v.key === videoData.key)) {
|
||||||
|
pendingVideoQueue.value.push(videoData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听布局变化,调整视频列表长度
|
// 监听布局变化,调整视频列表长度
|
||||||
watch(viewLayout, (newLayout) => {
|
watch(viewLayout, (newLayout, oldLayout) => {
|
||||||
const maxCount = parseInt(newLayout);
|
const newMaxCount = parseInt(newLayout);
|
||||||
|
const oldMaxCount = oldLayout ? parseInt(oldLayout) : newMaxCount;
|
||||||
|
|
||||||
|
// 布局减小时,超出部分移入队列
|
||||||
|
if (newMaxCount < oldMaxCount) {
|
||||||
|
for (let i = newMaxCount; i < oldMaxCount && i < videoList.value.length; i++) {
|
||||||
|
const video = videoList.value[i];
|
||||||
|
if (video && !pendingVideoQueue.value.find((v) => v.key === video.key)) {
|
||||||
|
pendingVideoQueue.value.push(video);
|
||||||
|
}
|
||||||
|
videoList.value[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 确保数组长度足够
|
// 确保数组长度足够
|
||||||
while (videoList.value.length < maxCount) {
|
while (videoList.value.length < newMaxCount) {
|
||||||
videoList.value.push(null);
|
videoList.value.push(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 布局增大时,从队列填充新空位
|
||||||
|
if (newMaxCount > oldMaxCount) {
|
||||||
|
const availableSlots = newMaxCount - oldMaxCount;
|
||||||
|
for (let i = 0; i < availableSlots && pendingVideoQueue.value.length > 0; i++) {
|
||||||
|
const emptyIndex = videoList.value.findIndex(
|
||||||
|
(v, i) => i < newMaxCount && (v === null || v === undefined)
|
||||||
|
);
|
||||||
|
if (emptyIndex !== -1) {
|
||||||
|
const nextVideo = pendingVideoQueue.value.shift();
|
||||||
|
if (nextVideo) {
|
||||||
|
videoList.value[emptyIndex] = nextVideo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 树形数据
|
// 树形数据
|
||||||
@ -408,8 +455,8 @@ const handlePlayRecord = (record: any) => {
|
|||||||
if (videoPath) {
|
if (videoPath) {
|
||||||
const maxCount = parseInt(viewLayout.value);
|
const maxCount = parseInt(viewLayout.value);
|
||||||
|
|
||||||
// 检查是否已经添加过该录像
|
// 检查是否已经添加过该录像(通过视频路径判断)
|
||||||
const existingIndex = videoList.value.findIndex((v) => v && v.flnm === record.flnm);
|
const existingIndex = videoList.value.findIndex((v) => v && v.url === videoPath);
|
||||||
|
|
||||||
if (existingIndex !== -1) {
|
if (existingIndex !== -1) {
|
||||||
return;
|
return;
|
||||||
@ -560,10 +607,11 @@ const initTree = async () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// 清空视频列表和勾选状态
|
// 清空视频列表、勾选状态和等待队列
|
||||||
videoList.value = Array(9).fill(null);
|
videoList.value = Array(9).fill(null);
|
||||||
checkedKeys.value = [];
|
checkedKeys.value = [];
|
||||||
expandedKeys.value = [];
|
expandedKeys.value = [];
|
||||||
|
pendingVideoQueue.value = [];
|
||||||
|
|
||||||
treeLoading.value = true;
|
treeLoading.value = true;
|
||||||
try {
|
try {
|
||||||
@ -679,6 +727,7 @@ const handleMonitorTypeChange = () => {
|
|||||||
// 清空中间视频
|
// 清空中间视频
|
||||||
videoList.value = Array(9).fill(null);
|
videoList.value = Array(9).fill(null);
|
||||||
checkedKeys.value = [];
|
checkedKeys.value = [];
|
||||||
|
pendingVideoQueue.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换到实时视频时,恢复在线默认状态
|
// 切换到实时视频时,恢复在线默认状态
|
||||||
@ -729,11 +778,15 @@ const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
|
|||||||
// 自动添加所有父节点到 checkedKeys
|
// 自动添加所有父节点到 checkedKeys
|
||||||
addParentKeys(nodeData.key);
|
addParentKeys(nodeData.key);
|
||||||
} else {
|
} else {
|
||||||
// 超出限制,使用 setTimeout 延迟取消勾选,避免与 Tree 组件的自动勾选冲突
|
// 超出限制,加入等待队列(保持勾选状态)
|
||||||
setTimeout(() => {
|
if (!pendingVideoQueue.value.find((v) => v.key === nodeData.key)) {
|
||||||
// 使用 filter 创建新数组以触发响应式更新
|
pendingVideoQueue.value.push({
|
||||||
checkedKeys.value = checkedKeys.value.filter((key) => key !== nodeData.key);
|
flnm: nodeData.name,
|
||||||
}, 50);
|
stnm: nodeData.stnm,
|
||||||
|
url: videoUrl,
|
||||||
|
...nodeData,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
@ -744,6 +797,17 @@ const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
|
|||||||
} else {
|
} else {
|
||||||
// 取消勾选:移除视频
|
// 取消勾选:移除视频
|
||||||
if (!nodeData.children || nodeData.children.length === 0) {
|
if (!nodeData.children || nodeData.children.length === 0) {
|
||||||
|
// 先检查是否在队列中
|
||||||
|
const queueIndex = pendingVideoQueue.value.findIndex(
|
||||||
|
(v) => v.key === nodeData.key
|
||||||
|
);
|
||||||
|
if (queueIndex !== -1) {
|
||||||
|
// 从队列中移除
|
||||||
|
pendingVideoQueue.value.splice(queueIndex, 1);
|
||||||
|
removeUnnecessaryParentKeys(nodeData.key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 叶子节点:直接移除
|
// 叶子节点:直接移除
|
||||||
removeVideoByNodeKey(nodeData.key);
|
removeVideoByNodeKey(nodeData.key);
|
||||||
|
|
||||||
@ -912,16 +976,23 @@ const addVideosFromNodeWithLimit = (node: any) => {
|
|||||||
const remainingSlots = maxCount - currentCount;
|
const remainingSlots = maxCount - currentCount;
|
||||||
|
|
||||||
if (remainingSlots <= 0) {
|
if (remainingSlots <= 0) {
|
||||||
// 没有剩余位置,延迟取消所有相关节点的勾选
|
// 没有剩余位置,全部加入队列
|
||||||
setTimeout(() => {
|
allLeafNodes.forEach((leafNode: any) => {
|
||||||
cancelNodeCheck(node);
|
if (!pendingVideoQueue.value.find((v) => v.key === leafNode.key)) {
|
||||||
}, 100);
|
pendingVideoQueue.value.push({
|
||||||
|
flnm: leafNode.name,
|
||||||
|
stnm: leafNode.stnm,
|
||||||
|
url: leafNode.url || leafNode.videoUrl || leafNode.playUrl,
|
||||||
|
...leafNode,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只添加前 remainingSlots 个叶子节点
|
// 只添加前 remainingSlots 个叶子节点
|
||||||
const nodesToAdd = allLeafNodes.slice(0, remainingSlots);
|
const nodesToAdd = allLeafNodes.slice(0, remainingSlots);
|
||||||
const nodesToCancel = allLeafNodes.slice(remainingSlots);
|
const nodesToQueue = allLeafNodes.slice(remainingSlots);
|
||||||
|
|
||||||
// 添加允许的视频并勾选对应节点
|
// 添加允许的视频并勾选对应节点
|
||||||
nodesToAdd.forEach((leafNode: any) => {
|
nodesToAdd.forEach((leafNode: any) => {
|
||||||
@ -938,37 +1009,26 @@ const addVideosFromNodeWithLimit = (node: any) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 先取消超出限制的节点的勾选
|
// 超出限制的节点加入队列(保持勾选状态)
|
||||||
if (nodesToCancel.length > 0) {
|
if (nodesToQueue.length > 0) {
|
||||||
setTimeout(() => {
|
nodesToQueue.forEach((leafNode: any) => {
|
||||||
cancelNodesCheck(nodesToCancel);
|
if (!pendingVideoQueue.value.find((v) => v.key === leafNode.key)) {
|
||||||
|
pendingVideoQueue.value.push({
|
||||||
// 取消后再为所有添加的子节点添加父节点
|
flnm: leafNode.name,
|
||||||
nodesToAdd.forEach((leafNode: any) => {
|
stnm: leafNode.stnm,
|
||||||
addParentKeys(leafNode.key);
|
url: leafNode.url || leafNode.videoUrl || leafNode.playUrl,
|
||||||
|
...leafNode,
|
||||||
});
|
});
|
||||||
}, 50);
|
|
||||||
} else {
|
|
||||||
// 没有超出限制,直接添加父节点
|
|
||||||
setTimeout(() => {
|
|
||||||
nodesToAdd.forEach((leafNode: any) => {
|
|
||||||
addParentKeys(leafNode.key);
|
|
||||||
});
|
|
||||||
}, 50);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// 取消单个节点的勾选
|
|
||||||
const cancelNodeCheck = (node: any) => {
|
|
||||||
// 使用 filter 创建新数组以触发响应式更新
|
|
||||||
checkedKeys.value = checkedKeys.value.filter((key) => key !== node.key);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 取消多个节点的勾选
|
|
||||||
const cancelNodesCheck = (nodes: any[]) => {
|
|
||||||
nodes.forEach((node: any) => {
|
|
||||||
cancelNodeCheck(node);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加父节点
|
||||||
|
setTimeout(() => {
|
||||||
|
nodesToAdd.forEach((leafNode: any) => {
|
||||||
|
addParentKeys(leafNode.key);
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 递归移除节点及其所有子节点的视频
|
// 递归移除节点及其所有子节点的视频
|
||||||
@ -986,9 +1046,20 @@ const removeVideosFromNode = (node: any) => {
|
|||||||
|
|
||||||
// 根据节点key移除视频
|
// 根据节点key移除视频
|
||||||
const removeVideoByNodeKey = (nodeKey: string) => {
|
const removeVideoByNodeKey = (nodeKey: string) => {
|
||||||
|
// 先检查是否在队列中
|
||||||
|
const queueIndex = pendingVideoQueue.value.findIndex(
|
||||||
|
(v) => v.key === nodeKey
|
||||||
|
);
|
||||||
|
if (queueIndex !== -1) {
|
||||||
|
pendingVideoQueue.value.splice(queueIndex, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const index = videoList.value.findIndex((video) => video && video.key === nodeKey);
|
const index = videoList.value.findIndex((video) => video && video.key === nodeKey);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
videoList.value[index] = null;
|
videoList.value[index] = null;
|
||||||
|
// 尝试从队列补位
|
||||||
|
fillEmptySlot(index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -354,8 +354,8 @@ export const handleCellEdit = (params: any, fWorksheet: any, year: string) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 重建该组的所有单元格引用
|
// 重建该组的所有单元格引用
|
||||||
let groupCells = [];
|
const groupCells = [];
|
||||||
let currentDayCount = groupStartDayOfYear;
|
const currentDayCount = groupStartDayOfYear;
|
||||||
let currentMonth = 1;
|
let currentMonth = 1;
|
||||||
let cumulativeDays = 0;
|
let cumulativeDays = 0;
|
||||||
|
|
||||||
@ -389,7 +389,7 @@ export const handleCellEdit = (params: any, fWorksheet: any, year: string) => {
|
|||||||
console.log('组中单元格:', groupCells);
|
console.log('组中单元格:', groupCells);
|
||||||
|
|
||||||
// 构建公式
|
// 构建公式
|
||||||
let formula = `=ROUND(AVERAGE(${groupCells.join(',')}), 1)`;
|
const formula = `=ROUND(AVERAGE(${groupCells.join(',')}), 1)`;
|
||||||
|
|
||||||
// 找到该组的结束位置用于显示公式
|
// 找到该组的结束位置用于显示公式
|
||||||
let endMonth = 1;
|
let endMonth = 1;
|
||||||
@ -446,7 +446,7 @@ export const getParams = (searchData: any, Psort?: any, Rstcd?: boolean) => {
|
|||||||
return result.slice(1, -1);
|
return result.slice(1, -1);
|
||||||
};
|
};
|
||||||
// if (searchData) {
|
// if (searchData) {
|
||||||
let params: any = [];
|
const params: any = [];
|
||||||
// if (sttpCode) {
|
// if (sttpCode) {
|
||||||
// params.push(
|
// params.push(
|
||||||
// {
|
// {
|
||||||
@ -783,7 +783,7 @@ export const getParams = (searchData: any, Psort?: any, Rstcd?: boolean) => {
|
|||||||
].filter((el: any) => el != null);
|
].filter((el: any) => el != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
let filter = {
|
const filter = {
|
||||||
logic: 'and',
|
logic: 'and',
|
||||||
filters: params
|
filters: params
|
||||||
};
|
};
|
||||||
@ -917,7 +917,7 @@ export const calculateCrossMonthAverages = async (
|
|||||||
let groupValues: string[] = []; // 存储单元格引用
|
let groupValues: string[] = []; // 存储单元格引用
|
||||||
let groupPositions: { month: number; day: number }[] = []; // 记录每个值的位置
|
let groupPositions: { month: number; day: number }[] = []; // 记录每个值的位置
|
||||||
let validDataCount = 0; // 记录当前组中有效数据的数量
|
let validDataCount = 0; // 记录当前组中有效数据的数量
|
||||||
let protectedRanges: any[] = [];
|
const protectedRanges: any[] = [];
|
||||||
for (let month = 1; month <= 12; month++) {
|
for (let month = 1; month <= 12; month++) {
|
||||||
const dataRow = month * 2 + 1; // 当前月份的数据行
|
const dataRow = month * 2 + 1; // 当前月份的数据行
|
||||||
const daysInMonth = getDaysInMonth(year, month); // 根据年份获取该月天数
|
const daysInMonth = getDaysInMonth(year, month); // 根据年份获取该月天数
|
||||||
@ -958,7 +958,7 @@ export const calculateCrossMonthAverages = async (
|
|||||||
if (validDataCount > 0) {
|
if (validDataCount > 0) {
|
||||||
// 构建平均值公式
|
// 构建平均值公式
|
||||||
const range = groupValues.join(',');
|
const range = groupValues.join(',');
|
||||||
let formula = `=ROUND(AVERAGE(${range}), 1)`;
|
const formula = `=ROUND(AVERAGE(${range}), 1)`;
|
||||||
|
|
||||||
// 在组的最后一天显示平均值
|
// 在组的最后一天显示平均值
|
||||||
const lastPosition = groupPositions[groupValues.length - 1];
|
const lastPosition = groupPositions[groupValues.length - 1];
|
||||||
@ -989,7 +989,7 @@ export const calculateCrossMonthAverages = async (
|
|||||||
if (groupValues.length > 0 && groupValues.length < 5 && validDataCount > 0) {
|
if (groupValues.length > 0 && groupValues.length < 5 && validDataCount > 0) {
|
||||||
// 构建平均值公式
|
// 构建平均值公式
|
||||||
const range = groupValues.join(',');
|
const range = groupValues.join(',');
|
||||||
let formula = `=ROUND(AVERAGE(${range}), 1)`;
|
const formula = `=ROUND(AVERAGE(${range}), 1)`;
|
||||||
|
|
||||||
// 在组的最后一天显示平均值
|
// 在组的最后一天显示平均值
|
||||||
const lastPosition = groupPositions[groupValues.length - 1];
|
const lastPosition = groupPositions[groupValues.length - 1];
|
||||||
|
|||||||
@ -0,0 +1,828 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑沿程配置' : '新增沿程配置'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="localLoading"
|
||||||
|
width="1200px"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
ok-text="保存"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
name="edit_form"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="沿程配置名称" name="name">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.name"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入沿程配置名称"
|
||||||
|
/> </a-form-item
|
||||||
|
></a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="沿程配置编码" name="code">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.code"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入沿程配置编码"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="所在河段" name="rvcd">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formData.rvcd"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择所在河段"
|
||||||
|
:options="riverOptions"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleRiverSelect"
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="备注" name="remark">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
v-model:value="formData.remark"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
<div class="config-tree-container">
|
||||||
|
<!-- 新增一级节点区域 -->
|
||||||
|
<div v-if="addingNewNode" class="add-node-row">
|
||||||
|
<a-select
|
||||||
|
v-model:value="newNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ item.stnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSaveNewNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleCancelAdd" style="margin-left: 8px">
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<a-button v-else class="mb-4" type="primary" @click="handleAdd">
|
||||||
|
<PlusOutlined /> 新增一级节点
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<!-- 树形结构 -->
|
||||||
|
<a-tree
|
||||||
|
v-if="treeData.length > 0"
|
||||||
|
:tree-data="treeData"
|
||||||
|
:default-expand-all="false"
|
||||||
|
:selectable="false"
|
||||||
|
block-node
|
||||||
|
style="width: 400px"
|
||||||
|
>
|
||||||
|
<template #title="{ dataRef }">
|
||||||
|
<!-- 编辑状态:只显示编辑区域 -->
|
||||||
|
<div
|
||||||
|
v-if="editingNode && editingNodeKey === dataRef.key"
|
||||||
|
class="add-child-node-row w-[300px]"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="editNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="() => handleEditNodeSelect(dataRef)"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in dataRef.parentId
|
||||||
|
? childStationList
|
||||||
|
: stationList"
|
||||||
|
:key="item.stcd"
|
||||||
|
:value="item.stcd"
|
||||||
|
>
|
||||||
|
{{ dataRef.parentId ? item.stnm : item.ennm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click.stop="handleSaveEditNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
@click.stop="handleCancelEditNode"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
>
|
||||||
|
<MinusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<!-- 非编辑状态:显示正常节点内容 -->
|
||||||
|
<template v-else>
|
||||||
|
<div class="tree-node-wrapper">
|
||||||
|
<span class="tree-node-title"> {{ getNodeTitle(dataRef) }} </span>
|
||||||
|
<div class="tree-node-actions">
|
||||||
|
<!-- 一级节点:支持新增子节点、编辑、排序、删除 -->
|
||||||
|
<template v-if="!dataRef.parentId">
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleAddChild(dataRef)"
|
||||||
|
:title="
|
||||||
|
dataRef.sttpName
|
||||||
|
? `子级添加-${dataRef.sttpName}`
|
||||||
|
: '子级添加'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<PlusOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleEditNode(dataRef)"
|
||||||
|
title="编辑"
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveUp(dataRef)"
|
||||||
|
title="上移"
|
||||||
|
:disabled="isFirstNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowUpOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveDown(dataRef)"
|
||||||
|
title="下移"
|
||||||
|
:disabled="isLastNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowDownOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="handleDeleteNode(dataRef)"
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<!-- 二级节点:只支持编辑、排序、删除 -->
|
||||||
|
<template v-else>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleEditNode(dataRef)"
|
||||||
|
title="编辑"
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveUp(dataRef)"
|
||||||
|
title="上移"
|
||||||
|
:disabled="isFirstNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowUpOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click.stop="handleMoveDown(dataRef)"
|
||||||
|
title="下移"
|
||||||
|
:disabled="isLastNode(dataRef)"
|
||||||
|
>
|
||||||
|
<ArrowDownOutlined />
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="handleDeleteNode(dataRef)"
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 子节点添加区域 -->
|
||||||
|
<div
|
||||||
|
v-if="addingChildNode && currentParentKey === dataRef.key"
|
||||||
|
class="add-child-node-row"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="childNodeData.stcd"
|
||||||
|
show-search
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 300px"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleChildNodeSelect"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in 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>
|
||||||
|
</a-tree>
|
||||||
|
<a-empty v-else description="暂无数据" style="margin-top: 20px" />
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
PlusOutlined,
|
||||||
|
MinusOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
ArrowUpOutlined,
|
||||||
|
ArrowDownOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import { getEngInfoDropdown, getAddvcdDropdownByRvcd } from '@/api/select';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
riverOptions?: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false,
|
||||||
|
riverOptions: () => []
|
||||||
|
});
|
||||||
|
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
code: undefined,
|
||||||
|
rvcd: undefined,
|
||||||
|
remark: undefined
|
||||||
|
});
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
name: [{ required: true, message: '请输入沿程配置名称', trigger: 'blur' }],
|
||||||
|
code: [{ required: true, message: '请输入配置编码', trigger: 'blur' }],
|
||||||
|
rvcd: [{ required: true, message: '请选择所在河段', trigger: 'change' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRiverSelect = async (value: string) => {
|
||||||
|
const res = await getEngInfoDropdown({ rvcd: value });
|
||||||
|
stationList.value = (res.data || []).map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
stnm: item.ennm
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
|
||||||
|
// 树形数据
|
||||||
|
const treeData = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 新增节点相关
|
||||||
|
const addingNewNode = ref(false);
|
||||||
|
const newNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
ennm: '',
|
||||||
|
sttpName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加子节点相关
|
||||||
|
const addingChildNode = ref(false);
|
||||||
|
const currentParentKey = ref<string | null>(null);
|
||||||
|
const childNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
ennm: '',
|
||||||
|
sttpName: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 编辑节点相关
|
||||||
|
const editingNode = ref(false);
|
||||||
|
const editingNodeKey = ref<string | null>(null);
|
||||||
|
const editNodeData = ref({
|
||||||
|
stcd: undefined,
|
||||||
|
ennm: '',
|
||||||
|
sttpName: '',
|
||||||
|
originalData: null as any
|
||||||
|
});
|
||||||
|
|
||||||
|
const stationList = ref([]);
|
||||||
|
const childStationList = ref([]);
|
||||||
|
|
||||||
|
// 生成唯一ID
|
||||||
|
let nodeIdCounter = 0;
|
||||||
|
const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`;
|
||||||
|
|
||||||
|
// 获取节点标题
|
||||||
|
const getNodeTitle = (dataRef: any) => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
return dataRef.ennm || '';
|
||||||
|
} else {
|
||||||
|
return `${dataRef.ennm || ''} ${dataRef.sttpName || ''}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索过滤
|
||||||
|
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 isFirstNode = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
return siblings.length > 0 && siblings[0].key === dataRef.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断是否为最后一个节点
|
||||||
|
const isLastNode = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
return (
|
||||||
|
siblings.length > 0 && siblings[siblings.length - 1].key === dataRef.key
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取兄弟节点
|
||||||
|
const getSiblings = (dataRef: any) => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 一级节点
|
||||||
|
return treeData.value;
|
||||||
|
} else {
|
||||||
|
// 二级节点,找到父节点的 children
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
return parent?.children || [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据 key 查找节点
|
||||||
|
const findNodeByKey = (nodes: any[], key: string): any => {
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (node.key === key) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (node.children && node.children.length > 0) {
|
||||||
|
const found = findNodeByKey(node.children, key);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增一级节点
|
||||||
|
const handleAdd = () => {
|
||||||
|
if (!formData.rvcd) {
|
||||||
|
message.warning('请先选择所在河段');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addingNewNode.value = true;
|
||||||
|
newNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
ennm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择节点
|
||||||
|
const handleNodeSelect = (value: string) => {
|
||||||
|
const station = stationList.value.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
newNodeData.value.ennm = station.stnm;
|
||||||
|
newNodeData.value.sttpName = station.sttpName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存新增节点
|
||||||
|
const handleSaveNewNode = () => {
|
||||||
|
if (!newNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newNode = {
|
||||||
|
key: generateNodeId(),
|
||||||
|
stcd: newNodeData.value.stcd,
|
||||||
|
ennm: newNodeData.value.ennm,
|
||||||
|
sttpName: newNodeData.value.sttpName,
|
||||||
|
parentId: null,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
treeData.value.push(newNode);
|
||||||
|
addingNewNode.value = false;
|
||||||
|
message.success('添加成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消新增
|
||||||
|
const handleCancelAdd = () => {
|
||||||
|
addingNewNode.value = false;
|
||||||
|
newNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
ennm: '',
|
||||||
|
sttpName: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加子节点(二级节点)
|
||||||
|
const handleAddChild = async (parentData: any) => {
|
||||||
|
addingChildNode.value = true;
|
||||||
|
currentParentKey.value = parentData.key;
|
||||||
|
childNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
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) => {
|
||||||
|
editingNode.value = true;
|
||||||
|
editingNodeKey.value = dataRef.key;
|
||||||
|
// 保存原始数据
|
||||||
|
editNodeData.value = {
|
||||||
|
stcd: dataRef.stcd,
|
||||||
|
ennm: dataRef.ennm,
|
||||||
|
sttpName: dataRef.sttpName,
|
||||||
|
originalData: { ...dataRef }
|
||||||
|
};
|
||||||
|
if (dataRef.parentId) {
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
if (parent) {
|
||||||
|
const res = await getAddvcdDropdownByRvcd({ stcd: parent.stcd });
|
||||||
|
childStationList.value = res.data || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择编辑节点
|
||||||
|
const handleEditNodeSelect = (dataRef: any) => {
|
||||||
|
const value = editNodeData.value.stcd;
|
||||||
|
const list = dataRef.parentId ? childStationList.value : stationList.value;
|
||||||
|
const station = list.find(item => item.stcd === value);
|
||||||
|
if (station) {
|
||||||
|
editNodeData.value.ennm = station.stnm;
|
||||||
|
editNodeData.value.sttpName = station.sttpName;
|
||||||
|
editNodeData.value.stcd = station.stcd;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存编辑节点
|
||||||
|
const handleSaveEditNode = () => {
|
||||||
|
if (!editNodeData.value.stcd) {
|
||||||
|
message.error('请选择站点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到要编辑的节点
|
||||||
|
const node = findNodeByKey(treeData.value, editingNodeKey.value!);
|
||||||
|
if (!node) {
|
||||||
|
message.error('节点不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新节点数据
|
||||||
|
node.stcd = editNodeData.value.stcd;
|
||||||
|
node.ennm = editNodeData.value.ennm;
|
||||||
|
node.sttpName = editNodeData.value.sttpName;
|
||||||
|
|
||||||
|
editingNode.value = false;
|
||||||
|
editingNodeKey.value = null;
|
||||||
|
message.success('编辑成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消编辑节点
|
||||||
|
const handleCancelEditNode = () => {
|
||||||
|
editingNode.value = false;
|
||||||
|
editingNodeKey.value = null;
|
||||||
|
editNodeData.value = {
|
||||||
|
stcd: undefined,
|
||||||
|
ennm: '',
|
||||||
|
sttpName: '',
|
||||||
|
originalData: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上移
|
||||||
|
const handleMoveUp = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
// 交换位置
|
||||||
|
[siblings[index - 1], siblings[index]] = [
|
||||||
|
siblings[index],
|
||||||
|
siblings[index - 1]
|
||||||
|
];
|
||||||
|
message.success('上移成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下移
|
||||||
|
const handleMoveDown = (dataRef: any) => {
|
||||||
|
const siblings = getSiblings(dataRef);
|
||||||
|
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||||
|
|
||||||
|
if (index < siblings.length - 1) {
|
||||||
|
// 交换位置
|
||||||
|
[siblings[index], siblings[index + 1]] = [
|
||||||
|
siblings[index + 1],
|
||||||
|
siblings[index]
|
||||||
|
];
|
||||||
|
message.success('下移成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除节点
|
||||||
|
const handleDeleteNode = (dataRef: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: `确定要删除节点"${dataRef.ennm}"吗?`,
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
if (!dataRef.parentId) {
|
||||||
|
// 删除一级节点
|
||||||
|
const index = treeData.value.findIndex(
|
||||||
|
item => item.key === dataRef.key
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
treeData.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 删除二级节点
|
||||||
|
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||||
|
if (parent && parent.children) {
|
||||||
|
const index = parent.children.findIndex(
|
||||||
|
item => item.key === dataRef.key
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
parent.children.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.success('删除成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
const submitValues = {
|
||||||
|
...formData,
|
||||||
|
captureDate: formData.captureDate
|
||||||
|
? dayjs(formData.captureDate).format('YYYY-MM-DD')
|
||||||
|
: undefined,
|
||||||
|
configNodes: treeData.value // 提交树形数据
|
||||||
|
};
|
||||||
|
emit('ok', submitValues);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initForm = async () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
const values = props.initialValues;
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
if (key === 'captureDate' && values[key]) {
|
||||||
|
formData[key] = dayjs(values[key]);
|
||||||
|
} else {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化树形数据
|
||||||
|
if (values.configNodes && Array.isArray(values.configNodes)) {
|
||||||
|
treeData.value = values.configNodes.map((node: any) => ({
|
||||||
|
...node,
|
||||||
|
children:
|
||||||
|
node.children?.map((child: any) => ({
|
||||||
|
...child
|
||||||
|
})) || []
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
treeData.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑时调用接口获取一级站点列表
|
||||||
|
if (formData.rvcd) {
|
||||||
|
const res = await getEngInfoDropdown({ rvcd: formData.rvcd });
|
||||||
|
stationList.value = (res.data || []).map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
stnm: item.ennm
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
treeData.value = [];
|
||||||
|
addingNewNode.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
emit('cancel');
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.config-tree-container {
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.add-node-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 8px;
|
||||||
|
|
||||||
|
.tree-node-title {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-actions {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保鼠标悬停时显示操作按钮
|
||||||
|
.tree-node-wrapper:hover {
|
||||||
|
.tree-node-actions {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子节点添加区域样式
|
||||||
|
.add-child-node-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 0 8px 24px;
|
||||||
|
margin-top: 4px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增配置">
|
||||||
|
<a-button @click="props.handleAdd" type="primary">
|
||||||
|
新增沿程配置
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from 'vue';
|
||||||
|
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: () => void;
|
||||||
|
riverOptions: any[];
|
||||||
|
riverOptionsLoad: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'reset', values: any): void;
|
||||||
|
(e: 'searchFinish', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
name: null,
|
||||||
|
rvcd: null
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: 'Input',
|
||||||
|
name: 'name',
|
||||||
|
label: '沿程配置名称',
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Select',
|
||||||
|
name: 'rvcd',
|
||||||
|
label: '所在河段',
|
||||||
|
width: 300,
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true
|
||||||
|
},
|
||||||
|
options: props.riverOptions,
|
||||||
|
loading: props.riverOptionsLoad
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit('searchFinish', values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
emit('reset', initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit('searchFinish', initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
379
frontend/src/views/system/ConfigManagement/index.vue
Normal file
379
frontend/src/views/system/ConfigManagement/index.vue
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\ConfigManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
<ConfigManagementSearch
|
||||||
|
ref="configManagementSearch"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
:river-options="riverOptions"
|
||||||
|
:river-options-load="riverOptionsLoad"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
ref="basicTable"
|
||||||
|
:columns="columns"
|
||||||
|
:list-url="getAllConfigTree"
|
||||||
|
:search-params="searchParams"
|
||||||
|
>
|
||||||
|
<template #action="{ record }">
|
||||||
|
<div class="flex gap-[6px]">
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="handleEdit(record)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
class="!p-0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click="handleDelete(record)"
|
||||||
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<ConfigManagementForm
|
||||||
|
ref="configManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:initial-values="currentRecord"
|
||||||
|
:river-options="riverOptions"
|
||||||
|
:river-options-load="riverOptionsLoad"
|
||||||
|
@cancel="editModalCancel"
|
||||||
|
@ok="handleEditSubmit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick, onMounted } from 'vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import ConfigManagementSearch from './ConfigManagementSearch.vue';
|
||||||
|
import ConfigManagementForm from './ConfigManagementForm.vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
getAllConfigTree,
|
||||||
|
deleteBaseWbsb,
|
||||||
|
saveBaseWbsbChild,
|
||||||
|
saveBaseWbsbChildDetail,
|
||||||
|
getChildConfigTree
|
||||||
|
} from '@/api/system/map/ConfigManagement';
|
||||||
|
import { getRvcdDropdown } from '@/api/select';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const basicTable = ref<any>(null);
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ index }) => index + 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '沿程配置名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '配置编码',
|
||||||
|
key: 'code',
|
||||||
|
dataIndex: 'code',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所在河段',
|
||||||
|
dataIndex: 'rvnm',
|
||||||
|
key: 'rvnm',
|
||||||
|
width: 300,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
key: 'recordUser',
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'recordUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'recordTime',
|
||||||
|
dataIndex: 'recordTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'modifyTime',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
key: 'remark',
|
||||||
|
width: 360
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({
|
||||||
|
"sort": [
|
||||||
|
{
|
||||||
|
"field": "recordTime",
|
||||||
|
"dir": "desc"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
// 编辑弹窗数据
|
||||||
|
const currentRecord = ref<any | null>(null);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
|
||||||
|
// 新增处理
|
||||||
|
const handleAdd = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 过滤掉值为 '-' 的字段
|
||||||
|
const filterRecord = (record: any) => {
|
||||||
|
const filtered: any = {};
|
||||||
|
Object.keys(record).forEach(key => {
|
||||||
|
if (record[key] !== '-') {
|
||||||
|
filtered[key] = record[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filtered;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑处理
|
||||||
|
const handleEdit = async (record: any) => {
|
||||||
|
currentRecord.value = filterRecord(record);
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
field: 'alongId',
|
||||||
|
operator: 'eq',
|
||||||
|
value: record.id
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
sort: [
|
||||||
|
{
|
||||||
|
field: 'sort',
|
||||||
|
dir: 'asc'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const res = await getChildConfigTree(params);
|
||||||
|
if (res.code == 0) {
|
||||||
|
const data = res.data.data || [];
|
||||||
|
const firstLevelNodes = data.filter((item: any) => !item.rstcd);
|
||||||
|
const secondLevelNodes = data.filter((item: any) => item.rstcd);
|
||||||
|
|
||||||
|
const configNodes = firstLevelNodes.map((node: any, index: number) => {
|
||||||
|
const children = secondLevelNodes.filter(
|
||||||
|
(child: any) => child.rstcd === node.stcd
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: `parent-${index}`,
|
||||||
|
stcd: node.stcd,
|
||||||
|
ennm: node.stnm,
|
||||||
|
sttpName: node.sttpName,
|
||||||
|
parentId: null,
|
||||||
|
children: children.map((child: any, childIndex: number) => ({
|
||||||
|
key: `child-${index}-${childIndex}`,
|
||||||
|
stcd: child.stcd,
|
||||||
|
ennm: child.stnm,
|
||||||
|
sttpName: child.sttpName,
|
||||||
|
parentId: `parent-${index}`,
|
||||||
|
children: []
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
currentRecord.value.configNodes = configNodes;
|
||||||
|
}
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
zIndex: 2002,
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
let res = await deleteBaseWbsb([record.id]);
|
||||||
|
if (res.code == 0) {
|
||||||
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} else {
|
||||||
|
message.error('删除失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索完成处理
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
const params = {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
values.rvcd
|
||||||
|
? {
|
||||||
|
field: 'rvcd',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.rvcd
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.name
|
||||||
|
? {
|
||||||
|
field: 'name',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.name
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
].filter(Boolean)
|
||||||
|
};
|
||||||
|
basicTable.value.getList(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
basicTable.value.getList({
|
||||||
|
logic: 'and',
|
||||||
|
filters: []
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单取消
|
||||||
|
const editModalCancel = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单提交
|
||||||
|
const handleEditSubmit = async (values: any) => {
|
||||||
|
try {
|
||||||
|
const formData = {
|
||||||
|
...currentRecord.value,
|
||||||
|
...values,
|
||||||
|
modifyTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
};
|
||||||
|
delete formData.configNodes;
|
||||||
|
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (key.includes('-')) {
|
||||||
|
delete formData[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let res = await saveBaseWbsbChild(formData);
|
||||||
|
if (res.code == 0) {
|
||||||
|
const alongId = res.data;
|
||||||
|
const treeData = values.configNodes || [];
|
||||||
|
|
||||||
|
if (treeData.length > 0) {
|
||||||
|
const formatTreeData = (
|
||||||
|
nodes: any[],
|
||||||
|
parentId: string | null = null,
|
||||||
|
parentStcd: string | null = null
|
||||||
|
) => {
|
||||||
|
return nodes.map(node => ({
|
||||||
|
alongId,
|
||||||
|
stcd: node.stcd,
|
||||||
|
stnm: node.ennm || node.stnm,
|
||||||
|
sttpName: node.sttpName,
|
||||||
|
parentId: parentId ? parentId : null,
|
||||||
|
rstcd: parentStcd || null,
|
||||||
|
children:
|
||||||
|
node.children && node.children.length > 0
|
||||||
|
? formatTreeData(node.children, node.key, node.stcd)
|
||||||
|
: []
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const detailData = formatTreeData(treeData);
|
||||||
|
|
||||||
|
const detailRes = await saveBaseWbsbChildDetail(detailData);
|
||||||
|
if (detailRes.code == 0) {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} else {
|
||||||
|
message.error(`保存子节点失败`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.success(`保存成功`);
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
editModalVisible.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const riverOptions = ref<any>([]);
|
||||||
|
const riverOptionsLoad = ref(false);
|
||||||
|
const initOption = () => {
|
||||||
|
const params = {};
|
||||||
|
riverOptionsLoad.value = true;
|
||||||
|
getRvcdDropdown(params).then((res: any) => {
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
item.value = item.rvcd;
|
||||||
|
item.label = item.rvnm;
|
||||||
|
});
|
||||||
|
riverOptions.value = res.data || [];
|
||||||
|
riverOptionsLoad.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
initOption();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
.config-management {
|
||||||
|
height: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,160 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑电站' : '新增电站'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="localLoading"
|
||||||
|
width="600px"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleOk"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
name="edit_form"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
>
|
||||||
|
<a-form-item label="电站名称" name="stationName">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.stationName"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入电站名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所属流域" name="basin">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.basin"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入所属流域"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="装机容量(MW)" name="capacity">
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="formData.capacity"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入装机容量"
|
||||||
|
:min="0"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="状态" name="status">
|
||||||
|
<a-select v-model:value="formData.status" style="width: 100%">
|
||||||
|
<a-select-option value="running">运行中</a-select-option>
|
||||||
|
<a-select-option value="stopped">停运</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="位置坐标" name="coordinates">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.coordinates"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入位置坐标"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
stationName: undefined,
|
||||||
|
basin: undefined,
|
||||||
|
capacity: undefined,
|
||||||
|
status: undefined,
|
||||||
|
coordinates: undefined
|
||||||
|
});
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
stationName: [{ required: true, message: '请输入电站名称', trigger: 'blur' }],
|
||||||
|
basin: [{ required: true, message: '请输入所属流域', trigger: 'blur' }],
|
||||||
|
capacity: [{ required: true, message: '请输入装机容量', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
const submitValues = {
|
||||||
|
...formData
|
||||||
|
};
|
||||||
|
emit('ok', submitValues);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initForm = () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
const values = props.initialValues;
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
emit('cancel');
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增电站">
|
||||||
|
<a-button @click="props.handleAdd" type="primary"> 新增电站 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from "vue";
|
||||||
|
import BasicSearch from "@/components/BasicSearch/index.vue";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "reset", values: any): void;
|
||||||
|
(e: "searchFinish", values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
stationName: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "stationName",
|
||||||
|
label: "电站名称",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit("searchFinish", values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
emit("reset", initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit("searchFinish", initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
203
frontend/src/views/system/StationManagement/index.vue
Normal file
203
frontend/src/views/system/StationManagement/index.vue
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\StationManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
<StationManagementSearch
|
||||||
|
ref="stationManagementSearch"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
:columns="columns"
|
||||||
|
:data="dataSource"
|
||||||
|
:list-url="fetchStationData"
|
||||||
|
:search-params="searchParams"
|
||||||
|
:enable-row-selection="true"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<template #action="{ column, record }">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="link" size="small" @click="handleEdit(record)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click="handleDelete(record)"
|
||||||
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #status="{ column, record }">
|
||||||
|
<a-tag :color="record.status === 'running' ? 'green' : 'red'">
|
||||||
|
{{ record.status === 'running' ? '运行中' : '停运' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<StationManagementForm
|
||||||
|
ref="stationManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:initial-values="currentRecord"
|
||||||
|
@cancel="editModalCancel"
|
||||||
|
@ok="handleEditSubmit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import StationManagementSearch from './StationManagementSearch.vue';
|
||||||
|
import StationManagementForm from './StationManagementForm.vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '电站名称',
|
||||||
|
dataIndex: 'stationName',
|
||||||
|
key: 'stationName',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属流域',
|
||||||
|
dataIndex: 'basin',
|
||||||
|
key: 'basin',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '装机容量(MW)',
|
||||||
|
dataIndex: 'capacity',
|
||||||
|
key: 'capacity',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
key: 'status',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 100,
|
||||||
|
slots: { customRender: 'status' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '位置坐标',
|
||||||
|
dataIndex: 'coordinates',
|
||||||
|
key: 'coordinates',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 150,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 搜索参数
|
||||||
|
const searchParams = ref({});
|
||||||
|
// 编辑弹窗数据
|
||||||
|
const currentRecord = ref<any | null>(null);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
|
||||||
|
// 数据源
|
||||||
|
const dataSource = ref([]);
|
||||||
|
|
||||||
|
// 模拟数据获取函数
|
||||||
|
const fetchStationData = (params: any) => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({
|
||||||
|
data: {
|
||||||
|
records: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
stationName: '三峡电站',
|
||||||
|
basin: '长江流域',
|
||||||
|
capacity: 22500,
|
||||||
|
status: 'running',
|
||||||
|
coordinates: '111.29,30.83'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
stationName: '葛洲坝电站',
|
||||||
|
basin: '长江流域',
|
||||||
|
capacity: 2715,
|
||||||
|
status: 'running',
|
||||||
|
coordinates: '111.28,30.75'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
stationName: '溪洛渡电站',
|
||||||
|
basin: '金沙江流域',
|
||||||
|
capacity: 13860,
|
||||||
|
status: 'stopped',
|
||||||
|
coordinates: '103.65,28.25'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
total: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑处理
|
||||||
|
const handleEdit = (record: any) => {
|
||||||
|
currentRecord.value = { ...record };
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
message.warning(`删除电站: ${record.stationName}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索完成处理
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
console.log(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = (params: any) => {};
|
||||||
|
|
||||||
|
// 选择变化处理
|
||||||
|
const handleSelectionChange = (selectedRows: any[]) => {
|
||||||
|
console.log('选中的行:', selectedRows);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单取消
|
||||||
|
const editModalCancel = () => {
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单提交
|
||||||
|
const handleEditSubmit = (values: any) => {
|
||||||
|
console.log(values);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
.station-management {
|
||||||
|
height: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,249 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:title="isEdit ? '编辑倾斜摄影' : '新增倾斜摄影'"
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:confirm-loading="localLoading"
|
||||||
|
width="600px"
|
||||||
|
: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-form-item label="倾斜影像名称" name="stnm">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.stnm"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入倾斜影像名称"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所在河段" name="hbrvcd">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formData.hbrvcd"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择所在河段"
|
||||||
|
:options="riverOptions"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
:disabled="isEdit"
|
||||||
|
@change="handleRiverSelect"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所属电站" name="rstcd">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formData.rstcd"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择所属电站"
|
||||||
|
:options="ennmOptions"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
<!-- <a-input
|
||||||
|
v-model:value="formData.ennm"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入所属电站"
|
||||||
|
/> -->
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="倾斜影像URL" name="url">
|
||||||
|
<a-input
|
||||||
|
v-model:value="formData.url"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入倾斜影像URL"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="模型坐标" name="location">
|
||||||
|
<a-textarea
|
||||||
|
v-model:value="formData.location"
|
||||||
|
:rows="4"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入模型坐标"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="模型精度" name="accuracy">
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="formData.accuracy"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入模型精度"
|
||||||
|
:min="0"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="边界范围" name="boundary">
|
||||||
|
<a-textarea
|
||||||
|
v-model:value="formData.boundary"
|
||||||
|
:rows="4"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入边界范围"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="模型高度" name="height">
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="formData.height"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入模型高度"
|
||||||
|
:min="0"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="备注" name="comments">
|
||||||
|
<a-textarea
|
||||||
|
v-model:value="formData.comments"
|
||||||
|
:rows="4"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { getEngInfoDropdown } from '@/api/select';
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
initialValues?: any | null;
|
||||||
|
loading?: boolean;
|
||||||
|
riverOptions?: any[];
|
||||||
|
}
|
||||||
|
const localLoading = ref(false);
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
initialValues: null,
|
||||||
|
loading: false,
|
||||||
|
riverOptions: () => []
|
||||||
|
});
|
||||||
|
|
||||||
|
const modalVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: val => emit('update:visible', val)
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'ok', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const defaultFormData = reactive({
|
||||||
|
id: undefined,
|
||||||
|
stnm: undefined,
|
||||||
|
hbrvcd: undefined,
|
||||||
|
rstcd: undefined,
|
||||||
|
url: undefined,
|
||||||
|
location: undefined,
|
||||||
|
accuracy: undefined,
|
||||||
|
boundary: undefined,
|
||||||
|
height: undefined,
|
||||||
|
comments: undefined
|
||||||
|
});
|
||||||
|
const formData: any = reactive({ ...defaultFormData });
|
||||||
|
|
||||||
|
const rules: Record<string, Rule[]> = {
|
||||||
|
stnm: [{ required: true, message: '请输入倾斜影像名称', trigger: 'blur' }],
|
||||||
|
hbrvcd: [{ required: true, message: '请输入所在河段', trigger: 'blur' }],
|
||||||
|
rstcd: [{ required: true, message: '请输入所属电站', trigger: 'blur' }],
|
||||||
|
url: [{ required: true, message: '请输入倾斜影像URL', trigger: 'blur' }],
|
||||||
|
location: [{ required: true, message: '请输入模型坐标', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEdit = computed(() => !!props.initialValues);
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
const ennmItem = ennmOptions.value.find(item => item.value == formData.rstcd);
|
||||||
|
const riverItem = props.riverOptions.find(item => item.value == formData.hbrvcd);
|
||||||
|
const submitValues = {
|
||||||
|
...formData,
|
||||||
|
ennm: ennmItem?.ennm || '',
|
||||||
|
hbrvcdName: riverItem?.label || '',
|
||||||
|
captureDate: formData.captureDate
|
||||||
|
? dayjs(formData.captureDate).format('YYYY-MM-DD')
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
emit('ok', submitValues);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validate Failed:', error);
|
||||||
|
message.error('请检查表单填写是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initForm = () => {
|
||||||
|
if (props.initialValues) {
|
||||||
|
const values = props.initialValues;
|
||||||
|
Object.keys(formData).forEach(key => {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
if (key === 'captureDate' && values[key]) {
|
||||||
|
formData[key] = dayjs(values[key]);
|
||||||
|
} else {
|
||||||
|
formData[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
Object.assign(formData, defaultFormData);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 = ref([]);
|
||||||
|
const handleRiverSelect = async (value: any) => {
|
||||||
|
let res: any = await getEngInfoDropdown({ reachcd: value });
|
||||||
|
if (res?.data?.length > 0) {
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
item.value = item.stcd;
|
||||||
|
item.label = item.ennm;
|
||||||
|
});
|
||||||
|
ennmOptions.value = res.data;
|
||||||
|
} else {
|
||||||
|
ennmOptions.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
newVisible => {
|
||||||
|
if (newVisible) {
|
||||||
|
initForm();
|
||||||
|
handleRiverSelect('');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
localLoading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
@reset="handleReset"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
>
|
||||||
|
<template #actions>
|
||||||
|
<a-tooltip title="新增倾斜摄影">
|
||||||
|
<a-button @click="props.handleAdd" type="primary"> 新增倾斜摄影 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from "vue";
|
||||||
|
import BasicSearch from "@/components/BasicSearch/index.vue";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
handleAdd: () => void;
|
||||||
|
riverOptions: any[];
|
||||||
|
riverOptionsLoad: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "reset", values: any): void;
|
||||||
|
(e: "searchFinish", values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const initSearchData = {
|
||||||
|
stnm: "",
|
||||||
|
rvcd:""
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
{
|
||||||
|
type: "Input",
|
||||||
|
name: "stnm",
|
||||||
|
label: "倾斜影像名称",
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Select',
|
||||||
|
name: 'rvcd',
|
||||||
|
label: '所在河段',
|
||||||
|
width: 300,
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true
|
||||||
|
},
|
||||||
|
options: props.riverOptions,
|
||||||
|
loading: props.riverOptionsLoad
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
emit("searchFinish", values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
emit("reset", initSearchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit("searchFinish", initSearchData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
269
frontend/src/views/system/TiltPhotoManagement/index.vue
Normal file
269
frontend/src/views/system/TiltPhotoManagement/index.vue
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\TiltPhotoManagement\index.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
<TiltPhotoManagementSearch
|
||||||
|
ref="tiltPhotoManagementSearch"
|
||||||
|
:river-options="riverOptions"
|
||||||
|
:river-options-load="riverOptionsLoad"
|
||||||
|
:handle-add="handleAdd"
|
||||||
|
@reset="handleReset"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
/>
|
||||||
|
<BasicTable
|
||||||
|
ref="basicTable"
|
||||||
|
:columns="columns"
|
||||||
|
:list-url="getAllTiltPhotoTree"
|
||||||
|
: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>
|
||||||
|
<TiltPhotoManagementForm
|
||||||
|
ref="tiltPhotoManagementForm"
|
||||||
|
v-model:visible="editModalVisible"
|
||||||
|
:river-options="riverOptions"
|
||||||
|
:river-options-load="riverOptionsLoad"
|
||||||
|
: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 TiltPhotoManagementSearch from './TiltPhotoManagementSearch.vue';
|
||||||
|
import TiltPhotoManagementForm from './TiltPhotoManagementForm.vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
getAllTiltPhotoTree,
|
||||||
|
saveTiltPhoto,
|
||||||
|
deleteTiltPhoto
|
||||||
|
} from '@/api/system/map/TiltPhotoManagement';
|
||||||
|
import { getRvcdDropdown } from '@/api/select';
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text, record, index }) => index + 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '倾斜影像名称',
|
||||||
|
dataIndex: 'stnm',
|
||||||
|
key: 'stnm',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'URL',
|
||||||
|
dataIndex: 'url',
|
||||||
|
key: 'url'
|
||||||
|
// width: 360
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所在河段',
|
||||||
|
dataIndex: 'hbrvcdName',
|
||||||
|
key: 'hbrvcdName',
|
||||||
|
width: 280
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属电站',
|
||||||
|
key: 'ennm',
|
||||||
|
dataIndex: 'ennm',
|
||||||
|
width: 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
key: 'recordUser',
|
||||||
|
dataIndex: 'recordUser',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'recordTime',
|
||||||
|
dataIndex: 'recordTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新时间',
|
||||||
|
key: 'modifyTime',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 handleEdit = (record: any) => {
|
||||||
|
currentRecord.value = { ...record };
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除处理
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
zIndex: 2002,
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
let res = await deleteTiltPhoto({ id: record.id });
|
||||||
|
message.success('删除成功');
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索完成处理
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
const params = {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
values.parentId
|
||||||
|
? {
|
||||||
|
field: 'parentId',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.parentId
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.stnm
|
||||||
|
? {
|
||||||
|
field: 'stnm',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.stnm
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.rvcd
|
||||||
|
? {
|
||||||
|
field: 'hbrvcd',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.rvcd
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
].filter(Boolean)
|
||||||
|
};
|
||||||
|
basicTable.value.getList(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
basicTable.value.getList({
|
||||||
|
logic: 'and',
|
||||||
|
filters: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单取消
|
||||||
|
const editModalCancel = () => {
|
||||||
|
currentRecord.value = null;
|
||||||
|
editModalVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单提交
|
||||||
|
const handleEditSubmit = async (values: any) => {
|
||||||
|
try {
|
||||||
|
let res = await saveTiltPhoto({
|
||||||
|
...currentRecord.value,
|
||||||
|
...values,
|
||||||
|
recordTime:currentRecord.value.recordTime != '-' ? currentRecord.value.recordTime : null
|
||||||
|
});
|
||||||
|
message.success(`保存成功`);
|
||||||
|
|
||||||
|
editModalVisible.value = false;
|
||||||
|
basicTable.value.refresh();
|
||||||
|
} catch (error) {
|
||||||
|
message.error(`保存失败`);
|
||||||
|
|
||||||
|
editModalVisible.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const riverOptions = ref<any>([]);
|
||||||
|
const riverOptionsLoad = ref(false);
|
||||||
|
const initOption = () => {
|
||||||
|
const params = {};
|
||||||
|
riverOptionsLoad.value = true;
|
||||||
|
getRvcdDropdown(params).then((res: any) => {
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
item.value = item.rvcd;
|
||||||
|
item.label = item.rvnm;
|
||||||
|
});
|
||||||
|
riverOptions.value = res.data || [];
|
||||||
|
riverOptionsLoad.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
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>
|
||||||
@ -20,6 +20,7 @@
|
|||||||
v-model:value="formData.title"
|
v-model:value="formData.title"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入图层名称"
|
placeholder="请输入图层名称"
|
||||||
|
:maxlength="50"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="图层编码" name="code">
|
<a-form-item label="图层编码" name="code">
|
||||||
|
|||||||
@ -265,7 +265,10 @@ const handleDelete = async (record: any) => {
|
|||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
let res = await deleteMapLayer([record.id]);
|
let res = await deleteMapLayer([record.id]);
|
||||||
|
if(res.code == 0){
|
||||||
message.success('删除成功');
|
message.success('删除成功');
|
||||||
|
}
|
||||||
|
|
||||||
basicTable.value.refresh();
|
basicTable.value.refresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error('删除失败');
|
message.error('删除失败');
|
||||||
|
|||||||
@ -250,7 +250,9 @@ const handleDelete = (record: any) => {
|
|||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
let res = await deleteMapLegend([record.id]);
|
let res = await deleteMapLegend([record.id]);
|
||||||
|
if (res.code == 0) {
|
||||||
message.success('删除成功');
|
message.success('删除成功');
|
||||||
|
}
|
||||||
basicTable.value.refresh();
|
basicTable.value.refresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error('删除失败');
|
message.error('删除失败');
|
||||||
@ -375,11 +377,13 @@ const handleEditSubmit = async (values: any, type: string) => {
|
|||||||
...values,
|
...values,
|
||||||
parentId: parentId.value
|
parentId: parentId.value
|
||||||
});
|
});
|
||||||
|
if (res.code == 0) {
|
||||||
if (type === 'switch') {
|
if (type === 'switch') {
|
||||||
message.success('修改状态成功');
|
message.success('修改状态成功');
|
||||||
} else {
|
} else {
|
||||||
message.success(`保存成功`);
|
message.success(`保存成功`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
editModalVisible.value = false;
|
editModalVisible.value = false;
|
||||||
basicTable.value.refresh();
|
basicTable.value.refresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -27,18 +27,18 @@ const tabs = [
|
|||||||
name: "图例数据管理",
|
name: "图例数据管理",
|
||||||
value: "legendData",
|
value: "legendData",
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: "电站专题管理",
|
// name: "电站专题管理",
|
||||||
value: "station",
|
// value: "station",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "沿程配置管理",
|
// name: "沿程配置管理",
|
||||||
value: "config",
|
// value: "config",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "倾斜摄影管理",
|
// name: "倾斜摄影管理",
|
||||||
value: "tilt",
|
// value: "tilt",
|
||||||
},
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 当前激活的 tab
|
// 当前激活的 tab
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\ConfigManagement\index.vue -->
|
<!-- d:\wordpack\WholeProcessPlatform\frontend\src\views\system\map\components\ConfigManagement\index.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
推送配置
|
<!-- 推送配置 -->
|
||||||
<!-- <ConfigManagementSearch
|
<!-- <ConfigManagementSearch
|
||||||
ref="configManagementSearch"
|
ref="configManagementSearch"
|
||||||
:handle-add="handleAdd"
|
:handle-add="handleAdd"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user