Merge branch 'main' into dev-tw
This commit is contained in:
commit
d88eca8b8f
@ -7,7 +7,7 @@ VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台'
|
|||||||
VITE_APP_PORT = 3000
|
VITE_APP_PORT = 3000
|
||||||
VITE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API = '/dev-api'
|
||||||
# 本地环境
|
# 本地环境
|
||||||
VITE_APP_BASE_URL = 'http://10.84.121.127:8093'
|
VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||||
# 测试环境
|
# 测试环境
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||||
|
|||||||
@ -199,7 +199,17 @@ const columns = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleView = (record: any) => {
|
const handleView = (record: any) => {
|
||||||
currentRecord.value = { ...record };
|
const transformDashToNull = obj => {
|
||||||
|
const result = { ...obj };
|
||||||
|
for (const key in result) {
|
||||||
|
if (result[key] === '-') {
|
||||||
|
result[key] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
currentRecord.value = transformDashToNull(record);
|
||||||
editModalVisible.value = true;
|
editModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -246,7 +246,9 @@
|
|||||||
:class="{ imgupload_hidden: isView }"
|
:class="{ imgupload_hidden: isView }"
|
||||||
>
|
>
|
||||||
<a-form-item label="图片" name="picpth">
|
<a-form-item label="图片" name="picpth">
|
||||||
|
<div class="flex align-center">
|
||||||
<a-upload
|
<a-upload
|
||||||
|
v-show="!isView"
|
||||||
v-model:file-list="imageFileList"
|
v-model:file-list="imageFileList"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
@ -262,12 +264,17 @@
|
|||||||
<div style="margin-top: 8px">上传</div>
|
<div style="margin-top: 8px">上传</div>
|
||||||
</div>
|
</div>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
|
<span v-show="isView && imageFileList.length === 0">
|
||||||
|
暂无图片
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="视频" name="vdpth">
|
<a-form-item label="视频" name="vdpth">
|
||||||
|
<div class="flex align-center">
|
||||||
<a-upload
|
<a-upload
|
||||||
v-if="!isView"
|
v-if="!isView"
|
||||||
v-model:file-list="videoFileList"
|
v-model:file-list="videoFileList"
|
||||||
@ -291,6 +298,10 @@
|
|||||||
>
|
>
|
||||||
点击预览视频
|
点击预览视频
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<span v-show="isView && videoFileList.length === 0">
|
||||||
|
暂无视频
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|||||||
@ -401,8 +401,18 @@ const handleEdit = (record: any, type: string) => {
|
|||||||
isView.value = true;
|
isView.value = true;
|
||||||
} else {
|
} else {
|
||||||
isView.value = false;
|
isView.value = false;
|
||||||
|
} // 浅层转换(只处理第一层属性)
|
||||||
|
const transformDashToNull = obj => {
|
||||||
|
const result = { ...obj };
|
||||||
|
for (const key in result) {
|
||||||
|
if (result[key] === '-') {
|
||||||
|
result[key] = null;
|
||||||
}
|
}
|
||||||
currentRecord.value = { ...record };
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
currentRecord.value = transformDashToNull(record);
|
||||||
editModalVisible.value = true;
|
editModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -14,22 +14,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import dayjs from "dayjs";
|
import dayjs from 'dayjs';
|
||||||
import BasicSearch from "@/components/BasicSearch/index.vue";
|
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||||
import { DateSetting } from "@/utils/enumeration";
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
import { useShuJuTianBaoStore } from "@/store/modules/shuJuTianBao";
|
import { useShuJuTianBaoStore } from '@/store/modules/shuJuTianBao';
|
||||||
|
|
||||||
interface Props {
|
|
||||||
direction: any[];
|
|
||||||
guoyuStatus: any[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "reset", values: any): void;
|
(e: 'reset', values: any): void;
|
||||||
(e: "search-finish", values: any): void;
|
(e: 'search-finish', values: any): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const shuJuTianBaoStore = useShuJuTianBaoStore();
|
const shuJuTianBaoStore = useShuJuTianBaoStore();
|
||||||
@ -37,51 +30,51 @@ const localTypeDate = ref<string>(null);
|
|||||||
const basicSearchRef = ref<any>();
|
const basicSearchRef = ref<any>();
|
||||||
|
|
||||||
const initSearchData = {
|
const initSearchData = {
|
||||||
rvcd: "all",
|
rvcd: 'all',
|
||||||
stcd: null,
|
stcd: null,
|
||||||
rstcd: null,
|
rstcd: null
|
||||||
strdt: [
|
// strdt: [
|
||||||
dayjs().subtract(1, "month").startOf("month").format("YYYY-MM-DD"),
|
// dayjs().subtract(1, "month").startOf("month").format("YYYY-MM-DD"),
|
||||||
dayjs().endOf("day").format("YYYY-MM-DD"),
|
// dayjs().endOf("day").format("YYYY-MM-DD"),
|
||||||
],
|
// ],
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchData = ref<any>({ ...initSearchData });
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
|
||||||
const searchList: any = computed(() => [
|
const searchList: any = computed(() => [
|
||||||
{
|
{
|
||||||
type: "waterStation",
|
type: 'waterStation',
|
||||||
name: "rvcd",
|
name: 'rvcd',
|
||||||
label: "流域",
|
label: '流域',
|
||||||
fieldProps: {
|
fieldProps: {
|
||||||
allowClear: true,
|
allowClear: true
|
||||||
},
|
|
||||||
options: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
span: 12,
|
|
||||||
type: "RangePicker",
|
|
||||||
name: "strdt",
|
|
||||||
label: "过鱼时间",
|
|
||||||
picker: "date",
|
|
||||||
fieldProps: {
|
|
||||||
format: "YYYY-MM-DD",
|
|
||||||
valueFormat: "YYYY-MM-DD",
|
|
||||||
allowClear: false,
|
|
||||||
},
|
|
||||||
presets: DateSetting.RangeButton.month,
|
|
||||||
},
|
},
|
||||||
|
options: []
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
// span: 12,
|
||||||
|
// type: "RangePicker",
|
||||||
|
// name: "strdt",
|
||||||
|
// label: "过鱼时间",
|
||||||
|
// picker: "date",
|
||||||
|
// fieldProps: {
|
||||||
|
// format: "YYYY-MM-DD",
|
||||||
|
// valueFormat: "YYYY-MM-DD",
|
||||||
|
// allowClear: false,
|
||||||
|
// },
|
||||||
|
// presets: DateSetting.RangeButton.month,
|
||||||
|
// },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onSearchFinish = (values: any) => {
|
const onSearchFinish = (values: any) => {
|
||||||
emit("search-finish", values);
|
emit('search-finish', values);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
searchData.value = { ...searchData.value, ...allValues };
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
if (
|
if (
|
||||||
Object.keys(changedValues)[0] == "rstcd" ||
|
Object.keys(changedValues)[0] == 'rstcd' ||
|
||||||
Object.keys(changedValues)[0] == "rvcd"
|
Object.keys(changedValues)[0] == 'rvcd'
|
||||||
) {
|
) {
|
||||||
const formInstance = basicSearchRef.value?.formData;
|
const formInstance = basicSearchRef.value?.formData;
|
||||||
formInstance.stcd = null;
|
formInstance.stcd = null;
|
||||||
@ -90,12 +83,12 @@ const onValuesChange = (changedValues: any, allValues: any) => {
|
|||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
localTypeDate.value = null;
|
localTypeDate.value = null;
|
||||||
emit("reset", initSearchData);
|
emit('reset', initSearchData);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
emit("search-finish", initSearchData);
|
emit('search-finish', initSearchData);
|
||||||
shuJuTianBaoStore.getFpssOption("", "");
|
shuJuTianBaoStore.getFpssOption('', '');
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<!-- 使用 bodyCell 插槽自定义单元格渲染 -->
|
<!-- 使用 bodyCell 插槽自定义单元格渲染 -->
|
||||||
<template #action="{ column, record }">
|
<template #action="{ record }">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<a-button type="link" size="small" @click="handleShowDetail(record)"
|
<a-button type="link" size="small" @click="handleShowDetail(record)"
|
||||||
>详情</a-button
|
>详情</a-button
|
||||||
@ -55,7 +55,7 @@
|
|||||||
:list-url="getApprovalLogList"
|
:list-url="getApprovalLogList"
|
||||||
:scroll-y="500"
|
:scroll-y="500"
|
||||||
>
|
>
|
||||||
<template #action="{ column, record }">
|
<template #action="{ record }">
|
||||||
{{ handName(record.action, actionTypeDict) }}
|
{{ handName(record.action, actionTypeDict) }}
|
||||||
</template>
|
</template>
|
||||||
</BasicTable>
|
</BasicTable>
|
||||||
@ -82,13 +82,13 @@
|
|||||||
:list-url="getApprovalChangeLogList"
|
:list-url="getApprovalChangeLogList"
|
||||||
:scroll-y="500"
|
:scroll-y="500"
|
||||||
>
|
>
|
||||||
<template #operationType="{ column, record }">
|
<template #operationType="{ record }">
|
||||||
{{ handName(record.operationType, operationTypeDict) }}
|
{{ handName(record.operationType, operationTypeDict) }}
|
||||||
</template>
|
</template>
|
||||||
<template #bizType="{ column, record }">
|
<template #bizType="{ record }">
|
||||||
{{ handName(record.bizType, yeWuType) }}
|
{{ handName(record.bizType, yeWuType) }}
|
||||||
</template>
|
</template>
|
||||||
<template #changeJson="{ column, record }">
|
<template #changeJson="{ record }">
|
||||||
<pre style="max-height: 200px; overflow: auto; margin: 0">{{
|
<pre style="max-height: 200px; overflow: auto; margin: 0">{{
|
||||||
record.changeJson
|
record.changeJson
|
||||||
}}</pre>
|
}}</pre>
|
||||||
@ -122,7 +122,7 @@
|
|||||||
:scroll-y="'500px'"
|
:scroll-y="'500px'"
|
||||||
:transform-data="customTransform"
|
:transform-data="customTransform"
|
||||||
>
|
>
|
||||||
<template #isfs="{ column, record }">
|
<template #isfs="{ record }">
|
||||||
<a-tag
|
<a-tag
|
||||||
:color="
|
:color="
|
||||||
record.isfs === 1 || record.isfs === '1' ? 'success' : 'error'
|
record.isfs === 1 || record.isfs === '1' ? 'success' : 'error'
|
||||||
@ -131,10 +131,10 @@
|
|||||||
{{ record.isfs === 1 || record.isfs === '1' ? '是' : '否' }}
|
{{ record.isfs === 1 || record.isfs === '1' ? '是' : '否' }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #direction="{ column, record }">
|
<template #direction="{ record }">
|
||||||
{{ handName(record.direction, direction) }}
|
{{ handName(record.direction, direction) }}
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ column, record }">
|
<template #action="{ record }">
|
||||||
<a-button type="link" size="small" @click="handleView(record)"
|
<a-button type="link" size="small" @click="handleView(record)"
|
||||||
>查看</a-button
|
>查看</a-button
|
||||||
>
|
>
|
||||||
@ -243,7 +243,7 @@ let columns = ref([
|
|||||||
dataIndex: 'rvnm',
|
dataIndex: 'rvnm',
|
||||||
key: 'rvnm',
|
key: 'rvnm',
|
||||||
title: '流域',
|
title: '流域',
|
||||||
width: 120,
|
width: 320,
|
||||||
fixed: 'left'
|
fixed: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -346,7 +346,7 @@ let columns = ref([
|
|||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'action',
|
key: 'action',
|
||||||
width: 120,
|
width: 130,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
slots: { customRender: 'action' }
|
slots: { customRender: 'action' }
|
||||||
}
|
}
|
||||||
@ -504,7 +504,7 @@ const detailColumns = ref([
|
|||||||
dataIndex: 'rvnm',
|
dataIndex: 'rvnm',
|
||||||
key: 'rvnm',
|
key: 'rvnm',
|
||||||
title: '流域',
|
title: '流域',
|
||||||
width: 120,
|
width: 320,
|
||||||
fixed: 'left'
|
fixed: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -518,7 +518,7 @@ const detailColumns = ref([
|
|||||||
dataIndex: 'stnm',
|
dataIndex: 'stnm',
|
||||||
key: 'stnm',
|
key: 'stnm',
|
||||||
title: '过鱼设施名称',
|
title: '过鱼设施名称',
|
||||||
width: 150,
|
width: 180,
|
||||||
fixed: 'left'
|
fixed: 'left'
|
||||||
},
|
},
|
||||||
{ dataIndex: 'strdt', key: 'strdt', title: '过鱼时间', width: 150 },
|
{ dataIndex: 'strdt', key: 'strdt', title: '过鱼时间', width: 150 },
|
||||||
@ -581,18 +581,18 @@ const handleDetailSearchFinish = (values: any) => {
|
|||||||
dataType: 'string',
|
dataType: 'string',
|
||||||
value: values.ftp
|
value: values.ftp
|
||||||
},
|
},
|
||||||
values.strdt && {
|
// values.strdt && {
|
||||||
field: 'strdt',
|
// field: 'strdt',
|
||||||
operator: 'gte',
|
// operator: 'gte',
|
||||||
dataType: 'date',
|
// dataType: 'date',
|
||||||
value: values.strdt[0] + ' 00:00:00'
|
// value: values.strdt[0] + ' 00:00:00'
|
||||||
},
|
// },
|
||||||
values.strdt && {
|
// values.strdt && {
|
||||||
field: 'strdt',
|
// field: 'strdt',
|
||||||
operator: 'lte',
|
// operator: 'lte',
|
||||||
dataType: 'date',
|
// dataType: 'date',
|
||||||
value: values.strdt[1] + ' 23:59:59'
|
// value: values.strdt[1] + ' 23:59:59'
|
||||||
},
|
// },
|
||||||
values.direction && {
|
values.direction && {
|
||||||
field: 'direction',
|
field: 'direction',
|
||||||
operator: 'eq',
|
operator: 'eq',
|
||||||
@ -643,7 +643,18 @@ const handleShowDetail = (record: any) => {
|
|||||||
|
|
||||||
// 查看单条记录
|
// 查看单条记录
|
||||||
const handleView = (record: any) => {
|
const handleView = (record: any) => {
|
||||||
currentViewRecord.value = { ...record };
|
// 浅层转换(只处理第一层属性)
|
||||||
|
const transformDashToNull = obj => {
|
||||||
|
const result = { ...obj };
|
||||||
|
for (const key in result) {
|
||||||
|
if (result[key] === '-') {
|
||||||
|
result[key] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
currentViewRecord.value = transformDashToNull(record);
|
||||||
viewModalVisible.value = true;
|
viewModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,17 +7,14 @@ VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台'
|
|||||||
VITE_APP_PORT = 3000
|
VITE_APP_PORT = 3000
|
||||||
VITE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API = '/dev-api'
|
||||||
# 本地环境
|
# 本地环境
|
||||||
# VITE_APP_BASE_URL = 'http://10.84.121.122:8093'
|
# VITE_APP_BASE_URL = 'http://localhost:8093'
|
||||||
# 测试环境
|
# 测试环境
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||||
# 汤伟
|
# 汤伟
|
||||||
VITE_APP_BASE_URL = 'http://10.84.121.127:8093'
|
# VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||||
# 李林
|
# 李林
|
||||||
# VITE_APP_BASE_URL = 'http://10.84.121.43:8093'
|
VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||||
# VITE_APP_BASE_URL = 'http://192.168.1.162:8093'
|
|
||||||
# 李林
|
|
||||||
# VITE_APP_BASE_URL = 'http://10.84.121.43:8093'
|
|
||||||
|
|
||||||
# 测试环境线上10.84.121.122:
|
# 测试环境线上10.84.121.122:
|
||||||
VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
||||||
@ -29,7 +26,6 @@ VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
|||||||
VITE_APP_BASE_API_URL = 'http://10.84.121.21:8093'
|
VITE_APP_BASE_API_URL = 'http://10.84.121.21:8093'
|
||||||
## 开发环境 附件服务地址
|
## 开发环境 附件服务地址
|
||||||
VITE_APP_ATTACHMENT_URL = 'https://211.99.26.225:12125'
|
VITE_APP_ATTACHMENT_URL = 'https://211.99.26.225:12125'
|
||||||
attachment
|
|
||||||
|
|
||||||
# 地图服务地址
|
# 地图服务地址
|
||||||
VITE_APP_MAP_URL = 'https://211.99.26.225:18085'
|
VITE_APP_MAP_URL = 'https://211.99.26.225:18085'
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
> 本记录用于跟踪项目开发过程中发现的问题,按日期倒序排列,并标注每项问题的发现人及处理状态。
|
> 本记录用于跟踪项目开发过程中发现的问题,按日期倒序排列,并标注每项问题的发现人及处理状态。
|
||||||
|
|
||||||
***
|
---
|
||||||
|
|
||||||
## 问题列表(2026-06-26)
|
## 问题列表(2026-06-26)
|
||||||
|
|
||||||
| 发现日期 | 解决人 | 编号 | 问题描述 | 状态 | 备注 |
|
| 发现日期 | 解决人 | 编号 | 问题描述 | 状态 | 备注 |
|
||||||
| ---------- | ------ | -- | ------------------------------------- | -- | ------ |
|
| ---------- | ------ | ---- | ---------------------------------------------------------------------- | ------ | -------- |
|
||||||
| 2026-06-26 | 扈 | 1 | 基础信息图片展示是什么逻辑 | ✅ | <br /> |
|
| 2026-06-26 | 扈 | 1 | 基础信息图片展示是什么逻辑 | ✅ | <br /> |
|
||||||
| 2026-06-26 | 扈 | 2 | 电站专题展示逻辑 | ✅ | <br /> |
|
| 2026-06-26 | 扈 | 2 | 电站专题展示逻辑 | ✅ | <br /> |
|
||||||
| 2026-06-26 | <br /> | 3 | 实时视频回放 少接口 | ⚠ | 缺少接口 |
|
| 2026-06-26 | <br /> | 3 | 实时视频回放 少接口 | ⚠ | 缺少接口 |
|
||||||
@ -24,8 +24,13 @@
|
|||||||
| 2026-06-26 | <br /> | 14 | 地图抽吸 碰撞检测 放大到具体层级锚点抽吸了但是 popup 弹框还在显示 | ⚠ | <br /> |
|
| 2026-06-26 | <br /> | 14 | 地图抽吸 碰撞检测 放大到具体层级锚点抽吸了但是 popup 弹框还在显示 | ⚠ | <br /> |
|
||||||
| 2026-06-26 | <br /> | 15 | 地图比如积石峡 放大到层级被公伯峡隐藏掉了,然后在放大才显示 抽吸的问题 | ⚠ | <br /> |
|
| 2026-06-26 | <br /> | 15 | 地图比如积石峡 放大到层级被公伯峡隐藏掉了,然后在放大才显示 抽吸的问题 | ⚠ | <br /> |
|
||||||
| 2026-06-26 | <br /> | 16 | 运行情况 计划开始运行时间 接口没接 | ⚠ | <br /> |
|
| 2026-06-26 | <br /> | 16 | 运行情况 计划开始运行时间 接口没接 | ⚠ | <br /> |
|
||||||
|
| 2026-07-01 | 王 | 17 | 所有弹框加拖动 | ✅ | <br /> |
|
||||||
|
| 2026-07-01 | 王 | 18 | 所有弹框检查宽度有的是固定的 | ✅ | <br /> |
|
||||||
|
| 2026-07-01 | 王 | 18 | 所有导出的添加 | <br /> | <br /> |
|
||||||
|
| 2026-07-02 | 扈 | 19 | 地图点击基地切换偶发性会全部展示出来所有锚点 | <br /> | <br /> |
|
||||||
|
| 2026-07-03 | 汤 | 20 | 图例数据关了选中配置需要添加一个字段是默认不显示 | <br /> | <br /> |
|
||||||
|
|
||||||
***
|
---
|
||||||
|
|
||||||
## 状态说明
|
## 状态说明
|
||||||
|
|
||||||
@ -33,6 +38,6 @@
|
|||||||
- ⚠ – 处理中 / 待解决
|
- ⚠ – 处理中 / 待解决
|
||||||
- ❌ – 阻塞 / 未开始
|
- ❌ – 阻塞 / 未开始
|
||||||
|
|
||||||
***
|
---
|
||||||
|
|
||||||
、
|
、
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
"@wangeditor/editor": "^5.0.0",
|
"@wangeditor/editor": "^5.0.0",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||||
"ant-design-vue": "latest",
|
"ant-design-vue": "latest",
|
||||||
|
"antdv-draggable-modal": "^1.1.6",
|
||||||
"axios": "^1.2.0",
|
"axios": "^1.2.0",
|
||||||
"better-scroll": "^2.4.2",
|
"better-scroll": "^2.4.2",
|
||||||
"cesium": "^1.141.0",
|
"cesium": "^1.141.0",
|
||||||
@ -52,6 +53,7 @@
|
|||||||
"video.js": "^8.23.7",
|
"video.js": "^8.23.7",
|
||||||
"videojs-contrib-hls": "^5.15.0",
|
"videojs-contrib-hls": "^5.15.0",
|
||||||
"vue": "^3.2.40",
|
"vue": "^3.2.40",
|
||||||
|
"vue-ant-modal-enhance": "^1.2.2",
|
||||||
"vue-i18n": "^9.1.9",
|
"vue-i18n": "^9.1.9",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vuedraggable": "^2.24.3",
|
"vuedraggable": "^2.24.3",
|
||||||
|
|||||||
@ -41,6 +41,9 @@ importers:
|
|||||||
ant-design-vue:
|
ant-design-vue:
|
||||||
specifier: latest
|
specifier: latest
|
||||||
version: 4.2.6(vue@3.5.33(typescript@6.0.3))
|
version: 4.2.6(vue@3.5.33(typescript@6.0.3))
|
||||||
|
antdv-draggable-modal:
|
||||||
|
specifier: ^1.1.6
|
||||||
|
version: 1.1.6(ant-design-vue@4.2.6(vue@3.5.33(typescript@6.0.3)))(vue@3.5.33(typescript@6.0.3))
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.2.0
|
specifier: ^1.2.0
|
||||||
version: 1.15.2
|
version: 1.15.2
|
||||||
@ -134,6 +137,9 @@ importers:
|
|||||||
vue:
|
vue:
|
||||||
specifier: ^3.2.40
|
specifier: ^3.2.40
|
||||||
version: 3.5.33(typescript@6.0.3)
|
version: 3.5.33(typescript@6.0.3)
|
||||||
|
vue-ant-modal-enhance:
|
||||||
|
specifier: ^1.2.2
|
||||||
|
version: 1.2.2(ant-design-vue@4.2.6(vue@3.5.33(typescript@6.0.3)))(vue@3.5.33(typescript@6.0.3))
|
||||||
vue-i18n:
|
vue-i18n:
|
||||||
specifier: ^9.1.9
|
specifier: ^9.1.9
|
||||||
version: 9.14.5(vue@3.5.33(typescript@6.0.3))
|
version: 9.14.5(vue@3.5.33(typescript@6.0.3))
|
||||||
@ -2220,6 +2226,13 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: '>=3.2.0'
|
vue: '>=3.2.0'
|
||||||
|
|
||||||
|
antdv-draggable-modal@1.1.6:
|
||||||
|
resolution: {integrity: sha512-nGYIbkHfXBwKOtcw9lknpCdXK/Co0MpikywHREdgGI7dNm5c0zwHgolWf2XQSRvQx9sAtv2+BJYeDsJF77bncg==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
ant-design-vue: '>=3.2.0 <4.0.0'
|
||||||
|
vue: '>=3.2.0 <3.4.0'
|
||||||
|
|
||||||
any-promise@1.3.0:
|
any-promise@1.3.0:
|
||||||
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
|
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
|
||||||
|
|
||||||
@ -5360,6 +5373,12 @@ packages:
|
|||||||
vscode-uri@3.1.0:
|
vscode-uri@3.1.0:
|
||||||
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
|
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
|
||||||
|
|
||||||
|
vue-ant-modal-enhance@1.2.2:
|
||||||
|
resolution: {integrity: sha512-gLozUM4K+pESYcV5ljsc9rAOvy94jL4fId4oNfuxu2pT/hx1HIGnQixi08yKV4FoBOwiFe4cd6dPVqCQLNAANQ==}
|
||||||
|
peerDependencies:
|
||||||
|
ant-design-vue: ^3.0.0 || ^4.0.0
|
||||||
|
vue: ^3.2.0
|
||||||
|
|
||||||
vue-component-type-helpers@3.2.7:
|
vue-component-type-helpers@3.2.7:
|
||||||
resolution: {integrity: sha512-+gPp5YGmhfsj1IN+xUo7y0fb4clfnOiiUA39y07yW1VzCRjzVgwLbtmdWlghh7mXrPsEaYc7rrIir/HT6C8vYQ==}
|
resolution: {integrity: sha512-+gPp5YGmhfsj1IN+xUo7y0fb4clfnOiiUA39y07yW1VzCRjzVgwLbtmdWlghh7mXrPsEaYc7rrIir/HT6C8vYQ==}
|
||||||
|
|
||||||
@ -8569,6 +8588,11 @@ snapshots:
|
|||||||
vue-types: 3.0.2(vue@3.5.33(typescript@6.0.3))
|
vue-types: 3.0.2(vue@3.5.33(typescript@6.0.3))
|
||||||
warning: 4.0.3
|
warning: 4.0.3
|
||||||
|
|
||||||
|
antdv-draggable-modal@1.1.6(ant-design-vue@4.2.6(vue@3.5.33(typescript@6.0.3)))(vue@3.5.33(typescript@6.0.3)):
|
||||||
|
dependencies:
|
||||||
|
ant-design-vue: 4.2.6(vue@3.5.33(typescript@6.0.3))
|
||||||
|
vue: 3.5.33(typescript@6.0.3)
|
||||||
|
|
||||||
any-promise@1.3.0: {}
|
any-promise@1.3.0: {}
|
||||||
|
|
||||||
anymatch@3.1.3:
|
anymatch@3.1.3:
|
||||||
@ -11975,6 +11999,11 @@ snapshots:
|
|||||||
|
|
||||||
vscode-uri@3.1.0: {}
|
vscode-uri@3.1.0: {}
|
||||||
|
|
||||||
|
vue-ant-modal-enhance@1.2.2(ant-design-vue@4.2.6(vue@3.5.33(typescript@6.0.3)))(vue@3.5.33(typescript@6.0.3)):
|
||||||
|
dependencies:
|
||||||
|
ant-design-vue: 4.2.6(vue@3.5.33(typescript@6.0.3))
|
||||||
|
vue: 3.5.33(typescript@6.0.3)
|
||||||
|
|
||||||
vue-component-type-helpers@3.2.7: {}
|
vue-component-type-helpers@3.2.7: {}
|
||||||
|
|
||||||
vue-demi@0.14.10(vue@3.5.33(typescript@6.0.3)):
|
vue-demi@0.14.10(vue@3.5.33(typescript@6.0.3)):
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
// import { SERVICE_URLS } from '../config'; // 引入配置
|
|
||||||
// 基本情况介绍
|
// 基本情况介绍
|
||||||
export function getBaseWbsb(data: any) {
|
export function getBaseWbsb(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/wbsb/GetKendoList',
|
url: '/eq/wbsb/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -12,7 +11,16 @@ export function getBaseWbsb(data: any) {
|
|||||||
// 水电开发及环境监测 - 获取列表数据
|
// 水电开发及环境监测 - 获取列表数据
|
||||||
export function getVmsstbprptKendoList(data: any) {
|
export function getVmsstbprptKendoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/vmsstbprpt/GetKendoList',
|
url: '/eq/vmsstbprpt/GetKendoList',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 水电开发及环境监测 - 获取列表数据(全基地模式)
|
||||||
|
export function getVmsstbprptKendoListCust(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/eq/vmsstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -21,7 +29,7 @@ export function getVmsstbprptKendoList(data: any) {
|
|||||||
// 环保设施建设情况
|
// 环保设施建设情况
|
||||||
export function environmentalProtectionConstruction(data: any) {
|
export function environmentalProtectionConstruction(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/operat/GetKendoListCust',
|
url: '/eng/base/operat/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -30,7 +38,7 @@ export function environmentalProtectionConstruction(data: any) {
|
|||||||
// 环保设施弹框表格
|
// 环保设施弹框表格
|
||||||
export function envOpdGetKendoListCust(data: any) {
|
export function envOpdGetKendoListCust(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/oped/GetKendoListCust',
|
url: '/overview/oped/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -39,7 +47,7 @@ export function envOpdGetKendoListCust(data: any) {
|
|||||||
// 获取基地列表
|
// 获取基地列表
|
||||||
export function getBaseList(data: any) {
|
export function getBaseList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/wbsb/GetKendoList',
|
url: '/eq/wbsb/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -48,7 +56,7 @@ export function getBaseList(data: any) {
|
|||||||
// 获取设施介绍列表
|
// 获取设施介绍列表
|
||||||
export function getMsstbprptKendoList(data: any) {
|
export function getMsstbprptKendoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msstbprpt/GetKendoList',
|
url: '/overview/msstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -57,7 +65,7 @@ export function getMsstbprptKendoList(data: any) {
|
|||||||
// 环保自动监测工作开展情况
|
// 环保自动监测工作开展情况
|
||||||
export function baseEvnmAutoMonitorGetKendoListCust(data: any) {
|
export function baseEvnmAutoMonitorGetKendoListCust(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/evnmAutoMonitor/GetKendoListCust',
|
url: '/wte/base/evnmAutoMonitor/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -66,7 +74,7 @@ export function baseEvnmAutoMonitorGetKendoListCust(data: any) {
|
|||||||
// 环保自动监测弹窗列表
|
// 环保自动监测弹窗列表
|
||||||
export function vmsstbprptGetKendoList(data: any) {
|
export function vmsstbprptGetKendoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/vmsstbprpt/GetKendoList',
|
url: '/eq/vmsstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -75,7 +83,7 @@ export function vmsstbprptGetKendoList(data: any) {
|
|||||||
// 获取基本信息
|
// 获取基本信息
|
||||||
export function baseMsstbprptGetKendoList(data: any) {
|
export function baseMsstbprptGetKendoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msstbprpt/GetKendoList',
|
url: '/overview/msstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,8 +3,10 @@ import request from '@/utils/request';
|
|||||||
// 获取图例列表
|
// 获取图例列表
|
||||||
export function getModuleMapLegendList(params?: { moduleId?: string }) {
|
export function getModuleMapLegendList(params?: { moduleId?: string }) {
|
||||||
const url = params?.moduleId
|
const url = params?.moduleId
|
||||||
? `/api/wmp-sys-server/mapLegend/getModuleMapLegendList?moduleId=${params.moduleId}`
|
? // ? `/api/wmp-sys-server/mapLegend/getModuleMapLegendList?moduleId=${params.moduleId}`
|
||||||
: '/api/wmp-sys-server/mapLegend/getModuleMapLegendList';
|
// : '/api/wmp-sys-server/mapLegend/getModuleMapLegendList';
|
||||||
|
`/mapLegend/getModuleMapLegendList?moduleId=${params.moduleId}`
|
||||||
|
: '/mapLegend/getModuleMapLegendList';
|
||||||
return request({
|
return request({
|
||||||
url,
|
url,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
@ -13,7 +15,8 @@ export function getModuleMapLegendList(params?: { moduleId?: string }) {
|
|||||||
// 获取地图配置列表
|
// 获取地图配置列表
|
||||||
export function getMapList(data: any) {
|
export function getMapList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-sys-server/mapmodule/getMapData',
|
// url: '/api/wmp-sys-server/mapmodule/getMapData',
|
||||||
|
url: '/mapmodule/getMapData',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export function postIdUrl(data: any) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ export function getBuildState(data: any) {
|
|||||||
// 查询鱼类栖息地监测数据类型可用性
|
// 查询鱼类栖息地监测数据类型可用性
|
||||||
export function getFishTab(stcd: string) {
|
export function getFishTab(stcd: string) {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/wmp-env-server/we/wer/getWeDefaultData`,
|
url: `/wte/we/wer/getWeDefaultData`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: { stcd }
|
params: { stcd }
|
||||||
});
|
});
|
||||||
@ -86,15 +86,15 @@ export function getPanoramaList(data: any) {
|
|||||||
// 实时视频
|
// 实时视频
|
||||||
export function getVideoList(data: any) {
|
export function getVideoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msstbprpt/GetKendoList',
|
url: '/vd/msstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 录像视频 - 时间查询 没接
|
// 录像视频 - 时间查询
|
||||||
export function getNoLiveVideoYear(data: any) {
|
export function getNoLiveVideoYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/vd/GetKendoListCust',
|
url: '/vd/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -103,7 +103,7 @@ export function getNoLiveVideoYear(data: any) {
|
|||||||
// 录像视频
|
// 录像视频
|
||||||
export function getNoLiveVideoList(data: any) {
|
export function getNoLiveVideoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/vd/runData/GetKendoListCust',
|
url: '/vd/runData/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -306,7 +306,6 @@ export function getFishZHFX(data: any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRunStateAnalysis(data: any) {
|
export function getRunStateAnalysis(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/fp/run/analysis/GetKendoListCust',
|
url: '/fp/run/analysis/GetKendoListCust',
|
||||||
@ -314,51 +313,51 @@ export function getRunStateAnalysis(data: any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ai运行识别 没接
|
// ai运行识别
|
||||||
export function getAIYXSB(data: any) {
|
export function getAIYXSB(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msstbprpt/getStInfoByStcd',
|
url: '/fp/msstbprpt/getStInfoByStcd',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ai运行识别 视频/表格 没接
|
// ai运行识别 视频/表格
|
||||||
export function getAIComList(data: any) {
|
export function getAIComList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/ai/com/GetKendoListCust',
|
url: '/warn/ai/com/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ai运行识别 日历 没接
|
// ai运行识别 日历
|
||||||
export function getAIComCalendar(data: any) {
|
export function getAIComCalendar(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/ai/com/qgc/aiRecord/GetKendoListCust',
|
url: '/warn/ai/com/qgc/aiRecord/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ai运行 日历点击 没接
|
// ai运行 日历点击
|
||||||
export function getAIComCalendarClick(data: any) {
|
export function getAIComCalendarClick(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/ai/com/qgc/aiFile/GetKendoListCust',
|
url: '/warn/ai/com/qgc/aiFile/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鱼类增殖站 - 运行数据 -获取年 没接
|
// 鱼类增殖站 - 运行数据 -获取年
|
||||||
export function getFishProgressionYear(data: any) {
|
export function getFishProgressionYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/fb/fbrdmr/getFbRelatedYrByStcd',
|
url: '/fb/fbrdmr/getFbRelatedYrByStcd',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//鱼类增殖站 - 运行数据 -获取鱼 没接
|
//鱼类增殖站 - 运行数据 -获取鱼
|
||||||
export function getFishProgressionFish(data: any) {
|
export function getFishProgressionFish(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/fishDic/stcd/GetKendoList',
|
url: '/fp/fishDic/stcd/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -367,7 +366,7 @@ export function getFishProgressionFish(data: any) {
|
|||||||
// 过程图 - 亲鱼
|
// 过程图 - 亲鱼
|
||||||
export function getProcessDiagramParentFish(data: any) {
|
export function getProcessDiagramParentFish(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/fb/bsmfr/fish/GetKendoListCust',
|
url: '/fb/bsmfr/fish/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -376,7 +375,7 @@ export function getProcessDiagramParentFish(data: any) {
|
|||||||
// 过程图 - 产卵/孵化
|
// 过程图 - 产卵/孵化
|
||||||
export function getProcessDiagramHatch(data: any, type: 1 | 2) {
|
export function getProcessDiagramHatch(data: any, type: 1 | 2) {
|
||||||
return request({
|
return request({
|
||||||
url: `/wmp-env-server/fb/fishhatchrecr/fish/GetKendoListCust?type=${type}`,
|
url: `/fb/fishhatchrecr/fish/GetKendoListCust?type=${type}`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -385,32 +384,31 @@ export function getProcessDiagramHatch(data: any, type: 1 | 2) {
|
|||||||
// 过程图 - 鱼苗
|
// 过程图 - 鱼苗
|
||||||
export function getProcessDiagramFishFry(data: any) {
|
export function getProcessDiagramFishFry(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/fb/fishbreedr/fish/GetKendoListCust',
|
url: '/fb/fishbreedr/fish/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//增值放流情况 获取年 没接
|
//增值放流情况 获取年
|
||||||
export function getNormalAddedSituationYear(data: any) {
|
export function getNormalAddedSituationYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/fb/msfbrdm/fbFlData/GetKendoListCust',
|
url: '/fb/msfbrdm/fbFlData/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//增值放流情况 列表 没接
|
//增值放流情况 列表
|
||||||
|
|
||||||
export function getNormalAddedSituation(data: any) {
|
export function getNormalAddedSituation(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/fb/msfbrdm/qgc/GetKendoListCust',
|
url: '/fb/msfbrdm/qgc/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 科研情况 没接
|
// 科研情况
|
||||||
export function getNormalResearchSituation(data: any) {
|
export function getNormalResearchSituation(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/base/researchb/GetKendoList',
|
url: '/fb/base/researchb/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -418,23 +416,23 @@ export function getNormalResearchSituation(data: any) {
|
|||||||
// 珍稀植物园 - 运行数据 没接
|
// 珍稀植物园 - 运行数据 没接
|
||||||
export function getNormalDataMonitoring2Year(data: any) {
|
export function getNormalDataMonitoring2Year(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/vpr/year/GetKendoListCust',
|
url: '/vap/vpr/year/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 珍稀植物园 - 运行数据 列表 没接
|
// 珍稀植物园 - 运行数据 列表
|
||||||
export function getNormalDataMonitoring2List(data: any) {
|
export function getNormalDataMonitoring2List(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/vpr/basinVpIntDetail',
|
url: '/vap/vpr/basinVpIntDetail',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 珍稀动物园 - 监测数据 时间 没接
|
// 珍稀动物园 - 监测数据 时间
|
||||||
export function getNormal2Year(data: any) {
|
export function getNormal2Year(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/var/year/GetKendoListCust',
|
url: '/vap/var/year/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -443,7 +441,7 @@ export function getNormal2Year(data: any) {
|
|||||||
// 珍稀动物园 - 监测数据 列表 没接
|
// 珍稀动物园 - 监测数据 列表 没接
|
||||||
export function getNormal2List(data: any) {
|
export function getNormal2List(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/var/GetKendoListCust',
|
url: '/vap/var/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -451,31 +449,23 @@ export function getNormal2List(data: any) {
|
|||||||
// 水生生态调查断面 - 监测数据 年份 没接
|
// 水生生态调查断面 - 监测数据 年份 没接
|
||||||
export function getEcologyYear(data: any) {
|
export function getEcologyYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/we/wer/getWeYr',
|
url: '/wte/we/wer/getWeYr',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 水生生态调查断面 - 监测数据 调查批次 没接
|
// 水生生态调查断面 - 监测数据 调查批次
|
||||||
export function getEcologyBatch(data: any) {
|
export function getEcologyBatch(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/we/fisht/GetKendoListCust',
|
url: '/wte/we/fisht/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 水生生态调查断面 - 监测数据 保护类型 没接
|
// 水生生态调查断面 - 监测数据 调查鱼类列表
|
||||||
export function getEcologyProtectType(data: any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/dec-modules-usm-springcloud-starter/usm/v1/dict/getRemoteDictTreeValue',
|
|
||||||
method: 'get',
|
|
||||||
params: data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// 水生生态调查断面 - 监测数据 调查鱼类列表 没接
|
|
||||||
export function getEcologyList(data: any) {
|
export function getEcologyList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/we/fisht/qgc/GetKendoListCust',
|
url: '/wte/we/fisht/qgc/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -483,7 +473,7 @@ export function getEcologyList(data: any) {
|
|||||||
// 水生生态调查断面 - 监测数据 水温列表 没接
|
// 水生生态调查断面 - 监测数据 水温列表 没接
|
||||||
export function getEcologyList1(data: any) {
|
export function getEcologyList1(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/we/wewtr/GetKendoListCust',
|
url: '/wte/we/wewtr/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -491,7 +481,7 @@ export function getEcologyList1(data: any) {
|
|||||||
// 水生生态调查断面 - 监测数据 水质列表 没接
|
// 水生生态调查断面 - 监测数据 水质列表 没接
|
||||||
export function getEcologyList2(data: any) {
|
export function getEcologyList2(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/we/wewqr/GetKendoListCust',
|
url: '/wte/we/wewqr/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -500,23 +490,23 @@ export function getEcologyList2(data: any) {
|
|||||||
// 水生生态调查断面 - 监测数据 流速列表 没接
|
// 水生生态调查断面 - 监测数据 流速列表 没接
|
||||||
export function getEcologyList3(data: any) {
|
export function getEcologyList3(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/we/fvR/GetKendoListCust',
|
url: '/wte/we/fvR/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 野生动物检测 -现场录像 - 年份 - 没接
|
// 野生动物检测 -现场录像 - 年份
|
||||||
export function getLiveFootageYear(data: any) {
|
export function getLiveFootageYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/wva/default/GetKendoListCust',
|
url: '/wte/wva/default/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 野生动物检测 -现场录像 - 没接
|
// 野生动物检测 -现场录像
|
||||||
export function getLiveFootageList(data: any) {
|
export function getLiveFootageList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/wva/GetKendoListCust',
|
url: '/wte/wva/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -524,15 +514,15 @@ export function getLiveFootageList(data: any) {
|
|||||||
// 鱼类分布明细 - 年 没接
|
// 鱼类分布明细 - 年 没接
|
||||||
export function getFishDistributionYear(data: any) {
|
export function getFishDistributionYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/we/wer/getWeYr',
|
url: '/wte/we/wer/getWeYr',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 鱼类分布明细 - 列表 没接
|
// 鱼类分布明细 - 列表
|
||||||
export function getFishDistributionList(data: any) {
|
export function getFishDistributionList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/we/fisht/qgc/GetKendoListCust',
|
url: '/wte/we/fisht/qgc/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -540,14 +530,14 @@ export function getFishDistributionList(data: any) {
|
|||||||
// 生态流量泄放设施 - 监测数据 年份 没接
|
// 生态流量泄放设施 - 监测数据 年份 没接
|
||||||
export function getFlowDischargeYear(data: any) {
|
export function getFlowDischargeYear(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/wmp-env-server/env/operat/default/year',
|
url: '/eq/operat/default/year',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export function getFlowDischargeList(code: string, data: any) {
|
export function getFlowDischargeList(code: string, data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/dec-lygk-base-server/base/stbprpData/GetKendoListCust?tbCode=${code}`,
|
url: `/env/engInfo/stbprpData/GetKendoListCust?tbCode=${code}`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|||||||
@ -106,3 +106,11 @@ export function uploadFile(data: any) {
|
|||||||
headers: { 'Content-Type': 'multipart/form-data' }
|
headers: { 'Content-Type': 'multipart/form-data' }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 所在位置下拉列表
|
||||||
|
export function getAddvcdDropdownByRvcd(params: any) {
|
||||||
|
return request({
|
||||||
|
url: '/base/msalongb/noAuth/GetKendoList',
|
||||||
|
method: 'post',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import request from '@/utils/request';
|
|||||||
// 获取所有沿程配置数据
|
// 获取所有沿程配置数据
|
||||||
export function getAllConfigTree(data: any) {
|
export function getAllConfigTree(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msalongb/GetKendoList',
|
url: '/base/msalongb/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -11,7 +11,7 @@ export function getAllConfigTree(data: any) {
|
|||||||
// 保存沿程配置
|
// 保存沿程配置
|
||||||
export function saveBaseWbsb(data: any) {
|
export function saveBaseWbsb(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/wbsb/addOrUpdate',
|
url: '/base/msalongb/save',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
@ -19,8 +19,24 @@ export function saveBaseWbsb(data: any) {
|
|||||||
// 删除沿程配置
|
// 删除沿程配置
|
||||||
export function deleteBaseWbsb(data: any) {
|
export function deleteBaseWbsb(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/wbsb/delete',
|
url: '/base/msalongb/delete',
|
||||||
method: 'get',
|
method: 'post',
|
||||||
params: data
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 保存沿程配置子节点
|
||||||
|
export function saveBaseWbsbChild(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/base/msalongb/save',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveBaseWbsbChildDetail(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/base/msalongdetb/save',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,16 +3,16 @@ import request from '@/utils/request';
|
|||||||
// AI识别大坝环境-获取统计数据(Tab数量)
|
// AI识别大坝环境-获取统计数据(Tab数量)
|
||||||
export function getAisbdbyxList(data: any) {
|
export function getAisbdbyxList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/qgcDmRun/GetKendoListCust',
|
url: '/warn/ai/com/qgcDmRun/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI识别大坝环境-获取饼图+表格数据
|
// AI识别大坝环境-获取饼图+表格数据 /api/wmp-env-server/env/ai/com/GetKendoListCust
|
||||||
export function getAiChartTable(data: any) {
|
export function getAiChartTable(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/GetKendoListCust',
|
url: '/warn/ai/com/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -21,7 +21,7 @@ export function getAiChartTable(data: any) {
|
|||||||
// AI识别大坝环境-获取电站列表
|
// AI识别大坝环境-获取电站列表
|
||||||
export function getAiRstcd(data: any) {
|
export function getAiRstcd(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/qgc/aiRstcd/GetKendoListCust',
|
url: '/warn/ai/com/qgc/aiRstcd/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -30,7 +30,7 @@ export function getAiRstcd(data: any) {
|
|||||||
// AI识别过鱼设施运行-获取统计数据
|
// AI识别过鱼设施运行-获取统计数据
|
||||||
export function getAiGyssList(data: any) {
|
export function getAiGyssList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/qgcProtect/GetKendoListCust',
|
url: '/warn/ai/com/qgcProtect/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -39,7 +39,7 @@ export function getAiGyssList(data: any) {
|
|||||||
// 生态流量低于限值告警-获取统计数据
|
// 生态流量低于限值告警-获取统计数据
|
||||||
export function getStllGaojingList(data: any) {
|
export function getStllGaojingList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/warn/stcd/eng/GetKendoListCust',
|
url: '/warn/stcd/eng/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -48,7 +48,7 @@ export function getStllGaojingList(data: any) {
|
|||||||
// 生态流量低于限值告警-获取表格详情数据
|
// 生态流量低于限值告警-获取表格详情数据
|
||||||
export function getStllGaojingDetail(data: any) {
|
export function getStllGaojingDetail(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/warn/stcd/GetKendoListCust',
|
url: '/warn/stcd/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -57,7 +57,7 @@ export function getStllGaojingDetail(data: any) {
|
|||||||
// 水质监测数据告警-获取统计数据
|
// 水质监测数据告警-获取统计数据
|
||||||
export function getShuizhiGaojingList(data: any) {
|
export function getShuizhiGaojingList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/dec-lygk-base-server/base/msstbprpt/GetKendoList',
|
url: '/wq/msstbprpt/GetKendoList',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -66,7 +66,7 @@ export function getShuizhiGaojingList(data: any) {
|
|||||||
// AI识别大坝环境-获取漂浮物/清漂日历数据
|
// AI识别大坝环境-获取漂浮物/清漂日历数据
|
||||||
export function getAiPfwRecord(data: any) {
|
export function getAiPfwRecord(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/qgc/aiPfwRecord/GetKendoListCust',
|
url: '/warn/ai/com/qgc/aiPfwRecord/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
@ -75,16 +75,16 @@ export function getAiPfwRecord(data: any) {
|
|||||||
// AI识别大坝环境-获取叠梁门日历数据
|
// AI识别大坝环境-获取叠梁门日历数据
|
||||||
export function getAiRecord(data: any) {
|
export function getAiRecord(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/qgc/aiRecord/GetKendoListCust',
|
url: '/warn/ai/com/qgc/aiRecord/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI识别大坝环境-获取日历详情视频数据
|
// AI识别大坝环境-获取日历详情视频数据 /warn/ai/com/qgc/aiFile/GetKendoListCust
|
||||||
export function getAiFile(data: any) {
|
export function getAiFile(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/wmp-env-server/env/ai/com/qgc/aiFile/GetKendoListCust',
|
url: '/warn/ai/com/qgc/aiFile/GetKendoListCust',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function overviewGetOverviewSecond(data: any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//增殖站介绍 /api/dec-lygk-base-server/base/msstbprpt/GetKendoList
|
//增殖站介绍
|
||||||
export function msstbprptGetKendoList(data: any) {
|
export function msstbprptGetKendoList(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/fb/msstbprpt/GetKendoList',
|
url: '/fb/msstbprpt/GetKendoList',
|
||||||
|
|||||||
@ -177,7 +177,84 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item-rest>
|
</a-form-item-rest>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 基地电站下拉框 -->
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex gap-[10px]"
|
||||||
|
v-else-if="item.type === 'jidiData'"
|
||||||
|
>
|
||||||
|
<a-form-item-rest>
|
||||||
|
<!-- 基地下拉框 -->
|
||||||
|
<a-select
|
||||||
|
:value="formData[item.name]"
|
||||||
|
placeholder="请选择"
|
||||||
|
@change="val => dataDimensionDataChange(val, item.name)"
|
||||||
|
show-search
|
||||||
|
allow-clear
|
||||||
|
:loading="shuJuTianBaoStore.baseLoading"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
style="width: 135px"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="opt in shuJuTianBaoStore.baseOption"
|
||||||
|
:key="opt.baseid"
|
||||||
|
:value="opt.baseid"
|
||||||
|
:label="opt.basename"
|
||||||
|
>
|
||||||
|
{{ opt.basename }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<!-- 电站下拉框 -->
|
||||||
|
<a-select
|
||||||
|
v-if="props.zhujianfujian == 'fu'"
|
||||||
|
:value="formData.rstcd"
|
||||||
|
placeholder="请选择电站"
|
||||||
|
@change="stcdIdChange"
|
||||||
|
show-search
|
||||||
|
allow-clear
|
||||||
|
:loading="shuJuTianBaoStore.engLoading"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
style="width: 135px"
|
||||||
|
:dropdown-style="{
|
||||||
|
maxHeight: '400px',
|
||||||
|
overflow: 'auto',
|
||||||
|
minWidth: '300px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="opt in shuJuTianBaoStore.engOption"
|
||||||
|
:key="opt.stcd"
|
||||||
|
:value="opt.stcd"
|
||||||
|
:label="opt.ennm"
|
||||||
|
:title="opt.ennm + ',' + opt.reachcdName"
|
||||||
|
:reachcdName="opt.reachcdName"
|
||||||
|
>
|
||||||
|
{{ opt.ennm }},{{ opt.reachcdName }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<!-- 电站下拉框 -->
|
||||||
|
<a-select
|
||||||
|
v-if="props.zhujianfujian == 'zhu'"
|
||||||
|
:value="formData.stcd"
|
||||||
|
placeholder="请选择电站"
|
||||||
|
@change="stcdIdChange"
|
||||||
|
show-search
|
||||||
|
allow-clear
|
||||||
|
:loading="shuJuTianBaoStore.engLoading"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
style="width: 135px"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="opt in shuJuTianBaoStore.engOption"
|
||||||
|
:key="opt.stcd"
|
||||||
|
:value="opt.stcd"
|
||||||
|
:label="opt.ennm"
|
||||||
|
>
|
||||||
|
{{ opt.ennm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item-rest>
|
||||||
|
</div>
|
||||||
<!-- 下拉选择 -->
|
<!-- 下拉选择 -->
|
||||||
<!-- <div v-else-if="item.type === 'Select'">
|
<!-- <div v-else-if="item.type === 'Select'">
|
||||||
<div v-for="i in item.options"> {{ i[item.values?.name] }} {{ i[item.values?.value] }}</div>
|
<div v-for="i in item.options"> {{ i[item.values?.name] }} {{ i[item.values?.value] }}</div>
|
||||||
@ -219,6 +296,7 @@
|
|||||||
children: 'children'
|
children: 'children'
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
:filterTreeNode="filterTreeNode"
|
||||||
:show-search="item.showSearch !== false"
|
:show-search="item.showSearch !== false"
|
||||||
:tree-checkable="item.treeCheckable"
|
:tree-checkable="item.treeCheckable"
|
||||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
@ -333,12 +411,15 @@ const formData = reactive<any>({});
|
|||||||
const rules = reactive<Record<string, any>>({});
|
const rules = reactive<Record<string, any>>({});
|
||||||
|
|
||||||
const filterOption = (inputValue: string, option: any) => {
|
const filterOption = (inputValue: string, option: any) => {
|
||||||
const label = option.label || '';
|
const label = option.label || option.name || '';
|
||||||
const reachcdName = option.reachcdName || '';
|
const reachcdName = option.reachcdName || '';
|
||||||
const keyword = inputValue || '';
|
const keyword = inputValue || '';
|
||||||
|
|
||||||
return label.indexOf(keyword) !== -1 || reachcdName.indexOf(keyword) !== -1;
|
return label.indexOf(keyword) !== -1 || reachcdName.indexOf(keyword) !== -1;
|
||||||
};
|
};
|
||||||
|
const filterTreeNode = (inputValue: string, option: any) => {
|
||||||
|
return filterOption(inputValue, option);
|
||||||
|
};
|
||||||
// 2. 创建计算属性,自动过滤掉 false/null/undefined 的项
|
// 2. 创建计算属性,自动过滤掉 false/null/undefined 的项
|
||||||
const validSearchList = computed(() => {
|
const validSearchList = computed(() => {
|
||||||
return props.searchList.filter(item => item);
|
return props.searchList.filter(item => item);
|
||||||
@ -358,9 +439,13 @@ const initForm = () => {
|
|||||||
validSearchList.value.forEach(item => {
|
validSearchList.value.forEach(item => {
|
||||||
if (item.type == 'waterStation') {
|
if (item.type == 'waterStation') {
|
||||||
// 下拉菜单
|
// 下拉菜单
|
||||||
// shuJuTianBaoStore.getBaseOption();
|
shuJuTianBaoStore.getBaseOption();
|
||||||
shuJuTianBaoStore.getSelectForOption();
|
shuJuTianBaoStore.getSelectForOption();
|
||||||
shuJuTianBaoStore.getEngOption(formData.rvcd);
|
shuJuTianBaoStore.getEngOption(formData.rvcd,'rvcd');
|
||||||
|
}
|
||||||
|
if (item.type == 'jidiData') {
|
||||||
|
shuJuTianBaoStore.getBaseOption();
|
||||||
|
shuJuTianBaoStore.getEngOption(formData[item.name] || 'all','baseId');
|
||||||
}
|
}
|
||||||
if (item.fieldProps?.required) {
|
if (item.fieldProps?.required) {
|
||||||
rules[item.name] = [
|
rules[item.name] = [
|
||||||
@ -383,19 +468,19 @@ const triggerManualValuesChange = (changedKey: string, newValue: any) => {
|
|||||||
emit('valuesChange', changedValues, { ...formData });
|
emit('valuesChange', changedValues, { ...formData });
|
||||||
};
|
};
|
||||||
|
|
||||||
// const dataDimensionDataChange = (value: any) => {
|
const dataDimensionDataChange = (value: any, fieldName: string = 'baseId') => {
|
||||||
// formData.baseId = value;
|
formData[fieldName] = value;
|
||||||
// formData.rstcd = "";
|
formData.rstcd = "";
|
||||||
// shuJuTianBaoStore.getEngOption(formData.baseId);
|
shuJuTianBaoStore.getEngOption(value,'baseId');
|
||||||
|
triggerManualValuesChange('baseId', formData.baseId);
|
||||||
// // 【关键修改】手动触发 valuesChange,因为 a-form-item-rest 阻断了自动监听
|
// 一次性触发所有变更通知,避免多次调用
|
||||||
// triggerManualValuesChange("baseId", formData.baseId);
|
// emit('valuesChange', { [fieldName]: value, rstcd: "" }, { ...formData });
|
||||||
// };
|
};
|
||||||
|
|
||||||
const lyChange = (value: any) => {
|
const lyChange = (value: any) => {
|
||||||
formData.rvcd = value;
|
formData.rvcd = value;
|
||||||
formData.rstcd = '';
|
formData.rstcd = '';
|
||||||
shuJuTianBaoStore.getEngOption(formData.rvcd);
|
shuJuTianBaoStore.getEngOption(formData.rvcd,'rvcd');
|
||||||
|
|
||||||
// 【关键修改】手动触发 valuesChange,因为 a-form-item-rest 阻断了自动监听
|
// 【关键修改】手动触发 valuesChange,因为 a-form-item-rest 阻断了自动监听
|
||||||
triggerManualValuesChange('rvcd', formData.rvcd);
|
triggerManualValuesChange('rvcd', formData.rvcd);
|
||||||
@ -404,12 +489,12 @@ const lyChange = (value: any) => {
|
|||||||
const stcdIdChange = (value: any) => {
|
const stcdIdChange = (value: any) => {
|
||||||
if (props.zhujianfujian == 'fu') {
|
if (props.zhujianfujian == 'fu') {
|
||||||
formData.rstcd = value;
|
formData.rstcd = value;
|
||||||
shuJuTianBaoStore.getFpssOption(formData.rvcd, value);
|
shuJuTianBaoStore.getFpssOption(formData.baseId, value);
|
||||||
// 【关键修改】手动触发 valuesChange
|
// 【关键修改】手动触发 valuesChange
|
||||||
triggerManualValuesChange('rstcd', formData.rstcd);
|
triggerManualValuesChange('rstcd', formData.rstcd);
|
||||||
} else {
|
} else {
|
||||||
formData.stcd = value;
|
formData.stcd = value;
|
||||||
shuJuTianBaoStore.getFpssOption(formData.rvcd, value);
|
shuJuTianBaoStore.getFpssOption(formData.baseId, value);
|
||||||
// 【关键修改】手动触发 valuesChange
|
// 【关键修改】手动触发 valuesChange
|
||||||
triggerManualValuesChange('stcd', formData.stcd);
|
triggerManualValuesChange('stcd', formData.stcd);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -638,7 +638,12 @@ const enhancedColumns = computed(() => {
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }: { text: any }) => {
|
customRender: ({ text }: { text: any }) => {
|
||||||
// 如果 text 是空值,直接返回占位符
|
// 如果 text 是空值,直接返回占位符
|
||||||
if (text === null || text === undefined || text === '') {
|
if (
|
||||||
|
text === null ||
|
||||||
|
text === undefined ||
|
||||||
|
text === '' ||
|
||||||
|
text === '-'
|
||||||
|
) {
|
||||||
return props.emptyPlaceholder;
|
return props.emptyPlaceholder;
|
||||||
}
|
}
|
||||||
// 使用 h 函数创建 Tooltip
|
// 使用 h 函数创建 Tooltip
|
||||||
|
|||||||
282
frontend/src/components/FishResource/FishResourceSearch.vue
Normal file
282
frontend/src/components/FishResource/FishResourceSearch.vue
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
<template>
|
||||||
|
<div class="approval-search">
|
||||||
|
<BasicSearch
|
||||||
|
ref="basicSearchRef"
|
||||||
|
:searchList="searchList"
|
||||||
|
:initial-values="initSearchData"
|
||||||
|
:zhujianfujian="'fu'"
|
||||||
|
@reset="handleResetWrapper"
|
||||||
|
@finish="onSearchFinish"
|
||||||
|
@values-change="onValuesChange"
|
||||||
|
><template #jcdt>
|
||||||
|
<a-date-picker
|
||||||
|
class="w-[120px]"
|
||||||
|
v-model:value="jcdt.min"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
placeholder="起始时间"
|
||||||
|
:showToday="false"
|
||||||
|
>
|
||||||
|
<template #renderExtraFooter>
|
||||||
|
<div class="flex items-center flex-wrap px-2">
|
||||||
|
<span
|
||||||
|
v-for="item in DateSetting.RangeButton.days1"
|
||||||
|
:key="item"
|
||||||
|
@click="handleRangeClick(item)"
|
||||||
|
>
|
||||||
|
<a class="text-[#1890ff] mr-1"> {{ item.label }}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-date-picker>
|
||||||
|
至
|
||||||
|
<a-form-item-rest>
|
||||||
|
<a-date-picker
|
||||||
|
class="w-[120px]"
|
||||||
|
v-model:value="jcdt.max"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
:disabledDate="disabledEndDate"
|
||||||
|
placeholder="结束时间"
|
||||||
|
:showToday="false"
|
||||||
|
>
|
||||||
|
<template #renderExtraFooter>
|
||||||
|
<div class="flex items-center flex-wrap px-2">
|
||||||
|
<span
|
||||||
|
v-for="item in DateSetting.RangeButton.days1"
|
||||||
|
:key="item"
|
||||||
|
@click="handleRangeClick(item)"
|
||||||
|
>
|
||||||
|
<a class="text-[#1890ff] mr-1"> {{ item.label }}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-date-picker>
|
||||||
|
</a-form-item-rest>
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<a-button :loading="exportLoading" @click="exportBtn">导出</a-button>
|
||||||
|
</template>
|
||||||
|
</BasicSearch>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from 'vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import BasicSearch from '@/components/BasicSearch/index.vue';
|
||||||
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
|
import { useTimeScale } from '@/store/composables/useTimeScale';
|
||||||
|
import { getFishReleaseMonitorSectionList } from '@/api/DataQueryMenuModule';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'export-btn'): void;
|
||||||
|
(e: 'reset', values: any): void;
|
||||||
|
(e: 'search-finish', values: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const basicSearchRef = ref<any>();
|
||||||
|
const btnLoading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
exportLoading?: boolean;
|
||||||
|
modalData: any;
|
||||||
|
}>();
|
||||||
|
const initSearchData = {
|
||||||
|
baseId: props.modalData.baseid ?? 'all',
|
||||||
|
rstcd: null,
|
||||||
|
stcd: '',
|
||||||
|
mway: '1'
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchData = ref<any>({ ...initSearchData });
|
||||||
|
|
||||||
|
const {
|
||||||
|
jcdt,
|
||||||
|
currentTimeScale,
|
||||||
|
handleRangeClick,
|
||||||
|
disabledEndDate,
|
||||||
|
handleSearchFinish,
|
||||||
|
handleValuesChange,
|
||||||
|
init,
|
||||||
|
setDefaultTimeRange
|
||||||
|
} = useTimeScale({
|
||||||
|
defaultTimeScale: initSearchData.timeScale,
|
||||||
|
onSearchFinish: values => emit('search-finish', values),
|
||||||
|
onReset: () => emit('reset', initSearchData)
|
||||||
|
});
|
||||||
|
const crossSectionListLoading = ref<any>(false);
|
||||||
|
const crossSectionList = ref<any>([]);
|
||||||
|
|
||||||
|
const searchList: any = computed(() => [
|
||||||
|
// {
|
||||||
|
// type: 'waterStation',
|
||||||
|
// name: 'rvcd',
|
||||||
|
// label: '流域',
|
||||||
|
// placeholder: '请输入流域名称',
|
||||||
|
// fieldProps: {
|
||||||
|
// allowClear: true
|
||||||
|
// },
|
||||||
|
// options: []
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'jidiData',
|
||||||
|
name: 'baseId',
|
||||||
|
label: '水电基地',
|
||||||
|
placeholder: '请输入水电基地名称',
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true
|
||||||
|
},
|
||||||
|
options: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Select',
|
||||||
|
name: 'stcd',
|
||||||
|
label: '过鱼设施名称',
|
||||||
|
width: 200,
|
||||||
|
placeholder: '请选择过鱼设施名称',
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: true
|
||||||
|
},
|
||||||
|
loading: crossSectionListLoading.value,
|
||||||
|
options: crossSectionList.value.map(item => ({
|
||||||
|
label: item.stnm,
|
||||||
|
value: item.stcd
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Radio',
|
||||||
|
name: 'mway',
|
||||||
|
label: '数据类型',
|
||||||
|
width: 140,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '人工',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '自动',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'custom',
|
||||||
|
name: 'jcdt',
|
||||||
|
label: '时间',
|
||||||
|
fieldProps: {
|
||||||
|
allowClear: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSearchFinish = (values: any) => {
|
||||||
|
handleSearchFinish(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportBtn = () => {
|
||||||
|
emit('export-btn');
|
||||||
|
};
|
||||||
|
const initCrossSectionList = params => {
|
||||||
|
const filters = [];
|
||||||
|
if (params) {
|
||||||
|
if (params.baseId != '' && params.baseId != 'all') {
|
||||||
|
filters.push({
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: params.baseId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (params.rstcd != '' && params.rstcd != null) {
|
||||||
|
filters.push({
|
||||||
|
field: 'rstcd',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: params.rstcd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crossSectionListLoading.value = true;
|
||||||
|
getFishReleaseMonitorSectionList({
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: filters
|
||||||
|
},
|
||||||
|
select: ['stcd', 'stnm', 'wtDeviceType', 'dtinType', 'mway']
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data?.data) {
|
||||||
|
crossSectionList.value = res.data?.data;
|
||||||
|
}
|
||||||
|
crossSectionListLoading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
// 当基地或断面变化时,清空过鱼设施选中并重新请求列表
|
||||||
|
if ('baseId' in changedValues || 'rstcd' in changedValues) {
|
||||||
|
allValues.stcd = null;
|
||||||
|
if (basicSearchRef.value?.formData) {
|
||||||
|
basicSearchRef.value.formData.stcd = null;
|
||||||
|
}
|
||||||
|
initCrossSectionList(allValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleValuesChange(changedValues, allValues);
|
||||||
|
searchData.value = { ...searchData.value, ...allValues };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleResetWrapper = () => {
|
||||||
|
// 手动重置内部状态,避免触发两次请求
|
||||||
|
currentTimeScale.value = initSearchData.timeScale;
|
||||||
|
const now = dayjs();
|
||||||
|
if (props.modalData.year) {
|
||||||
|
jcdt.value = {
|
||||||
|
min: `${props.modalData.year}-01-01 00:00:00`,
|
||||||
|
max: `${props.modalData.year}-12-31 23:59:59`
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
jcdt.value = {
|
||||||
|
min: `${now
|
||||||
|
.subtract(5, 'year')
|
||||||
|
.startOf('year')
|
||||||
|
.format('YYYY-MM-DD')} 00:00:00`,
|
||||||
|
max: `${now.endOf('year').format('YYYY-MM-DD')} 23:59:59`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultTimeRange(initSearchData.timeScale);
|
||||||
|
// 触发搜索,使用当前状态而非 initSearchData
|
||||||
|
handleSearchFinish({
|
||||||
|
...initSearchData
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
btnLoading,
|
||||||
|
searchData
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
// 设置默认年份:前一年到当前年
|
||||||
|
const now = dayjs();
|
||||||
|
if (props.modalData.year) {
|
||||||
|
jcdt.value = {
|
||||||
|
min: `${props.modalData.year}-01-01 00:00:00`,
|
||||||
|
max: `${props.modalData.year}-12-31 23:59:59`
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
jcdt.value = {
|
||||||
|
min: `${now.subtract(5, 'year').format('YYYY-MM-DD')} 00:00:00`,
|
||||||
|
max: `${now.format('YYYY-MM-DD')} 23:59:59`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
initCrossSectionList();
|
||||||
|
// 使用 handleSearchFinish 确保包含 jcdt 等完整参数
|
||||||
|
handleSearchFinish({ ...initSearchData });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss"></style>
|
||||||
554
frontend/src/components/FishResource/index.vue
Normal file
554
frontend/src/components/FishResource/index.vue
Normal file
@ -0,0 +1,554 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-full h-full flex flex-col" style="height:calc(60vh)">
|
||||||
|
<!-- 搜索组件 -->
|
||||||
|
<FishDataSearch
|
||||||
|
@export-btn="exportBtn"
|
||||||
|
@search-finish="onSearchFinish"
|
||||||
|
@reset="onReset"
|
||||||
|
:exportLoading="exportLoading"
|
||||||
|
:modalData = "props.modalData"
|
||||||
|
ref="searchRef"
|
||||||
|
/>
|
||||||
|
<!-- 表格组件 -->
|
||||||
|
<BasicTable
|
||||||
|
ref="tableRef"
|
||||||
|
:scrollX="tableScrollX"
|
||||||
|
:scrollY="tableScrollY"
|
||||||
|
:columns="tableColumns"
|
||||||
|
:list-url="getFishReleaseMonitorList"
|
||||||
|
:searchParams="{
|
||||||
|
sort: sort
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
</BasicTable>
|
||||||
|
|
||||||
|
<!-- 图片预览弹框 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="imagePreviewVisible"
|
||||||
|
title="图片预览"
|
||||||
|
:footer="null"
|
||||||
|
width="800px"
|
||||||
|
>
|
||||||
|
<div style="text-align: center">
|
||||||
|
<img :src="previewImageUrl" style="width: 100%; height: 600px" />
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<!-- 视频预览弹框 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="videoPreviewVisible"
|
||||||
|
title="视频预览"
|
||||||
|
:footer="null"
|
||||||
|
width="800px"
|
||||||
|
>
|
||||||
|
<div style="text-align: center">
|
||||||
|
<video
|
||||||
|
:src="previewVideoUrl"
|
||||||
|
controls
|
||||||
|
style="width: 100%; height: 600px"
|
||||||
|
></video>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted, nextTick, h } from 'vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
import FishDataSearch from './FishResourceSearch.vue';
|
||||||
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
import { getFishReleaseMonitorList } from '@/api/DataQueryMenuModule';
|
||||||
|
import { calcTableScrollY } from '@/utils/index';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
const props = defineProps<{
|
||||||
|
modalData?: any;
|
||||||
|
}>();
|
||||||
|
const sort = ref<any>([
|
||||||
|
{
|
||||||
|
field: 'baseStepSort',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'rvcdStepSort',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'rstcdStepSort',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'ttpwr',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
dir: 'desc'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableRef = ref();
|
||||||
|
const searchRef = ref();
|
||||||
|
const tableScrollY = ref<string | number>(0);
|
||||||
|
const currentSearchParams = ref<any>({});
|
||||||
|
const exportLoading = ref(false);
|
||||||
|
|
||||||
|
// 图片预览
|
||||||
|
const imagePreviewVisible = ref(false);
|
||||||
|
const previewImageUrl = ref('');
|
||||||
|
// 视频预览
|
||||||
|
const videoPreviewVisible = ref(false);
|
||||||
|
const previewVideoUrl = ref('');
|
||||||
|
useDraggable(imagePreviewVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(videoPreviewVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
const openImagePreview = (url: string) => {
|
||||||
|
previewImageUrl.value = import.meta.env.VITE_APP_ATTACHMENT_URL + '/?' + url;
|
||||||
|
imagePreviewVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const openVideoPreview = (url: string) => {
|
||||||
|
previewVideoUrl.value = import.meta.env.VITE_APP_ATTACHMENT_URL + '/?' + url;
|
||||||
|
videoPreviewVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableScrollX = computed(() =>
|
||||||
|
Math.max(
|
||||||
|
tableColumns.value.reduce(
|
||||||
|
(sum: number, col: any) => sum + (col.width || 180),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
600
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 人工列
|
||||||
|
const columnsManual: any[] = [
|
||||||
|
{
|
||||||
|
key: 'stnm',
|
||||||
|
title: '电站名称',
|
||||||
|
dataIndex: 'stnm',
|
||||||
|
visible: true,
|
||||||
|
width: 200,
|
||||||
|
sort: true,
|
||||||
|
merge: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'baseName',
|
||||||
|
title: '所属基地',
|
||||||
|
dataIndex: 'baseName',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'stnm',
|
||||||
|
title: '过鱼设施名称',
|
||||||
|
dataIndex: 'stnm',
|
||||||
|
sort: true,
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'strdt',
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'strdt',
|
||||||
|
sort: true,
|
||||||
|
width: 100,
|
||||||
|
customRender: ({ text }) => dayjs(text).format('YYYY-MM-DD') || '-'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'enddt',
|
||||||
|
title: '结束时间',
|
||||||
|
dataIndex: 'enddt',
|
||||||
|
sort: true,
|
||||||
|
width: 100,
|
||||||
|
customRender: ({ text }) => dayjs(text).format('YYYY-MM-DD') || '-'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'tm',
|
||||||
|
title: '填报时间',
|
||||||
|
dataIndex: 'tm',
|
||||||
|
sort: true,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ftp',
|
||||||
|
title: '鱼种类',
|
||||||
|
dataIndex: 'ftp',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fcnt',
|
||||||
|
title: '过鱼数量(尾)',
|
||||||
|
dataIndex: 'fcnt',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'directionName',
|
||||||
|
title: '鱼游向',
|
||||||
|
dataIndex: 'directionName',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fsz',
|
||||||
|
title: '鱼类规格',
|
||||||
|
dataIndex: 'fsz',
|
||||||
|
sort: true,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'firstimgurl',
|
||||||
|
title: '图片',
|
||||||
|
dataIndex: 'firstimgurl',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const hasValidUrl =
|
||||||
|
text &&
|
||||||
|
text !== '-' &&
|
||||||
|
text.trim() !== '' &&
|
||||||
|
text !== 'null' &&
|
||||||
|
text !== 'undefined';
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
disabled: !hasValidUrl,
|
||||||
|
style: {
|
||||||
|
color: !hasValidUrl ? '#ccc' : '#1890ff',
|
||||||
|
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if (hasValidUrl) {
|
||||||
|
openImagePreview(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => '查看图片'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'videourl',
|
||||||
|
title: '视频',
|
||||||
|
dataIndex: 'videourl',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const hasValidUrl =
|
||||||
|
text &&
|
||||||
|
text !== '-' &&
|
||||||
|
text.trim() !== '' &&
|
||||||
|
text !== 'null' &&
|
||||||
|
text !== 'undefined';
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
disabled: !hasValidUrl,
|
||||||
|
style: {
|
||||||
|
color: !hasValidUrl ? '#ccc' : '#1890ff',
|
||||||
|
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if (hasValidUrl) {
|
||||||
|
openVideoPreview(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => '查看视频'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 自动列
|
||||||
|
const columnsAuto: any[] = [
|
||||||
|
{
|
||||||
|
key: 'stnm',
|
||||||
|
title: '电站名称',
|
||||||
|
dataIndex: 'stnm',
|
||||||
|
visible: true,
|
||||||
|
width: 200,
|
||||||
|
sort: true,
|
||||||
|
merge: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'baseName',
|
||||||
|
title: '所属基地',
|
||||||
|
dataIndex: 'baseName',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'stnm',
|
||||||
|
title: '过鱼设施名称',
|
||||||
|
dataIndex: 'stnm',
|
||||||
|
sort: true,
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'tm',
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'tm',
|
||||||
|
sort: true,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ftp',
|
||||||
|
title: '鱼种类',
|
||||||
|
dataIndex: 'ftp',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'length',
|
||||||
|
title: '鱼长度(cm)',
|
||||||
|
dataIndex: 'length',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'width',
|
||||||
|
title: '鱼宽度(cm)',
|
||||||
|
dataIndex: 'width',
|
||||||
|
sort: true,
|
||||||
|
width: 120,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const num = parseFloat(text);
|
||||||
|
return isNaN(num) ? '-' : num.toFixed(2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fishspeed',
|
||||||
|
title: '鱼速度(m/s)',
|
||||||
|
dataIndex: 'fishspeed',
|
||||||
|
sort: true,
|
||||||
|
width: 80,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const num = parseFloat(text);
|
||||||
|
return isNaN(num) ? '-' : num.toFixed(2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'directionName',
|
||||||
|
title: '鱼游向',
|
||||||
|
dataIndex: 'directionName',
|
||||||
|
sort: true,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'temperature',
|
||||||
|
title: '水温(℃)',
|
||||||
|
dataIndex: 'temperature',
|
||||||
|
sort: true,
|
||||||
|
width: 160,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const num = parseFloat(text);
|
||||||
|
return isNaN(num) ? '-' : num.toFixed(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'speed',
|
||||||
|
title: '流速(m/s)',
|
||||||
|
dataIndex: 'speed',
|
||||||
|
sort: true,
|
||||||
|
width: 160,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const num = parseFloat(text);
|
||||||
|
return isNaN(num) ? '-' : num.toFixed(2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fcnt',
|
||||||
|
title: '过鱼数量(尾)',
|
||||||
|
dataIndex: 'fcnt',
|
||||||
|
sort: true,
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'channelno',
|
||||||
|
title: '过鱼通道',
|
||||||
|
dataIndex: 'channelno',
|
||||||
|
sort: true,
|
||||||
|
width: 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'firstimgurl',
|
||||||
|
title: '轮廓图',
|
||||||
|
dataIndex: 'firstimgurl',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const hasValidUrl =
|
||||||
|
text &&
|
||||||
|
text !== '-' &&
|
||||||
|
text.trim() !== '' &&
|
||||||
|
text !== 'null' &&
|
||||||
|
text !== 'undefined';
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
disabled: !hasValidUrl,
|
||||||
|
style: {
|
||||||
|
color: !hasValidUrl ? '#ccc' : '#1890ff',
|
||||||
|
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if (hasValidUrl) {
|
||||||
|
openImagePreview(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => '查看图片'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'videourl',
|
||||||
|
title: '短视频',
|
||||||
|
dataIndex: 'videourl',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
customRender: ({ text }: any) => {
|
||||||
|
const hasValidUrl =
|
||||||
|
text &&
|
||||||
|
text !== '-' &&
|
||||||
|
text.trim() !== '' &&
|
||||||
|
text !== 'null' &&
|
||||||
|
text !== 'undefined';
|
||||||
|
return h(
|
||||||
|
Button,
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
disabled: !hasValidUrl,
|
||||||
|
style: {
|
||||||
|
color: !hasValidUrl ? '#ccc' : '#1890ff',
|
||||||
|
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if (hasValidUrl) {
|
||||||
|
openVideoPreview(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => '查看视频'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据数据类型动态切换列
|
||||||
|
const tableColumns = computed(() => {
|
||||||
|
const mway = currentSearchParams.value.mway;
|
||||||
|
return mway === '2' ? columnsAuto : columnsManual;
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSearchFinish = async (values: any) => {
|
||||||
|
currentSearchParams.value = values;
|
||||||
|
// 等待 prop 更新后再调用 getList
|
||||||
|
await nextTick();
|
||||||
|
initTable(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onReset = async (values: any) => {
|
||||||
|
currentSearchParams.value = values;
|
||||||
|
await nextTick();
|
||||||
|
initTable(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportBtn = () => {
|
||||||
|
if (exportLoading.value) return;
|
||||||
|
|
||||||
|
exportLoading.value = true;
|
||||||
|
searchRef.value.btnLoading = true;
|
||||||
|
|
||||||
|
tableRef.value
|
||||||
|
.exportTable({
|
||||||
|
fileName: `过鱼监测数据_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
exportLoading.value = false;
|
||||||
|
searchRef.value.btnLoading = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const initTable = (values: any) => {
|
||||||
|
console.log(values);
|
||||||
|
const filters = [
|
||||||
|
values.baseId && values.baseId !== 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.baseId
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.rstcd
|
||||||
|
? {
|
||||||
|
field: 'rstcd',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.rstcd
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
values.mway
|
||||||
|
? {
|
||||||
|
field: 'mway',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.mway
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
].filter(Boolean); // 移除空项
|
||||||
|
if (values.stcd) {
|
||||||
|
filters.push({
|
||||||
|
logic: 'or',
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
field: 'stcd',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.stcd
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'stcode',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: values.stcd
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (values.jcdt) {
|
||||||
|
filters.push(
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'gte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: dayjs(values.jcdt.min).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'lte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: dayjs(values.jcdt.max).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
logic: 'and',
|
||||||
|
filters
|
||||||
|
};
|
||||||
|
tableRef.value.getList(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
tableScrollY.value = calcTableScrollY();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -136,7 +136,6 @@
|
|||||||
@panel-change="handleCalendarPanelChange"
|
@panel-change="handleCalendarPanelChange"
|
||||||
@select="handleCalendarSelect"
|
@select="handleCalendarSelect"
|
||||||
>
|
>
|
||||||
<template #headerRender="{ current }"> </template>
|
|
||||||
<template #dateCellRender="{ current }">
|
<template #dateCellRender="{ current }">
|
||||||
<div class="calendar-content">
|
<div class="calendar-content">
|
||||||
<template v-if="isCurrentMonth(current)">
|
<template v-if="isCurrentMonth(current)">
|
||||||
@ -246,6 +245,7 @@ import { useModelStore } from '@/store/modules/model';
|
|||||||
import videoCover from '@/assets/images/videFm.jpg';
|
import videoCover from '@/assets/images/videFm.jpg';
|
||||||
import MediaViewer from './MediaViewer.vue';
|
import MediaViewer from './MediaViewer.vue';
|
||||||
import AttachmentPreview from './AttachmentPreview.vue';
|
import AttachmentPreview from './AttachmentPreview.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
|
|
||||||
@ -876,7 +876,8 @@ const notRunningMediaViewerRef = ref();
|
|||||||
// 附件预览弹窗
|
// 附件预览弹窗
|
||||||
const attachmentModalVisible = ref(false);
|
const attachmentModalVisible = ref(false);
|
||||||
const currentAttachmentFid = ref('');
|
const currentAttachmentFid = ref('');
|
||||||
|
useDraggable(detailModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(attachmentModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 查看附件
|
// 查看附件
|
||||||
const handleViewAttachment = (record: any) => {
|
const handleViewAttachment = (record: any) => {
|
||||||
if (!record.fid) {
|
if (!record.fid) {
|
||||||
|
|||||||
@ -152,7 +152,7 @@ import { getStcdDetail } from '@/api/mapModal';
|
|||||||
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
const hasLoaded = ref(false); // 标记是否已经请求过
|
const hasLoaded = ref(false); // 标记是否已经请求过
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
url: {
|
url: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -168,6 +168,7 @@ const isLogo = ref(false);
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const data2: any = ref({});
|
const data2: any = ref({});
|
||||||
const tabledata = ref([]);
|
const tabledata = ref([]);
|
||||||
|
useDraggable(visible, { boundary: true, resetOnOpen: true });
|
||||||
const columnsConfig = ref([
|
const columnsConfig = ref([
|
||||||
{
|
{
|
||||||
type: 'ENG',
|
type: 'ENG',
|
||||||
|
|||||||
@ -56,6 +56,7 @@ import { getMonitorDataFpq, getMonitorDataOnline } from '@/api/mapModal';
|
|||||||
import { useModelStore } from '@/store/modules/model';
|
import { useModelStore } from '@/store/modules/model';
|
||||||
import { DateSetting } from '@/utils/enumeration';
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
@ -72,7 +73,8 @@ const previewImageUrl = ref('');
|
|||||||
// 视频预览
|
// 视频预览
|
||||||
const videoPreviewVisible = ref(false);
|
const videoPreviewVisible = ref(false);
|
||||||
const previewVideoUrl = ref('');
|
const previewVideoUrl = ref('');
|
||||||
|
useDraggable(imagePreviewVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(videoPreviewVisible, { boundary: true, resetOnOpen: true });
|
||||||
const openImagePreview = (url: string) => {
|
const openImagePreview = (url: string) => {
|
||||||
previewImageUrl.value = import.meta.env.VITE_APP_ATTACHMENT_URL + '/?' + url;
|
previewImageUrl.value = import.meta.env.VITE_APP_ATTACHMENT_URL + '/?' + url;
|
||||||
imagePreviewVisible.value = true;
|
imagePreviewVisible.value = true;
|
||||||
|
|||||||
@ -102,6 +102,7 @@ import { getDictItemsByCode } from '@/api/dict';
|
|||||||
import { getFishDictoryDropdown } from '@/api/select';
|
import { getFishDictoryDropdown } from '@/api/select';
|
||||||
import { useModelStore } from '@/store/modules/model';
|
import { useModelStore } from '@/store/modules/model';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
@ -125,7 +126,8 @@ const previewImageUrl = ref('');
|
|||||||
// 视频预览
|
// 视频预览
|
||||||
const videoPreviewVisible = ref(false);
|
const videoPreviewVisible = ref(false);
|
||||||
const currentVideoUrl = ref('');
|
const currentVideoUrl = ref('');
|
||||||
|
useDraggable(imagePreviewVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(videoPreviewVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 鱼类搜索过滤
|
// 鱼类搜索过滤
|
||||||
const filterFtpOption = (input: string, option: any) => {
|
const filterFtpOption = (input: string, option: any) => {
|
||||||
console.log('filterOption', input, option);
|
console.log('filterOption', input, option);
|
||||||
|
|||||||
@ -79,6 +79,7 @@ import { queryPostUrlList } from '@/api/mapModal';
|
|||||||
import { useModelStore } from '@/store/modules/model';
|
import { useModelStore } from '@/store/modules/model';
|
||||||
import BasicTable from '@/components/BasicTable/index.vue';
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
import { DateSetting } from '@/utils/enumeration';
|
import { DateSetting } from '@/utils/enumeration';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ let chartInstance: echarts.ECharts | null = null;
|
|||||||
const videoModalVisible = ref(false);
|
const videoModalVisible = ref(false);
|
||||||
const videoModalTitle = ref('');
|
const videoModalTitle = ref('');
|
||||||
const currentVideoUrl = ref('');
|
const currentVideoUrl = ref('');
|
||||||
|
useDraggable(videoModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const tabsList = [{ name: '流量监测', key: 'flowMeasure' }];
|
const tabsList = [{ name: '流量监测', key: 'flowMeasure' }];
|
||||||
const activeTabKey = ref('flowMeasure');
|
const activeTabKey = ref('flowMeasure');
|
||||||
|
|
||||||
|
|||||||
@ -110,6 +110,7 @@ import {
|
|||||||
type OperationFilterField,
|
type OperationFilterField,
|
||||||
type OperationTableItem
|
type OperationTableItem
|
||||||
} from './operationConfig';
|
} from './operationConfig';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
isActive: { type: Boolean, default: false }
|
isActive: { type: Boolean, default: false }
|
||||||
@ -141,6 +142,7 @@ const loadYear = ref(false);
|
|||||||
const loadFtp = ref(false);
|
const loadFtp = ref(false);
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const attachmentModalVisible = ref(false);
|
const attachmentModalVisible = ref(false);
|
||||||
|
useDraggable(attachmentModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const currentAttachmentFid = ref('');
|
const currentAttachmentFid = ref('');
|
||||||
const fieldOptionsMap = reactive<Record<string, OperationFilterOption[]>>({});
|
const fieldOptionsMap = reactive<Record<string, OperationFilterOption[]>>({});
|
||||||
const selectLoadingMap = reactive<Record<string, boolean>>({});
|
const selectLoadingMap = reactive<Record<string, boolean>>({});
|
||||||
|
|||||||
@ -247,7 +247,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch, computed } from 'vue';
|
import { ref, watch, computed, toRef } from 'vue';
|
||||||
// 导入预定义的 Tab 内容组件
|
// 导入预定义的 Tab 内容组件
|
||||||
import BasicInfo from './components/BasicInfo.vue'; // 基本信息
|
import BasicInfo from './components/BasicInfo.vue'; // 基本信息
|
||||||
import VideoInfo from './components/videoInfo.vue'; // 实时视频
|
import VideoInfo from './components/videoInfo.vue'; // 实时视频
|
||||||
@ -300,6 +300,7 @@ import {
|
|||||||
getMonitorDataWaterTempPowerStation2,
|
getMonitorDataWaterTempPowerStation2,
|
||||||
checkPowerStationTopic
|
checkPowerStationTopic
|
||||||
} from '@/api/mapModal';
|
} from '@/api/mapModal';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
// import { useRouter } from 'vue-router';
|
// import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
@ -601,7 +602,6 @@ const setQGCTabList = async (_tabs: any, stcd: string) => {
|
|||||||
};
|
};
|
||||||
const res2 = await getVideoList(params);
|
const res2 = await getVideoList(params);
|
||||||
console.log('', modelStore.params.sttp);
|
console.log('', modelStore.params.sttp);
|
||||||
//
|
|
||||||
if (
|
if (
|
||||||
res2?.data?.data?.length > 0 ||
|
res2?.data?.data?.length > 0 ||
|
||||||
res2?.data?.records?.length > 0 ||
|
res2?.data?.records?.length > 0 ||
|
||||||
@ -645,17 +645,10 @@ const applyTabFilters = async (params: any) => {
|
|||||||
} else if (isLCJ && sttpCode === 'WE') {
|
} else if (isLCJ && sttpCode === 'WE') {
|
||||||
// LCJ 鱼类栖息地数据类型检查
|
// LCJ 鱼类栖息地数据类型检查
|
||||||
await checkFishTab(stcd);
|
await checkFishTab(stcd);
|
||||||
} else if (
|
} else if (sttpCode === 'WQ' || sttpCode === 'WQFB' || sttpCode === 'wq') {
|
||||||
( sttpCode === 'WQ') ||
|
|
||||||
sttpCode === 'WQFB' ||
|
|
||||||
sttpCode === 'wq'
|
|
||||||
) {
|
|
||||||
// 水质 AI 预测检查(React 逻辑:WQ 需要条件,WQFB/wq 无条件)
|
// 水质 AI 预测检查(React 逻辑:WQ 需要条件,WQFB/wq 无条件)
|
||||||
await checkAnalysisAvailability(stcd);
|
await checkAnalysisAvailability(stcd);
|
||||||
} else if (
|
} else if (sttpCode === 'WT' || sttpCode === 'wt') {
|
||||||
( sttpCode === 'WT') ||
|
|
||||||
sttpCode === 'wt'
|
|
||||||
) {
|
|
||||||
// 水温站特殊处理(React 逻辑:WT 需要条件,wt 无条件)
|
// 水温站特殊处理(React 逻辑:WT 需要条件,wt 无条件)
|
||||||
await checkWaterTempConfig(stcd);
|
await checkWaterTempConfig(stcd);
|
||||||
} else if (
|
} else if (
|
||||||
@ -841,6 +834,8 @@ const props = defineProps<{
|
|||||||
data?: any; // 可选:传递给内部组件的数据
|
data?: any; // 可选:传递给内部组件的数据
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
// 启用弹窗拖拽(限制在可视区域内)
|
||||||
|
useDraggable(toRef(props, 'visible'), { boundary: true, resetOnOpen: true });
|
||||||
// 定义 Emits
|
// 定义 Emits
|
||||||
// 添加 'update:activeKey' 以支持 v-model:active-key
|
// 添加 'update:activeKey' 以支持 v-model:active-key
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@ -2,6 +2,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="basic_body">
|
<div class="basic_body">
|
||||||
<div ref="chartContainer" class="chart-container"></div>
|
<div ref="chartContainer" class="chart-container"></div>
|
||||||
|
|
||||||
|
<!-- 水电开发情况弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
title="水电开发情况"
|
||||||
|
width="80%"
|
||||||
|
:footer="null"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
>
|
||||||
|
<ShuiDianKaiFQKTwoLayer
|
||||||
|
v-if="modalVisible"
|
||||||
|
:defaultJidiInfo="modalProps.defaultJidiInfo"
|
||||||
|
:seriesName="modalProps.seriesName"
|
||||||
|
:stateName="modalProps.stateName"
|
||||||
|
:defaultTab="modalProps.defaultTab"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -10,21 +27,31 @@ import { ref, onMounted, onUnmounted, watch } from 'vue';
|
|||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { getVmsstbprptKendoList } from '@/api/home';
|
import { getVmsstbprptKendoList } from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import ShuiDianKaiFQKTwoLayer from '@/modules/shuidianhuangjingjieruMod/TwoLayer/ShuiDianKaiFQKTwoLayer.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'developStatusChart'
|
name: 'developStatusChart'
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'chart-click', params: any): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
const chartContainer = ref<HTMLDivElement | null>(null);
|
const chartContainer = ref<HTMLDivElement | null>(null);
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
let chartInstance: echarts.ECharts | null = null;
|
||||||
const dataLoading = ref(false);
|
const dataLoading = ref(false);
|
||||||
|
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const modalProps = ref<any>({});
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
function openModal(props: any) {
|
||||||
|
modalProps.value = props;
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
openModal,
|
||||||
|
dataLoading
|
||||||
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (chartInstance) {
|
if (chartInstance) {
|
||||||
chartInstance.dispose();
|
chartInstance.dispose();
|
||||||
@ -75,7 +102,6 @@ const getData = async () => {
|
|||||||
|
|
||||||
const res1Data = res1?.data?.data || [];
|
const res1Data = res1?.data?.data || [];
|
||||||
const res2Data = res2?.data?.data || [];
|
const res2Data = res2?.data?.data || [];
|
||||||
// debugger
|
|
||||||
|
|
||||||
if (res1Data.length > 0 || res2Data.length > 0) {
|
if (res1Data.length > 0 || res2Data.length > 0) {
|
||||||
const ttpwrlist = res1Data.map((item: any) => ({
|
const ttpwrlist = res1Data.map((item: any) => ({
|
||||||
@ -234,12 +260,16 @@ const initChart = () => {
|
|||||||
|
|
||||||
chartInstance.setOption(option);
|
chartInstance.setOption(option);
|
||||||
|
|
||||||
// 添加点击事件
|
|
||||||
chartInstance.on('click', (params: any) => {
|
chartInstance.on('click', (params: any) => {
|
||||||
emit('chart-click', {
|
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
||||||
|
openModal({
|
||||||
|
defaultJidiInfo: {
|
||||||
|
baseid: currentJidiInfo?.wbsCode || 'all',
|
||||||
|
basename: currentJidiInfo?.wbsName || '全部基地'
|
||||||
|
},
|
||||||
seriesName: params.seriesName,
|
seriesName: params.seriesName,
|
||||||
name: params.name,
|
stateName: params.name,
|
||||||
dataIndex: params.dataIndex
|
defaultTab: params.name
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
title="环境监测数据接入情况"
|
||||||
|
width="80%"
|
||||||
|
:footer="null"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
>
|
||||||
|
<HuanJingSJJRQK
|
||||||
|
v-if="modalVisible"
|
||||||
|
:dataDimensionVal="modalProps.dataDimensionVal"
|
||||||
|
:name="modalProps.name"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -45,20 +59,30 @@
|
|||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { getVmsstbprptKendoList } from '@/api/home';
|
import { getVmsstbprptKendoList } from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import HuanJingSJJRQK from '@/modules/shuidianhuangjingjieruMod/TwoLayer/HuanJingSJJRQK.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'EngEnvironmentData'
|
name: 'EngEnvironmentData'
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'item-click', params: any): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
const dataLoading = ref(false);
|
const dataLoading = ref(false);
|
||||||
const data = ref<Record<string, number>>({ one: 0, two: 0, three: 0 });
|
const data = ref<Record<string, number>>({ one: 0, two: 0, three: 0 });
|
||||||
|
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const modalProps = ref<any>({});
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
function openModal(props: any) {
|
||||||
|
modalProps.value = props;
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
openModal,
|
||||||
|
dataLoading
|
||||||
|
});
|
||||||
|
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
if (!baseid.value) return;
|
if (!baseid.value) return;
|
||||||
|
|
||||||
@ -77,7 +101,8 @@ const getData = async () => {
|
|||||||
...baseFilters,
|
...baseFilters,
|
||||||
{ field: 'prsc', operator: 'in', dataType: 'string', value: ['1', '2', '3'] }
|
{ field: 'prsc', operator: 'in', dataType: 'string', value: ['1', '2', '3'] }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
group: [{ dir: 'desc', field: 'sttpCode' }]
|
||||||
};
|
};
|
||||||
|
|
||||||
const params2 = {
|
const params2 = {
|
||||||
@ -88,7 +113,8 @@ const getData = async () => {
|
|||||||
{ field: 'runState', operator: 'eq', dataType: 'number', value: 4 },
|
{ field: 'runState', operator: 'eq', dataType: 'number', value: 4 },
|
||||||
{ field: 'dtin', operator: 'eq', dataType: 'number', value: 1 }
|
{ field: 'dtin', operator: 'eq', dataType: 'number', value: 1 }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
group: [{ dir: 'desc', field: 'sttpCode' }]
|
||||||
};
|
};
|
||||||
|
|
||||||
const params3 = {
|
const params3 = {
|
||||||
@ -99,7 +125,8 @@ const getData = async () => {
|
|||||||
{ field: 'prsc', operator: 'in', dataType: 'string', value: ['1', '2', '3'] },
|
{ field: 'prsc', operator: 'in', dataType: 'string', value: ['1', '2', '3'] },
|
||||||
{ field: 'dtinEnv', operator: 'in', dataType: 'string', value: ['2'] }
|
{ field: 'dtinEnv', operator: 'in', dataType: 'string', value: ['2'] }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
group: [{ dir: 'desc', field: 'dtinEnv' }]
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -113,21 +140,22 @@ const getData = async () => {
|
|||||||
const record = { one: 0, two: 0, three: 0 };
|
const record = { one: 0, two: 0, three: 0 };
|
||||||
const responses = [res1, res2, res3];
|
const responses = [res1, res2, res3];
|
||||||
responses.forEach((res, index) => {
|
responses.forEach((res, index) => {
|
||||||
const total = res?.data?.total ?? 0;
|
if (res?.data?.data && Array.isArray(res.data.data) && res.data.data.length > 0) {
|
||||||
|
const count = res.data.data[0].count ?? 0;
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
record.one = total;
|
record.one = count;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
record.two = total;
|
record.two = count;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
record.three = total;
|
record.three = count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
data.value = record;
|
data.value = record;
|
||||||
// debugger
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('EngEnvironmentData getData error:', error);
|
console.error('EngEnvironmentData getData error:', error);
|
||||||
} finally {
|
} finally {
|
||||||
@ -136,7 +164,11 @@ const getData = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleItemClick = (name: string) => {
|
const handleItemClick = (name: string) => {
|
||||||
emit('item-click', { name });
|
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
||||||
|
openModal({
|
||||||
|
dataDimensionVal: currentJidiInfo?.wbsCode || 'all',
|
||||||
|
name
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@ -128,7 +128,6 @@ watch(
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init();
|
init();
|
||||||
// @ts-ignore
|
|
||||||
window.mapClass = mapClass;
|
window.mapClass = mapClass;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import Stroke from 'ol/style/Stroke';
|
|||||||
import Icon from 'ol/style/Icon';
|
import Icon from 'ol/style/Icon';
|
||||||
import Text from 'ol/style/Text';
|
import Text from 'ol/style/Text';
|
||||||
import Circle from 'ol/style/Circle';
|
import Circle from 'ol/style/Circle';
|
||||||
import RegularShape from 'ol/style/RegularShape';
|
|
||||||
import Cluster from 'ol/source/Cluster';
|
|
||||||
import WMTS from 'ol/source/WMTS';
|
import WMTS from 'ol/source/WMTS';
|
||||||
import WMTSTileGrid from 'ol/tilegrid/WMTS';
|
import WMTSTileGrid from 'ol/tilegrid/WMTS';
|
||||||
import { get as getProjection, fromLonLat } from 'ol/proj';
|
import { get as getProjection, fromLonLat } from 'ol/proj';
|
||||||
@ -75,6 +73,7 @@ export class MapOl implements MapInterface {
|
|||||||
geoJsonData1: any = null;
|
geoJsonData1: any = null;
|
||||||
private BASEID = '';
|
private BASEID = '';
|
||||||
private currentClipGeoJson: any | null = null;
|
private currentClipGeoJson: any | null = null;
|
||||||
|
private clipRequestController: AbortController | null = null;
|
||||||
private hoveredFeatureId: string | number | null = null;
|
private hoveredFeatureId: string | number | null = null;
|
||||||
private popupManager: PopupManager;
|
private popupManager: PopupManager;
|
||||||
private regionMaskManager: RegionMaskManager;
|
private regionMaskManager: RegionMaskManager;
|
||||||
@ -98,15 +97,20 @@ export class MapOl implements MapInterface {
|
|||||||
defaultZoom: INITIAL_ZOOM
|
defaultZoom: INITIAL_ZOOM
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private async loadGeoJsonData(url): Promise<any> {
|
private async loadGeoJsonData(url, signal?: AbortSignal): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url, { signal });
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
|
if (error.name !== 'AbortError') {
|
||||||
console.error('配置加载失败:', error);
|
console.error('配置加载失败:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//地图初始化
|
//地图初始化
|
||||||
init(container: HTMLElement): Promise<any> {
|
init(container: HTMLElement): Promise<any> {
|
||||||
try {
|
try {
|
||||||
@ -222,6 +226,11 @@ export class MapOl implements MapInterface {
|
|||||||
_mdoptions?: MDOptions
|
_mdoptions?: MDOptions
|
||||||
): void {
|
): void {
|
||||||
this.pointLayerManager.addDataLayer(pointData, layerType);
|
this.pointLayerManager.addDataLayer(pointData, layerType);
|
||||||
|
|
||||||
|
if (this.currentClipGeoJson) {
|
||||||
|
this.regionMaskManager.filterPointsByRegion(this.currentClipGeoJson);
|
||||||
|
}
|
||||||
|
|
||||||
const currentZoom = this.view ? this.view.getZoom() : INITIAL_ZOOM;
|
const currentZoom = this.view ? this.view.getZoom() : INITIAL_ZOOM;
|
||||||
this.pointLayerManager.updateNearbyFeatureLayout(currentZoom);
|
this.pointLayerManager.updateNearbyFeatureLayout(currentZoom);
|
||||||
this.requestRefreshPointLabelVisibility(true);
|
this.requestRefreshPointLabelVisibility(true);
|
||||||
@ -1124,11 +1133,7 @@ export class MapOl implements MapInterface {
|
|||||||
* 初始化加载基础图层
|
* 初始化加载基础图层
|
||||||
* @param layer 图层配置对象
|
* @param layer 图层配置对象
|
||||||
*/
|
*/
|
||||||
addBaseDataLayer(
|
addBaseDataLayer(layer: any, isShow: boolean, isCache = false): void {
|
||||||
layer: any,
|
|
||||||
isShow: boolean,
|
|
||||||
isCache: boolean = false
|
|
||||||
): void {
|
|
||||||
if (!this.map) return;
|
if (!this.map) return;
|
||||||
|
|
||||||
// 备注:同 key 的底图重复添加前先移除旧实例,避免注册表覆盖后旧图层仍残留在地图上。
|
// 备注:同 key 的底图重复添加前先移除旧实例,避免注册表覆盖后旧图层仍残留在地图上。
|
||||||
@ -1142,7 +1147,7 @@ export class MapOl implements MapInterface {
|
|||||||
|
|
||||||
if (layer.type === 'wmts') {
|
if (layer.type === 'wmts') {
|
||||||
if (!layer.url) return;
|
if (!layer.url) return;
|
||||||
let url = !isCache ? layer.url : layer.url_3d;
|
const url = !isCache ? layer.url : layer.url_3d;
|
||||||
const urlParams = new URLSearchParams(url.split('?')[1]);
|
const urlParams = new URLSearchParams(url.split('?')[1]);
|
||||||
if (layer.key === this.REGISTRY_KEY) {
|
if (layer.key === this.REGISTRY_KEY) {
|
||||||
this.baseLayerConfig = layer;
|
this.baseLayerConfig = layer;
|
||||||
@ -1311,6 +1316,11 @@ export class MapOl implements MapInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.clipRequestController) {
|
||||||
|
this.clipRequestController.abort();
|
||||||
|
this.clipRequestController = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.BASEID = _regionId;
|
this.BASEID = _regionId;
|
||||||
|
|
||||||
if (!isAll) {
|
if (!isAll) {
|
||||||
@ -1327,21 +1337,40 @@ export class MapOl implements MapInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.regionMaskManager.hideAllPoints();
|
this.regionMaskManager.hideAllPoints();
|
||||||
|
this.clipRequestController = new AbortController();
|
||||||
|
const signal = this.clipRequestController.signal;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url =
|
const url =
|
||||||
this.hydropBaseConfig.geojson_url +
|
this.hydropBaseConfig.geojson_url +
|
||||||
`&cql_filter=BASEID='${this.BASEID}'`;
|
`&cql_filter=BASEID='${this.BASEID}'`;
|
||||||
|
|
||||||
const geoJsonData = await this.loadGeoJsonData(url);
|
const geoJsonData = await this.loadGeoJsonData(url, signal);
|
||||||
|
|
||||||
|
if (signal.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.BASEID !== _regionId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.currentClipGeoJson = geoJsonData;
|
this.currentClipGeoJson = geoJsonData;
|
||||||
this.regionMaskManager.filterPointsByRegion(geoJsonData);
|
this.regionMaskManager.filterPointsByRegion(geoJsonData);
|
||||||
this.regionMaskManager.fitViewToGeoJson(geoJsonData);
|
this.regionMaskManager.fitViewToGeoJson(geoJsonData);
|
||||||
this.regionMaskManager.applyMapMaskToLayers(baseLayers, geoJsonData);
|
this.regionMaskManager.applyMapMaskToLayers(baseLayers, geoJsonData);
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
|
if (error.name === 'AbortError') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.currentClipGeoJson = null;
|
this.currentClipGeoJson = null;
|
||||||
console.error('加载裁切数据失败:', error);
|
console.error('加载裁切数据失败:', error);
|
||||||
this.regionMaskManager.clearMapMask();
|
this.regionMaskManager.clearMapMask();
|
||||||
this.regionMaskManager.showAllPoints();
|
this.regionMaskManager.showAllPoints();
|
||||||
|
} finally {
|
||||||
|
if (this.clipRequestController?.signal === signal) {
|
||||||
|
this.clipRequestController = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -400,6 +400,7 @@ export class PointLayerManager {
|
|||||||
);
|
);
|
||||||
feature.set('_baseCoordinates', coord);
|
feature.set('_baseCoordinates', coord);
|
||||||
feature.set('_legendVisible', true);
|
feature.set('_legendVisible', true);
|
||||||
|
feature.set('_regionVisible', true);
|
||||||
feature.set('_sttpMap', item.sttpMap);
|
feature.set('_sttpMap', item.sttpMap);
|
||||||
if (item.popupHtml) {
|
if (item.popupHtml) {
|
||||||
feature.set('popupHtml', item.popupHtml);
|
feature.set('popupHtml', item.popupHtml);
|
||||||
|
|||||||
@ -56,7 +56,6 @@ const layerConfigs = computed(() => {
|
|||||||
|
|
||||||
return convertCheckedToBoolean(mapConfigStore.layerConfigTree);
|
return convertCheckedToBoolean(mapConfigStore.layerConfigTree);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 备注:选中图层完全以运行态 store 为唯一来源,组件不再维护额外同步状态。
|
// 备注:选中图层完全以运行态 store 为唯一来源,组件不再维护额外同步状态。
|
||||||
const checkedKeys = computed(() => mapViewStore.checkedLayerKeys || []);
|
const checkedKeys = computed(() => mapViewStore.checkedLayerKeys || []);
|
||||||
const tooltipVisible = ref(false);
|
const tooltipVisible = ref(false);
|
||||||
|
|||||||
@ -26,11 +26,9 @@
|
|||||||
<a-form-item label="" name="siteRangePicker">
|
<a-form-item label="" name="siteRangePicker">
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
v-model:value="searchTimeRange"
|
v-model:value="searchTimeRange"
|
||||||
picker="date"
|
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
:allow-clear="false"
|
:allow-clear="false"
|
||||||
show-time
|
|
||||||
:presets="DateSetting.RangeButton.days1"
|
:presets="DateSetting.RangeButton.days1"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="triggerManualValuesChange"
|
@change="triggerManualValuesChange"
|
||||||
|
|||||||
@ -87,6 +87,7 @@ const hasEnvFac = computed(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const legendItemClick = (item: any) => {
|
const legendItemClick = (item: any) => {
|
||||||
|
console.log(item);
|
||||||
if (item.parentName == '环保设施') return;
|
if (item.parentName == '环保设施') return;
|
||||||
if (item.canBeChecked == 0) {
|
if (item.canBeChecked == 0) {
|
||||||
return;
|
return;
|
||||||
@ -121,6 +122,7 @@ const toggleGroup = (group: any) => {
|
|||||||
if (leafItems.length === 0) return;
|
if (leafItems.length === 0) return;
|
||||||
|
|
||||||
const hasAnyChecked = leafItems.some((item: any) => item.checked === 1);
|
const hasAnyChecked = leafItems.some((item: any) => item.checked === 1);
|
||||||
|
|
||||||
const targetChecked = hasAnyChecked ? 0 : 1;
|
const targetChecked = hasAnyChecked ? 0 : 1;
|
||||||
const targetNameEns = leafItems
|
const targetNameEns = leafItems
|
||||||
.filter(
|
.filter(
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import Antd from 'ant-design-vue';
|
|||||||
import 'ant-design-vue/dist/reset.css'; // Ant Design 全局样式重置
|
import 'ant-design-vue/dist/reset.css'; // Ant Design 全局样式重置
|
||||||
import dayjs from 'dayjs'; // ant 中文语言
|
import dayjs from 'dayjs'; // ant 中文语言
|
||||||
import 'dayjs/locale/zh-cn';
|
import 'dayjs/locale/zh-cn';
|
||||||
// @ts-ignore
|
|
||||||
import 'virtual:svg-icons-register';
|
import 'virtual:svg-icons-register';
|
||||||
// 3d地图
|
// 3d地图
|
||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
|||||||
@ -63,6 +63,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { vpcGetKendoListCust } from '@/api/zxdzw';
|
import { vpcGetKendoListCust } from '@/api/zxdzw';
|
||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -83,7 +84,7 @@ const baseid = ref('');
|
|||||||
// 弹框控制
|
// 弹框控制
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentItem = ref<any>(null);
|
const currentItem = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
|||||||
@ -109,6 +109,7 @@ import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'
|
|||||||
import BasicTable from '@/components/BasicTable/index.vue'
|
import BasicTable from '@/components/BasicTable/index.vue'
|
||||||
import { wqGetKendoList } from '@/api/sz'
|
import { wqGetKendoList } from '@/api/sz'
|
||||||
import HJMZDTwoLays from "./HJMZDTwoLays.vue"
|
import HJMZDTwoLays from "./HJMZDTwoLays.vue"
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 注册 dayjs 插件
|
// 注册 dayjs 插件
|
||||||
dayjs.extend(isSameOrAfter)
|
dayjs.extend(isSameOrAfter)
|
||||||
@ -155,7 +156,7 @@ const detailModalVisible = ref(false)
|
|||||||
const detailData = ref<any>({})
|
const detailData = ref<any>({})
|
||||||
const mapModalVisible = ref(false)
|
const mapModalVisible = ref(false)
|
||||||
const mapModalData = ref<any>({})
|
const mapModalData = ref<any>({})
|
||||||
|
useDraggable(detailModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 排序配置
|
// 排序配置
|
||||||
const sortConfig = computed(() => [
|
const sortConfig = computed(() => [
|
||||||
{ field: 'rstcdStepSort', dir: 'asc' },
|
{ field: 'rstcdStepSort', dir: 'asc' },
|
||||||
|
|||||||
@ -36,6 +36,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { wqGetKendoListCust } from '@/api/sz'
|
import { wqGetKendoListCust } from '@/api/sz'
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
import EnvironmentalQualityTwoLayers from "./TwoLayers/EnvironmentalQualityTwoLayers.vue"
|
import EnvironmentalQualityTwoLayers from "./TwoLayers/EnvironmentalQualityTwoLayers.vue"
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'EnvironmentalQuality'
|
name: 'EnvironmentalQuality'
|
||||||
@ -774,7 +776,7 @@ onUnmounted(() => {
|
|||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const clickedBarData = ref<{ name: string; current: number | null; lastYear: number | null; selectedId?: string } | null>(null);
|
const clickedBarData = ref<{ name: string; current: number | null; lastYear: number | null; selectedId?: string } | null>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<SidePanelItem :title="title" :datetimePicker="datetimePicker" @update-values="handlePanelChange1">
|
<SidePanelItem
|
||||||
|
:title="title"
|
||||||
|
:datetimePicker="datetimePicker"
|
||||||
|
@update-values="handlePanelChange1"
|
||||||
|
>
|
||||||
<!-- 加载状态 -->
|
<!-- 加载状态 -->
|
||||||
<div v-if="loading" class="loading-container">
|
<div v-if="loading" class="loading-container">
|
||||||
<a-spin tip="加载中..." />
|
<a-spin tip="加载中..." />
|
||||||
@ -12,12 +16,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 正常显示图表 -->
|
<!-- 正常显示图表 -->
|
||||||
<div v-else class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
|
<div
|
||||||
|
v-else
|
||||||
|
class="container"
|
||||||
|
@mouseenter="handleMouseEnter"
|
||||||
|
@mouseleave="handleMouseLeave"
|
||||||
|
>
|
||||||
<!-- 跑马灯轨道容器 -->
|
<!-- 跑马灯轨道容器 -->
|
||||||
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
|
<div
|
||||||
:style="{ transform: `translateX(-${currentIndex * 100}%)` }">
|
class="carousel-track"
|
||||||
|
:class="{ 'no-transition': isTransitioning }"
|
||||||
|
:style="{ transform: `translateX(-${currentIndex * 100}%)` }"
|
||||||
|
>
|
||||||
<!-- 遍历所有图表项(包含克隆项) -->
|
<!-- 遍历所有图表项(包含克隆项) -->
|
||||||
<div v-for="(item, index) in renderChartData" :key="index" class="carousel-item">
|
<div
|
||||||
|
v-for="(item, index) in renderChartData"
|
||||||
|
:key="index"
|
||||||
|
class="carousel-item"
|
||||||
|
>
|
||||||
<div class="pie-chart-container">
|
<div class="pie-chart-container">
|
||||||
<!-- 图表区域 -->
|
<!-- 图表区域 -->
|
||||||
<div :ref="el => setChartRef(el, index)" class="chart"></div>
|
<div :ref="el => setChartRef(el, index)" class="chart"></div>
|
||||||
@ -31,45 +47,12 @@
|
|||||||
<!-- 详情弹框 -->
|
<!-- 详情弹框 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
:title="modalTitle"
|
:title="'过鱼监测数据'"
|
||||||
width="1650px"
|
width="1650px"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@cancel="handleModalClose"
|
@cancel="handleModalClose"
|
||||||
>
|
>
|
||||||
<div class="modal-content">
|
<FishResource v-if="modalVisible" :modalData = "modalData" />
|
||||||
<a-descriptions bordered :column="2" size="small">
|
|
||||||
<a-descriptions-item label="年份">
|
|
||||||
{{ modalData.year }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="流域/设施">
|
|
||||||
{{ modalData.basinName }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="鱼类总数">
|
|
||||||
<span style="color: #1890ff; font-weight: bold;">
|
|
||||||
{{ modalData.totalCount }} {{ getUnit() }}
|
|
||||||
</span>
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="">
|
|
||||||
{{ modalData.baseid }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
|
|
||||||
<a-divider orientation="left">鱼类分布详情</a-divider>
|
|
||||||
|
|
||||||
<a-table
|
|
||||||
:columns="fishColumns"
|
|
||||||
:data-source="modalData.fishList"
|
|
||||||
:pagination="false"
|
|
||||||
size="small"
|
|
||||||
:scroll="{ y: 300 }"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'percentage'">
|
|
||||||
{{ record.percentage }}%
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</template>
|
</template>
|
||||||
@ -80,8 +63,10 @@ import * as echarts from 'echarts';
|
|||||||
import type { ECharts } from 'echarts';
|
import type { ECharts } from 'echarts';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { yearGetYearFpStatistics } from '@/api/gyss';
|
import { yearGetYearFpStatistics } from '@/api/gyss';
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import type { ColumnsType } from 'ant-design-vue/es/table/Table';
|
import type { ColumnsType } from 'ant-design-vue/es/table/Table';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
import FishResource from '@/components/FishResource/index.vue';
|
||||||
|
|
||||||
// API 数据类型定义
|
// API 数据类型定义
|
||||||
interface FpFtpStatisticsVo {
|
interface FpFtpStatisticsVo {
|
||||||
@ -108,10 +93,11 @@ const JidiSelectEventStore = useJidiSelectEventStore();
|
|||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: { // 标题
|
title: {
|
||||||
|
// 标题
|
||||||
type: String,
|
type: String,
|
||||||
default: '过鱼总量'
|
default: '过鱼总量'
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const datetimePicker = ref({
|
const datetimePicker = ref({
|
||||||
@ -134,7 +120,7 @@ const currentYear = ref<string>(''); // 当前选中的年份
|
|||||||
interface ChartDataItem {
|
interface ChartDataItem {
|
||||||
title: string;
|
title: string;
|
||||||
baseid?: string; // 流域ID(用于标识该图表所属的流域)
|
baseid?: string; // 流域ID(用于标识该图表所属的流域)
|
||||||
data: Array<{ name: string; value: number; baseId?: string }>; // 扩展数据项,支持存储流域ID
|
data: Array<{ name: string; value: number; baseId?: string; ftp?: string }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 原始图表数据(多组数据用于跑马灯)
|
// 原始图表数据(多组数据用于跑马灯)
|
||||||
@ -151,13 +137,16 @@ let timer: any = null;
|
|||||||
|
|
||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const modalTitle = ref('');
|
const modalTitle = ref('');
|
||||||
const modalData = ref<{
|
const modalData = ref<{
|
||||||
year: string;
|
year: string;
|
||||||
basinName: string;
|
basinName: string;
|
||||||
baseid?: string; // 添加流域ID
|
baseid?: string;
|
||||||
totalCount: number;
|
totalCount: number;
|
||||||
fishTypes: number;
|
fishTypes: number;
|
||||||
|
fishName?: string;
|
||||||
|
ftp?: string;
|
||||||
fishList: Array<{
|
fishList: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
@ -169,6 +158,8 @@ const modalData = ref<{
|
|||||||
baseid: '',
|
baseid: '',
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
fishTypes: 0,
|
fishTypes: 0,
|
||||||
|
fishName: '',
|
||||||
|
ftp: '',
|
||||||
fishList: []
|
fishList: []
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -351,12 +342,12 @@ const updateChart = (index: number) => {
|
|||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
color: '#333',
|
color: '#333'
|
||||||
},
|
},
|
||||||
subtextStyle: {
|
subtextStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: '#999',
|
color: '#999',
|
||||||
align: 'center',
|
align: 'center'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -377,7 +368,8 @@ const updateChart = (index: number) => {
|
|||||||
const found = chartData.data.find(item => item.name === name);
|
const found = chartData.data.find(item => item.name === name);
|
||||||
const value = found ? found.value : '-';
|
const value = found ? found.value : '-';
|
||||||
const maxLength = 7;
|
const maxLength = 7;
|
||||||
const truncatedName = name.length > maxLength ? name.substring(0, maxLength) + '...' : name;
|
const truncatedName =
|
||||||
|
name.length > maxLength ? name.substring(0, maxLength) + '...' : name;
|
||||||
return `${truncatedName} ${value}${unit}`;
|
return `${truncatedName} ${value}${unit}`;
|
||||||
},
|
},
|
||||||
textStyle: {
|
textStyle: {
|
||||||
@ -538,13 +530,17 @@ onUnmounted(() => {
|
|||||||
/**
|
/**
|
||||||
* 构建单一流域的图表数据
|
* 构建单一流域的图表数据
|
||||||
*/
|
*/
|
||||||
const buildSingleBasinChartData = (basin: BasinData, year: string): ChartDataItem => {
|
const buildSingleBasinChartData = (
|
||||||
|
basin: BasinData,
|
||||||
|
year: string
|
||||||
|
): ChartDataItem => {
|
||||||
return {
|
return {
|
||||||
title: `${basin.baseName}`,
|
title: `${basin.baseName}`,
|
||||||
baseid: basin.baseId, // 保存流域ID
|
baseid: basin.baseId, // 保存流域ID
|
||||||
data: basin.fpFtpStatitcsVos.map((fish: FpFtpStatisticsVo) => ({
|
data: basin.fpFtpStatitcsVos.map((fish: FpFtpStatisticsVo) => ({
|
||||||
name: fish.fishName,
|
name: fish.fishName,
|
||||||
value: fish.fcnt
|
value: fish.fcnt,
|
||||||
|
ftp: fish.ftp
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -552,12 +548,17 @@ const buildSingleBasinChartData = (basin: BasinData, year: string): ChartDataIte
|
|||||||
/**
|
/**
|
||||||
* 构建全部流域的图表数据(包含流域对比图和各流域鱼类分布图)
|
* 构建全部流域的图表数据(包含流域对比图和各流域鱼类分布图)
|
||||||
*/
|
*/
|
||||||
const buildAllBasinsChartData = (apiData: BasinData[], year: string): ChartDataItem[] => {
|
const buildAllBasinsChartData = (
|
||||||
|
apiData: BasinData[],
|
||||||
|
year: string
|
||||||
|
): ChartDataItem[] => {
|
||||||
const charts: ChartDataItem[] = [];
|
const charts: ChartDataItem[] = [];
|
||||||
|
|
||||||
// 1️⃣ 第一张:各流域总量对比图(使用 fpCount)
|
// 1️⃣ 第一张:各流域总量对比图(使用 fpCount)
|
||||||
const basinComparisonData = apiData
|
const basinComparisonData = apiData
|
||||||
.filter(basin => basin.fpFtpStatitcsVos && basin.fpFtpStatitcsVos.length > 0)
|
.filter(
|
||||||
|
basin => basin.fpFtpStatitcsVos && basin.fpFtpStatitcsVos.length > 0
|
||||||
|
)
|
||||||
.map(basin => ({
|
.map(basin => ({
|
||||||
name: basin.baseName,
|
name: basin.baseName,
|
||||||
value: basin.fpCount,
|
value: basin.fpCount,
|
||||||
@ -613,7 +614,8 @@ const rebuildCharts = async () => {
|
|||||||
*/
|
*/
|
||||||
const controlCarousel = () => {
|
const controlCarousel = () => {
|
||||||
// 判断是否需要停止跑马灯
|
// 判断是否需要停止跑马灯
|
||||||
const shouldStop = baseid.value !== 'all' || originalChartData.value.length <= 1;
|
const shouldStop =
|
||||||
|
baseid.value !== 'all' || originalChartData.value.length <= 1;
|
||||||
|
|
||||||
if (shouldStop) {
|
if (shouldStop) {
|
||||||
stopAutoPlay(); // 停止轮播,但不重置 currentIndex
|
stopAutoPlay(); // 停止轮播,但不重置 currentIndex
|
||||||
@ -636,12 +638,21 @@ const updateChartByBaseid = () => {
|
|||||||
|
|
||||||
if (baseid.value === 'all') {
|
if (baseid.value === 'all') {
|
||||||
// === 全部流域模式 ===
|
// === 全部流域模式 ===
|
||||||
originalChartData.value = buildAllBasinsChartData(cachedApiData.value, currentYear.value);
|
originalChartData.value = buildAllBasinsChartData(
|
||||||
|
cachedApiData.value,
|
||||||
|
currentYear.value
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// === 单一流域模式 ===
|
// === 单一流域模式 ===
|
||||||
const targetBasin = cachedApiData.value.find(item => item.baseId === baseid.value);
|
const targetBasin = cachedApiData.value.find(
|
||||||
|
item => item.baseId === baseid.value
|
||||||
|
);
|
||||||
|
|
||||||
if (!targetBasin || !targetBasin.fpFtpStatitcsVos || targetBasin.fpFtpStatitcsVos.length === 0) {
|
if (
|
||||||
|
!targetBasin ||
|
||||||
|
!targetBasin.fpFtpStatitcsVos ||
|
||||||
|
targetBasin.fpFtpStatitcsVos.length === 0
|
||||||
|
) {
|
||||||
hasData.value = false;
|
hasData.value = false;
|
||||||
originalChartData.value = [];
|
originalChartData.value = [];
|
||||||
renderChartData.value = []; // 清空渲染数据
|
renderChartData.value = []; // 清空渲染数据
|
||||||
@ -649,7 +660,9 @@ const updateChartByBaseid = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
originalChartData.value = [buildSingleBasinChartData(targetBasin, currentYear.value)];
|
originalChartData.value = [
|
||||||
|
buildSingleBasinChartData(targetBasin, currentYear.value)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先构建渲染数据
|
// 先构建渲染数据
|
||||||
@ -720,7 +733,6 @@ const getechartsdata = async (yearOne: string) => {
|
|||||||
currentYear.value = yearOne;
|
currentYear.value = yearOne;
|
||||||
// 根据 baseid 更新显示
|
// 根据 baseid 更新显示
|
||||||
updateChartByBaseid();
|
updateChartByBaseid();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取过鱼统计数据失败:', error);
|
console.error('获取过鱼统计数据失败:', error);
|
||||||
hasData.value = false;
|
hasData.value = false;
|
||||||
@ -755,40 +767,43 @@ const handlePanelChange1 = (data: any) => {
|
|||||||
* @param params ECharts 点击事件参数(可选)
|
* @param params ECharts 点击事件参数(可选)
|
||||||
*/
|
*/
|
||||||
const handleChartClick = (item: ChartDataItem, index: number, params?: any) => {
|
const handleChartClick = (item: ChartDataItem, index: number, params?: any) => {
|
||||||
// 计算总数量和百分比
|
|
||||||
const totalCount = getTotalAmount(item.data);
|
const totalCount = getTotalAmount(item.data);
|
||||||
const fishList = item.data.map(fish => ({
|
const fishList = item.data.map(fish => ({
|
||||||
name: fish.name,
|
name: fish.name,
|
||||||
value: fish.value,
|
value: fish.value,
|
||||||
percentage: totalCount > 0 ? ((fish.value / totalCount) * 100).toFixed(2) : '0.00'
|
percentage:
|
||||||
|
totalCount > 0 ? ((fish.value / totalCount) * 100).toFixed(2) : '0.00'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 确定流域ID
|
|
||||||
let clickedBaseId: string | undefined;
|
let clickedBaseId: string | undefined;
|
||||||
|
let fishName = '';
|
||||||
|
let ftp = '';
|
||||||
|
|
||||||
if (params && params.data && params.data.baseId) {
|
if (params && params.data && params.data.baseId) {
|
||||||
// 情况1:总量对比图,点击了某个流域的数据项
|
|
||||||
clickedBaseId = params.data.baseId;
|
clickedBaseId = params.data.baseId;
|
||||||
} else if (item.baseid && item.baseid !== 'all') {
|
} else if (item.baseid && item.baseid !== 'all') {
|
||||||
// 情况2:单一流域图,使用图表整体的 baseid
|
|
||||||
clickedBaseId = item.baseid;
|
clickedBaseId = item.baseid;
|
||||||
} else {
|
} else {
|
||||||
// 情况3:总量图表但未获取到具体数据项的 baseId(理论上不应该发生)
|
|
||||||
clickedBaseId = item.baseid;
|
clickedBaseId = item.baseid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置弹框数据
|
if (item.baseid !== 'all' && params && params.data) {
|
||||||
|
fishName = params.data.name || '';
|
||||||
|
ftp = params.data.ftp || '';
|
||||||
|
}
|
||||||
|
|
||||||
modalTitle.value = `${item.title} - 详情`;
|
modalTitle.value = `${item.title} - 详情`;
|
||||||
modalData.value = {
|
modalData.value = {
|
||||||
year: currentYear.value || '-',
|
year: currentYear.value || '-',
|
||||||
basinName: params?.name || item.title, // 优先使用被点击的数据项名称
|
basinName: params?.name || item.title,
|
||||||
baseid: clickedBaseId, // 保存正确的流域ID
|
baseid: clickedBaseId,
|
||||||
totalCount: totalCount,
|
totalCount: totalCount,
|
||||||
fishTypes: item.data.length,
|
fishTypes: item.data.length,
|
||||||
|
fishName,
|
||||||
|
ftp,
|
||||||
fishList: fishList
|
fishList: fishList
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开弹框
|
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -801,7 +816,7 @@ const handleModalClose = () => {
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => JidiSelectEventStore.selectedItem,
|
() => JidiSelectEventStore.selectedItem,
|
||||||
(newVal) => {
|
newVal => {
|
||||||
if (newVal && newVal.wbsCode) {
|
if (newVal && newVal.wbsCode) {
|
||||||
baseid.value = newVal.wbsCode;
|
baseid.value = newVal.wbsCode;
|
||||||
|
|
||||||
@ -813,7 +828,6 @@ watch(
|
|||||||
},
|
},
|
||||||
{ deep: true, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { vpcGetKendoListCust } from '@/api/zxdzw';
|
import { vpcGetKendoListCust } from '@/api/zxdzw';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import ZhiWuYuanDetailTable from './ZhiWuYuanDetailTable.vue';
|
import ZhiWuYuanDetailTable from './ZhiWuYuanDetailTable.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -50,7 +51,7 @@ const loading = ref(false);
|
|||||||
// 弹窗状态
|
// 弹窗状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const modalJidi = ref('all');
|
const modalJidi = ref('all');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 基地选项(用于弹窗中的下拉)
|
// 基地选项(用于弹窗中的下拉)
|
||||||
const jidiOptions = ref<any[]>([]);
|
const jidiOptions = ref<any[]>([]);
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,7 @@ import Yanchengyulei from './TwoLayers/Yanchengyulei.vue';
|
|||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { wbsbGetKendoList, getDftYear, fishChanges2 } from '@/api/stdc';
|
import { wbsbGetKendoList, getDftYear, fishChanges2 } from '@/api/stdc';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'alongFishMod'
|
name: 'alongFishMod'
|
||||||
@ -108,7 +109,7 @@ const modalHbrvcd = ref('');
|
|||||||
const modalStateName = ref('');
|
const modalStateName = ref('');
|
||||||
const modalSectionName = ref('');
|
const modalSectionName = ref('');
|
||||||
const modalStcd = ref('');
|
const modalStcd = ref('');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// ==================== 图表相关 ====================
|
// ==================== 图表相关 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -53,6 +53,8 @@ import { getVmsstbprpt, inOutOneGetKendoListCust } from '@/api/sw';
|
|||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import churukushuiwen from './churukushuiwen.vue';
|
import churukushuiwen from './churukushuiwen.vue';
|
||||||
import { MapClass } from '@/components/gis/map.class';
|
import { MapClass } from '@/components/gis/map.class';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// ==================== 组件基础配置 ====================
|
// ==================== 组件基础配置 ====================
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -96,7 +98,7 @@ const modalVisible = ref(false); // 弹框显示状态
|
|||||||
const clickDataInfo = ref<any>(null); // 点击的数据点信息
|
const clickDataInfo = ref<any>(null); // 点击的数据点信息
|
||||||
const stationName = ref(''); // 站点名称
|
const stationName = ref(''); // 站点名称
|
||||||
// ==================== 数据处理函数 ====================
|
// ==================== 数据处理函数 ====================
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
/**
|
/**
|
||||||
* 转换图表数据格式
|
* 转换图表数据格式
|
||||||
* 将后端返回的扁平数据结构转换为ECharts所需的双线数据格式
|
* 将后端返回的扁平数据结构转换为ECharts所需的双线数据格式
|
||||||
|
|||||||
@ -53,7 +53,7 @@
|
|||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
|
|
||||||
<!-- 设施详情弹框 -->
|
<!-- 设施详情弹框 -->
|
||||||
<a-modal v-model:open="modalVisible" :title="'设施详情'" width="1536px" :footer="null">
|
<a-modal v-model:open="modalVisibleone" :title="'设施详情'" width="80%" :footer="null">
|
||||||
<div v-if="currentItem" class="detail-container">
|
<div v-if="currentItem" class="detail-container">
|
||||||
<ArtsDetail :dataSource="currentItem" :index="getCurrentRealIndex()" />
|
<ArtsDetail :dataSource="currentItem" :index="getCurrentRealIndex()" />
|
||||||
</div>
|
</div>
|
||||||
@ -66,6 +66,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
import { getMsstbprptKendoList } from '@/api/home';
|
import { getMsstbprptKendoList } from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -84,9 +85,9 @@ interface MediaItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 弹框控制
|
// 弹框控制
|
||||||
const modalVisible = ref(false);
|
const modalVisibleone = ref(false);
|
||||||
const currentItem = ref<any>(null);
|
const currentItem = ref<any>(null);
|
||||||
|
useDraggable(modalVisibleone, { boundary: true, resetOnOpen: true });
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ const handleItemClick = () => {
|
|||||||
description: item.description || '',
|
description: item.description || '',
|
||||||
title: item.title || ''
|
title: item.title || ''
|
||||||
}));
|
}));
|
||||||
modalVisible.value = true;
|
modalVisibleone.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理下拉选择变化
|
// 处理下拉选择变化
|
||||||
|
|||||||
@ -36,6 +36,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { dwInfoGetKendoListCust } from "@/api/sw";
|
import { dwInfoGetKendoListCust } from "@/api/sw";
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
import DiwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers from "./TwoLayers/diwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers.vue"
|
import DiwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers from "./TwoLayers/diwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers.vue"
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -73,7 +75,7 @@ const baseid = ref('')
|
|||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const selectedItem: any = ref<DataString | null>(null);
|
const selectedItem: any = ref<DataString | null>(null);
|
||||||
const twoLayersRef = ref();
|
const twoLayersRef = ref();
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
|
||||||
const getListData = async () => {
|
const getListData = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|||||||
@ -4,9 +4,17 @@
|
|||||||
:datetimePicker="datetimePicker"
|
:datetimePicker="datetimePicker"
|
||||||
@update-values="handlePanelChange"
|
@update-values="handlePanelChange"
|
||||||
>
|
>
|
||||||
<a-spin :spinning="loading" style="width: 100%;">
|
<a-spin :spinning="loading" style="width: 100%">
|
||||||
<div ref="chartContainer" class="chart-container" v-show="sourceData.length > 0"></div>
|
<div
|
||||||
<a-empty v-show="sourceData.length === 0" description="暂无数据" class="empty-container" />
|
ref="chartContainer"
|
||||||
|
class="chart-container"
|
||||||
|
v-show="sourceData.length > 0"
|
||||||
|
></div>
|
||||||
|
<a-empty
|
||||||
|
v-show="sourceData.length === 0"
|
||||||
|
description="暂无数据"
|
||||||
|
class="empty-container"
|
||||||
|
/>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</template>
|
</template>
|
||||||
@ -296,8 +304,12 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
.empty-container {
|
.empty-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
p{
|
||||||
|
text-indent:0px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -68,6 +68,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { fishDicGetKendoList, wbsbGetKendoList } from '@/api/yldc';
|
import { fishDicGetKendoList, wbsbGetKendoList } from '@/api/yldc';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'zengZhiZhanJieShaoMod'
|
name: 'zengZhiZhanJieShaoMod'
|
||||||
@ -87,7 +89,7 @@ let rvcd = ref('');
|
|||||||
// 弹框控制
|
// 弹框控制
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentItem = ref<any>(null);
|
const currentItem = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
|||||||
@ -62,6 +62,8 @@ import { ref, onMounted, onUnmounted, computed } from 'vue';
|
|||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { msstbprptGetKendoList } from '@/api/yldc';
|
import { msstbprptGetKendoList } from '@/api/yldc';
|
||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'zengZhiZhanJieShaoMod'
|
name: 'zengZhiZhanJieShaoMod'
|
||||||
@ -79,7 +81,7 @@ const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
|||||||
// 弹框控制
|
// 弹框控制
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentItem = ref<any>(null);
|
const currentItem = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { vmsstbprptGetKendoList } from '@/api/gyss'
|
import { vmsstbprptGetKendoList } from '@/api/gyss'
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
import FPVDDetailMD from './components/FPVDDetailMD.vue'
|
import FPVDDetailMD from './components/FPVDDetailMD.vue'
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'guoyusheshijiansheqingkuang'
|
name: 'guoyusheshijiansheqingkuang'
|
||||||
@ -81,6 +83,7 @@ const loading = ref(false);
|
|||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const selectedFacility = ref<any>(null);
|
const selectedFacility = ref<any>(null);
|
||||||
const title = ref('');
|
const title = ref('');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 处理卡片点击事件
|
// 处理卡片点击事件
|
||||||
const handleCardClick = (facility: any) => {
|
const handleCardClick = (facility: any) => {
|
||||||
selectedFacility.value = facility;
|
selectedFacility.value = facility;
|
||||||
|
|||||||
@ -3,25 +3,49 @@
|
|||||||
<SidePanelItem title="过鱼设施">
|
<SidePanelItem title="过鱼设施">
|
||||||
<a-spin :spinning="loading" tip="加载中...">
|
<a-spin :spinning="loading" tip="加载中...">
|
||||||
<div class="facility-grid">
|
<div class="facility-grid">
|
||||||
<div v-for="facility in facilities" :key="facility.name" class="facility-card"
|
<div
|
||||||
@click="handleFacilityClick(facility)">
|
v-for="facility in facilities"
|
||||||
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
:key="facility.name"
|
||||||
|
class="facility-card"
|
||||||
|
@click="handleFacilityClick(facility)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
width: 60px;
|
||||||
|
height: 62px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
<div class="facility-icon">
|
<div class="facility-icon">
|
||||||
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
|
<i
|
||||||
|
style="color: #fff"
|
||||||
|
:class="facility.icon"
|
||||||
|
type="icon-shengtailiuliang2"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="facility-info">
|
<div class="facility-info">
|
||||||
<div class="facility-name">{{ facility.name }}</div>
|
<div class="facility-name">{{ facility.name }}</div>
|
||||||
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count
|
<div style="font-size: 16px">
|
||||||
}}</span><span>座</span></div>
|
<span class="facility-count">{{ facility.count }}</span
|
||||||
|
><span>座</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
<!-- 弹框 -->
|
<!-- 弹框 -->
|
||||||
<a-modal v-model:open="modalVisible" :title="'过鱼设施'" :footer="null" width="1536px" @cancel="handleCloseModal">
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:title="'过鱼设施'"
|
||||||
|
:footer="null"
|
||||||
|
width="1536px"
|
||||||
|
@cancel="handleCloseModal"
|
||||||
|
>
|
||||||
<ModalPage v-if="currentFacility" :data="currentFacility" :jdId="'all'" />
|
<ModalPage v-if="currentFacility" :data="currentFacility" :jdId="'all'" />
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
@ -29,9 +53,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { buildGetKendoListCust } from '@/api/gyss';
|
import { buildGetKendoListCust } from '@/api/gyss';
|
||||||
import ModalPage from './ModalPage/index.vue'
|
import ModalPage from './ModalPage/index.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'qixidibaohugongzuokaizhanQK'
|
name: 'qixidibaohugongzuokaizhanQK'
|
||||||
@ -64,23 +90,23 @@ const facilities = ref([
|
|||||||
count: 0,
|
count: 0,
|
||||||
icon: 'icon iconfont icon-map-gyssQita',
|
icon: 'icon iconfont icon-map-gyssQita',
|
||||||
key: 'FP_5'
|
key: 'FP_5'
|
||||||
},
|
}
|
||||||
|
|
||||||
]);
|
]);
|
||||||
const baseid = ref('')
|
const baseid = ref('');
|
||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentFacility = ref<any>(null);
|
const currentFacility = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
//获取页面数据
|
//获取页面数据
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
let params = {
|
let params = {
|
||||||
"filter": {
|
filter: {
|
||||||
"logic": "and",
|
logic: 'and',
|
||||||
"filters": []
|
filters: []
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
const res = await buildGetKendoListCust(params); //适配监控-VD
|
const res = await buildGetKendoListCust(params); //适配监控-VD
|
||||||
let data = res?.data?.data || res?.data || [];
|
let data = res?.data?.data || res?.data || [];
|
||||||
|
|
||||||
@ -91,15 +117,21 @@ const getData = async () => {
|
|||||||
|
|
||||||
// 遍历接口返回的所有数据
|
// 遍历接口返回的所有数据
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
const matchedFacility = facilities.value.find(facility => facility.key === item.sttpCode);
|
const matchedFacility = facilities.value.find(
|
||||||
|
facility => facility.key === item.sttpCode
|
||||||
|
);
|
||||||
if (matchedFacility) {
|
if (matchedFacility) {
|
||||||
// 如果在facilities中找到对应的key,累加到该设施
|
// 如果在facilities中找到对应的key,累加到该设施
|
||||||
matchedFacility.count += Number(item.built) + Number(item.building) || 0;
|
matchedFacility.count +=
|
||||||
|
Number(item.built) + Number(item.building) || 0;
|
||||||
} else {
|
} else {
|
||||||
// 如果没有找到对应的key,累加到FP_5(其他)
|
// 如果没有找到对应的key,累加到FP_5(其他)
|
||||||
const otherFacility = facilities.value.find(facility => facility.key === 'FP_5');
|
const otherFacility = facilities.value.find(
|
||||||
|
facility => facility.key === 'FP_5'
|
||||||
|
);
|
||||||
if (otherFacility) {
|
if (otherFacility) {
|
||||||
otherFacility.count += Number(item.built) + Number(item.building) || 0;
|
otherFacility.count +=
|
||||||
|
Number(item.built) + Number(item.building) || 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -108,13 +140,11 @@ const getData = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
// 点击处理函数
|
// 点击处理函数
|
||||||
const handleFacilityClick = (facility: any) => {
|
const handleFacilityClick = (facility: any) => {
|
||||||
currentFacility.value = facility;
|
currentFacility.value = facility;
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
// 关闭弹框
|
// 关闭弹框
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = () => {
|
||||||
@ -124,22 +154,19 @@ const handleCloseModal = () => {
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => JidiSelectEventStore.selectedItem,
|
() => JidiSelectEventStore.selectedItem,
|
||||||
(newVal) => {
|
newVal => {
|
||||||
baseid.value = newVal.wbsCode;
|
baseid.value = newVal.wbsCode;
|
||||||
getData()
|
getData();
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
);
|
);
|
||||||
// 页面加载时执行
|
// 页面加载时执行
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 延迟初始化,确保容器已渲染
|
// 延迟初始化,确保容器已渲染
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 组件卸载时清理
|
// 组件卸载时清理
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {});
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -148,7 +175,9 @@ onUnmounted(() => {
|
|||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
||||||
|
Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji,
|
||||||
|
Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-card {
|
.facility-card {
|
||||||
|
|||||||
@ -3,13 +3,25 @@
|
|||||||
<SidePanelItem title="过鱼设施介绍">
|
<SidePanelItem title="过鱼设施介绍">
|
||||||
<!-- Loading 和空状态容器 -->
|
<!-- Loading 和空状态容器 -->
|
||||||
<a-spin :spinning="loading" class="carousel-container-wrapper">
|
<a-spin :spinning="loading" class="carousel-container-wrapper">
|
||||||
<div v-if="hasData" class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
|
<div
|
||||||
|
v-if="hasData"
|
||||||
|
class="container"
|
||||||
|
@mouseenter="handleMouseEnter"
|
||||||
|
@mouseleave="handleMouseLeave"
|
||||||
|
>
|
||||||
<!-- 跑马灯轨道容器 -->
|
<!-- 跑马灯轨道容器 -->
|
||||||
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
|
<div
|
||||||
:style="{ transform: `translateX(-${currentIndex * 100}%)` }">
|
class="carousel-track"
|
||||||
|
:class="{ 'no-transition': isTransitioning }"
|
||||||
|
:style="{ transform: `translateX(-${currentIndex * 100}%)` }"
|
||||||
|
>
|
||||||
<!-- 遍历所有媒体项(包含克隆项) -->
|
<!-- 遍历所有媒体项(包含克隆项) -->
|
||||||
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item"
|
<div
|
||||||
@click="handleItemClick(originalMediaData)">
|
v-for="(item, index) in renderMediaData"
|
||||||
|
:key="index"
|
||||||
|
class="carousel-item"
|
||||||
|
@click="handleItemClick(originalMediaData)"
|
||||||
|
>
|
||||||
<!-- 图片 -->
|
<!-- 图片 -->
|
||||||
<img :src="item.url" :alt="item.stnm" loading="lazy" />
|
<img :src="item.url" :alt="item.stnm" loading="lazy" />
|
||||||
<!-- 说明文字(随媒体项移动) -->
|
<!-- 说明文字(随媒体项移动) -->
|
||||||
@ -19,36 +31,50 @@
|
|||||||
|
|
||||||
<!-- 面板指示器(固定在底部右侧) -->
|
<!-- 面板指示器(固定在底部右侧) -->
|
||||||
<div class="pagination-dots-fixed">
|
<div class="pagination-dots-fixed">
|
||||||
<span v-for="(dot, index) in originalMediaData" :key="index" class="dot"
|
<span
|
||||||
:class="{ active: currentRealIndex === index }" @click="goToSlide(index)"></span>
|
v-for="(dot, index) in originalMediaData"
|
||||||
|
:key="index"
|
||||||
|
class="dot"
|
||||||
|
:class="{ active: currentRealIndex === index }"
|
||||||
|
@click="goToSlide(index)"
|
||||||
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 暂无数据状态 -->
|
<!-- 暂无数据状态 -->
|
||||||
|
|
||||||
<!-- 独立的文字说明区域(随跑马灯切换而变化) -->
|
<!-- 独立的文字说明区域(随跑马灯切换而变化) -->
|
||||||
<div v-if="hasData" class="description-text" @click="handleItemClick(originalMediaData)">
|
<div
|
||||||
|
v-if="hasData"
|
||||||
|
class="description-text"
|
||||||
|
@click="handleItemClick(originalMediaData)"
|
||||||
|
>
|
||||||
{{ currentDescription }}
|
{{ currentDescription }}
|
||||||
</div>
|
</div>
|
||||||
<a-empty v-else description="暂无数据" :image="simpleImage" />
|
<a-empty v-else description="暂无数据" :image="simpleImage" />
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
<!-- 设施详情弹框 -->
|
<!-- 设施详情弹框 -->
|
||||||
<a-modal v-model:open="modalVisible" :title="'设施类型介绍'" width="1536px" :footer="null">
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
:title="'设施类型介绍'"
|
||||||
|
width="1536px"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
<!-- 你在这里编写弹框内容 -->
|
<!-- 你在这里编写弹框内容 -->
|
||||||
<div v-if="currentItem">
|
<div v-if="currentItem">
|
||||||
<ArtsDetail :dataSource='currentItem' :index="getCurrentRealIndex()" />
|
<ArtsDetail :dataSource="currentItem" :index="getCurrentRealIndex()" />
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, onUnmounted, computed, watch } from 'vue';
|
import { ref, onMounted, onUnmounted, computed, watch } from 'vue';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { fpVmsstbprptGetKendoList } from '@/api/gyss';
|
import { fpVmsstbprptGetKendoList } from '@/api/gyss';
|
||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
import { Empty } from 'ant-design-vue';
|
import { Empty } from 'ant-design-vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// ==================== 类型定义 ====================
|
// ==================== 类型定义 ====================
|
||||||
interface MediaItem {
|
interface MediaItem {
|
||||||
@ -79,6 +105,7 @@ const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
|||||||
// 弹框控制
|
// 弹框控制
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentItem = ref<any>(null);
|
const currentItem = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// ==================== 数据状态 ====================
|
// ==================== 数据状态 ====================
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -247,12 +274,14 @@ const getCarouselData = async () => {
|
|||||||
operator: 'isnotnull',
|
operator: 'isnotnull',
|
||||||
dataType: 'string'
|
dataType: 'string'
|
||||||
},
|
},
|
||||||
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)
|
||||||
},
|
},
|
||||||
select: ['introduce', 'logo', 'stnm', 'precis'],
|
select: ['introduce', 'logo', 'stnm', 'precis'],
|
||||||
@ -298,7 +327,7 @@ onUnmounted(() => {
|
|||||||
// ==================== 监听器 ====================
|
// ==================== 监听器 ====================
|
||||||
watch(
|
watch(
|
||||||
() => JidiSelectEventStore.selectedItem,
|
() => JidiSelectEventStore.selectedItem,
|
||||||
(newVal) => {
|
newVal => {
|
||||||
if (newVal?.wbsCode) {
|
if (newVal?.wbsCode) {
|
||||||
baseid.value = newVal.wbsCode;
|
baseid.value = newVal.wbsCode;
|
||||||
} else {
|
} else {
|
||||||
@ -391,7 +420,7 @@ const handleItemClick = (item: any) => {
|
|||||||
width: 5px;
|
width: 5px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #D8D8D8;
|
background-color: #d8d8d8;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
title="环保设施情况"
|
title="环保设施情况"
|
||||||
width="1536px"
|
width="80%"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
>
|
>
|
||||||
<HuanbaoModTwoLayers
|
<HuanbaoModTwoLayers
|
||||||
@ -49,6 +49,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { environmentalProtectionConstruction } from '@/api/home';
|
import { environmentalProtectionConstruction } from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import HuanbaoModTwoLayers from './TwoLayers/HuanbaoModTwoLayers.vue';
|
import HuanbaoModTwoLayers from './TwoLayers/HuanbaoModTwoLayers.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -82,7 +83,7 @@ const modalRes = ref({
|
|||||||
bldstt: '',
|
bldstt: '',
|
||||||
hydrodtin: '1'
|
hydrodtin: '1'
|
||||||
});
|
});
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 获取数据
|
// 获取数据
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
if (!baseid.value) return;
|
if (!baseid.value) return;
|
||||||
|
|||||||
@ -21,6 +21,14 @@
|
|||||||
:options="jiDiList"
|
:options="jiDiList"
|
||||||
@change="handleBaseChange"
|
@change="handleBaseChange"
|
||||||
/>
|
/>
|
||||||
|
<a-select
|
||||||
|
v-model:value="searchData.stcd"
|
||||||
|
placeholder=" "
|
||||||
|
style="width: 200px"
|
||||||
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
:options="rstcdOptions"
|
||||||
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-if="tabIndex !== '7'"
|
v-if="tabIndex !== '7'"
|
||||||
v-model:value="searchData.stnm"
|
v-model:value="searchData.stnm"
|
||||||
@ -44,7 +52,6 @@
|
|||||||
:search-params="searchParams"
|
:search-params="searchParams"
|
||||||
:transform-data="customTransform"
|
:transform-data="customTransform"
|
||||||
>
|
>
|
||||||
|
|
||||||
<template #coenvwState="{ column, record }">
|
<template #coenvwState="{ column, record }">
|
||||||
<a-tag :color="record.coenvwState > 0 ? 'green' : '#999'">
|
<a-tag :color="record.coenvwState > 0 ? 'green' : '#999'">
|
||||||
{{ record.coenvwState > 0 ? '在线' : '离线' }}
|
{{ record.coenvwState > 0 ? '在线' : '离线' }}
|
||||||
@ -85,13 +92,15 @@ const props = defineProps<{
|
|||||||
const tabIndex = ref(String(props.activeKey ?? ''));
|
const tabIndex = ref(String(props.activeKey ?? ''));
|
||||||
const searchData = ref<any>({
|
const searchData = ref<any>({
|
||||||
baseId: props.baseId || 'all',
|
baseId: props.baseId || 'all',
|
||||||
stnm: null
|
stnm: null,
|
||||||
|
stcd: null
|
||||||
});
|
});
|
||||||
const modelStore = useModelStore();
|
const modelStore = useModelStore();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
|
||||||
// ==================== 基地列表数据 ====================
|
// ==================== 基地列表数据 ====================
|
||||||
const jiDiList: any = ref([]);
|
const jiDiList: any = ref([]);
|
||||||
|
const rstcdOptions: any = ref([]);
|
||||||
|
|
||||||
// ==================== 表格列定义 ====================
|
// ==================== 表格列定义 ====================
|
||||||
const columns = computed(() => {
|
const columns = computed(() => {
|
||||||
@ -104,14 +113,12 @@ const columns = computed(() => {
|
|||||||
dataIndex: 'baseName',
|
dataIndex: 'baseName',
|
||||||
width: '150px',
|
width: '150px',
|
||||||
merge: true
|
merge: true
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'stnm',
|
key: 'stnm',
|
||||||
title: '电站名称',
|
title: '电站名称',
|
||||||
dataIndex: 'stnm',
|
dataIndex: 'stnm',
|
||||||
width: '176px',
|
width: '176px'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'dvtp',
|
key: 'dvtp',
|
||||||
@ -167,8 +174,7 @@ const columns = computed(() => {
|
|||||||
key: 'stnm',
|
key: 'stnm',
|
||||||
title: '测站名称',
|
title: '测站名称',
|
||||||
dataIndex: 'stnm',
|
dataIndex: 'stnm',
|
||||||
width: '176px',
|
width: '176px'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'ennm',
|
key: 'ennm',
|
||||||
@ -189,8 +195,7 @@ const columns = computed(() => {
|
|||||||
key: 'stindx',
|
key: 'stindx',
|
||||||
title: '监测指标',
|
title: '监测指标',
|
||||||
dataIndex: 'stindx',
|
dataIndex: 'stindx',
|
||||||
width: '150px',
|
width: '150px'
|
||||||
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -260,15 +265,66 @@ const searchParams = computed(() => {
|
|||||||
// ==================== 方法 ====================
|
// ==================== 方法 ====================
|
||||||
const handleTabChange = (key: string) => {
|
const handleTabChange = (key: string) => {
|
||||||
tabIndex.value = key;
|
tabIndex.value = key;
|
||||||
|
handleReset();
|
||||||
handleSearch();
|
handleSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterOption = (input: string, option: any) => {
|
const filterOption = (input: string, option: any) => {
|
||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||||
};
|
};
|
||||||
|
const getRstcdData = async () => {
|
||||||
|
const parmas = {
|
||||||
|
filter: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: [
|
||||||
|
searchData.value.baseId != 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'contains',
|
||||||
|
dataType: 'string',
|
||||||
|
value: '02'
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
{
|
||||||
|
field: 'sttpCode',
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value: 'ENG'
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
},
|
||||||
|
sort: [
|
||||||
|
{
|
||||||
|
field: 'baseId',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'rvcdStepSort',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'rstcdStepSort',
|
||||||
|
dir: 'asc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'siteStepSort',
|
||||||
|
dir: 'asc'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
select: ['stcd', 'stnm']
|
||||||
|
};
|
||||||
|
const res = await vmsstbprptGetKendoList(parmas);
|
||||||
|
rstcdOptions.value = res.data.data.map((item) => {
|
||||||
|
return {
|
||||||
|
value: item.stcd,
|
||||||
|
label: item.stnm
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
const handleBaseChange = () => {
|
const handleBaseChange = () => {
|
||||||
handleSearch();
|
searchData.value.stcd = null
|
||||||
|
getRstcdData();
|
||||||
|
// handleSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const dvtpText = (dvtp: number) => {
|
const dvtpText = (dvtp: number) => {
|
||||||
@ -287,7 +343,13 @@ const handleSearch = () => {
|
|||||||
value: searchData.value.baseId
|
value: searchData.value.baseId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if(searchData.value.stcd){
|
||||||
|
filters.push({
|
||||||
|
field: 'stcd',
|
||||||
|
operator: 'eq',
|
||||||
|
value: searchData.value.stcd
|
||||||
|
});
|
||||||
|
}
|
||||||
if (searchData.value.stnm) {
|
if (searchData.value.stnm) {
|
||||||
filters.push({
|
filters.push({
|
||||||
field: 'stnm',
|
field: 'stnm',
|
||||||
@ -441,8 +503,10 @@ const handleSearch = () => {
|
|||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
searchData.value = {
|
searchData.value = {
|
||||||
baseId: 'all',
|
baseId: 'all',
|
||||||
stnm: null
|
stnm: null,
|
||||||
|
stcd: null
|
||||||
};
|
};
|
||||||
|
getRstcdData()
|
||||||
handleSearch();
|
handleSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -557,6 +621,7 @@ onMounted(() => {
|
|||||||
value: element.wbsCode
|
value: element.wbsCode
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
getRstcdData()
|
||||||
handleSearch();
|
handleSearch();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -68,6 +68,7 @@ import svg_liuliangjiancezhan from '@/assets/svg/liuliangjiancezhan.svg';
|
|||||||
import svg_shuizhijiancezhan from '@/assets/svg/shuizhijiancezhan.svg';
|
import svg_shuizhijiancezhan from '@/assets/svg/shuizhijiancezhan.svg';
|
||||||
import svg_zengzhizhanshuizhizhan from '@/assets/svg/zengzhizhanshuizhizhan.svg';
|
import svg_zengzhizhanshuizhizhan from '@/assets/svg/zengzhizhanshuizhizhan.svg';
|
||||||
import svg_qixidi from '@/assets/svg/qixidi.svg';
|
import svg_qixidi from '@/assets/svg/qixidi.svg';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'huanbaoMod'
|
name: 'huanbaoMod'
|
||||||
@ -103,7 +104,7 @@ const baseid = ref('');
|
|||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentFacility = ref<IFacility | null>(null);
|
const currentFacility = ref<IFacility | null>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const fetchData = () => {
|
const fetchData = () => {
|
||||||
let params = {
|
let params = {
|
||||||
filter: {
|
filter: {
|
||||||
|
|||||||
1957
frontend/src/modules/liuyu/ai/spdzwaijc/AISPTK.vue
Normal file
1957
frontend/src/modules/liuyu/ai/spdzwaijc/AISPTK.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,317 @@
|
|||||||
|
<template>
|
||||||
|
<div class="video-details">
|
||||||
|
<a-tabs v-model:activeKey="activeKey" @change="handleTabChange">
|
||||||
|
<a-tab-pane key="2" tab="运行">
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<div class="video-container">
|
||||||
|
<VideoPlayer
|
||||||
|
:list="videoList"
|
||||||
|
:activeFid="activeFid"
|
||||||
|
:activeMedia="activeMedia"
|
||||||
|
:loading="loading"
|
||||||
|
:page="page"
|
||||||
|
:pageSize="pageSize"
|
||||||
|
:pageSizeOptions="pageSizeOptions"
|
||||||
|
:total="total"
|
||||||
|
@select="handleSelectMedia"
|
||||||
|
@pageChange="handlePageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="1" tab="未运行">
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<div class="video-container">
|
||||||
|
<VideoPlayer
|
||||||
|
:list="videoList"
|
||||||
|
:activeFid="activeFid"
|
||||||
|
:activeMedia="activeMedia"
|
||||||
|
:loading="loading"
|
||||||
|
:page="page"
|
||||||
|
:pageSize="pageSize"
|
||||||
|
:pageSizeOptions="pageSizeOptions"
|
||||||
|
:total="total"
|
||||||
|
@select="handleSelectMedia"
|
||||||
|
@pageChange="handlePageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch, onMounted } from 'vue';
|
||||||
|
import VideoPlayer from '@/modules/yunXingGaoJIng/Aisbdbyx/components/VideoPlayer.vue';
|
||||||
|
import { getAiFile } from '@/api/zngj';
|
||||||
|
import { postIdUrl } from '@/api/mapModal';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
||||||
|
|
||||||
|
// ==================== Props ====================
|
||||||
|
const props = defineProps<{
|
||||||
|
baseid?: string;
|
||||||
|
month?: any;
|
||||||
|
type?: string;
|
||||||
|
vdDate?: string;
|
||||||
|
activeKey?: string;
|
||||||
|
stnm?: string;
|
||||||
|
rstcd?: string;
|
||||||
|
pieCode?: string[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// ==================== 状态 ====================
|
||||||
|
const activeKey = ref(props.activeKey || '2');
|
||||||
|
const loading = ref(false);
|
||||||
|
const videoList = ref<any[]>([]);
|
||||||
|
const activeFid = ref('');
|
||||||
|
const activeMedia = ref<{ type: string; src: string }>({ type: '', src: '' });
|
||||||
|
const page = ref(1);
|
||||||
|
const pageSize = ref(20);
|
||||||
|
const pageSizeOptions = ['20', '50', '100'];
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
// ==================== 获取视频列表 ====================
|
||||||
|
const fetchVideoList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const filters: any[] = [
|
||||||
|
// baseId过滤
|
||||||
|
props.pieCode && props.pieCode.length > 0 && props.baseid === 'all'
|
||||||
|
? {
|
||||||
|
field: 'baseId',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: props.pieCode
|
||||||
|
}
|
||||||
|
: props.baseid && props.baseid !== 'all'
|
||||||
|
? { field: 'baseId', operator: 'eq', value: props.baseid }
|
||||||
|
: null,
|
||||||
|
// rstcd过滤
|
||||||
|
props.pieCode && props.pieCode.length > 0 && props.baseid !== 'all'
|
||||||
|
? {
|
||||||
|
field: 'rstcd',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: props.pieCode
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
// type过滤
|
||||||
|
{ field: 'type', operator: 'eq', value: props.type },
|
||||||
|
// dataType过滤(运行/未运行)
|
||||||
|
{ field: 'dataType', operator: 'eq', value: activeKey.value },
|
||||||
|
// 时间范围(按天)
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'gte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: dayjs(props.vdDate)
|
||||||
|
.startOf('day')
|
||||||
|
.format('YYYY-MM-DD 00:00:00')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tm',
|
||||||
|
operator: 'lte',
|
||||||
|
dataType: 'date',
|
||||||
|
value: dayjs(props.vdDate)
|
||||||
|
.endOf('day')
|
||||||
|
.format('YYYY-MM-DD 23:59:59')
|
||||||
|
},
|
||||||
|
// stnm文本搜索
|
||||||
|
props.stnm
|
||||||
|
? { field: 'stnm', operator: 'contains', value: props.stnm }
|
||||||
|
: null,
|
||||||
|
// rstcd电站选择
|
||||||
|
props.rstcd
|
||||||
|
? {
|
||||||
|
field: 'rstcd',
|
||||||
|
operator: 'in',
|
||||||
|
dataType: 'string',
|
||||||
|
value: [props.rstcd]
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
].filter(Boolean);
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
filter: { logic: 'and', filters },
|
||||||
|
sort: [{ field: 'tm', dir: 'desc' }],
|
||||||
|
skip: (page.value - 1) * pageSize.value,
|
||||||
|
take: pageSize.value
|
||||||
|
};
|
||||||
|
|
||||||
|
const res: any = await getAiFile(params);
|
||||||
|
const rData = res?.data ?? {};
|
||||||
|
const rawData = rData?.data || [];
|
||||||
|
total.value = rData?.total || rawData.length;
|
||||||
|
|
||||||
|
// 按 fid 展开
|
||||||
|
const expandedData = rawData
|
||||||
|
.map((item: any) => {
|
||||||
|
const fids = item.fid ? item.fid.split(',') : [];
|
||||||
|
return fids.map((fid: string) => ({ ...item, fid: fid.trim() }));
|
||||||
|
})
|
||||||
|
.flat();
|
||||||
|
|
||||||
|
// 收集所有 fid
|
||||||
|
const allFids = expandedData
|
||||||
|
.filter((item: any) => item.fid)
|
||||||
|
.map((item: any) => item.fid)
|
||||||
|
.join(',');
|
||||||
|
|
||||||
|
// 调用 postIdUrl 获取媒体详情
|
||||||
|
let mediaMap: Record<string, any> = {};
|
||||||
|
if (allFids) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('id', allFids);
|
||||||
|
const mediaRes: any = await postIdUrl(formData);
|
||||||
|
mediaMap = mediaRes?.data || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建列表
|
||||||
|
const list: any[] = [];
|
||||||
|
expandedData.forEach((vd: any) => {
|
||||||
|
const fileInfo = mediaMap[vd.fid];
|
||||||
|
const hasValidExtension =
|
||||||
|
fileInfo && ['.jpg', '.png'].includes(fileInfo.ext);
|
||||||
|
|
||||||
|
let flpth = '';
|
||||||
|
let imgPath = '';
|
||||||
|
let type = '';
|
||||||
|
|
||||||
|
if (hasValidExtension !== undefined && !hasValidExtension) {
|
||||||
|
flpth = fileInfo.fullpath;
|
||||||
|
type = 'vdsp';
|
||||||
|
} else if (hasValidExtension !== undefined) {
|
||||||
|
imgPath = fileInfo.fullpath;
|
||||||
|
type = 'img';
|
||||||
|
}
|
||||||
|
|
||||||
|
const tm = vd.tm ? dayjs(vd.tm).format('YYYY-MM-DD HH:mm:ss') : '-';
|
||||||
|
list.push({
|
||||||
|
...vd,
|
||||||
|
flpth,
|
||||||
|
imgPath,
|
||||||
|
flnm: `${vd.ennm || ''}${tm}`,
|
||||||
|
type,
|
||||||
|
tm
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 过滤掉无效项
|
||||||
|
const listMap = list.filter(
|
||||||
|
item => item.flpth !== '' || item.imgPath !== ''
|
||||||
|
);
|
||||||
|
videoList.value = listMap;
|
||||||
|
|
||||||
|
// 默认选中第一条
|
||||||
|
if (listMap.length > 0) {
|
||||||
|
const first = listMap[0];
|
||||||
|
activeFid.value = first.fid;
|
||||||
|
if (first.type === 'img') {
|
||||||
|
activeMedia.value = {
|
||||||
|
type: 'image',
|
||||||
|
src: baseUrl + '?' + first.fid + '&view=jpg'
|
||||||
|
};
|
||||||
|
} else if (first.type === 'vdsp') {
|
||||||
|
activeMedia.value = {
|
||||||
|
type: 'video',
|
||||||
|
src: baseUrl + '?' + first.fid + '&view=jpg'
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
activeFid.value = '';
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取视频详情列表失败:', error);
|
||||||
|
videoList.value = [];
|
||||||
|
activeFid.value = '';
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== 事件处理 ====================
|
||||||
|
const handleTabChange = () => {
|
||||||
|
page.value = 1;
|
||||||
|
activeFid.value = '';
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
fetchVideoList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectMedia = (item: any) => {
|
||||||
|
activeFid.value = item.fid;
|
||||||
|
|
||||||
|
if (item.type === 'img') {
|
||||||
|
activeMedia.value = {
|
||||||
|
type: 'image',
|
||||||
|
src: baseUrl + '?' + item.fid + '&view=jpg'
|
||||||
|
};
|
||||||
|
} else if (item.type === 'vdsp') {
|
||||||
|
activeMedia.value = {
|
||||||
|
type: 'video',
|
||||||
|
src: baseUrl + '?' + item.fid + '&view=jpg'
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = (newPage: number, newPageSize: number) => {
|
||||||
|
page.value = newPage;
|
||||||
|
pageSize.value = newPageSize;
|
||||||
|
activeFid.value = '';
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
fetchVideoList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== 监听 ====================
|
||||||
|
watch(
|
||||||
|
() => [props.vdDate, props.type, activeKey.value],
|
||||||
|
() => {
|
||||||
|
if (props.vdDate) {
|
||||||
|
page.value = 1;
|
||||||
|
fetchVideoList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// ==================== 生命周期 ====================
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.vdDate) {
|
||||||
|
fetchVideoList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.video-details {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
:deep(.ant-tabs) {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs-content) {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs-tabpane) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -3,7 +3,12 @@
|
|||||||
<SidePanelItem title="AI识别过鱼设施运行" :datetimePicker="datetimePicker" @update-values="handlePanelChange">
|
<SidePanelItem title="AI识别过鱼设施运行" :datetimePicker="datetimePicker" @update-values="handlePanelChange">
|
||||||
<a-spin :spinning="dataLoading" tip="加载中...">
|
<a-spin :spinning="dataLoading" tip="加载中...">
|
||||||
<div class="facility-grid">
|
<div class="facility-grid">
|
||||||
<div v-for="facility in facilities" :key="facility.key" class="facility-card">
|
<div
|
||||||
|
v-for="facility in facilities"
|
||||||
|
:key="facility.key"
|
||||||
|
class="facility-card"
|
||||||
|
@click="handleCardClick(facility.action)"
|
||||||
|
>
|
||||||
<div style="width: 70px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
<div style="width: 70px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
||||||
<div class="facility-icon">
|
<div class="facility-icon">
|
||||||
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
|
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
|
||||||
@ -20,14 +25,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
|
|
||||||
|
<!-- AI识别过鱼设施运行详情弹框 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
title="AI识别过鱼设施运行"
|
||||||
|
width="1536px"
|
||||||
|
:footer="null"
|
||||||
|
@cancel="handleModalClose"
|
||||||
|
>
|
||||||
|
<AISPTK
|
||||||
|
v-if="modalVisible"
|
||||||
|
:month="datetimePicker.value"
|
||||||
|
:action="currentAction"
|
||||||
|
:baseid="baseid"
|
||||||
|
:ly-name="lyName"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, computed, 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 AISPTK from './AISPTK.vue';
|
||||||
import { getAiGyssList } from '@/api/zngj';
|
import { getAiGyssList } from '@/api/zngj';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -39,6 +63,10 @@ const baseid = ref('');
|
|||||||
const dataLoading = ref(false);
|
const dataLoading = ref(false);
|
||||||
const panelDetail = ref<any>({});
|
const panelDetail = ref<any>({});
|
||||||
|
|
||||||
|
// ==================== 弹框状态 ====================
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const currentAction = ref('AI_5006');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const lyName = computed(() => baseid.value === '02' ? '升鱼斗运行' : '升鱼机运行');
|
const lyName = computed(() => baseid.value === '02' ? '升鱼斗运行' : '升鱼机运行');
|
||||||
|
|
||||||
// ==================== 日期选择器配置 ====================
|
// ==================== 日期选择器配置 ====================
|
||||||
@ -56,37 +84,43 @@ const facilities = computed(() => [
|
|||||||
key: 'gys',
|
key: 'gys',
|
||||||
name: '赶鱼栅运行',
|
name: '赶鱼栅运行',
|
||||||
count: panelDetail.value?.fpGysCnt ?? 0,
|
count: panelDetail.value?.fpGysCnt ?? 0,
|
||||||
icon: 'icon iconfont icon-ganyushan'
|
icon: 'icon iconfont icon-ganyushan',
|
||||||
|
action: 'AI_5006'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'syj',
|
key: 'syj',
|
||||||
name: lyName.value,
|
name: lyName.value,
|
||||||
count: panelDetail.value?.fpSyjCnt ?? 0,
|
count: panelDetail.value?.fpSyjCnt ?? 0,
|
||||||
icon: 'icon iconfont icon-liuliangjiancezhan1'
|
icon: 'icon iconfont icon-liuliangjiancezhan1',
|
||||||
|
action: 'AI_5007'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'agv',
|
key: 'agv',
|
||||||
name: 'AGV小车',
|
name: 'AGV小车',
|
||||||
count: panelDetail.value?.fpAgvCnt ?? 0,
|
count: panelDetail.value?.fpAgvCnt ?? 0,
|
||||||
icon: 'icon iconfont icon-agvxiaoche'
|
icon: 'icon iconfont icon-agvxiaoche',
|
||||||
|
action: 'AI_5008'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'yych',
|
key: 'yych',
|
||||||
name: '运鱼车运行',
|
name: '运鱼车运行',
|
||||||
count: panelDetail.value?.fpYychCnt ?? 0,
|
count: panelDetail.value?.fpYychCnt ?? 0,
|
||||||
icon: 'icon iconfont icon-yunyuche'
|
icon: 'icon iconfont icon-yunyuche',
|
||||||
|
action: 'AI_5002'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'yyc',
|
key: 'yyc',
|
||||||
name: '运鱼船出港',
|
name: '运鱼船出港',
|
||||||
count: panelDetail.value?.fpYycCnt ?? 0,
|
count: panelDetail.value?.fpYycCnt ?? 0,
|
||||||
icon: 'icon iconfont icon-yunyuchuan'
|
icon: 'icon iconfont icon-yunyuchuan',
|
||||||
|
action: 'AI_5003'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'ydh',
|
key: 'ydh',
|
||||||
name: '鱼道放流',
|
name: '鱼道放流',
|
||||||
count: panelDetail.value?.fpYdhCnt ?? 0,
|
count: panelDetail.value?.fpYdhCnt ?? 0,
|
||||||
icon: 'icon iconfont icon-yudaofangliu'
|
icon: 'icon iconfont icon-yudaofangliu',
|
||||||
|
action: 'AI_5012'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -99,6 +133,15 @@ const handlePanelChange = (data: any) => {
|
|||||||
getCardData();
|
getCardData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCardClick = (action: string) => {
|
||||||
|
currentAction.value = action;
|
||||||
|
modalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleModalClose = () => {
|
||||||
|
modalVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
// ==================== 获取卡片统计数据 ====================
|
// ==================== 获取卡片统计数据 ====================
|
||||||
const getCardData = async () => {
|
const getCardData = async () => {
|
||||||
if (!datetimePicker.value.value || !baseid.value) return;
|
if (!datetimePicker.value.value || !baseid.value) return;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
|||||||
import SidePanelItem from "@/components/SidePanelItem/index.vue";
|
import SidePanelItem from "@/components/SidePanelItem/index.vue";
|
||||||
import { getStllGaojingList } from '@/api/zngj';
|
import { getStllGaojingList } from '@/api/zngj';
|
||||||
import ModeGaoJing from './ModeGaoJing.vue';
|
import ModeGaoJing from './ModeGaoJing.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -51,7 +52,7 @@ const baseid = ref('');
|
|||||||
const dataLoading = ref(false);
|
const dataLoading = ref(false);
|
||||||
const isModalOpen = ref(false);
|
const isModalOpen = ref(false);
|
||||||
const currentWarnState = ref('');
|
const currentWarnState = ref('');
|
||||||
|
useDraggable(isModalOpen, { boundary: true, resetOnOpen: true });
|
||||||
const data = ref([
|
const data = ref([
|
||||||
{
|
{
|
||||||
name:'正常',
|
name:'正常',
|
||||||
|
|||||||
@ -38,6 +38,7 @@ 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';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "shuizhijianceshuju",
|
name: "shuizhijianceshuju",
|
||||||
@ -51,7 +52,7 @@ const defaultValue = ref<string>('0');
|
|||||||
// 弹框状态
|
// 弹框状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentWarnState = ref('');
|
const currentWarnState = ref('');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const handleCardClick = (warnState: string) => {
|
const handleCardClick = (warnState: string) => {
|
||||||
currentWarnState.value = warnState;
|
currentWarnState.value = warnState;
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
|
|||||||
@ -68,6 +68,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import LsstjkTk from './LsstjkTk.vue';
|
import LsstjkTk from './LsstjkTk.vue';
|
||||||
import { wbsbGetKendoList, getEvnmAutoMonitor } from '@/api/stdc';
|
import { wbsbGetKendoList, getEvnmAutoMonitor } from '@/api/stdc';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名
|
// 定义组件名
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -81,7 +82,7 @@ const dataLoading = ref(false);
|
|||||||
// ==================== 弹框状态 ====================
|
// ==================== 弹框状态 ====================
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentOrderIndex = ref('16');
|
const currentOrderIndex = ref('16');
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// ==================== 响应式变量定义 ====================
|
// ==================== 响应式变量定义 ====================
|
||||||
// 选择器配置
|
// 选择器配置
|
||||||
const select = ref({
|
const select = ref({
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { watch, type WatchStopHandle } from 'vue';
|
import { watch, type WatchStopHandle, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { unByKey } from 'ol/Observable';
|
import { unByKey } from 'ol/Observable';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { MapClass } from '@/components/gis/map.class';
|
import { MapClass } from '@/components/gis/map.class';
|
||||||
@ -17,6 +18,7 @@ type InitializeOptions = {
|
|||||||
|
|
||||||
type LoadPageOptions = {
|
type LoadPageOptions = {
|
||||||
pageKey: string;
|
pageKey: string;
|
||||||
|
isInitialLoad?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ApplyLayerSelectionOptions = {
|
type ApplyLayerSelectionOptions = {
|
||||||
@ -24,9 +26,7 @@ type ApplyLayerSelectionOptions = {
|
|||||||
triggerKey?: string;
|
triggerKey?: string;
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
};
|
};
|
||||||
|
const SYSTEM_ID = 'qgc';
|
||||||
const SYSTEM_ID = '974975A6-47FD-4C04-9ACD-68938D2992BD';
|
|
||||||
const MODULE_ID = '2157c1a1-e909-4c9f-af94-b4ccebe05808';
|
|
||||||
const HYDRO_DYNAMIC_LAYER_KEYS = [
|
const HYDRO_DYNAMIC_LAYER_KEYS = [
|
||||||
'dw_point',
|
'dw_point',
|
||||||
'stinfo_video_point',
|
'stinfo_video_point',
|
||||||
@ -47,6 +47,7 @@ const LARGE_ENG_LEGEND_PREFIX = 'large_eng_';
|
|||||||
const MID_ENG_LEGEND_PREFIX = 'mid_eng_';
|
const MID_ENG_LEGEND_PREFIX = 'mid_eng_';
|
||||||
|
|
||||||
export const useMapOrchestrator = () => {
|
export const useMapOrchestrator = () => {
|
||||||
|
const route = useRoute();
|
||||||
const mapClass = MapClass.getInstance();
|
const mapClass = MapClass.getInstance();
|
||||||
const mapStore = useMapStore();
|
const mapStore = useMapStore();
|
||||||
const mapConfigStore = useMapConfigStore();
|
const mapConfigStore = useMapConfigStore();
|
||||||
@ -56,6 +57,9 @@ export const useMapOrchestrator = () => {
|
|||||||
let zoomListenerKey: any = null;
|
let zoomListenerKey: any = null;
|
||||||
let stopBaseSelectionWatch: WatchStopHandle | null = null;
|
let stopBaseSelectionWatch: WatchStopHandle | null = null;
|
||||||
const initializedBaseLayerKeys = new Set<string>();
|
const initializedBaseLayerKeys = new Set<string>();
|
||||||
|
const baseSelectionDebounceTimer = ref<ReturnType<typeof setTimeout> | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
// 备注:统一获取当前地图视图对象,避免在多个组件里重复兼容 2D/3D view 访问方式。
|
// 备注:统一获取当前地图视图对象,避免在多个组件里重复兼容 2D/3D view 访问方式。
|
||||||
const getCurrentView = () => {
|
const getCurrentView = () => {
|
||||||
@ -107,50 +111,86 @@ export const useMapOrchestrator = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 备注:统一加载当前页面所需的图层配置、图例配置以及首批锚点数据。
|
// 备注:统一加载当前页面所需的图层配置、图例配置以及首批锚点数据。
|
||||||
const loadPage = async ({ pageKey }: LoadPageOptions) => {
|
const loadPage = async ({
|
||||||
|
pageKey,
|
||||||
|
isInitialLoad = false
|
||||||
|
}: LoadPageOptions) => {
|
||||||
mapDataStore.setLoading(true);
|
mapDataStore.setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const hasGlobalLegendConfig =
|
||||||
|
Array.isArray(mapConfigStore.legendConfigOriginal) &&
|
||||||
|
mapConfigStore.legendConfigOriginal.length > 0;
|
||||||
|
const hasPointLayerCache =
|
||||||
|
Object.keys(mapDataStore.pointDataCache || {}).length > 0;
|
||||||
|
const shouldLoadGlobalLegend = isInitialLoad && !hasGlobalLegendConfig;
|
||||||
|
const shouldPreloadLayerData = isInitialLoad && !hasPointLayerCache;
|
||||||
const previousPageKey = mapConfigStore.lastLoadOptions?.pageKey || '';
|
const previousPageKey = mapConfigStore.lastLoadOptions?.pageKey || '';
|
||||||
const previousCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
const previousCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
||||||
|
const moduleId = (route.meta?.moduleId as string) || '';
|
||||||
const loadOptions = {
|
const loadOptions = {
|
||||||
systemId: SYSTEM_ID,
|
systemId: SYSTEM_ID,
|
||||||
moduleId: MODULE_ID,
|
moduleId,
|
||||||
pageKey,
|
pageKey,
|
||||||
description: 'true'
|
description: 'true'
|
||||||
};
|
};
|
||||||
const layerConfigPromise =
|
const layerConfigPromise =
|
||||||
mapConfigStore.loadPageLayerConfig(loadOptions);
|
mapConfigStore.loadPageLayerConfig(loadOptions);
|
||||||
const legendConfigPromise = mapConfigStore.loadPageLegendConfig(pageKey);
|
const legendConfigPromise = mapConfigStore.loadPageLegendConfig(
|
||||||
const { legendOriginal, pageLegend } = await legendConfigPromise;
|
moduleId,
|
||||||
|
{
|
||||||
if (legendOriginal.length > 0) {
|
includeGlobal: shouldLoadGlobalLegend
|
||||||
mapStore.setLegendData(legendOriginal, pageLegend);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { layerConfig } = await layerConfigPromise;
|
// 同时等待两个 promise
|
||||||
|
const [{ layerConfig }, { legendOriginal, pageLegend }] =
|
||||||
|
await Promise.all([layerConfigPromise, legendConfigPromise]);
|
||||||
|
|
||||||
|
// 先设置图层数据(更新 checkedLayerKeys),再设置图例数据
|
||||||
if (layerConfig.length > 0) {
|
if (layerConfig.length > 0) {
|
||||||
mapStore.setLayerData(layerConfig);
|
mapStore.setLayerData(layerConfig);
|
||||||
ensureBaseLayersInitialized(layerConfig);
|
ensureBaseLayersInitialized(layerConfig);
|
||||||
|
|
||||||
let checkedKeys = mapViewStore.getCheckedLayerKeys();
|
let checkedKeys = mapViewStore.getCheckedLayerKeys();
|
||||||
if (previousPageKey === pageKey && previousCheckedKeys.length > 0) {
|
if (previousPageKey === pageKey && previousCheckedKeys.length > 0) {
|
||||||
const currentLayerKeys = new Set(
|
const getAllLayerKeys = (items: any[]): string[] => {
|
||||||
layerConfig
|
const keys: string[] = [];
|
||||||
.flatMap((item: any) => layerConfig2Flat([item]))
|
const walk = (nodes: any[]) => {
|
||||||
.map((item: any) => item?.key)
|
nodes.forEach(item => {
|
||||||
.filter(Boolean)
|
if (item?.key) {
|
||||||
);
|
keys.push(item.key);
|
||||||
|
}
|
||||||
|
if (item?.children?.length > 0) {
|
||||||
|
walk(item.children);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
walk(items);
|
||||||
|
return keys;
|
||||||
|
};
|
||||||
|
const currentLayerKeys = new Set(getAllLayerKeys(layerConfig));
|
||||||
const runtimeCheckedKeys = previousCheckedKeys.filter(key =>
|
const runtimeCheckedKeys = previousCheckedKeys.filter(key =>
|
||||||
currentLayerKeys.has(key)
|
currentLayerKeys.has(key)
|
||||||
);
|
);
|
||||||
if (runtimeCheckedKeys.length > 0) {
|
if (runtimeCheckedKeys.length > 0) {
|
||||||
mapViewStore.setCheckedLayerKeys(runtimeCheckedKeys);
|
mapViewStore.setCheckedLayerKeys(runtimeCheckedKeys);
|
||||||
mapStore.setSelectedLegendData();
|
|
||||||
checkedKeys = runtimeCheckedKeys;
|
checkedKeys = runtimeCheckedKeys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置图例数据(此时 checkedLayerKeys 已正确设置)
|
||||||
|
if (legendOriginal.length > 0) {
|
||||||
|
mapStore.setLegendData(legendOriginal, pageLegend);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldPreloadLayerData) {
|
||||||
|
mapStore.setSelectedLegendData();
|
||||||
await mapStore.loadAllLayerData(layerConfig, checkedKeys);
|
await mapStore.loadAllLayerData(layerConfig, checkedKeys);
|
||||||
|
} else {
|
||||||
|
await mapStore.updateLayerData(checkedKeys, true);
|
||||||
|
mapStore.setSelectedLegendData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// mapDataStore.setLoading(false);
|
// mapDataStore.setLoading(false);
|
||||||
@ -180,7 +220,7 @@ export const useMapOrchestrator = () => {
|
|||||||
popupContainer,
|
popupContainer,
|
||||||
pageKey
|
pageKey
|
||||||
});
|
});
|
||||||
await loadPage({ pageKey });
|
await loadPage({ pageKey, isInitialLoad: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 备注:统一绑定地图缩放监听,让页面组件只负责触发初始化,不再直接处理缩放联动细节。
|
// 备注:统一绑定地图缩放监听,让页面组件只负责触发初始化,不再直接处理缩放联动细节。
|
||||||
@ -218,13 +258,23 @@ export const useMapOrchestrator = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stopBaseSelectionWatch = watch(
|
stopBaseSelectionWatch = watch(
|
||||||
() => jidiSelectEventStore.selectedItem,
|
() => jidiSelectEventStore.selectedItem?.wbsCode,
|
||||||
newVal => {
|
newWbsCode => {
|
||||||
if (newVal?.wbsCode) {
|
if (!newWbsCode) {
|
||||||
changeBaseId(newVal.wbsCode);
|
changeBaseId('');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (baseSelectionDebounceTimer.value) {
|
||||||
|
clearTimeout(baseSelectionDebounceTimer.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
baseSelectionDebounceTimer.value = setTimeout(() => {
|
||||||
|
changeBaseId(newWbsCode);
|
||||||
|
baseSelectionDebounceTimer.value = null;
|
||||||
|
}, 100);
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -237,13 +287,31 @@ export const useMapOrchestrator = () => {
|
|||||||
await initializeMapShell(options);
|
await initializeMapShell(options);
|
||||||
bindBaseSelection();
|
bindBaseSelection();
|
||||||
bindZoomListener(options.getIsHydroMenu);
|
bindZoomListener(options.getIsHydroMenu);
|
||||||
await loadPage({ pageKey: options.pageKey });
|
await loadPage({ pageKey: options.pageKey, isInitialLoad: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 备注:统一处理菜单切换后的页面配置重载,供页面 watch 直接复用。
|
// 备注:统一处理菜单切换后的页面配置重载,供页面 watch 直接复用。
|
||||||
const reloadPage = async (pageKey: string) => {
|
const reloadPage = async (pageKey: string) => {
|
||||||
if (!pageKey) return;
|
if (!pageKey) return;
|
||||||
await loadPage({ pageKey });
|
await loadPage({ pageKey, isInitialLoad: false });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 备注:菜单切换前先隐藏旧页面当前可见的点图层,避免旧锚点残留到新页面接口返回之后才消失。
|
||||||
|
const hideCurrentVisiblePointLayers = () => {
|
||||||
|
const currentCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
||||||
|
|
||||||
|
currentCheckedKeys.forEach(layerKey => {
|
||||||
|
const layerItem = mapStore.findLayerByKey(mapStore.layerData, layerKey);
|
||||||
|
if (
|
||||||
|
!layerItem?.key ||
|
||||||
|
layerItem.type !== 'pointMap' ||
|
||||||
|
!mapClass.hasLayer(layerItem.key)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapClass.mdLayerTreeShowOrHidden(layerItem.key, false);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 备注:统一处理图层树勾选结果归一化和地图联动,供图层树组件复用。
|
// 备注:统一处理图层树勾选结果归一化和地图联动,供图层树组件复用。
|
||||||
@ -277,6 +345,9 @@ export const useMapOrchestrator = () => {
|
|||||||
// 备注:统一控制水电开发菜单下的动态图层增删,避免页面组件直接操作加载和勾选细节。
|
// 备注:统一控制水电开发菜单下的动态图层增删,避免页面组件直接操作加载和勾选细节。
|
||||||
const syncHydroDynamicLayers = async (visible: boolean) => {
|
const syncHydroDynamicLayers = async (visible: boolean) => {
|
||||||
const currentCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
const currentCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
||||||
|
const pageDefaultCheckedKeys = new Set(
|
||||||
|
mapConfigStore.extractCheckedLayerKeys(mapStore.layerData || [])
|
||||||
|
);
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
const layersToAdd = HYDRO_DYNAMIC_LAYER_KEYS.filter(
|
const layersToAdd = HYDRO_DYNAMIC_LAYER_KEYS.filter(
|
||||||
@ -293,9 +364,12 @@ export const useMapOrchestrator = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextCheckedKeys = currentCheckedKeys.filter(
|
const nextCheckedKeys = currentCheckedKeys.filter(key => {
|
||||||
key => !HYDRO_DYNAMIC_LAYER_KEYS.includes(key)
|
if (!HYDRO_DYNAMIC_LAYER_KEYS.includes(key)) {
|
||||||
);
|
return true;
|
||||||
|
}
|
||||||
|
return pageDefaultCheckedKeys.has(key);
|
||||||
|
});
|
||||||
|
|
||||||
if (nextCheckedKeys.length === currentCheckedKeys.length) {
|
if (nextCheckedKeys.length === currentCheckedKeys.length) {
|
||||||
return currentCheckedKeys;
|
return currentCheckedKeys;
|
||||||
@ -348,6 +422,11 @@ export const useMapOrchestrator = () => {
|
|||||||
const handlePageChange = async (pageKey: string, isHydroMenu: boolean) => {
|
const handlePageChange = async (pageKey: string, isHydroMenu: boolean) => {
|
||||||
if (!pageKey) return;
|
if (!pageKey) return;
|
||||||
|
|
||||||
|
const previousPageKey = mapConfigStore.lastLoadOptions?.pageKey || '';
|
||||||
|
if (previousPageKey && previousPageKey !== pageKey) {
|
||||||
|
hideCurrentVisiblePointLayers();
|
||||||
|
}
|
||||||
|
|
||||||
await reloadPage(pageKey);
|
await reloadPage(pageKey);
|
||||||
|
|
||||||
const currentZoom = getCurrentZoom();
|
const currentZoom = getCurrentZoom();
|
||||||
@ -452,7 +531,7 @@ export const useMapOrchestrator = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 备注:统一处理搜索定位,按点位编码从缓存数据中查找并飞行到目标位置。
|
// 备注:统一处理搜索定位,按点位编码从缓存数据中查找并飞行到目标位置。
|
||||||
const focusPoint = (pointId: string, zoom: number = 15) => {
|
const focusPoint = (pointId: string, zoom = 15) => {
|
||||||
if (!pointId) return;
|
if (!pointId) return;
|
||||||
const targetPoint = mapDataStore.pointData.find((item: any) => {
|
const targetPoint = mapDataStore.pointData.find((item: any) => {
|
||||||
return item.stcd === pointId || item._id === pointId;
|
return item.stcd === pointId || item._id === pointId;
|
||||||
@ -472,6 +551,11 @@ export const useMapOrchestrator = () => {
|
|||||||
stopBaseSelectionWatch();
|
stopBaseSelectionWatch();
|
||||||
stopBaseSelectionWatch = null;
|
stopBaseSelectionWatch = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (baseSelectionDebounceTimer.value) {
|
||||||
|
clearTimeout(baseSelectionDebounceTimer.value);
|
||||||
|
baseSelectionDebounceTimer.value = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -9,6 +9,10 @@ type MapConfigLoadOptions = {
|
|||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type LegendConfigLoadOptions = {
|
||||||
|
includeGlobal?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
const cloneConfigData = <T>(data: T): T => {
|
const cloneConfigData = <T>(data: T): T => {
|
||||||
return JSON.parse(JSON.stringify(data));
|
return JSON.parse(JSON.stringify(data));
|
||||||
};
|
};
|
||||||
@ -55,7 +59,7 @@ export const useMapConfigStore = defineStore('map-config', () => {
|
|||||||
|
|
||||||
const walk = (nodes: any[] = []) => {
|
const walk = (nodes: any[] = []) => {
|
||||||
nodes.forEach(item => {
|
nodes.forEach(item => {
|
||||||
if (item?.checked === 1 && item?.key) {
|
if (Number(item?.checked) === 1 && item?.key) {
|
||||||
keys.push(item.key);
|
keys.push(item.key);
|
||||||
}
|
}
|
||||||
if (item?.children?.length > 0) {
|
if (item?.children?.length > 0) {
|
||||||
@ -157,6 +161,7 @@ export const useMapConfigStore = defineStore('map-config', () => {
|
|||||||
moduleId: options.moduleId,
|
moduleId: options.moduleId,
|
||||||
description: options.description ?? 'true'
|
description: options.description ?? 'true'
|
||||||
});
|
});
|
||||||
|
console.log(cloneConfigData(layerRes));
|
||||||
|
|
||||||
const layerConfig = layerRes?.data?.mapLayerVos || [];
|
const layerConfig = layerRes?.data?.mapLayerVos || [];
|
||||||
setLayerConfigTree(layerConfig);
|
setLayerConfigTree(layerConfig);
|
||||||
@ -168,17 +173,32 @@ export const useMapConfigStore = defineStore('map-config', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadPageLegendConfig = async (pageKey?: string) => {
|
const loadPageLegendConfig = async (
|
||||||
|
pageKey?: string,
|
||||||
|
options: LegendConfigLoadOptions = {}
|
||||||
|
) => {
|
||||||
legendLoading.value = true;
|
legendLoading.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const includeGlobal = options.includeGlobal !== false;
|
||||||
|
|
||||||
|
let legendOriginal = legendConfigOriginal.value || [];
|
||||||
|
let pageLegend: any[] = [];
|
||||||
|
|
||||||
|
if (includeGlobal) {
|
||||||
const [legendAllRes, legendPageRes] = await Promise.all([
|
const [legendAllRes, legendPageRes] = await Promise.all([
|
||||||
getModuleMapLegendList(),
|
getModuleMapLegendList(),
|
||||||
getModuleMapLegendList(pageKey ? { moduleId: pageKey } : undefined)
|
getModuleMapLegendList(pageKey ? { moduleId: pageKey } : undefined)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const legendOriginal = legendAllRes?.data || [];
|
legendOriginal = legendAllRes?.data || [];
|
||||||
const pageLegend = legendPageRes?.data || [];
|
pageLegend = legendPageRes?.data || [];
|
||||||
|
} else {
|
||||||
|
const legendPageRes = await getModuleMapLegendList(
|
||||||
|
pageKey ? { moduleId: pageKey } : undefined
|
||||||
|
);
|
||||||
|
pageLegend = legendPageRes?.data || [];
|
||||||
|
}
|
||||||
|
|
||||||
setLegendConfigOriginal(legendOriginal);
|
setLegendConfigOriginal(legendOriginal);
|
||||||
setPageLegendConfig(pageLegend);
|
setPageLegendConfig(pageLegend);
|
||||||
@ -194,10 +214,9 @@ export const useMapConfigStore = defineStore('map-config', () => {
|
|||||||
|
|
||||||
// 备注:加载页面地图配置,只负责请求和保存配置数据,不处理锚点或地图渲染逻辑。
|
// 备注:加载页面地图配置,只负责请求和保存配置数据,不处理锚点或地图渲染逻辑。
|
||||||
const loadPageMapConfig = async (options: MapConfigLoadOptions) => {
|
const loadPageMapConfig = async (options: MapConfigLoadOptions) => {
|
||||||
const [{ layerConfig }, { legendOriginal, pageLegend }] = await Promise.all([
|
const [{ layerConfig }, { legendOriginal, pageLegend }] = await Promise.all(
|
||||||
loadPageLayerConfig(options),
|
[loadPageLayerConfig(options), loadPageLegendConfig(options.pageKey)]
|
||||||
loadPageLegendConfig(options.pageKey)
|
);
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
layerConfig,
|
layerConfig,
|
||||||
|
|||||||
@ -70,6 +70,7 @@ import dayjs from 'dayjs';
|
|||||||
import { ZoomInOutlined } from '@ant-design/icons-vue';
|
import { ZoomInOutlined } from '@ant-design/icons-vue';
|
||||||
import type { Dayjs } from 'dayjs';
|
import type { Dayjs } from 'dayjs';
|
||||||
import MonthlyAverage from '../monthlyAverage.vue';
|
import MonthlyAverage from '../monthlyAverage.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MonthlyAverageMaxModal'
|
name: 'MonthlyAverageMaxModal'
|
||||||
@ -101,7 +102,7 @@ const detailModalData = ref<any>(null);
|
|||||||
// 选择器相关 - 内部状态管理
|
// 选择器相关 - 内部状态管理
|
||||||
const selectValue = ref('');
|
const selectValue = ref('');
|
||||||
const selectOptions = ref<any[]>([]);
|
const selectOptions = ref<any[]>([]);
|
||||||
|
useDraggable(detailModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 树形选择器展开状态管理
|
// 树形选择器展开状态管理
|
||||||
const treeExpandedKeys = ref<string[]>([])
|
const treeExpandedKeys = ref<string[]>([])
|
||||||
const nodeMap = new Map<string, { node: any; parentKey: string | null }>()
|
const nodeMap = new Map<string, { node: any; parentKey: string | null }>()
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import dayjs from 'dayjs'
|
|||||||
import {
|
import {
|
||||||
ZoomInOutlined
|
ZoomInOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'monthlyAvgWaterTemCompareHistory'
|
name: 'monthlyAvgWaterTemCompareHistory'
|
||||||
@ -68,7 +69,8 @@ const stationName = ref('');
|
|||||||
|
|
||||||
// 图表放大展示弹框状态
|
// 图表放大展示弹框状态
|
||||||
const zoomModalVisible = ref(false);
|
const zoomModalVisible = ref(false);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(zoomModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 选择器配置
|
// 选择器配置
|
||||||
const select = ref({
|
const select = ref({
|
||||||
show: true,
|
show: true,
|
||||||
|
|||||||
@ -104,7 +104,6 @@ import { message } from 'ant-design-vue';
|
|||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import type { EChartsOption } from 'echarts';
|
import type { EChartsOption } from 'echarts';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { wbsbGetKendoList, getVmsstbprpt, DetGetKendoListCust } from '@/api/sw';
|
import { wbsbGetKendoList, getVmsstbprpt, DetGetKendoListCust } from '@/api/sw';
|
||||||
import BasicTable from '@/components/BasicTable/index.vue';
|
import BasicTable from '@/components/BasicTable/index.vue';
|
||||||
|
|||||||
@ -3,36 +3,66 @@
|
|||||||
<SidePanelItem title="栖息地保护工作开展情况">
|
<SidePanelItem title="栖息地保护工作开展情况">
|
||||||
<a-spin :spinning="loading" tip="加载中...">
|
<a-spin :spinning="loading" tip="加载中...">
|
||||||
<div class="facility-grid">
|
<div class="facility-grid">
|
||||||
<div v-for="facility in facilities" :key="facility.name" class="facility-card"
|
<div
|
||||||
@click="handleFacilityClick(facility)">
|
v-for="facility in facilities"
|
||||||
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
|
:key="facility.name"
|
||||||
|
class="facility-card"
|
||||||
|
@click="handleFacilityClick(facility)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
width: 60px;
|
||||||
|
height: 62px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
<div class="facility-icon">
|
<div class="facility-icon">
|
||||||
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
|
<i
|
||||||
|
style="color: #fff"
|
||||||
|
:class="facility.icon"
|
||||||
|
type="icon-shengtailiuliang2"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="facility-info">
|
<div class="facility-info">
|
||||||
<div class="facility-name">{{ facility.name }}</div>
|
<div class="facility-name">{{ facility.name }}</div>
|
||||||
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count
|
<div style="font-size: 16px">
|
||||||
}}</span><span>个</span></div>
|
<span class="facility-count">{{ facility.count }}</span
|
||||||
|
><span>个</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
<!-- 弹框 -->
|
<!-- 弹框 -->
|
||||||
<a-modal v-model:open="modalVisible" :title="'栖息地保护工作开展情况'" :footer="null" width="1536px" @cancel="handleCloseModal">
|
<a-modal
|
||||||
<QixidiheduanjianceqingkuangEJ v-if="currentFacility" :activeKey="currentFacility.sttpCode" :tabs="facilities"
|
v-model:open="modalVisible"
|
||||||
:baseId="baseid" />
|
:title="'栖息地保护工作开展情况'"
|
||||||
|
:footer="null"
|
||||||
|
width="1536px"
|
||||||
|
@cancel="handleCloseModal"
|
||||||
|
>
|
||||||
|
<QixidiheduanjianceqingkuangEJ
|
||||||
|
v-if="currentFacility"
|
||||||
|
:activeKey="currentFacility.sttpCode"
|
||||||
|
:tabs="facilities"
|
||||||
|
:baseId="baseid"
|
||||||
|
/>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { fhGetKendoListCust } from '@/api/qxd'
|
import { fhGetKendoListCust } from '@/api/qxd';
|
||||||
import QixidiheduanjianceqingkuangEJ from "./qixidiheduanjianceqingkuangEJ/index.vue"
|
import QixidiheduanjianceqingkuangEJ from './qixidiheduanjianceqingkuangEJ/index.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'qixidibaohugongzuokaizhanQK'
|
name: 'qixidibaohugongzuokaizhanQK'
|
||||||
@ -65,43 +95,47 @@ const facilities = ref([
|
|||||||
count: 0,
|
count: 0,
|
||||||
icon: 'icon iconfont icon-shipinjiankongshebei',
|
icon: 'icon iconfont icon-shipinjiankongshebei',
|
||||||
sttpCode: 'VD'
|
sttpCode: 'VD'
|
||||||
},
|
}
|
||||||
|
|
||||||
]);
|
]);
|
||||||
const baseid = ref('')
|
const baseid = ref('');
|
||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentFacility = ref<any>(null);
|
const currentFacility = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
//获取页面数据
|
//获取页面数据
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
let params = {
|
let params = {
|
||||||
"filter": {
|
filter: {
|
||||||
"logic": "and",
|
logic: 'and',
|
||||||
"filters": [
|
filters: [
|
||||||
baseid.value != 'all' ? {
|
baseid.value != 'all'
|
||||||
"field": "baseId",
|
? {
|
||||||
"operator": "eq",
|
field: 'baseId',
|
||||||
"dataType": "string",
|
operator: 'eq',
|
||||||
"value": baseid.value
|
dataType: 'string',
|
||||||
} : null
|
value: baseid.value
|
||||||
|
}
|
||||||
|
: null
|
||||||
].filter(Boolean)
|
].filter(Boolean)
|
||||||
},
|
},
|
||||||
"group": [
|
group: [
|
||||||
{
|
{
|
||||||
"dir": "asc",
|
dir: 'asc',
|
||||||
"field": "sttpCode"
|
field: 'sttpCode'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groupResultFlat": true
|
groupResultFlat: true
|
||||||
}
|
};
|
||||||
const res = await fhGetKendoListCust(params); //适配监控-VD
|
const res = await fhGetKendoListCust(params); //适配监控-VD
|
||||||
let data = res?.data?.data || res?.data || [];
|
let data = res?.data?.data || res?.data || [];
|
||||||
|
|
||||||
// 根据接口返回的数据更新 facilities 的 count
|
// 根据接口返回的数据更新 facilities 的 count
|
||||||
facilities.value.forEach(facility => {
|
facilities.value.forEach(facility => {
|
||||||
const matchedItem = data.find(item => item.sttpCode === facility.sttpCode);
|
const matchedItem = data.find(
|
||||||
|
item => item.sttpCode === facility.sttpCode
|
||||||
|
);
|
||||||
if (matchedItem) {
|
if (matchedItem) {
|
||||||
facility.count = matchedItem.count_sttpCode || 0;
|
facility.count = matchedItem.count_sttpCode || 0;
|
||||||
} else {
|
} else {
|
||||||
@ -113,13 +147,11 @@ const getData = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
// 点击处理函数
|
// 点击处理函数
|
||||||
const handleFacilityClick = (facility: any) => {
|
const handleFacilityClick = (facility: any) => {
|
||||||
currentFacility.value = facility;
|
currentFacility.value = facility;
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
// 关闭弹框
|
// 关闭弹框
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = () => {
|
||||||
@ -129,22 +161,19 @@ const handleCloseModal = () => {
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => JidiSelectEventStore.selectedItem,
|
() => JidiSelectEventStore.selectedItem,
|
||||||
(newVal) => {
|
newVal => {
|
||||||
baseid.value = newVal.wbsCode;
|
baseid.value = newVal.wbsCode;
|
||||||
getData()
|
getData();
|
||||||
},
|
},
|
||||||
{ deep: true, immediate: true }
|
{ deep: true, immediate: true }
|
||||||
);
|
);
|
||||||
// 页面加载时执行
|
// 页面加载时执行
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 延迟初始化,确保容器已渲染
|
// 延迟初始化,确保容器已渲染
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 组件卸载时清理
|
// 组件卸载时清理
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {});
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -153,7 +182,9 @@ onUnmounted(() => {
|
|||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
||||||
|
Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji,
|
||||||
|
Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
.facility-card {
|
.facility-card {
|
||||||
|
|||||||
@ -55,7 +55,7 @@
|
|||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:scrollY="380"
|
:scrollY="380"
|
||||||
:scrollX="100"
|
|
||||||
:list-url="vmsstbprptGetKendoList"
|
:list-url="vmsstbprptGetKendoList"
|
||||||
:search-params="searchParams"
|
:search-params="searchParams"
|
||||||
:transform-data="customTransform"
|
:transform-data="customTransform"
|
||||||
@ -834,7 +834,6 @@ const handleResize = () => {
|
|||||||
width: 35%;
|
width: 35%;
|
||||||
height: 482px;
|
height: 482px;
|
||||||
// position: relative;
|
// position: relative;
|
||||||
min-width: 521px;
|
|
||||||
|
|
||||||
.pie-chart {
|
.pie-chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
:title="'生态流量泄放方式'"
|
:title="'生态流量泄放方式'"
|
||||||
width="1536px"
|
width="80%"
|
||||||
@cancel="handleModalCancel"
|
@cancel="handleModalCancel"
|
||||||
>
|
>
|
||||||
<STLLXFFS
|
<STLLXFFS
|
||||||
@ -57,6 +57,8 @@ import type { ECharts } from 'echarts';
|
|||||||
import { msstbprptGetKendoList } from '@/api/stll';
|
import { msstbprptGetKendoList } from '@/api/stll';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import STLLXFFS from './TwoLayer/STLLXFFS.vue';
|
import STLLXFFS from './TwoLayer/STLLXFFS.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'xieFangFangShi'
|
name: 'xieFangFangShi'
|
||||||
@ -78,7 +80,7 @@ const apiRawData = ref<any[]>([]); // 保存原始 API 数据
|
|||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const modalTitle = ref('');
|
const modalTitle = ref('');
|
||||||
const selectedData = ref<any>(null);
|
const selectedData = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 颜色配置(根据图片配色)
|
// 颜色配置(根据图片配色)
|
||||||
const colors = [
|
const colors = [
|
||||||
'#9556a4', // 基荷发电 - 紫色
|
'#9556a4', // 基荷发电 - 紫色
|
||||||
|
|||||||
@ -676,7 +676,7 @@ onUnmounted(() => {
|
|||||||
.chart-section {
|
.chart-section {
|
||||||
width: 35%;
|
width: 35%;
|
||||||
height: 482px;
|
height: 482px;
|
||||||
min-width: 521px;
|
|
||||||
|
|
||||||
.pie-chart {
|
.pie-chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
title="泄放方式分布情况"
|
title="泄放方式分布情况"
|
||||||
width="1536px"
|
width="80%"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@cancel="handleModalCancel"
|
@cancel="handleModalCancel"
|
||||||
>
|
>
|
||||||
@ -38,6 +38,8 @@ import type { ECharts } from 'echarts';
|
|||||||
import { vmsstbprptGetKendoList } from '@/api/stll';
|
import { vmsstbprptGetKendoList } from '@/api/stll';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import FBQKTwolayer from './TwoLayer/FenBuQingKuangTwoLayer.vue';
|
import FBQKTwolayer from './TwoLayer/FenBuQingKuangTwoLayer.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名
|
// 定义组件名
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'XieFangFenBu'
|
name: 'XieFangFenBu'
|
||||||
@ -59,7 +61,7 @@ const wbsCode = ref('');
|
|||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const selectData = ref(''); // 选中的设施类型名称
|
const selectData = ref(''); // 选中的设施类型名称
|
||||||
const jidiName = ref(''); // 选中的基地名称
|
const jidiName = ref(''); // 选中的基地名称
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 设施类型配置
|
// 设施类型配置
|
||||||
const typeName = [
|
const typeName = [
|
||||||
{ label: '生态放流孔', eqtp: 'EQ_1' },
|
{ label: '生态放流孔', eqtp: 'EQ_1' },
|
||||||
|
|||||||
@ -8,10 +8,10 @@
|
|||||||
<p>
|
<p>
|
||||||
1、统计电站范围:接入过生态流量数据的电站
|
1、统计电站范围:接入过生态流量数据的电站
|
||||||
<span
|
<span
|
||||||
style="color: #5989ad; cursor: pointer; "
|
style="color: #5989ad; cursor: pointer"
|
||||||
@click.stop="handleStationClick()"
|
@click.stop="handleStationClick()"
|
||||||
>
|
>
|
||||||
({{titleData.cnt}})
|
({{ titleData.cnt }})
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p>2、当来水不足时,生态流量不小于入库流量判定为达标</p>
|
<p>2、当来水不足时,生态流量不小于入库流量判定为达标</p>
|
||||||
@ -88,7 +88,11 @@
|
|||||||
width="1536px"
|
width="1536px"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
>
|
>
|
||||||
<ModalYkzhbzdjcgz v-if="huanbaoModalVisible" :baseId="baseid" :titleData = titleData />
|
<ModalYkzhbzdjcgz
|
||||||
|
v-if="huanbaoModalVisible"
|
||||||
|
:baseId="baseid"
|
||||||
|
:titleData="titleData"
|
||||||
|
/>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -105,6 +109,7 @@ import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
|||||||
import STLLXFFS from './TwoLayer/ShengTaiLiuLiangDaBQKTwoLayer.vue';
|
import STLLXFFS from './TwoLayer/ShengTaiLiuLiangDaBQKTwoLayer.vue';
|
||||||
import ModalYkzhbzdjcgz from './TwoLayer/ModalYkzhbzdjcgz.vue';
|
import ModalYkzhbzdjcgz from './TwoLayer/ModalYkzhbzdjcgz.vue';
|
||||||
import HuanbaoZDJCGZKZ from '@/modules/huanbaozdjcgzkzQK/index.vue';
|
import HuanbaoZDJCGZKZ from '@/modules/huanbaozdjcgzkzQK/index.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shengtaidabiaoMod'
|
name: 'shengtaidabiaoMod'
|
||||||
@ -146,10 +151,13 @@ const datalist: any = ref([]);
|
|||||||
const allArr: any = ref(Array.from({ length: 20 }, (_, i) => i));
|
const allArr: any = ref(Array.from({ length: 20 }, (_, i) => i));
|
||||||
const spinning = ref(false);
|
const spinning = ref(false);
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const modalTitle = ref('');
|
|
||||||
const selectedItem = ref<any>(null);
|
const selectedItem = ref<any>(null);
|
||||||
const huanbaoModalVisible = ref(false);
|
const huanbaoModalVisible = ref(false);
|
||||||
|
|
||||||
|
// 启用弹窗拖拽(限制在可视区域内)
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
// 启用弹窗拖拽(限制在可视区域内)
|
||||||
|
useDraggable(huanbaoModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 处理电站数量点击事件
|
// 处理电站数量点击事件
|
||||||
const handleStationClick = () => {
|
const handleStationClick = () => {
|
||||||
huanbaoModalVisible.value = true;
|
huanbaoModalVisible.value = true;
|
||||||
@ -158,7 +166,6 @@ const handleStationClick = () => {
|
|||||||
// 处理进度条点击事件
|
// 处理进度条点击事件
|
||||||
const handleBarClick = (item: any) => {
|
const handleBarClick = (item: any) => {
|
||||||
selectedItem.value = item;
|
selectedItem.value = item;
|
||||||
// modalTitle.value = `${item.name} - 详细信息`;
|
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -316,43 +323,41 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
//统计电站范围:接入过生态流量数据的电站
|
//统计电站范围:接入过生态流量数据的电站
|
||||||
const titleData:any = ref({ cnt: 0 })
|
const titleData: any = ref({ cnt: 0 });
|
||||||
const getcont = async () => {
|
const getcont = async () => {
|
||||||
let params = {
|
let params = {
|
||||||
"filter": {
|
filter: {
|
||||||
"logic": "and",
|
logic: 'and',
|
||||||
"filters": [
|
filters: [
|
||||||
{
|
{
|
||||||
"field": "showIds",
|
field: 'showIds',
|
||||||
"operator": "in",
|
operator: 'in',
|
||||||
"value": [
|
value: ['7']
|
||||||
"7"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
let res = await evnmAutoMonitorGetKendoListCust(params);
|
let res = await evnmAutoMonitorGetKendoListCust(params);
|
||||||
// [
|
// [
|
||||||
// {
|
// {
|
||||||
// "cnt": 452,
|
// "cnt": 452,
|
||||||
// "orderInx": 7,
|
// "orderInx": 7,
|
||||||
// "orderInxName": "生态流量",
|
// "orderInxName": "生态流量",
|
||||||
// "sttpFullPath": "ENG",
|
// "sttpFullPath": "ENG",
|
||||||
// "sttpCode": "ENG",
|
// "sttpCode": "ENG",
|
||||||
// "sttpName": "生态流量"
|
// "sttpName": "生态流量"
|
||||||
// }
|
// }
|
||||||
// ]
|
// ]
|
||||||
let list = res?.data?.data[0];
|
let list = res?.data?.data[0];
|
||||||
if (list) {
|
if (list) {
|
||||||
titleData.value = list
|
titleData.value = list;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
};
|
};
|
||||||
// 页面加载时执行的逻辑
|
// 页面加载时执行的逻辑
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setStyle();
|
setStyle();
|
||||||
getcont()
|
getcont();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -105,6 +105,8 @@ import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
|||||||
import STLLXFFS from './TwoLayer/ShengTaiLiuLiangDaBQKTwoLayer.vue';
|
import STLLXFFS from './TwoLayer/ShengTaiLiuLiangDaBQKTwoLayer.vue';
|
||||||
import ModalYkzhbzdjcgz from './TwoLayer/ModalYkzhbzdjcgz.vue';
|
import ModalYkzhbzdjcgz from './TwoLayer/ModalYkzhbzdjcgz.vue';
|
||||||
import HuanbaoZDJCGZKZ from '@/modules/huanbaozdjcgzkzQK/index.vue';
|
import HuanbaoZDJCGZKZ from '@/modules/huanbaozdjcgzkzQK/index.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shengtaidabiaoMod'
|
name: 'shengtaidabiaoMod'
|
||||||
@ -149,7 +151,8 @@ const modalVisible = ref(false);
|
|||||||
const modalTitle = ref('');
|
const modalTitle = ref('');
|
||||||
const selectedItem = ref<any>(null);
|
const selectedItem = ref<any>(null);
|
||||||
const huanbaoModalVisible = ref(false);
|
const huanbaoModalVisible = ref(false);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(huanbaoModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 处理电站数量点击事件
|
// 处理电站数量点击事件
|
||||||
const handleStationClick = () => {
|
const handleStationClick = () => {
|
||||||
huanbaoModalVisible.value = true;
|
huanbaoModalVisible.value = true;
|
||||||
|
|||||||
@ -67,6 +67,8 @@ import { eqqecRateCount, evnmAutoMonitorGetKendoListCust } from '@/api/stll';
|
|||||||
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
|
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
|
||||||
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
|
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
|
||||||
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shengtaidabiaoMod'
|
name: 'shengtaidabiaoMod'
|
||||||
@ -604,6 +606,8 @@ watch(
|
|||||||
const detailModalVisible = ref(false);
|
const detailModalVisible = ref(false);
|
||||||
const detailModalTitle = ref('');
|
const detailModalTitle = ref('');
|
||||||
const detailData = ref<any[]>([]);
|
const detailData = ref<any[]>([]);
|
||||||
|
useDraggable(huanbaoModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(detailModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const detailColumns = ref([
|
const detailColumns = ref([
|
||||||
{
|
{
|
||||||
title: mode.value === 'top' ? '基地名称' : '调节性能',
|
title: mode.value === 'top' ? '基地名称' : '调节性能',
|
||||||
|
|||||||
@ -68,6 +68,8 @@ import { eqqecRateCount, evnmAutoMonitorGetKendoListCust } from '@/api/stll';
|
|||||||
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
|
import ModalYkzhbzdjcgz from '../shengtaidabiaoMod/TwoLayer/ModalYkzhbzdjcgz.vue';
|
||||||
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
|
import STLLXFFS from './TwoLayer/STLLXFFS.vue'
|
||||||
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shengtaidabiaoMod'
|
name: 'shengtaidabiaoMod'
|
||||||
@ -97,6 +99,7 @@ const huanbaoModalVisible = ref(false);
|
|||||||
const handleStationClick = () => {
|
const handleStationClick = () => {
|
||||||
huanbaoModalVisible.value = true;
|
huanbaoModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
@ -633,6 +636,8 @@ const detailColumns = ref([
|
|||||||
watch(mode, () => {
|
watch(mode, () => {
|
||||||
loadData();
|
loadData();
|
||||||
});
|
});
|
||||||
|
useDraggable(huanbaoModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
useDraggable(detailModalVisible, { boundary: true, resetOnOpen: true });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -62,6 +62,8 @@ import { ref, onMounted, onUnmounted, computed } from 'vue';
|
|||||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
import { sttpbGetKendoList } from '@/api/sw';
|
import { sttpbGetKendoList } from '@/api/sw';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'diwenshuijianhuansheshileixingzuchengjijieruqingkuang'
|
name: 'diwenshuijianhuansheshileixingzuchengjijieruqingkuang'
|
||||||
@ -96,6 +98,7 @@ const isTransitioning = ref(false);
|
|||||||
// 弹框控制
|
// 弹框控制
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentItem = ref<any>(null);
|
const currentItem = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 初始化渲染数组(克隆首尾项)
|
// 初始化渲染数组(克隆首尾项)
|
||||||
const initRenderData = () => {
|
const initRenderData = () => {
|
||||||
const length = originalMediaData.value.length;
|
const length = originalMediaData.value.length;
|
||||||
|
|||||||
@ -43,6 +43,7 @@ import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
|||||||
import YaerAverage from './TwoLayers/yaerAverage.vue';
|
import YaerAverage from './TwoLayers/yaerAverage.vue';
|
||||||
|
|
||||||
import { MapClass } from '@/components/gis/map.class';
|
import { MapClass } from '@/components/gis/map.class';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
// 水温年内分布数据(响应式)
|
// 水温年内分布数据(响应式)
|
||||||
@ -52,7 +53,7 @@ const showemit = ref(true);
|
|||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentData = ref<any>({});
|
const currentData = ref<any>({});
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
const chartRef = ref<HTMLElement | null>(null);
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
let chartInstance: echarts.ECharts | null = null;
|
||||||
// 选择器配置
|
// 选择器配置
|
||||||
|
|||||||
@ -4,6 +4,21 @@
|
|||||||
<a-table :columns="columns" :data-source="tableData" :pagination="false" size="middle" :customRow="customRow"
|
<a-table :columns="columns" :data-source="tableData" :pagination="false" size="middle" :customRow="customRow"
|
||||||
:loading="dataLoading" bordered class="custom-table">
|
:loading="dataLoading" bordered class="custom-table">
|
||||||
</a-table>
|
</a-table>
|
||||||
|
<a-modal
|
||||||
|
v-model:open="modalVisible"
|
||||||
|
title="水电开发情况"
|
||||||
|
width="80%"
|
||||||
|
:footer="null"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
>
|
||||||
|
<ShuiDianKaiFQKTwoLayer
|
||||||
|
v-if="modalVisible"
|
||||||
|
:defaultJidiInfo="modalProps.defaultJidiInfo"
|
||||||
|
:seriesName="modalProps.seriesName"
|
||||||
|
:stateName="modalProps.stateName"
|
||||||
|
:defaultTab="modalProps.defaultTab"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -11,6 +26,8 @@
|
|||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { getVmsstbprptKendoList } from '@/api/home';
|
import { getVmsstbprptKendoList } from '@/api/home';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import ShuiDianKaiFQKTwoLayer from './TwoLayer/ShuiDianKaiFQKTwoLayer.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'DataTable'
|
name: 'DataTable'
|
||||||
@ -25,6 +42,26 @@ const baseid = ref('');
|
|||||||
const dataLoading = ref(false);
|
const dataLoading = ref(false);
|
||||||
const tableData = ref<any[]>([]);
|
const tableData = ref<any[]>([]);
|
||||||
|
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const modalProps = ref<any>({});
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
|
const openDialog = (record: any) => {
|
||||||
|
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
||||||
|
const isAll = currentJidiInfo?.wbsCode === 'all';
|
||||||
|
const stateName = record.bldsttCcode === '0' ? '未建' : record.bldsttCcode === '1' ? '在建' : '已建';
|
||||||
|
|
||||||
|
modalProps.value = {
|
||||||
|
defaultJidiInfo: {
|
||||||
|
baseid: isAll ? record.key : currentJidiInfo?.wbsCode || 'all',
|
||||||
|
basename: isAll ? record.name : currentJidiInfo?.wbsName || '全部基地'
|
||||||
|
},
|
||||||
|
seriesName: '装机容量(万kW)',
|
||||||
|
stateName,
|
||||||
|
defaultTab: stateName
|
||||||
|
};
|
||||||
|
modalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '基地名称',
|
title: '基地名称',
|
||||||
@ -183,6 +220,7 @@ const customRow = (record: any, index: number) => {
|
|||||||
},
|
},
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
if (record.name !== '总计') {
|
if (record.name !== '总计') {
|
||||||
|
openDialog(record);
|
||||||
emit('row-click', record);
|
emit('row-click', record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,58 +1,24 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
|
||||||
<template>
|
<template>
|
||||||
<div class="basic_body">
|
<div class="basic_body">
|
||||||
<SidePanelItem title="大中型水电开发及环境监测数据接入情况" :prompt="prompt">
|
<SidePanelItem title="大中型水电开发及环境监测数据接入情况" >
|
||||||
<div>
|
<div>
|
||||||
<div class="body_top">
|
<div class="body_top">
|
||||||
<!-- {/* 水电开发情况图表 */} -->
|
|
||||||
<div style="flex: 1;">
|
<div style="flex: 1;">
|
||||||
<div>水电开发情况</div>
|
<div>水电开发情况</div>
|
||||||
<div style="color: #757575;font-size: 12px;line-height: 16px;">图释:数量(内)/装机容量(外)</div>
|
<div style="color: #757575;font-size: 12px;line-height: 16px;">图释:数量(内)/装机容量(外)</div>
|
||||||
<div>
|
<a-spin :spinning="developStatusChartRef?.dataLoading">
|
||||||
<DevelopStatusChart @chart-click="handleChartClick" />
|
<DevelopStatusChart ref="developStatusChartRef" />
|
||||||
|
</a-spin>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<!-- style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center" }} -->
|
|
||||||
<div style="flex: 1;display: flex; flex-direction: column; align-items: center;">
|
<div style="flex: 1;display: flex; flex-direction: column; align-items: center;">
|
||||||
<EngEnvironmentData @item-click="handleEnvItemClick" />
|
<a-spin :spinning="engEnvironmentDataRef?.dataLoading">
|
||||||
|
<EngEnvironmentData ref="engEnvironmentDataRef" />
|
||||||
|
</a-spin>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DataTable @row-click="handleRowClick" />
|
<DataTable />
|
||||||
</div>
|
</div>
|
||||||
<!-- <div v-else class="zanwushujv"> <a-empty /></div> -->
|
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
|
|
||||||
<!-- 水电开发情况弹窗 -->
|
|
||||||
<a-modal
|
|
||||||
v-model:open="shuidianModalVisible"
|
|
||||||
:title="shuidianModalTitle"
|
|
||||||
width="1536px"
|
|
||||||
:footer="null"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
>
|
|
||||||
<ShuiDianKaiFQKTwoLayer
|
|
||||||
v-if="shuidianModalVisible"
|
|
||||||
:defaultJidiInfo="shuidianModalProps.defaultJidiInfo"
|
|
||||||
:seriesName="shuidianModalProps.seriesName"
|
|
||||||
:stateName="shuidianModalProps.stateName"
|
|
||||||
:defaultTab="shuidianModalProps.defaultTab"
|
|
||||||
/>
|
|
||||||
</a-modal>
|
|
||||||
|
|
||||||
<!-- 环境监测数据接入情况弹窗 -->
|
|
||||||
<a-modal
|
|
||||||
v-model:open="huanjingModalVisible"
|
|
||||||
:title="huanjingModalTitle"
|
|
||||||
width="1536px"
|
|
||||||
:footer="null"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
>
|
|
||||||
<HuanJingSJJRQK
|
|
||||||
v-if="huanjingModalVisible"
|
|
||||||
:dataDimensionVal="huanjingModalProps.dataDimensionVal"
|
|
||||||
:name="huanjingModalProps.name"
|
|
||||||
/>
|
|
||||||
</a-modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -62,36 +28,21 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import DevelopStatusChart from "@/components/developStatusChart/index.vue"
|
import DevelopStatusChart from "@/components/developStatusChart/index.vue"
|
||||||
import EngEnvironmentData from "@/components/engEnvironmentData/index.vue"
|
import EngEnvironmentData from "@/components/engEnvironmentData/index.vue"
|
||||||
import DataTable from "./DataTable.vue"
|
import DataTable from "./DataTable.vue"
|
||||||
import ShuiDianKaiFQKTwoLayer from "./TwoLayer/ShuiDianKaiFQKTwoLayer.vue"
|
|
||||||
import HuanJingSJJRQK from "./TwoLayer/HuanJingSJJRQK.vue"
|
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
|
import { Spin } from 'ant-design-vue';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shuidianhuangjingjieruMod'
|
name: 'shuidianhuangjingjieruMod'
|
||||||
});
|
});
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
|
||||||
const prompt = ref({
|
const developStatusChartRef = ref<InstanceType<typeof DevelopStatusChart> | null>(null);
|
||||||
show: true,
|
const engEnvironmentDataRef = ref<InstanceType<typeof EngEnvironmentData> | null>(null);
|
||||||
value: '统计大中型已建,在建水电站',
|
|
||||||
})
|
|
||||||
|
|
||||||
// 水电开发情况弹窗状态
|
|
||||||
const shuidianModalVisible = ref(false);
|
|
||||||
const shuidianModalTitle = ref('水电开发情况');
|
|
||||||
const shuidianModalProps = ref<any>({});
|
|
||||||
|
|
||||||
// 环境监测数据接入情况弹窗状态
|
|
||||||
const huanjingModalVisible = ref(false);
|
|
||||||
const huanjingModalTitle = ref('环境监测数据接入情况');
|
|
||||||
const huanjingModalProps = ref<any>({});
|
|
||||||
|
|
||||||
// DataTable 行点击事件
|
|
||||||
const handleRowClick = (record: any) => {
|
const handleRowClick = (record: any) => {
|
||||||
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
||||||
shuidianModalProps.value = {
|
developStatusChartRef.value?.openModal({
|
||||||
defaultJidiInfo: {
|
defaultJidiInfo: {
|
||||||
baseid: currentJidiInfo?.wbsCode || 'all',
|
baseid: currentJidiInfo?.wbsCode || 'all',
|
||||||
basename: currentJidiInfo?.wbsName || '全部基地'
|
basename: currentJidiInfo?.wbsName || '全部基地'
|
||||||
@ -99,41 +50,10 @@ const handleRowClick = (record: any) => {
|
|||||||
seriesName: currentJidiInfo?.wbsCode === 'other' ? '数量(座)' : '装机容量(万kW)',
|
seriesName: currentJidiInfo?.wbsCode === 'other' ? '数量(座)' : '装机容量(万kW)',
|
||||||
stateName: record.bldsttCcode === '0' ? '未建' : record.bldsttCcode === '1' ? '在建' : '已建',
|
stateName: record.bldsttCcode === '0' ? '未建' : record.bldsttCcode === '1' ? '在建' : '已建',
|
||||||
defaultTab: record.bldsttCcode === '0' ? '未建' : record.bldsttCcode === '1' ? '在建' : '已建'
|
defaultTab: record.bldsttCcode === '0' ? '未建' : record.bldsttCcode === '1' ? '在建' : '已建'
|
||||||
};
|
});
|
||||||
shuidianModalTitle.value = '水电开发情况';
|
|
||||||
shuidianModalVisible.value = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// DevelopStatusChart 饼图点击事件
|
|
||||||
const handleChartClick = (params: any) => {
|
|
||||||
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
|
||||||
shuidianModalProps.value = {
|
|
||||||
defaultJidiInfo: {
|
|
||||||
baseid: currentJidiInfo?.wbsCode || 'all',
|
|
||||||
basename: currentJidiInfo?.wbsName || '全部基地'
|
|
||||||
},
|
|
||||||
seriesName: params.seriesName,
|
|
||||||
stateName: params.name,
|
|
||||||
defaultTab: params.name
|
|
||||||
};
|
|
||||||
shuidianModalTitle.value = '水电开发情况';
|
|
||||||
shuidianModalVisible.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// EngEnvironmentData 指标点击事件
|
|
||||||
const handleEnvItemClick = (params: any) => {
|
|
||||||
const currentJidiInfo = JidiSelectEventStore.selectedItem;
|
|
||||||
huanjingModalProps.value = {
|
|
||||||
dataDimensionVal: currentJidiInfo?.wbsCode || 'all',
|
|
||||||
name: params.name
|
|
||||||
};
|
|
||||||
huanjingModalTitle.value = '环境监测数据接入情况';
|
|
||||||
huanjingModalVisible.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 页面加载时执行的逻辑
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,7 @@ import SsstdcgkTk from './SsstdcgkTk.vue';
|
|||||||
import { wbsbGetKendoList, getDftYear, getWeFisht } from '@/api/stdc';
|
import { wbsbGetKendoList, getDftYear, getWeFisht } from '@/api/stdc';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Label } from 'cesium';
|
import { Label } from 'cesium';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名
|
// 定义组件名
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -80,7 +81,7 @@ const dataLoading = ref(false);
|
|||||||
|
|
||||||
// ==================== 弹框状态 ====================
|
// ==================== 弹框状态 ====================
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// ==================== 响应式变量定义 ====================
|
// ==================== 响应式变量定义 ====================
|
||||||
// 选择器配置
|
// 选择器配置
|
||||||
const select = ref({
|
const select = ref({
|
||||||
|
|||||||
@ -40,6 +40,8 @@ import SidePanelItem from "@/components/SidePanelItem/index.vue";
|
|||||||
import { getKendoListCust, baseEvnmAutoMonitorGetKendoListCust } from "@/api/sw";
|
import { getKendoListCust, baseEvnmAutoMonitorGetKendoListCust } from "@/api/sw";
|
||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
import ShuiwenjiancegongzuoEJ from "./shuiwenjiancegongzuoEJ.vue"
|
import ShuiwenjiancegongzuoEJ from "./shuiwenjiancegongzuoEJ.vue"
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -68,7 +70,7 @@ const loading = ref(false);
|
|||||||
// 弹框相关状态
|
// 弹框相关状态
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
const currentFacility = ref<any>(null);
|
const currentFacility = ref<any>(null);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 点击处理函数
|
// 点击处理函数
|
||||||
const handleFacilityClick = (facility: any) => {
|
const handleFacilityClick = (facility: any) => {
|
||||||
// console.log(facility);
|
// console.log(facility);
|
||||||
|
|||||||
@ -33,6 +33,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
import { msstbprptGetKendoList } from '@/api/sz'
|
import { msstbprptGetKendoList } from '@/api/sz'
|
||||||
import ShuiwenjiancegongzuoEJ from "./shuiwenjiancegongzuoEJ.vue"
|
import ShuiwenjiancegongzuoEJ from "./shuiwenjiancegongzuoEJ.vue"
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'shuizhijiancegongzuoQK'
|
name: 'shuizhijiancegongzuoQK'
|
||||||
@ -74,7 +76,7 @@ const modalVisible = ref(false);
|
|||||||
const currentFacility = ref<any>(null);
|
const currentFacility = ref<any>(null);
|
||||||
const baseid = ref("")
|
const baseid = ref("")
|
||||||
|
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
//获取水质监测工作开展情况数据
|
//获取水质监测工作开展情况数据
|
||||||
const getDataList = async () => {
|
const getDataList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|||||||
@ -460,9 +460,7 @@ const getSelectConfig = async () => {
|
|||||||
return indexA - indexB;
|
return indexA - indexB;
|
||||||
});
|
});
|
||||||
select.value.options = filterSelectOptions(dataMapNameArr);
|
select.value.options = filterSelectOptions(dataMapNameArr);
|
||||||
if (baseid.value === 'all') {
|
if (filterSelectOptions(dataMapNameArr)[0]?.children) {
|
||||||
select.value.value = 'SJLY1U';
|
|
||||||
} else if (filterSelectOptions(dataMapNameArr)[0]?.children) {
|
|
||||||
select.value.value =
|
select.value.value =
|
||||||
filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value;
|
filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value;
|
||||||
} else if (filterSelectOptions(dataMapNameArr)[0]?.value) {
|
} else if (filterSelectOptions(dataMapNameArr)[0]?.value) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,218 @@
|
|||||||
|
<template>
|
||||||
|
<div class="video-section">
|
||||||
|
<div class="video-mode">
|
||||||
|
<div class="video-main" v-loading="loading">
|
||||||
|
<div v-if="activeMedia.type === 'image' && activeMedia.src" class="media-display">
|
||||||
|
<img :src="activeMedia.src" style="width: 100%; height: 100%; object-fit: contain" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="activeMedia.type === 'video' && activeMedia.src" class="media-display">
|
||||||
|
<LiveVideoBox :videoData="{ url: activeMedia.src }" height="100%" :showTitle="false" />
|
||||||
|
</div>
|
||||||
|
<div v-else class="media-empty">
|
||||||
|
<a-empty :description="emptyText" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="video-sidebar" v-loading="loading">
|
||||||
|
<div class="sidebar-list" v-if="list.length > 0">
|
||||||
|
<div
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.fid"
|
||||||
|
class="sidebar-item"
|
||||||
|
:class="{ active: activeFid === item.fid }"
|
||||||
|
@click="handleSelect(item)"
|
||||||
|
>
|
||||||
|
<div class="item-thumb">
|
||||||
|
<img v-if="item.type === 'img'" :src="item.imgPath" />
|
||||||
|
<div v-else-if="item.type === 'vdsp'" class="thumb-placeholder">
|
||||||
|
<img :src="videoCover" />
|
||||||
|
</div>
|
||||||
|
<span v-else class="no-media">无媒体</span>
|
||||||
|
</div>
|
||||||
|
<div class="item-time">{{ item.stName || item.ennm }}{{ item.tm }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a-empty v-else description="暂无数据" class="sidebar-empty" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-pagination" style="margin-top: 10px; display: flex; justify-content: end">
|
||||||
|
<a-pagination
|
||||||
|
v-model:current="currentPage"
|
||||||
|
v-model:pageSize="currentPageSize"
|
||||||
|
:page-size-options="pageSizeOptions"
|
||||||
|
:total="total"
|
||||||
|
show-size-changer
|
||||||
|
size="small"
|
||||||
|
@change="handlePageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import LiveVideoBox from '@/views/shiPinJianKong/components/LiveVideoBox.vue';
|
||||||
|
import videoCover from '@/assets/images/videFm.jpg';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
list: any[];
|
||||||
|
activeFid: string;
|
||||||
|
activeMedia: { type: string; src: string };
|
||||||
|
loading: boolean;
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
pageSizeOptions: string[];
|
||||||
|
total: number;
|
||||||
|
emptyText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
emptyText: '请选择右侧数据'
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'select', item: any): void;
|
||||||
|
(e: 'pageChange', page: number, pageSize: number): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const currentPage = ref(props.page);
|
||||||
|
const currentPageSize = ref(props.pageSize);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.page,
|
||||||
|
val => {
|
||||||
|
currentPage.value = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.pageSize,
|
||||||
|
val => {
|
||||||
|
currentPageSize.value = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSelect = (item: any) => {
|
||||||
|
emit('select', item);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = (page: number, pageSize: number) => {
|
||||||
|
currentPage.value = page;
|
||||||
|
currentPageSize.value = pageSize;
|
||||||
|
emit('pageChange', page, pageSize);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.video-mode {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
height: 520px;
|
||||||
|
|
||||||
|
.video-main {
|
||||||
|
flex: 0 0 80%;
|
||||||
|
background: #000;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.media-display {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-sidebar {
|
||||||
|
flex: 0 0 20%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.sidebar-list {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.sidebar-item {
|
||||||
|
padding: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
transition: background 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-thumb {
|
||||||
|
width: 100%;
|
||||||
|
height: 110px;
|
||||||
|
background: #1a1a1a;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumb-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
.no-media {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-time {
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-empty {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-pagination {
|
||||||
|
padding: 8px;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 样式继承自父组件 */
|
||||||
|
</style>
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
import * as echarts from 'echarts';
|
||||||
|
import type { ECharts, EChartsOption } from 'echarts';
|
||||||
|
|
||||||
|
export interface ChartDataItem {
|
||||||
|
name: string;
|
||||||
|
value: number;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usePieChart(
|
||||||
|
chartRefs: Map<string, HTMLElement>,
|
||||||
|
chartData: { value: ChartDataItem[] },
|
||||||
|
tabIndex: { value: string },
|
||||||
|
typeMap: Record<string, string>,
|
||||||
|
legendCallback?: (e: any) => void
|
||||||
|
) {
|
||||||
|
let chartInstance: ECharts | null = null;
|
||||||
|
|
||||||
|
const initChart = (retryCount = 0) => {
|
||||||
|
const dom = chartRefs.get(tabIndex.value);
|
||||||
|
if (!dom) {
|
||||||
|
if (retryCount < 10) {
|
||||||
|
setTimeout(() => initChart(retryCount + 1), 100);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = dom.getBoundingClientRect();
|
||||||
|
if (rect.width === 0 || rect.height === 0) {
|
||||||
|
if (retryCount < 10) {
|
||||||
|
setTimeout(() => initChart(retryCount + 1), 100);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chartInstance) {
|
||||||
|
chartInstance = echarts.init(dom);
|
||||||
|
}
|
||||||
|
|
||||||
|
const option: EChartsOption = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: (params: any) => `${params.marker} ${params.name}: ${params.value}(次)`
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
right: 10,
|
||||||
|
top: 80,
|
||||||
|
textStyle: { fontSize: 12 }
|
||||||
|
},
|
||||||
|
series: []
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!chartData.value || chartData.value.length === 0) {
|
||||||
|
chartInstance.setOption(option, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const total = chartData.value.reduce((acc: number, item: ChartDataItem) => acc + (item.value || 0), 0);
|
||||||
|
const titleText = typeMap[tabIndex.value] || '识别(次)';
|
||||||
|
|
||||||
|
option.series = [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['26%', '35%'],
|
||||||
|
center: ['35%', '50%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
formatter: '{c}'
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: true,
|
||||||
|
length: 12,
|
||||||
|
length2: 12
|
||||||
|
},
|
||||||
|
data: chartData.value.map((item: ChartDataItem) => ({
|
||||||
|
name: item.name,
|
||||||
|
value: item.value
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
option.title = {
|
||||||
|
text: String(total),
|
||||||
|
left: '34%',
|
||||||
|
top: '44%',
|
||||||
|
textAlign: 'center',
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#333'
|
||||||
|
},
|
||||||
|
subtext: titleText,
|
||||||
|
subtextStyle: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: '#333'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
chartInstance.setOption(option, true);
|
||||||
|
|
||||||
|
if (legendCallback) {
|
||||||
|
chartInstance.off('legendselectchanged');
|
||||||
|
chartInstance.on('legendselectchanged', legendCallback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dispose = () => {
|
||||||
|
chartInstance?.dispose();
|
||||||
|
chartInstance = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const resize = () => {
|
||||||
|
chartInstance?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
return { initChart, dispose, resize };
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
import { postIdUrl } from '@/api/mapModal';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
export interface VideoListItem {
|
||||||
|
fid: string;
|
||||||
|
media: any;
|
||||||
|
thumbUrl: string;
|
||||||
|
isVideo: boolean;
|
||||||
|
isImage: boolean;
|
||||||
|
tm: string;
|
||||||
|
ennm?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useVideoList(
|
||||||
|
fetchFn: (params: any) => Promise<any>,
|
||||||
|
baseUrl: string
|
||||||
|
) {
|
||||||
|
const page = ref(1);
|
||||||
|
const take = ref(20);
|
||||||
|
const total = ref(0);
|
||||||
|
const loading = ref(false);
|
||||||
|
const list = ref<VideoListItem[]>([]);
|
||||||
|
const activeFid = ref('');
|
||||||
|
const activeMedia = ref<{ type: string; src: string }>({ type: '', src: '' });
|
||||||
|
|
||||||
|
const fetchList = async (filter: any, options: any = {}) => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const skip = (page.value - 1) * take.value;
|
||||||
|
const params = { filter, skip, take: take.value, ...options };
|
||||||
|
const res = await fetchFn(params);
|
||||||
|
const dataObj = res?.data?.data ?? {};
|
||||||
|
const rawData = dataObj?.data || [];
|
||||||
|
total.value = dataObj?.total || 0;
|
||||||
|
|
||||||
|
const allFids: string[] = [];
|
||||||
|
rawData.forEach((item: any) => {
|
||||||
|
if (item.fid) {
|
||||||
|
item.fid.split(',').forEach((f: string) => {
|
||||||
|
const trimmed = f.trim();
|
||||||
|
if (trimmed) allFids.push(trimmed);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mediaMap: Record<string, any> = {};
|
||||||
|
if (allFids.length > 0) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('id', allFids.join(','));
|
||||||
|
const mediaRes: any = await postIdUrl(formData);
|
||||||
|
mediaMap = mediaRes?.data || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const flatList: VideoListItem[] = [];
|
||||||
|
rawData.forEach((item: any) => {
|
||||||
|
const fids = item.fid
|
||||||
|
? item.fid.split(',').map((f: string) => f.trim()).filter(Boolean)
|
||||||
|
: [];
|
||||||
|
const tm = item.tm ? dayjs(item.tm).format('YYYY-MM-DD HH:mm:ss') : '-';
|
||||||
|
|
||||||
|
fids.forEach((fid: string) => {
|
||||||
|
const m = mediaMap[fid];
|
||||||
|
const ext = m?.ext || '';
|
||||||
|
const isVideo = ext === '.mp4';
|
||||||
|
const isImage = ext === '.jpg' || ext === '.png';
|
||||||
|
|
||||||
|
flatList.push({
|
||||||
|
...item,
|
||||||
|
fid,
|
||||||
|
media: m || null,
|
||||||
|
thumbUrl: isImage ? baseUrl + '?' + fid + '&view=jpg' : '',
|
||||||
|
isVideo,
|
||||||
|
isImage,
|
||||||
|
tm
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
list.value = flatList;
|
||||||
|
|
||||||
|
if (list.value.length > 0 && !activeFid.value) {
|
||||||
|
selectMedia(list.value[0]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取视频列表失败:', error);
|
||||||
|
list.value = [];
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectMedia = (item: VideoListItem) => {
|
||||||
|
activeFid.value = item.fid;
|
||||||
|
const { isVideo, isImage } = item;
|
||||||
|
|
||||||
|
if (isImage) {
|
||||||
|
activeMedia.value = { type: 'image', src: baseUrl + '?' + item.fid + '&view=jpg' };
|
||||||
|
} else if (isVideo) {
|
||||||
|
activeMedia.value = { type: 'video', src: baseUrl + '?' + item.fid + '&view=jpg' };
|
||||||
|
} else {
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = () => {
|
||||||
|
activeFid.value = '';
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
};
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
page.value = 1;
|
||||||
|
activeFid.value = '';
|
||||||
|
activeMedia.value = { type: '', src: '' };
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
page,
|
||||||
|
take,
|
||||||
|
total,
|
||||||
|
loading,
|
||||||
|
list,
|
||||||
|
activeFid,
|
||||||
|
activeMedia,
|
||||||
|
fetchList,
|
||||||
|
selectMedia,
|
||||||
|
handlePageChange,
|
||||||
|
reset
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -50,6 +50,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import AISBTK from './AISBTK.vue';
|
import AISBTK from './AISBTK.vue';
|
||||||
import { getAisbdbyxList } from '@/api/zngj';
|
import { getAisbdbyxList } from '@/api/zngj';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -104,7 +105,7 @@ const handleCardClick = (tabIdx: string) => {
|
|||||||
const handleModalClose = () => {
|
const handleModalClose = () => {
|
||||||
modalVisible.value = false;
|
modalVisible.value = false;
|
||||||
};
|
};
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// ==================== 获取卡片统计数据 ====================
|
// ==================== 获取卡片统计数据 ====================
|
||||||
const getCardData = async () => {
|
const getCardData = async () => {
|
||||||
if (!datetimePicker.value.value || !baseid.value) return;
|
if (!datetimePicker.value.value || !baseid.value) return;
|
||||||
|
|||||||
60
frontend/src/modules/yunXingGaoJIng/Aisbdbyx/types/index.ts
Normal file
60
frontend/src/modules/yunXingGaoJIng/Aisbdbyx/types/index.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
export enum TabType {
|
||||||
|
PFW = '1',
|
||||||
|
DLM = '2',
|
||||||
|
QP = '3'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AiType {
|
||||||
|
PFW = 'AI_5001',
|
||||||
|
DLM = 'AI_5005',
|
||||||
|
QP = 'AI_5011'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChartDataItem {
|
||||||
|
name: string;
|
||||||
|
value: number;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VideoListItem {
|
||||||
|
fid: string;
|
||||||
|
media: any;
|
||||||
|
thumbUrl: string;
|
||||||
|
isVideo: boolean;
|
||||||
|
isImage: boolean;
|
||||||
|
tm: string;
|
||||||
|
ennm?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CalendarDayData {
|
||||||
|
dt: string;
|
||||||
|
status?: string;
|
||||||
|
qpStatus?: string;
|
||||||
|
fid?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CalendarStatusInfo {
|
||||||
|
name: string;
|
||||||
|
className: string;
|
||||||
|
type: string;
|
||||||
|
dataType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TabItem {
|
||||||
|
key: number;
|
||||||
|
value: string;
|
||||||
|
unit: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchData {
|
||||||
|
baseid: string;
|
||||||
|
stnm: string;
|
||||||
|
month: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DetailTabItem {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
@ -50,6 +50,8 @@ import {
|
|||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { MapClass } from '@/components/gis/map.class';
|
import { MapClass } from '@/components/gis/map.class';
|
||||||
import ZengZhiZhanQingKuangTwoLayers from './TwoLayers/ZengZhiZhanQingKuangTwoLayers.vue';
|
import ZengZhiZhanQingKuangTwoLayers from './TwoLayers/ZengZhiZhanQingKuangTwoLayers.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
|
||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
@ -65,7 +67,7 @@ let chartInstance: ECharts | null = null;
|
|||||||
// 弹窗控制
|
// 弹窗控制
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
const dialogData = ref<any>(null);
|
const dialogData = ref<any>(null);
|
||||||
|
useDraggable(dialogVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 当前选中的站点选项
|
// 当前选中的站点选项
|
||||||
const selectedOption = computed(() => {
|
const selectedOption = computed(() => {
|
||||||
return select.value.options.find(
|
return select.value.options.find(
|
||||||
|
|||||||
@ -63,6 +63,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import { msstbprptGetKendoList } from '@/api/zzfl';
|
import { msstbprptGetKendoList } from '@/api/zzfl';
|
||||||
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
import ArtsDetail from '@/components/carouselIntroduce/ArtsDetail.vue';
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'zengZhiZhanJieShaoMod'
|
name: 'zengZhiZhanJieShaoMod'
|
||||||
@ -103,7 +105,7 @@ const isHovering = ref(false);
|
|||||||
|
|
||||||
// 是否正在切换动画中(用于禁用transition)
|
// 是否正在切换动画中(用于禁用transition)
|
||||||
const isTransitioning = ref(false);
|
const isTransitioning = ref(false);
|
||||||
|
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||||
// 初始化渲染数组(克隆首尾项)
|
// 初始化渲染数组(克隆首尾项)
|
||||||
const initRenderData = () => {
|
const initRenderData = () => {
|
||||||
const length = originalMediaData.value.length;
|
const length = originalMediaData.value.length;
|
||||||
|
|||||||
@ -60,6 +60,8 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
import { overviewGetKendoListCust } from '@/api/zzfl';
|
import { overviewGetKendoListCust } from '@/api/zzfl';
|
||||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||||
import WholeValuedStationOverviewDetail from "./WholeValuedStationOverviewDetail/index.vue"
|
import WholeValuedStationOverviewDetail from "./WholeValuedStationOverviewDetail/index.vue"
|
||||||
|
import { useDraggable } from '@/utils/drag';
|
||||||
|
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'zengzhizhanjiansheyunxing'
|
name: 'zengzhizhanjiansheyunxing'
|
||||||
@ -68,6 +70,7 @@ const JidiSelectEventStore = useJidiSelectEventStore();
|
|||||||
const baseid = ref('');
|
const baseid = ref('');
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
|
useDraggable(dialogVisible, { boundary: true, resetOnOpen: true });
|
||||||
const dialogTitle = ref('增殖站概况');
|
const dialogTitle = ref('增殖站概况');
|
||||||
const datetimePicker = ref({
|
const datetimePicker = ref({
|
||||||
show: true,
|
show: true,
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { useMapConfigStore } from '@/modules/map/stores/map-config.store';
|
|||||||
import { useMapDataStore } from '@/modules/map/stores/map-data.store';
|
import { useMapDataStore } from '@/modules/map/stores/map-data.store';
|
||||||
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { urlList } from '@/utils/GisUrlList';
|
// import { urlList } from '@/utils/GisUrlList';
|
||||||
const mapClass = MapClass.getInstance();
|
const mapClass = MapClass.getInstance();
|
||||||
const DEFAULT_LAYER_REQUEST_CONCURRENCY = 4;
|
const DEFAULT_LAYER_REQUEST_CONCURRENCY = 4;
|
||||||
const ENG_POINT_LAYER_KEY = 'eng_point';
|
const ENG_POINT_LAYER_KEY = 'eng_point';
|
||||||
@ -47,23 +47,23 @@ const normalizeCachePayload = (value: any): any => {
|
|||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildUrlListIndex = (items: any[] = []) => {
|
// const buildUrlListIndex = (items: any[] = []) => {
|
||||||
const index: Record<string, any[]> = {};
|
// const index: Record<string, any[]> = {};
|
||||||
|
//
|
||||||
items.forEach(item => {
|
// items.forEach(item => {
|
||||||
[item.url, item.title, item.keyType].forEach(key => {
|
// [item.url, item.title, item.keyType].forEach(key => {
|
||||||
if (!key) return;
|
// if (!key) return;
|
||||||
if (!index[key]) {
|
// if (!index[key]) {
|
||||||
index[key] = [];
|
// index[key] = [];
|
||||||
}
|
// }
|
||||||
index[key].push(item);
|
// index[key].push(item);
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
return index;
|
// return index;
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const urlListIndex = buildUrlListIndex(urlList);
|
// const urlListIndex = buildUrlListIndex(urlList);
|
||||||
|
|
||||||
const isCanceledRequestError = (error: unknown) => {
|
const isCanceledRequestError = (error: unknown) => {
|
||||||
const message = error instanceof Error ? error.message : String(error || '');
|
const message = error instanceof Error ? error.message : String(error || '');
|
||||||
@ -74,6 +74,72 @@ const isCanceledRequestError = (error: unknown) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buildFiltersFromParamsObject = (
|
||||||
|
paramsObject: Record<string, any> = {}
|
||||||
|
) => {
|
||||||
|
const filtersArray: any[] = [];
|
||||||
|
|
||||||
|
Object.keys(paramsObject).forEach(paramKey => {
|
||||||
|
const value = paramsObject[paramKey];
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((filter: any) => {
|
||||||
|
filtersArray.push({
|
||||||
|
...filter,
|
||||||
|
dataType: filter?.dataType || 'string'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtersArray.push({
|
||||||
|
field: paramKey,
|
||||||
|
operator: 'eq',
|
||||||
|
dataType: 'string',
|
||||||
|
value
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return filtersArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeRequestParams = (rawParams: any) => {
|
||||||
|
if (!rawParams || !Object.keys(rawParams).length) {
|
||||||
|
return { logic: 'and', filters: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(rawParams.filters)) {
|
||||||
|
return {
|
||||||
|
logic: rawParams.logic || 'and',
|
||||||
|
filters: rawParams.filters.map((filter: any) => ({
|
||||||
|
...filter,
|
||||||
|
dataType: filter?.dataType || 'string'
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
logic: 'and',
|
||||||
|
filters: buildFiltersFromParamsObject(rawParams)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseAnchorParamFilters = (anchorParamJson?: string) => {
|
||||||
|
if (!anchorParamJson) return [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsedParams = JSON.parse(anchorParamJson);
|
||||||
|
if (!parsedParams || typeof parsedParams !== 'object') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildFiltersFromParamsObject(parsedParams);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析 anchorParamJson 失败:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const useMapStore = defineStore('map', () => {
|
export const useMapStore = defineStore('map', () => {
|
||||||
const mapConfigStore = useMapConfigStore();
|
const mapConfigStore = useMapConfigStore();
|
||||||
const mapDataStore = useMapDataStore();
|
const mapDataStore = useMapDataStore();
|
||||||
@ -260,7 +326,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getRuntimeCheckedLayerKeys = (): string[] => {
|
const getRuntimeCheckedLayerKeys = (): string[] => {
|
||||||
return normalizeCheckedLayerKeys(mapViewStore.getCheckedLayerKeys());
|
return mapViewStore.getCheckedLayerKeys();
|
||||||
};
|
};
|
||||||
|
|
||||||
const syncPointDataForFilter = () => {
|
const syncPointDataForFilter = () => {
|
||||||
@ -300,6 +366,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
mapConfigStore.setLayerConfigTree(data);
|
mapConfigStore.setLayerConfigTree(data);
|
||||||
const nextCheckedLayerKeys = mapConfigStore.extractCheckedLayerKeys(data);
|
const nextCheckedLayerKeys = mapConfigStore.extractCheckedLayerKeys(data);
|
||||||
mapViewStore.setCheckedLayerKeys(nextCheckedLayerKeys);
|
mapViewStore.setCheckedLayerKeys(nextCheckedLayerKeys);
|
||||||
|
console.log(1);
|
||||||
rebuildLegendRuntimeData(nextCheckedLayerKeys);
|
rebuildLegendRuntimeData(nextCheckedLayerKeys);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -374,6 +441,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
mapViewStore.setLegendCheckedState(
|
mapViewStore.setLegendCheckedState(
|
||||||
buildLegendCheckedState(legendDataOriginal.value, normalizeLegendNameEn)
|
buildLegendCheckedState(legendDataOriginal.value, normalizeLegendNameEn)
|
||||||
);
|
);
|
||||||
|
console.log(2);
|
||||||
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -381,6 +449,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
* 设置选中的图例数据(在图层加载完成后调用)
|
* 设置选中的图例数据(在图层加载完成后调用)
|
||||||
*/
|
*/
|
||||||
const setSelectedLegendData = () => {
|
const setSelectedLegendData = () => {
|
||||||
|
console.log(3);
|
||||||
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -458,7 +527,10 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
* @param isInit - 是否是初始化阶段(初始化时遍历所有图层)
|
* @param isInit - 是否是初始化阶段(初始化时遍历所有图层)
|
||||||
*/
|
*/
|
||||||
const updateLayerData = async (checkKeys: string[], isInit = false) => {
|
const updateLayerData = async (checkKeys: string[], isInit = false) => {
|
||||||
|
console.log(checkKeys);
|
||||||
|
if (!isInit) {
|
||||||
checkKeys = normalizeCheckedLayerKeys(checkKeys);
|
checkKeys = normalizeCheckedLayerKeys(checkKeys);
|
||||||
|
}
|
||||||
|
|
||||||
mapViewStore.setCheckedLayerKeys(checkKeys);
|
mapViewStore.setCheckedLayerKeys(checkKeys);
|
||||||
|
|
||||||
@ -594,6 +666,11 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
const allPointData = mapDataStore.rebuildPointDataFromCache(allLayerKeys);
|
const allPointData = mapDataStore.rebuildPointDataFromCache(allLayerKeys);
|
||||||
attachNearbyPointRuntimeMeta(allPointData);
|
attachNearbyPointRuntimeMeta(allPointData);
|
||||||
const runtimeCheckedKeys = getRuntimeCheckedLayerKeys();
|
const runtimeCheckedKeys = getRuntimeCheckedLayerKeys();
|
||||||
|
const treeCheckedKeys = mapConfigStore.extractCheckedLayerKeys(
|
||||||
|
layerData.value.length > 0 ? layerData.value : items
|
||||||
|
);
|
||||||
|
const finalCheckedKeys =
|
||||||
|
runtimeCheckedKeys.length > 0 ? runtimeCheckedKeys : treeCheckedKeys;
|
||||||
|
|
||||||
// 备注:近邻点元数据需要基于全量点位统一识别,识别完成后同步刷新各图层 Feature。
|
// 备注:近邻点元数据需要基于全量点位统一识别,识别完成后同步刷新各图层 Feature。
|
||||||
for (const key of allLayerKeys) {
|
for (const key of allLayerKeys) {
|
||||||
@ -608,7 +685,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
const shouldRestoreVisible =
|
const shouldRestoreVisible =
|
||||||
typeof cacheChecked === 'boolean'
|
typeof cacheChecked === 'boolean'
|
||||||
? cacheChecked
|
? cacheChecked
|
||||||
: layer.checked === 1 || runtimeCheckedKeys.includes(key);
|
: layer.checked === 1 || finalCheckedKeys.includes(key);
|
||||||
layer.data = layerPoints;
|
layer.data = layerPoints;
|
||||||
mapClass.addInitDataLayer(displayData, key);
|
mapClass.addInitDataLayer(displayData, key);
|
||||||
if (shouldRestoreVisible) {
|
if (shouldRestoreVisible) {
|
||||||
@ -622,7 +699,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
|
|
||||||
// 备注:初始化 loading 期间用户可能已经手动改过图层勾选,这里必须以最新运行态收尾,
|
// 备注:初始化 loading 期间用户可能已经手动改过图层勾选,这里必须以最新运行态收尾,
|
||||||
// 不能再回放 load 启动瞬间的默认 checked 快照。
|
// 不能再回放 load 启动瞬间的默认 checked 快照。
|
||||||
await updateLayerData(runtimeCheckedKeys, true);
|
await updateLayerData(finalCheckedKeys, true);
|
||||||
} finally {
|
} finally {
|
||||||
mapDataStore.setLoading(false);
|
mapDataStore.setLoading(false);
|
||||||
}
|
}
|
||||||
@ -736,6 +813,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
normalizedNameEn,
|
normalizedNameEn,
|
||||||
checked
|
checked
|
||||||
);
|
);
|
||||||
|
console.log(5);
|
||||||
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
||||||
applyLegendItemVisibility(legendItem, checked);
|
applyLegendItemVisibility(legendItem, checked);
|
||||||
};
|
};
|
||||||
@ -754,14 +832,13 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
mapViewStore.setLegendCheckedState(nextState);
|
mapViewStore.setLegendCheckedState(nextState);
|
||||||
|
console.log(6);
|
||||||
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
rebuildLegendRuntimeData(checkedLayerKeys.value);
|
||||||
changedLegendItems.forEach(legendItem =>
|
changedLegendItems.forEach(legendItem =>
|
||||||
applyLegendItemVisibility(legendItem, checked)
|
applyLegendItemVisibility(legendItem, checked)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成请求标识符,用于避免重复请求
|
* 生成请求标识符,用于避免重复请求
|
||||||
*/
|
*/
|
||||||
@ -777,75 +854,32 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
layer: any,
|
layer: any,
|
||||||
sessionId: number = loadSessionSeed
|
sessionId: number = loadSessionSeed
|
||||||
) => {
|
) => {
|
||||||
const { key, url, params = {}, paramJson } = layer;
|
const { key, url, params = {}, paramJson, anchorParamJson } = layer;
|
||||||
|
|
||||||
// 没有URL,跳过
|
// 没有URL,跳过
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
const requestUrl = url;
|
||||||
// 参考 React 版本:使用 urlList 匹配图层配置
|
|
||||||
let requestUrl = url;
|
|
||||||
let requestParams: any = params;
|
let requestParams: any = params;
|
||||||
let requestOrders: any = null;
|
let requestOrders: any = null;
|
||||||
|
|
||||||
// 根据图层的 key(keyType)、title、url 查找匹配的 urlList 项
|
|
||||||
const layerKey = layer?.key || '';
|
const layerKey = layer?.key || '';
|
||||||
const layerTitle = layer?.title || '';
|
|
||||||
const matchedList =
|
|
||||||
urlListIndex[layerKey] || urlListIndex[layerTitle] || urlListIndex[url];
|
|
||||||
|
|
||||||
if (matchedList && matchedList.length > 0) {
|
const voidSttp = 'all';
|
||||||
let matchedItem: any = null;
|
const ylfbKeys = ['ylfb_point'];
|
||||||
if (key == 'va_built_point ' || key == 'vp_built_point') {
|
const timeRangeLayerKeys = ['ef_point'];
|
||||||
matchedList.forEach(item => {
|
|
||||||
if (item.title === layerTitle) {
|
|
||||||
matchedItem = item;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
matchedItem = matchedList[0];
|
|
||||||
}
|
|
||||||
requestUrl = matchedItem.url;
|
|
||||||
|
|
||||||
// 转换 params 为 filter 格式
|
|
||||||
if (matchedItem.params) {
|
|
||||||
const filtersArray: any[] = [];
|
|
||||||
for (const key in matchedItem.params) {
|
|
||||||
const value = matchedItem.params[key];
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
// 处理数组格式: { field: 'sttpCode', operator: 'eq', value: 'WQ' }
|
|
||||||
value.forEach((filter: any) => {
|
|
||||||
filtersArray.push({
|
|
||||||
...filter,
|
|
||||||
dataType: filter.dataType || 'string'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 处理简单格式: sttpCode: 'VP'
|
|
||||||
filtersArray.push({
|
|
||||||
field: key,
|
|
||||||
operator: 'eq',
|
|
||||||
dataType: 'string',
|
|
||||||
value: value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
requestParams = {
|
|
||||||
logic: 'and',
|
|
||||||
filters: filtersArray
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let voidSttp = 'all';
|
|
||||||
const ylfbKeys = ['ylfb_point']; // 需要时间搜索的图层key
|
|
||||||
const timeRangeLayerKeys = ['ef_point']; // 需要时间搜索的图层key
|
|
||||||
const spjkz = ['stinfo_video_point'];
|
const spjkz = ['stinfo_video_point'];
|
||||||
const lineTimeLayerKeys = [
|
|
||||||
'wt_rive_gradient_line',
|
|
||||||
'wq_rive_gradient_line'
|
|
||||||
]; // 需要时间搜索的图层key
|
|
||||||
|
|
||||||
let yearTime = dayjs().subtract(1, 'years'); // 鱼类分布年份
|
const yearTime = dayjs().subtract(1, 'years');
|
||||||
|
|
||||||
|
requestParams = normalizeRequestParams(requestParams);
|
||||||
|
|
||||||
|
const anchorParamFilters = parseAnchorParamFilters(anchorParamJson);
|
||||||
|
if (anchorParamFilters.length) {
|
||||||
|
requestParams.filters.push(...anchorParamFilters);
|
||||||
|
}
|
||||||
|
|
||||||
if (timeRangeLayerKeys.includes(layerKey)) {
|
if (timeRangeLayerKeys.includes(layerKey)) {
|
||||||
requestParams.filters.push({
|
requestParams.filters.push({
|
||||||
field: 'tm',
|
field: 'tm',
|
||||||
@ -885,10 +919,10 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 转换 orders 格式:从 JSON 字符串转换为数组格式
|
|
||||||
if (matchedItem.orders) {
|
if (layer?.orders) {
|
||||||
try {
|
try {
|
||||||
const ordersObj = JSON.parse(matchedItem.orders);
|
const ordersObj = JSON.parse(layer.orders);
|
||||||
const ordersArray = Object.entries(ordersObj).map(([field, dir]) => ({
|
const ordersArray = Object.entries(ordersObj).map(([field, dir]) => ({
|
||||||
field,
|
field,
|
||||||
dir
|
dir
|
||||||
@ -898,9 +932,7 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
console.error('解析 orders 失败:', e);
|
console.error('解析 orders 失败:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有匹配到 urlList,尝试解析 paramJson
|
|
||||||
if (!Object.keys(requestParams).length && paramJson) {
|
if (!Object.keys(requestParams).length && paramJson) {
|
||||||
try {
|
try {
|
||||||
const jsonObj = JSON.parse(paramJson);
|
const jsonObj = JSON.parse(paramJson);
|
||||||
@ -1109,6 +1141,8 @@ export const useMapStore = defineStore('map', () => {
|
|||||||
|
|
||||||
const allPointData = mapDataStore.rebuildPointDataFromCache();
|
const allPointData = mapDataStore.rebuildPointDataFromCache();
|
||||||
|
|
||||||
|
console.log(888);
|
||||||
|
console.log(currentCheckedKeys);
|
||||||
// 更新地图锚点显示
|
// 更新地图锚点显示
|
||||||
await updateLayerData(currentCheckedKeys, false);
|
await updateLayerData(currentCheckedKeys, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,8 @@ const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
|
|||||||
// ✅ 保存原始名称到 meta,用于菜单显示
|
// ✅ 保存原始名称到 meta,用于菜单显示
|
||||||
tmp.meta = {
|
tmp.meta = {
|
||||||
...tmp.meta,
|
...tmp.meta,
|
||||||
title: tmp.name || tmp.menuName // 原始名称用于显示
|
title: tmp.name || tmp.menuName, // 原始名称用于显示
|
||||||
|
moduleId: tmp.id // 保存菜单ID,供地图模块使用
|
||||||
};
|
};
|
||||||
// ✅ name 使用路径生成唯一值
|
// ✅ name 使用路径生成唯一值
|
||||||
tmp.name = tmp.path || tmp.opturl;
|
tmp.name = tmp.path || tmp.opturl;
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export const useShuJuTianBaoStore = defineStore('shuJuTianBao', () => {
|
|||||||
try {
|
try {
|
||||||
baseLoading.value = true;
|
baseLoading.value = true;
|
||||||
const res = await getBaseDropdown({});
|
const res = await getBaseDropdown({});
|
||||||
|
// debugger
|
||||||
if (res.data && Array.isArray(res.data)) {
|
if (res.data && Array.isArray(res.data)) {
|
||||||
const list = [...res.data];
|
const list = [...res.data];
|
||||||
// 直接赋值给 ref,触发响应式更新
|
// 直接赋值给 ref,触发响应式更新
|
||||||
@ -58,10 +59,15 @@ export const useShuJuTianBaoStore = defineStore('shuJuTianBao', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 获取电站列表
|
// 获取电站列表
|
||||||
const getEngOption = async (rvcd: string) => {
|
const getEngOption = async (rvcd: string, type: string) => {
|
||||||
try {
|
try {
|
||||||
engLoading.value = true;
|
engLoading.value = true;
|
||||||
const param = rvcd === 'all' ? {} : { reachcd: rvcd };
|
let param:any
|
||||||
|
if (type == 'baseId') {
|
||||||
|
param = rvcd === 'all' ? {} : { baseId: rvcd };
|
||||||
|
} else {
|
||||||
|
param = rvcd === 'all' ? {} : { reachcd: 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)) {
|
||||||
// 直接赋值给 ref
|
// 直接赋值给 ref
|
||||||
|
|||||||
@ -39,3 +39,6 @@
|
|||||||
.ant-message {
|
.ant-message {
|
||||||
z-index: 2005 !important;
|
z-index: 2005 !important;
|
||||||
}
|
}
|
||||||
|
.ant-modal-header {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|||||||
@ -25,16 +25,16 @@ export const urlList = [
|
|||||||
orders:
|
orders:
|
||||||
'{"baseId":"asc","rvcdStepSort":"asc","siteStepSort":"asc","ennm":"asc"}'
|
'{"baseId":"asc","rvcdStepSort":"asc","siteStepSort":"asc","ennm":"asc"}'
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/wq/anchorPoint/reach/GetKendoListCust',
|
// url: '/wmp-env-server/env/wq/anchorPoint/reach/GetKendoListCust',
|
||||||
title: '实际水质',
|
// title: '实际水质',
|
||||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
// params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/wq/anchorPoint/reach/GetKendoListCust',
|
// url: '/wmp-env-server/env/wq/anchorPoint/reach/GetKendoListCust',
|
||||||
title: '目标水质',
|
// title: '目标水质',
|
||||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
// params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||||
},
|
// },
|
||||||
// {
|
// {
|
||||||
// url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
// url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||||
// title: '自建站',
|
// title: '自建站',
|
||||||
@ -171,11 +171,11 @@ export const urlList = [
|
|||||||
title: '水电站告警情况',
|
title: '水电站告警情况',
|
||||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/fb/point/discharge/GetKendoListCust',
|
// url: '/wmp-env-server/fb/point/discharge/GetKendoListCust',
|
||||||
title: '水电站',
|
// title: '水电站',
|
||||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
// params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
url: '/wmp-env-server/env/fh/zqpoint/GetKendoListCust',
|
url: '/wmp-env-server/env/fh/zqpoint/GetKendoListCust',
|
||||||
title: '国家水文站',
|
title: '国家水文站',
|
||||||
@ -200,19 +200,19 @@ export const urlList = [
|
|||||||
title: '视频监控站',
|
title: '视频监控站',
|
||||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/wb/point/GetKendoListCust',
|
// url: '/wmp-env-server/env/wb/point/GetKendoListCust',
|
||||||
title: '气象站',
|
// title: '气象站',
|
||||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
// params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/sw/getEngTempPointList/getLastData',
|
// url: '/wmp-env-server/sw/getEngTempPointList/getLastData',
|
||||||
title: '水温站点',
|
// title: '水温站点',
|
||||||
params: {
|
// params: {
|
||||||
logic: 'and',
|
// logic: 'and',
|
||||||
filters: []
|
// filters: []
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||||
title: '水质站点',
|
title: '水质站点',
|
||||||
@ -233,38 +233,38 @@ export const urlList = [
|
|||||||
},
|
},
|
||||||
orders: '{"orderIndex":"asc"}'
|
orders: '{"orderIndex":"asc"}'
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
// url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
||||||
title: '水质告警',
|
// title: '水质告警',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WQ' }]
|
// sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WQ' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
// url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
||||||
title: '水温告警',
|
// title: '水温告警',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WTRV' }]
|
// sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WTRV' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
// url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
||||||
title: '水位告警',
|
// title: '水位告警',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'ENG' }]
|
// sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'ENG' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/warn/stcd/operatePoint/GetKendoListCust',
|
// url: '/wmp-env-server/env/warn/stcd/operatePoint/GetKendoListCust',
|
||||||
title: '环保设施告警',
|
// title: '环保设施告警',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
yr: dayjs().format('YYYY')
|
// yr: dayjs().format('YYYY')
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
url: '/wmp-env-server/env/fp/point/built/GetKendoListCust',
|
url: '/wmp-env-server/env/fp/point/built/GetKendoListCust',
|
||||||
title: '在建过鱼设施-地图锚点',
|
title: '在建过鱼设施-地图锚点',
|
||||||
@ -273,24 +273,24 @@ export const urlList = [
|
|||||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/fb/point/built/GetKendoListCust',
|
// url: '/wmp-env-server/env/fb/point/built/GetKendoListCust',
|
||||||
title: '在建鱼类增殖站',
|
// title: '在建鱼类增殖站',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'FB' }],
|
// sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'FB' }],
|
||||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
// bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/fb/point/built/GetKendoListCust',
|
// url: '/wmp-env-server/env/fb/point/built/GetKendoListCust',
|
||||||
title: '在建人工产卵场',
|
// title: '在建人工产卵场',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'SG' }],
|
// sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'SG' }],
|
||||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
// bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
url: '/wmp-env-server/env/fhvap/built/GetKendoListCust',
|
url: '/wmp-env-server/env/fhvap/built/GetKendoListCust',
|
||||||
title: '在建珍稀植物园',
|
title: '在建珍稀植物园',
|
||||||
@ -309,21 +309,21 @@ export const urlList = [
|
|||||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/eng/eq/eqds/built/GetKendoListCust',
|
// url: '/wmp-env-server/eng/eq/eqds/built/GetKendoListCust',
|
||||||
title: '在建生态流量泄放设施',
|
// title: '在建生态流量泄放设施',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||||
BLDSTT_CCODE: [{ field: 'BLDSTT_CCODE', operator: 'eq', value: '1' }]
|
// BLDSTT_CCODE: [{ field: 'BLDSTT_CCODE', operator: 'eq', value: '1' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/we/fishList/point/GetKendoList',
|
// url: '/wmp-env-server/env/we/fishList/point/GetKendoList',
|
||||||
title: '鱼类沿程',
|
// title: '鱼类沿程',
|
||||||
params: {
|
// params: {
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
url: '/wmp-env-server/env/wva/point/GetKendoListCust',
|
url: '/wmp-env-server/env/wva/point/GetKendoListCust',
|
||||||
title: '野生动物监测',
|
title: '野生动物监测',
|
||||||
@ -332,15 +332,15 @@ export const urlList = [
|
|||||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WVA' }]
|
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WVA' }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
url: '/wmp-env-server/env/we/fishList/point/GetNativeRareFish',
|
// url: '/wmp-env-server/env/we/fishList/point/GetNativeRareFish',
|
||||||
title: '土著珍稀鱼类',
|
// title: '土著珍稀鱼类',
|
||||||
params: {
|
// params: {
|
||||||
rare: '1',
|
// rare: '1',
|
||||||
specOrigin: '1',
|
// specOrigin: '1',
|
||||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
// lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
// { url: '/wmp-env-server/te/tet/point/GetTerrestrialAnimal', title: '陆生动物分布', params: { baseId: window?.__lyConfigs?.baseId, lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] } },
|
// { url: '/wmp-env-server/te/tet/point/GetTerrestrialAnimal', title: '陆生动物分布', params: { baseId: window?.__lyConfigs?.baseId, lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] } },
|
||||||
{
|
{
|
||||||
url: '/wmp-env-server/sdFprdR/point/getFprdPointList',
|
url: '/wmp-env-server/sdFprdR/point/getFprdPointList',
|
||||||
|
|||||||
182
frontend/src/utils/drag.ts
Normal file
182
frontend/src/utils/drag.ts
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
import { nextTick, watch } from 'vue';
|
||||||
|
|
||||||
|
export interface DraggableOptions {
|
||||||
|
/** 拖拽手柄选择器,默认 '.ant-modal-header' */
|
||||||
|
handle?: string;
|
||||||
|
/** 弹窗内容选择器,默认 '.ant-modal-content' */
|
||||||
|
modalSelector?: string;
|
||||||
|
/** 是否限制在可视区域内,默认 true */
|
||||||
|
boundary?: boolean;
|
||||||
|
/** 打开弹窗时是否自动重置到居中位置,默认 true */
|
||||||
|
resetOnOpen?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useDraggable(
|
||||||
|
openRef: { value: boolean },
|
||||||
|
options: DraggableOptions = {}
|
||||||
|
) {
|
||||||
|
console.log(openRef);
|
||||||
|
const {
|
||||||
|
handle = '.ant-modal-header',
|
||||||
|
modalSelector = '.ant-modal-content',
|
||||||
|
boundary = true,
|
||||||
|
resetOnOpen = true
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
let cleanup: (() => void) | null = null;
|
||||||
|
|
||||||
|
const initDrag = (): (() => void) | null => {
|
||||||
|
if (resetOnOpen) {
|
||||||
|
const modalContents = document.querySelectorAll(
|
||||||
|
modalSelector
|
||||||
|
) as NodeListOf<HTMLElement>;
|
||||||
|
modalContents.forEach(content => {
|
||||||
|
if (content.offsetParent !== null) {
|
||||||
|
content.style.position = '';
|
||||||
|
content.style.left = '';
|
||||||
|
content.style.top = '';
|
||||||
|
content.style.margin = '';
|
||||||
|
content.style.transform = '';
|
||||||
|
content.style.width = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentModalContent: HTMLElement | null = null;
|
||||||
|
let isDragging = false;
|
||||||
|
let startX = 0;
|
||||||
|
let startY = 0;
|
||||||
|
let startLeft = 0;
|
||||||
|
let startTop = 0;
|
||||||
|
|
||||||
|
const getPointerPos = (e: MouseEvent | TouchEvent) => {
|
||||||
|
if (e instanceof TouchEvent) {
|
||||||
|
const touch = e.touches[0];
|
||||||
|
return { clientX: touch.clientX, clientY: touch.clientY };
|
||||||
|
}
|
||||||
|
return { clientX: e.clientX, clientY: e.clientY };
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPointerDown = (e: MouseEvent | TouchEvent) => {
|
||||||
|
const target = e.target instanceof HTMLElement ? e.target : null;
|
||||||
|
const dragHandle = target?.closest(handle) as HTMLElement | null;
|
||||||
|
|
||||||
|
if (!dragHandle) return;
|
||||||
|
|
||||||
|
const modalContent = dragHandle.closest(
|
||||||
|
modalSelector
|
||||||
|
) as HTMLElement | null;
|
||||||
|
if (!modalContent) return;
|
||||||
|
|
||||||
|
if (
|
||||||
|
target.closest('.ant-modal-close') ||
|
||||||
|
target.closest('button') ||
|
||||||
|
target.closest('input') ||
|
||||||
|
target.closest('select') ||
|
||||||
|
target.closest('textarea') ||
|
||||||
|
target.closest('a')
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
isDragging = true;
|
||||||
|
currentModalContent = modalContent;
|
||||||
|
|
||||||
|
const rect = modalContent.getBoundingClientRect();
|
||||||
|
startLeft = rect.left;
|
||||||
|
startTop = rect.top;
|
||||||
|
const pos = getPointerPos(e);
|
||||||
|
startX = pos.clientX - startLeft;
|
||||||
|
startY = pos.clientY - startTop;
|
||||||
|
|
||||||
|
const currentWidth = modalContent.offsetWidth;
|
||||||
|
modalContent.style.width = currentWidth + 'px';
|
||||||
|
|
||||||
|
modalContent.style.userSelect = 'none';
|
||||||
|
modalContent.style.webkitUserSelect = 'none';
|
||||||
|
modalContent.style.position = 'fixed';
|
||||||
|
modalContent.style.margin = '0';
|
||||||
|
modalContent.style.transform = 'none';
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', onPointerMove, { passive: false });
|
||||||
|
document.addEventListener('mouseup', onPointerUp);
|
||||||
|
document.addEventListener('touchmove', onPointerMove, { passive: false });
|
||||||
|
document.addEventListener('touchend', onPointerUp);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPointerMove = (e: MouseEvent | TouchEvent) => {
|
||||||
|
if (!isDragging || !currentModalContent) return;
|
||||||
|
e.preventDefault();
|
||||||
|
const pos = getPointerPos(e);
|
||||||
|
let newLeft = pos.clientX - startX;
|
||||||
|
let newTop = pos.clientY - startY;
|
||||||
|
|
||||||
|
if (boundary) {
|
||||||
|
const maxX = window.innerWidth - currentModalContent.offsetWidth;
|
||||||
|
const maxY = window.innerHeight - currentModalContent.offsetHeight;
|
||||||
|
newLeft = Math.max(0, Math.min(newLeft, maxX));
|
||||||
|
newTop = Math.max(0, Math.min(newTop, maxY));
|
||||||
|
}
|
||||||
|
|
||||||
|
currentModalContent.style.left = `${newLeft}px`;
|
||||||
|
currentModalContent.style.top = `${newTop}px`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPointerUp = () => {
|
||||||
|
if (!currentModalContent) return;
|
||||||
|
isDragging = false;
|
||||||
|
currentModalContent.style.userSelect = '';
|
||||||
|
currentModalContent.style.webkitUserSelect = '';
|
||||||
|
document.removeEventListener('mousemove', onPointerMove);
|
||||||
|
document.removeEventListener('mouseup', onPointerUp);
|
||||||
|
document.removeEventListener('touchmove', onPointerMove);
|
||||||
|
document.removeEventListener('touchend', onPointerUp);
|
||||||
|
currentModalContent = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', onPointerDown);
|
||||||
|
document.addEventListener('touchstart', onPointerDown, {
|
||||||
|
passive: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', onPointerDown);
|
||||||
|
document.removeEventListener('touchstart', onPointerDown);
|
||||||
|
document.removeEventListener('mousemove', onPointerMove);
|
||||||
|
document.removeEventListener('mouseup', onPointerUp);
|
||||||
|
document.removeEventListener('touchmove', onPointerMove);
|
||||||
|
document.removeEventListener('touchend', onPointerUp);
|
||||||
|
|
||||||
|
const modalContents = document.querySelectorAll(
|
||||||
|
modalSelector
|
||||||
|
) as NodeListOf<HTMLElement>;
|
||||||
|
modalContents.forEach(content => {
|
||||||
|
content.style.position = '';
|
||||||
|
content.style.left = '';
|
||||||
|
content.style.top = '';
|
||||||
|
content.style.margin = '';
|
||||||
|
content.style.transform = '';
|
||||||
|
content.style.width = '';
|
||||||
|
content.style.userSelect = '';
|
||||||
|
content.style.webkitUserSelect = '';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
openRef,
|
||||||
|
newVal => {
|
||||||
|
if (newVal) {
|
||||||
|
nextTick(() => {
|
||||||
|
cleanup = initDrag();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cleanup?.();
|
||||||
|
cleanup = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
return { initDrag };
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user