模块完善
This commit is contained in:
parent
cd59030f07
commit
e3022c2db6
@ -10,6 +10,7 @@ VITE_APP_BASE_API = '/dev-api'
|
|||||||
# VITE_APP_BASE_URL = 'http://localhost:8093'
|
# VITE_APP_BASE_URL = 'http://localhost: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://172.16.21.142:8096'
|
||||||
# 汤伟
|
# 汤伟
|
||||||
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
||||||
|
|
||||||
|
|||||||
62
frontend/src/api/shuidiankaifa/index.ts
Normal file
62
frontend/src/api/shuidiankaifa/index.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 Kendo 列表数据(支持聚合和分组)
|
||||||
|
* @param params 过滤条件
|
||||||
|
* @param sortConfig 排序配置
|
||||||
|
*/
|
||||||
|
export function getKendoList(params: any, sortConfig?: any[]) {
|
||||||
|
return request({
|
||||||
|
url: '/dec-lygk-base-server/base/vmsstbprpt/GetKendoList',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
filters: params,
|
||||||
|
sorts: sortConfig || []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取自定义 Kendo 列表数据(用于全基地模式)
|
||||||
|
* @param params 过滤条件
|
||||||
|
* @param sortConfig 排序配置
|
||||||
|
*/
|
||||||
|
export function getKendoListCust(params: any, sortConfig?: any[]) {
|
||||||
|
return request({
|
||||||
|
url: '/dec-lygk-base-server/base/vmsstbprpt/GetKendoListCust',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
filters: params,
|
||||||
|
sorts: sortConfig || []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取介绍信息(用于 other 类型排序)
|
||||||
|
* @param filters 过滤条件
|
||||||
|
* @param sorts 排序配置
|
||||||
|
* @param needTotal 是否需要总数
|
||||||
|
* @param fields 返回字段
|
||||||
|
* @param defaultSort 默认排序
|
||||||
|
*/
|
||||||
|
export function getIntroduce(
|
||||||
|
filters: any[],
|
||||||
|
sorts?: any[],
|
||||||
|
needTotal?: boolean,
|
||||||
|
fields?: string[],
|
||||||
|
defaultSort?: any
|
||||||
|
) {
|
||||||
|
return request({
|
||||||
|
url: '/dec-lygk-base-server/base/introduce/getIntroduce',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
logic: 'and',
|
||||||
|
filters: filters,
|
||||||
|
sorts: sorts || [],
|
||||||
|
needTotal: needTotal || false,
|
||||||
|
fields: fields || [],
|
||||||
|
defaultSort: defaultSort
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -15,6 +15,12 @@
|
|||||||
<InfoCircleOutlined />
|
<InfoCircleOutlined />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
<span v-if="iconmap.show" class="title_icon">
|
||||||
|
<a-tooltip placement="top" :title="iconmap.value"
|
||||||
|
:get-popup-container="getPopupContainer">
|
||||||
|
<span :class="iconmap.icon"></span>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="title_right">
|
<div class="title_right">
|
||||||
<div v-if="select.show">
|
<div v-if="select.show">
|
||||||
@ -36,7 +42,7 @@
|
|||||||
<div v-if="datetimePicker.show">
|
<div v-if="datetimePicker.show">
|
||||||
<!-- 添加 locale 属性来设置语言 -->
|
<!-- 添加 locale 属性来设置语言 -->
|
||||||
<a-date-picker v-model:value="datetimeValue" show-time
|
<a-date-picker v-model:value="datetimeValue" show-time
|
||||||
:style="{ width: datetimePicker.picker === 'year' ? '80px' : '' }"
|
:style="{ width: datetimePicker.picker === 'year' ? '80px' : '120px' }"
|
||||||
:format="datetimePicker.format !== null ? datetimePicker.format : undefined"
|
:format="datetimePicker.format !== null ? datetimePicker.format : undefined"
|
||||||
:picker="datetimePicker.picker" placeholder=" " @change="handleDateTimeChange"
|
:picker="datetimePicker.picker" placeholder=" " @change="handleDateTimeChange"
|
||||||
:size="'small'" />
|
:size="'small'" />
|
||||||
@ -73,6 +79,7 @@ import dayjs, { Dayjs } from 'dayjs';
|
|||||||
interface PromptConfig {
|
interface PromptConfig {
|
||||||
show: boolean;
|
show: boolean;
|
||||||
value: string;
|
value: string;
|
||||||
|
icon?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SelectConfig {
|
interface SelectConfig {
|
||||||
@ -112,6 +119,14 @@ const props = defineProps({
|
|||||||
value: '',
|
value: '',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
iconmap: {//自定义图标浮动
|
||||||
|
type: Object as () => PromptConfig,
|
||||||
|
default: () => ({
|
||||||
|
show: false,
|
||||||
|
value: '',
|
||||||
|
icon:'iconfont icon-time',
|
||||||
|
})
|
||||||
|
},
|
||||||
select: { // 选择框
|
select: { // 选择框
|
||||||
type: Object as () => SelectConfig,
|
type: Object as () => SelectConfig,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
|
|||||||
@ -13,24 +13,13 @@ import { ref, onMounted, 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 { getBaseKenWbsbdoList } from "@/api/home";
|
import { getBaseWbsb } from "@/api/home";
|
||||||
|
|
||||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
// 定义组件名(便于调试和递归)
|
// 定义组件名(便于调试和递归)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "jidiInfoMod",
|
name: "jidiInfoMod",
|
||||||
});
|
});
|
||||||
const title_text = ref("");
|
|
||||||
watch(
|
|
||||||
() => JidiSelectEventStore.selectedItem,
|
|
||||||
(newVal) => {
|
|
||||||
console.log(newVal);
|
|
||||||
if (newVal.name == "当前全部") {
|
|
||||||
}
|
|
||||||
initText();
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
const initText = () => {
|
const initText = () => {
|
||||||
const params = {
|
const params = {
|
||||||
filter: {
|
filter: {
|
||||||
@ -46,15 +35,26 @@ const initText = () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
getBaseKenWbsbdoList(params).then((res) => {
|
getBaseWbsb(params).then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
title_text.value = res.data.data[0].introduce;
|
title_text.value = res.data.data[0].introduce;
|
||||||
|
// debugger
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const title_text = ref("");
|
||||||
|
watch(
|
||||||
|
() => JidiSelectEventStore.selectedItem,
|
||||||
|
(newVal) => {
|
||||||
|
initText();
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
// 页面加载时执行的逻辑
|
// 页面加载时执行的逻辑
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initText();
|
initText();
|
||||||
console.log(JidiSelectEventStore.selectedItem);
|
console.log(JidiSelectEventStore.selectedItem);
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// ==================== 导入依赖 ====================
|
// ==================== 导入依赖 ====================
|
||||||
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import type { EChartsOption } from 'echarts'
|
import type { EChartsOption } from 'echarts'
|
||||||
import type { ColumnsType } from 'ant-design-vue/es/table/interface'
|
import type { ColumnsType } from 'ant-design-vue/es/table/interface'
|
||||||
@ -8,9 +8,12 @@ import { DownloadOutlined } from '@ant-design/icons-vue'
|
|||||||
import BasicSearch from '@/components/BasicSearch/index.vue'
|
import BasicSearch from '@/components/BasicSearch/index.vue'
|
||||||
import BasicTable from '@/components/BasicTable/index.vue'
|
import BasicTable from '@/components/BasicTable/index.vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
// TODO: 需要确认项目中是否有这些组件
|
import { useModelStore } from '@/store/modules/model'
|
||||||
// import { ModalTabs } from '@/components/MapModal/modalTabs'
|
import { handleTabs } from '@/components/MapModal/setting.config'
|
||||||
// import { handleTabs, modalTabSetting } from '@/components/MapModal/setting.config'
|
import { getKendoList, getKendoListCust, getIntroduce } from '@/api/shuidiankaifa'
|
||||||
|
|
||||||
|
// ==================== 开发配置 ====================
|
||||||
|
const USE_MOCK_DATA = true // 开发时使用模拟数据,生产时改为 false
|
||||||
|
|
||||||
// ==================== Props 定义 ====================
|
// ==================== Props 定义 ====================
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -57,6 +60,9 @@ interface ModalData {
|
|||||||
|
|
||||||
// ==================== 响应式状态 ====================
|
// ==================== 响应式状态 ====================
|
||||||
|
|
||||||
|
// 引入 modelStore 用于控制全局 MapModal
|
||||||
|
const modelStore = useModelStore()
|
||||||
|
|
||||||
// 基地相关
|
// 基地相关
|
||||||
const qid = ref<string>('')
|
const qid = ref<string>('')
|
||||||
const jiDiList = ref<any[]>([])
|
const jiDiList = ref<any[]>([])
|
||||||
@ -78,11 +84,12 @@ const pieCode = ref<string[]>([])
|
|||||||
const pikData = ref<PieDataItem[]>([])
|
const pikData = ref<PieDataItem[]>([])
|
||||||
const chartRef = ref<HTMLElement | null>(null)
|
const chartRef = ref<HTMLElement | null>(null)
|
||||||
const chartInstance = ref<any>(null)
|
const chartInstance = ref<any>(null)
|
||||||
|
const chartInitialized = ref<boolean>(false) // 关键:图表初始化标志
|
||||||
const dataLoading = ref<boolean>(false)
|
const dataLoading = ref<boolean>(false)
|
||||||
|
|
||||||
// 弹窗相关
|
// 弹窗相关(已废弃,改用全局 MapModal)
|
||||||
const mapModal = ref<boolean>(false)
|
// const mapModal = ref<boolean>(false)
|
||||||
const modalData = ref<ModalData>({ sttp: '', stcd: '', titleName: '' })
|
// const modalData = ref<ModalData>({ sttp: '', stcd: '', titleName: '' })
|
||||||
|
|
||||||
// 单位配置
|
// 单位配置
|
||||||
const unit = computed(() => getUnitConfigByCode('Other', 'ZJRL').unit)
|
const unit = computed(() => getUnitConfigByCode('Other', 'ZJRL').unit)
|
||||||
@ -99,46 +106,70 @@ const tableRef = ref<any>(null)
|
|||||||
* 获取Tab统计数据
|
* 获取Tab统计数据
|
||||||
*/
|
*/
|
||||||
async function fetchTabData(params: any): Promise<TabItem[]> {
|
async function fetchTabData(params: any): Promise<TabItem[]> {
|
||||||
// TODO: 替换为实际API调用
|
console.log('【API】获取Tab数据,参数:', params)
|
||||||
// const res = await shuiDianKaifaZhuangKung.GetKendoList(params, sortConfig)
|
|
||||||
|
|
||||||
console.log('【模拟】获取Tab数据,参数:', params)
|
|
||||||
|
|
||||||
|
// 开发模式:返回模拟数据
|
||||||
|
if (USE_MOCK_DATA) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 根据 seriesName 决定是否包含 ttpwr 过滤
|
|
||||||
const _name = `装机容量(${unit.value})`
|
const _name = `装机容量(${unit.value})`
|
||||||
const useTtpwrFilter = props.seriesName === _name
|
const useTtpwrFilter = props.seriesName === _name
|
||||||
|
|
||||||
// 模拟返回数据结构(与后端GetKendoList返回格式一致)
|
resolve([
|
||||||
const mockResponse = [
|
|
||||||
{
|
{
|
||||||
key: '2',
|
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
|
||||||
items: [{
|
key: 'build',
|
||||||
SUM_TTPWR: 1069300000, // kW单位
|
unit: useTtpwrFilter ? unit.value : '座',
|
||||||
COUNT_ENGID: 150
|
value: '已建',
|
||||||
}]
|
count: useTtpwrFilter ? 4568.50 : 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '1',
|
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
|
||||||
items: [{
|
key: 'building',
|
||||||
SUM_TTPWR: 331000000,
|
unit: useTtpwrFilter ? unit.value : '座',
|
||||||
COUNT_ENGID: 80
|
value: '在建',
|
||||||
}]
|
count: useTtpwrFilter ? 2345.30 : 85
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '0',
|
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
|
||||||
items: [{
|
key: 'noBuild',
|
||||||
SUM_TTPWR: 179000000,
|
unit: useTtpwrFilter ? unit.value : '座',
|
||||||
COUNT_ENGID: 30
|
value: '未建',
|
||||||
}]
|
count: useTtpwrFilter ? 1230.20 : 60
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}, 300)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
|
||||||
// 模拟数据处理逻辑(与React版本一致)
|
// 生产模式:调用真实 API
|
||||||
|
try {
|
||||||
|
const _name = `装机容量(${unit.value})`
|
||||||
|
const useTtpwrFilter = props.seriesName === _name
|
||||||
|
|
||||||
|
// 构建排序配置
|
||||||
|
const aggregates = [{ field: 'ttpwr', aggregate: 'sum' }]
|
||||||
|
const sortConfig = useTtpwrFilter
|
||||||
|
? [{ dir: 'desc', field: 'bldsttCcode', aggregates }]
|
||||||
|
: [{ dir: 'desc', field: 'bldsttCcode' }]
|
||||||
|
|
||||||
|
// 调用真实 API
|
||||||
|
const res = await getKendoList(
|
||||||
|
useTtpwrFilter
|
||||||
|
? { ...params, ttpwr: [{ field: 'ttpwr', operator: 'isnotnull' }] }
|
||||||
|
: params,
|
||||||
|
sortConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!res?.data || !Array.isArray(res.data)) {
|
||||||
|
console.warn('【API】Tab数据返回格式异常:', res)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据处理逻辑(与React版本一致)
|
||||||
let list: TabItem[] = []
|
let list: TabItem[] = []
|
||||||
|
|
||||||
const result = mockResponse.reduce((acc: any, cur: any) => {
|
res.data.reduce((acc: any, cur: any) => {
|
||||||
if (cur.key === '0') {
|
if (cur.key === '0') {
|
||||||
list.push({
|
list.push({
|
||||||
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
|
col: useTtpwrFilter ? 'ttpwr' : 'engTotal',
|
||||||
@ -167,120 +198,109 @@ async function fetchTabData(params: any): Promise<TabItem[]> {
|
|||||||
return list
|
return list
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
resolve(result)
|
console.log('【API】Tab数据处理结果:', list)
|
||||||
}, 500)
|
return list
|
||||||
})
|
} catch (error) {
|
||||||
|
console.error('【API】获取Tab数据失败:', error)
|
||||||
|
message.error('获取Tab数据失败')
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取饼图分组数据(完整实现React版本的复杂逻辑)
|
* 获取饼图分组数据(完整实现React版本的复杂逻辑)
|
||||||
*/
|
*/
|
||||||
async function fetchPieData(params: any): Promise<PieDataItem[]> {
|
async function fetchPieData(params: any): Promise<PieDataItem[]> {
|
||||||
// TODO: 替换为实际API调用
|
console.log('【API】获取饼图数据,参数:', params)
|
||||||
|
console.log('【API】USE_MOCK_DATA:', USE_MOCK_DATA, 'qid.value:', qid.value)
|
||||||
console.log('【模拟】获取饼图数据,参数:', params)
|
|
||||||
|
|
||||||
|
// 开发模式:返回模拟数据
|
||||||
|
if (USE_MOCK_DATA) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const _name = `装机容量(${unit.value})`
|
const _name = `装机容量(${unit.value})`
|
||||||
const useTtpwrFilter = props.seriesName === _name
|
const useTtpwrFilter = props.seriesName === _name
|
||||||
|
|
||||||
// 模拟后端返回的嵌套数据结构(与GetKendoList返回格式一致)
|
console.log('【模拟数据】生成饼图数据,useTtpwrFilter:', useTtpwrFilter, 'qid.value:', qid.value)
|
||||||
let mockResponse: any[]
|
|
||||||
|
let mockData: PieDataItem[]
|
||||||
|
|
||||||
if (qid.value === 'all') {
|
if (qid.value === 'all') {
|
||||||
// 全基地模式:按baseId分组
|
// 全基地模式:按基地分组
|
||||||
mockResponse = [
|
mockData = [
|
||||||
{
|
{ key: 'cj', name: '长江流域', value: useTtpwrFilter ? 4568.50 : 120, unit: '', dataDimensionRecursive: 'true' },
|
||||||
key: 'cj',
|
{ key: 'hh', name: '黄河流域', value: useTtpwrFilter ? 2345.30 : 85, unit: '', dataDimensionRecursive: 'true' },
|
||||||
items: [{
|
{ key: 'zj', name: '珠江流域', value: useTtpwrFilter ? 1230.20 : 60, unit: '', dataDimensionRecursive: 'true' },
|
||||||
key: 'cj_base',
|
{ key: 'hh2', name: '淮河流域', value: useTtpwrFilter ? 890.10 : 45, unit: '', dataDimensionRecursive: 'true' },
|
||||||
items: [{
|
{ key: 'hj', name: '海河流域', value: useTtpwrFilter ? 567.80 : 30, unit: '', dataDimensionRecursive: 'true' }
|
||||||
BASENAME: '长江流域',
|
|
||||||
SUM_TTPWR: 456800000, // kW
|
|
||||||
COUNT_BASEID: 120
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'hh',
|
|
||||||
items: [{
|
|
||||||
key: 'hh_base',
|
|
||||||
items: [{
|
|
||||||
BASENAME: '黄河流域',
|
|
||||||
SUM_TTPWR: 234500000,
|
|
||||||
COUNT_BASEID: 85
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zj',
|
|
||||||
items: [{
|
|
||||||
key: 'zj_base',
|
|
||||||
items: [{
|
|
||||||
BASENAME: '珠江流域',
|
|
||||||
SUM_TTPWR: 123000000,
|
|
||||||
COUNT_BASEID: 60
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
console.log('【模拟数据】全基地模式,生成 5 条数据')
|
||||||
} else if (qid.value === 'other') {
|
} else if (qid.value === 'other') {
|
||||||
// other模式:特殊处理
|
// other 模式:按河段分组
|
||||||
mockResponse = [
|
mockData = [
|
||||||
{
|
{ key: 'river1', name: '长江干流', value: useTtpwrFilter ? 890.50 : 25, unit: '', dataDimensionRecursive: 'true', index: 1 },
|
||||||
key: 'river1',
|
{ key: 'river2', name: '黄河干流', value: useTtpwrFilter ? 567.30 : 18, unit: '', dataDimensionRecursive: 'true', index: 2 },
|
||||||
items: [{
|
{ key: 'river3', name: '珠江干流', value: useTtpwrFilter ? 345.20 : 12, unit: '', dataDimensionRecursive: 'true', index: 3 }
|
||||||
HBRVCDNAME: '长江干流',
|
|
||||||
SUM_TTPWR: 89000000,
|
|
||||||
COUNT_BLDSTTCCODE: 25
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'river2',
|
|
||||||
items: [{
|
|
||||||
HBRVCDNAME: '黄河干流',
|
|
||||||
SUM_TTPWR: 56000000,
|
|
||||||
COUNT_BLDSTTCCODE: 18
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'river3',
|
|
||||||
items: [{
|
|
||||||
HBRVCDNAME: '珠江干流',
|
|
||||||
SUM_TTPWR: 34000000,
|
|
||||||
COUNT_BLDSTTCCODE: 12
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
console.log('【模拟数据】other 模式,生成 3 条数据')
|
||||||
} else {
|
} else {
|
||||||
// 单个基地模式:按hbrvcd分组
|
// 单个基地模式:按河段分组
|
||||||
mockResponse = [
|
mockData = [
|
||||||
{
|
{ key: 'cjgl', name: '长江干流', value: useTtpwrFilter ? 2345.60 : 50, unit: '', dataDimensionRecursive: 'true' },
|
||||||
items: [{
|
{ key: 'cjzl', name: '长江支流', value: useTtpwrFilter ? 1234.50 : 35, unit: '', dataDimensionRecursive: 'true' },
|
||||||
key: 'cjgl',
|
{ key: 'cjxz', name: '长江下游', value: useTtpwrFilter ? 987.40 : 25, unit: '', dataDimensionRecursive: 'true' }
|
||||||
items: [{
|
|
||||||
HBRVCDNAME: '长江干流',
|
|
||||||
SUM_TTPWR: 456800000,
|
|
||||||
COUNT_BLDSTTCCODE: 50
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
items: [{
|
|
||||||
key: 'hhgl',
|
|
||||||
items: [{
|
|
||||||
HBRVCDNAME: '黄河干流',
|
|
||||||
SUM_TTPWR: 234500000,
|
|
||||||
COUNT_BLDSTTCCODE: 35
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
console.log('【模拟数据】单基地模式,生成 3 条数据')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模拟数据处理逻辑(完全复刻React版本的flatMap逻辑)
|
console.log('【模拟数据】✅ 饼图数据生成成功:', mockData.length, '条')
|
||||||
let list = mockResponse.flatMap((item: any) => {
|
console.log('【模拟数据】数据详情:', mockData)
|
||||||
|
|
||||||
|
resolve(mockData)
|
||||||
|
}, 300)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生产模式:调用真实 API
|
||||||
|
try {
|
||||||
|
const _name = `装机容量(${unit.value})`
|
||||||
|
const useTtpwrFilter = props.seriesName === _name
|
||||||
|
|
||||||
|
// 构建排序配置
|
||||||
|
const aggregates = [{ field: 'ttpwr', aggregate: 'sum' }]
|
||||||
|
const sortConfig = [
|
||||||
|
qid.value === 'all' || qid.value === 'other' ? null : { dir: 'asc', field: 'rvcdStepSort' },
|
||||||
|
qid.value === 'all' ? { dir: 'asc', field: 'baseStepSort' } : null,
|
||||||
|
{
|
||||||
|
dir: 'asc',
|
||||||
|
field: qid.value === 'all' ? 'baseId' : 'hbrvcd'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dir: 'desc',
|
||||||
|
field: qid.value === 'all' ? 'baseName' : 'hbrvcdName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dir: 'desc',
|
||||||
|
field: 'bldsttCcode',
|
||||||
|
aggregates
|
||||||
|
}
|
||||||
|
].filter(Boolean)
|
||||||
|
|
||||||
|
// 调用真实 API
|
||||||
|
const res = await getKendoList(
|
||||||
|
useTtpwrFilter
|
||||||
|
? { ...params, ttpwr: [{ field: 'ttpwr', operator: 'isnotnull' }] }
|
||||||
|
: params,
|
||||||
|
sortConfig as any[]
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!res?.data || !Array.isArray(res.data)) {
|
||||||
|
console.warn('【API】饼图数据返回格式异常:', res)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据处理逻辑(完全复刻React版本的flatMap逻辑)
|
||||||
|
let list = res.data.flatMap((item: any) => {
|
||||||
let arr: PieDataItem[] = []
|
let arr: PieDataItem[] = []
|
||||||
|
|
||||||
// 关键:根据 qid 决定数据提取路径
|
// 关键:根据 qid 决定数据提取路径
|
||||||
@ -319,16 +339,20 @@ async function fetchPieData(params: any): Promise<PieDataItem[]> {
|
|||||||
|
|
||||||
// 特殊处理:other 类型需要调用 getIntroduce 接口排序
|
// 特殊处理:other 类型需要调用 getIntroduce 接口排序
|
||||||
if (qid.value === 'other' && list.length > 0) {
|
if (qid.value === 'other' && list.length > 0) {
|
||||||
// 模拟 getIntroduce 接口返回
|
const introRes = await getIntroduce(
|
||||||
const introRes = [
|
[
|
||||||
{ wbsCode: 'river1', orderIndex: 1 },
|
{ field: 'wbsType', operator: 'eq', value: 'PSB_RVCD' },
|
||||||
{ wbsCode: 'river2', orderIndex: 2 },
|
{ field: 'objId', operator: 'eq', value: 'other' },
|
||||||
{ wbsCode: 'river3', orderIndex: 3 }
|
{ field: 'orderIndex', operator: 'isnotnull' }
|
||||||
]
|
],
|
||||||
|
[{ field: 'orderIndex', dir: 'asc' }],
|
||||||
|
false,
|
||||||
|
['wbsCode', 'wbsName', 'orderIndex']
|
||||||
|
)
|
||||||
|
|
||||||
if (introRes?.length && list?.length) {
|
if (introRes?.data?.length && list?.length) {
|
||||||
list = list.map((el: any) => {
|
list = list.map((el: any) => {
|
||||||
const found = introRes.find((item: any) => el?.key === item?.wbsCode)
|
const found = introRes.data.find((item: any) => el?.key === item?.wbsCode)
|
||||||
return {
|
return {
|
||||||
...el,
|
...el,
|
||||||
index: found?.orderIndex
|
index: found?.orderIndex
|
||||||
@ -337,9 +361,13 @@ async function fetchPieData(params: any): Promise<PieDataItem[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(list)
|
console.log('【API】饼图数据处理结果:', list)
|
||||||
}, 500)
|
return list
|
||||||
})
|
} catch (error) {
|
||||||
|
console.error('【API】获取饼图数据失败:', error)
|
||||||
|
message.error('获取饼图数据失败')
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -364,42 +392,40 @@ async function fetchIntroduce(params: any): Promise<any[]> {
|
|||||||
/**
|
/**
|
||||||
* 表格数据请求函数
|
* 表格数据请求函数
|
||||||
*/
|
*/
|
||||||
async function fetchTableData(params: any): Promise<{ records: any[], total: number }> {
|
async function fetchTableData(params: any): Promise<any> {
|
||||||
// TODO: 替换为实际API调用
|
console.log('【API】获取表格数据,参数:', params)
|
||||||
// const url = qid.value === 'all'
|
|
||||||
// ? '/dec-lygk-base-server/base/vmsstbprpt/GetKendoListCust'
|
|
||||||
// : '/dec-lygk-base-server/base/vmsstbprpt/GetKendoList'
|
|
||||||
|
|
||||||
console.log('【模拟】获取表格数据,参数:', params)
|
|
||||||
|
|
||||||
|
// 开发模式:返回模拟数据
|
||||||
|
if (USE_MOCK_DATA) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 根据建设状态和河段过滤生成对应的模拟数据
|
|
||||||
const buildStatus = params.bldsttCcode
|
const buildStatus = params.bldsttCcode
|
||||||
const hbrvcdFilter = params.hbrvcd?.value || []
|
const hbrvcdFilter = Array.isArray(params.hbrvcd)
|
||||||
|
? params.hbrvcd[0]?.value || []
|
||||||
|
: []
|
||||||
|
|
||||||
// 电站基础数据模板
|
// 电站基础数据模板
|
||||||
const stationTemplates = [
|
const stationTemplates = [
|
||||||
{ name: '三峡', river: 'cjgl', baseName: '长江基地', province: '湖北省' },
|
{ name: '三峡', river: 'cjgl', baseName: '长江流域', province: '湖北省' },
|
||||||
{ name: '葛洲坝', river: 'cjgl', baseName: '长江基地', province: '湖北省' },
|
{ name: '葛洲坝', river: 'cjgl', baseName: '长江流域', province: '湖北省' },
|
||||||
{ name: '向家坝', river: 'cjgl', baseName: '长江基地', province: '四川省' },
|
{ name: '向家坝', river: 'cjgl', baseName: '长江流域', province: '四川省' },
|
||||||
{ name: '溪洛渡', river: 'cjgl', baseName: '长江基地', province: '云南省' },
|
{ name: '溪洛渡', river: 'cjgl', baseName: '长江流域', province: '云南省' },
|
||||||
{ name: '白鹤滩', river: 'cjgl', baseName: '长江基地', province: '四川省' },
|
{ name: '白鹤滩', river: 'cjgl', baseName: '长江流域', province: '四川省' },
|
||||||
{ name: '乌东德', river: 'cjgl', baseName: '长江基地', province: '云南省' },
|
{ name: '乌东德', river: 'cjgl', baseName: '长江流域', province: '云南省' },
|
||||||
{ name: '小浪底', river: 'hhgl', baseName: '黄河基地', province: '河南省' },
|
{ name: '小浪底', river: 'hhgl', baseName: '黄河流域', province: '河南省' },
|
||||||
{ name: '刘家峡', river: 'hhgl', baseName: '黄河基地', province: '甘肃省' },
|
{ name: '刘家峡', river: 'hhgl', baseName: '黄河流域', province: '甘肃省' },
|
||||||
{ name: '龙羊峡', river: 'hhgl', baseName: '黄河基地', province: '青海省' },
|
{ name: '龙羊峡', river: 'hhgl', baseName: '黄河流域', province: '青海省' },
|
||||||
{ name: '拉西瓦', river: 'hhgl', baseName: '黄河基地', province: '青海省' },
|
{ name: '拉西瓦', river: 'hhgl', baseName: '黄河流域', province: '青海省' },
|
||||||
{ name: '天生桥', river: 'zjgl', baseName: '珠江基地', province: '贵州省' },
|
{ name: '天生桥', river: 'zjgl', baseName: '珠江流域', province: '贵州省' },
|
||||||
{ name: '岩滩', river: 'zjgl', baseName: '珠江基地', province: '广西区' },
|
{ name: '岩滩', river: 'zjgl', baseName: '珠江流域', province: '广西区' },
|
||||||
{ name: '大化', river: 'zjgl', baseName: '珠江基地', province: '广西区' },
|
{ name: '大化', river: 'zjgl', baseName: '珠江流域', province: '广西区' },
|
||||||
{ name: '响洪甸', river: 'hhgl', baseName: '淮河基地', province: '安徽省' },
|
{ name: '响洪甸', river: 'hhgl2', baseName: '淮河流域', province: '安徽省' },
|
||||||
{ name: '梅山', river: 'hhgl', baseName: '淮河基地', province: '安徽省' },
|
{ name: '梅山', river: 'hhgl2', baseName: '淮河流域', province: '安徽省' },
|
||||||
{ name: '潘家口', river: 'hjgl', baseName: '海河基地', province: '河北省' },
|
{ name: '潘家口', river: 'hjgl', baseName: '海河流域', province: '河北省' },
|
||||||
{ name: '大黑汀', river: 'hjgl', baseName: '海河基地', province: '河北省' },
|
{ name: '大黑汀', river: 'hjgl', baseName: '海河流域', province: '河北省' },
|
||||||
{ name: '丰满', river: 'sjgl', baseName: '松花江基地', province: '吉林省' },
|
{ name: '丰满', river: 'sjgl', baseName: '松花江流域', province: '吉林省' },
|
||||||
{ name: '白山', river: 'sjgl', baseName: '松花江基地', province: '吉林省' },
|
{ name: '白山', river: 'sjgl', baseName: '松花江流域', province: '吉林省' },
|
||||||
{ name: '水丰', river: 'ljgl', baseName: '辽河基地', province: '辽宁省' }
|
{ name: '水丰', river: 'ljgl', baseName: '辽河流域', province: '辽宁省' }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 根据建设状态筛选电站
|
// 根据建设状态筛选电站
|
||||||
@ -412,7 +438,13 @@ async function fetchTableData(params: any): Promise<{ records: any[], total: num
|
|||||||
|
|
||||||
// 如果没有匹配的河段,返回空数组
|
// 如果没有匹配的河段,返回空数组
|
||||||
if (filteredStations.length === 0) {
|
if (filteredStations.length === 0) {
|
||||||
resolve({ records: [], total: 0 })
|
// 关键:返回 BasicTable 期望的格式 { data: { records: [], total: 0 } }
|
||||||
|
resolve({
|
||||||
|
data: {
|
||||||
|
records: [],
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,21 +511,61 @@ async function fetchTableData(params: any): Promise<{ records: any[], total: num
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('【调试】模拟表格数据:', {
|
||||||
|
records: mockRecords.length,
|
||||||
|
total: mockRecords.length,
|
||||||
|
firstRecord: mockRecords[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 关键:返回 BasicTable 期望的格式 { data: { records: [], total: 0 } }
|
||||||
resolve({
|
resolve({
|
||||||
|
data: {
|
||||||
records: mockRecords,
|
records: mockRecords,
|
||||||
total: mockRecords.length
|
total: mockRecords.length
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}, 600)
|
}, 400)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生产模式:调用真实 API
|
||||||
|
try {
|
||||||
|
// 根据 qid 决定使用哪个接口
|
||||||
|
const url = qid.value === 'all'
|
||||||
|
? '/dec-lygk-base-server/base/vmsstbprpt/GetKendoListCust'
|
||||||
|
: '/dec-lygk-base-server/base/vmsstbprpt/GetKendoList'
|
||||||
|
|
||||||
|
const apiFunc = qid.value === 'all' ? getKendoListCust : getKendoList
|
||||||
|
|
||||||
|
// 调用真实 API
|
||||||
|
const res = await apiFunc(params, [])
|
||||||
|
|
||||||
|
// 关键:确保返回格式为 { data: { records: [], total: 0 } }
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
records: res?.data?.records || res?.data?.items || [],
|
||||||
|
total: res?.data?.total || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('【API】获取表格数据失败:', error)
|
||||||
|
message.error('获取表格数据失败')
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
records: [],
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 工具函数 ====================
|
// ==================== 工具函数 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单位转换函数(待完善)
|
* 单位转换函数
|
||||||
*/
|
*/
|
||||||
function transUnit(value: number, from: string, to: string): number {
|
function transUnit(value: number, from: string, to: string): number {
|
||||||
// TODO: 根据实际业务规则实现
|
// 根据实际业务规则实现
|
||||||
// 当前假设:接口返回的单位是 kW,需要转换为万kW
|
// 当前假设:接口返回的单位是 kW,需要转换为万kW
|
||||||
if (from === 'Other' && to === 'ZJRL') {
|
if (from === 'Other' && to === 'ZJRL') {
|
||||||
return value / 10000 // kW → 万kW
|
return value / 10000 // kW → 万kW
|
||||||
@ -523,20 +595,15 @@ function handleExport() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理弹窗关闭
|
|
||||||
*/
|
|
||||||
function handleModalCancel() {
|
|
||||||
mapModal.value = false
|
|
||||||
modalData.value = { sttp: '', stcd: '', titleName: '' }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== ECharts 饼图配置 ====================
|
// ==================== ECharts 饼图配置 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算饼图配置(增强版,支持themeecList自定义颜色)
|
* 计算饼图配置(增强版,支持themeecList自定义颜色)
|
||||||
*/
|
*/
|
||||||
const chartSetting = computed<EChartsOption>(() => {
|
const chartSetting = computed<EChartsOption>(() => {
|
||||||
|
console.log('【chartSetting】计算饼图配置,pieData.value 长度:', pieData.value.length)
|
||||||
|
console.log('【chartSetting】pieData.value 内容:', pieData.value)
|
||||||
|
|
||||||
const total = pieData.value.reduce((acc, item) => acc + item.value, 0).toFixed(2)
|
const total = pieData.value.reduce((acc, item) => acc + item.value, 0).toFixed(2)
|
||||||
const flag = props.seriesName === '数量(座)'
|
const flag = props.seriesName === '数量(座)'
|
||||||
|
|
||||||
@ -544,6 +611,8 @@ const chartSetting = computed<EChartsOption>(() => {
|
|||||||
const dddd = flag ? '电站数量' : '装机容量'
|
const dddd = flag ? '电站数量' : '装机容量'
|
||||||
const cccc = flag ? ' (座)' : ` (${unit.value})`
|
const cccc = flag ? ' (座)' : ` (${unit.value})`
|
||||||
|
|
||||||
|
console.log('【chartSetting】配置信息:', { total, bbbb, dddd, cccc, seriesDataLength: pieData.value.length })
|
||||||
|
|
||||||
// 关键:根据 themeecList 动态设置颜色(与React版本一致)
|
// 关键:根据 themeecList 动态设置颜色(与React版本一致)
|
||||||
const colors = pieData.value.map((item: any, index: any) => {
|
const colors = pieData.value.map((item: any, index: any) => {
|
||||||
if (props.themeecList && props.themeecList.length > 0) {
|
if (props.themeecList && props.themeecList.length > 0) {
|
||||||
@ -623,14 +692,78 @@ const chartSetting = computed<EChartsOption>(() => {
|
|||||||
* 初始化图表
|
* 初始化图表
|
||||||
*/
|
*/
|
||||||
function initChart() {
|
function initChart() {
|
||||||
if (!chartRef.value) return
|
console.log('【图表初始化】尝试初始化,chartRef.value:', chartRef.value)
|
||||||
|
console.log('【图表初始化】当前 pieData.value 长度:', pieData.value.length)
|
||||||
|
|
||||||
|
if (!chartRef.value) {
|
||||||
|
console.warn('【图表初始化】容器未就绪,延迟重试')
|
||||||
|
setTimeout(initChart, 200)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证容器尺寸
|
||||||
|
const rect = chartRef.value.getBoundingClientRect()
|
||||||
|
const containerWidth = chartRef.value.offsetWidth
|
||||||
|
const containerHeight = chartRef.value.offsetHeight
|
||||||
|
|
||||||
|
console.log('【图表初始化】容器信息:', {
|
||||||
|
offsetWidth: containerWidth,
|
||||||
|
offsetHeight: containerHeight,
|
||||||
|
getBoundingClientRect: {
|
||||||
|
width: rect.width,
|
||||||
|
height: rect.height,
|
||||||
|
top: rect.top,
|
||||||
|
left: rect.left
|
||||||
|
},
|
||||||
|
display: window.getComputedStyle(chartRef.value).display,
|
||||||
|
visibility: window.getComputedStyle(chartRef.value).visibility,
|
||||||
|
parentDisplay: window.getComputedStyle(chartRef.value.parentElement).display
|
||||||
|
})
|
||||||
|
|
||||||
|
// 临时添加红色边框验证容器可见性
|
||||||
|
chartRef.value.style.border = '3px solid red'
|
||||||
|
chartRef.value.style.background = 'rgba(255, 0, 0, 0.1)'
|
||||||
|
|
||||||
|
if (containerWidth === 0 || containerHeight === 0) {
|
||||||
|
console.error('【图表初始化】❌ 容器尺寸为0,无法初始化')
|
||||||
|
console.log('【图表初始化】⏰ 200ms 后重试...')
|
||||||
|
setTimeout(initChart, 200)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('【图表初始化】✅ 容器尺寸正常,开始初始化 ECharts')
|
||||||
|
|
||||||
// 关键:使用固定的图表尺寸(541px × 412px)
|
// 关键:使用固定的图表尺寸(541px × 412px)
|
||||||
chartInstance.value = echarts.init(chartRef.value, null, {
|
chartInstance.value = echarts.init(chartRef.value, null, {
|
||||||
width: 541,
|
width: 541,
|
||||||
height: 412
|
height: 412
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('【图表初始化】ECharts 实例创建成功')
|
||||||
|
|
||||||
|
// 绑定图例选择事件
|
||||||
|
chartInstance.value.on('legendselectchanged', handleLegendSelectChanged)
|
||||||
|
|
||||||
|
// 绑定点击事件
|
||||||
|
chartInstance.value.on('click', handlePieClick)
|
||||||
|
|
||||||
|
// 关键:只有当有数据时才调用 updateChart
|
||||||
|
if (pieData.value.length > 0) {
|
||||||
|
console.log('【图表初始化】✅ 数据已就绪,渲染图表')
|
||||||
updateChart()
|
updateChart()
|
||||||
|
|
||||||
|
// 关键:延迟调用 resize 确保渲染完成
|
||||||
|
setTimeout(() => {
|
||||||
|
chartInstance.value?.resize()
|
||||||
|
console.log('【图表初始化】✅ resize 完成')
|
||||||
|
console.log('【图表初始化】图表数据:', pieData.value.length, '条')
|
||||||
|
chartInitialized.value = true
|
||||||
|
}, 100)
|
||||||
|
} else {
|
||||||
|
console.log('【图表初始化】⏰ 数据未就绪,标记为已初始化,等待 watch 触发更新')
|
||||||
|
// 设置标志,数据加载后会触发渲染
|
||||||
|
chartInitialized.value = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -771,12 +904,17 @@ const columns: ColumnsType = [
|
|||||||
* 处理表格行点击(打开详情弹窗)
|
* 处理表格行点击(打开详情弹窗)
|
||||||
*/
|
*/
|
||||||
function handleRowClick(record: any) {
|
function handleRowClick(record: any) {
|
||||||
modalData.value = {
|
// 使用全局 MapModal 组件
|
||||||
|
modelStore.params = {
|
||||||
sttp: 'ENG',
|
sttp: 'ENG',
|
||||||
stcd: record.stcd,
|
stcd: record.stcd,
|
||||||
titleName: record.stnm
|
titleName: record.stnm
|
||||||
}
|
} as any // 临时类型断言,因为 store 定义不完整
|
||||||
mapModal.value = true
|
modelStore.title = record.stnm ? `${record.stnm} 详情信息` : '详情信息'
|
||||||
|
modelStore.tabList = handleTabs(modelStore.params)
|
||||||
|
modelStore.modalVisible = true
|
||||||
|
|
||||||
|
console.log('【打开详情弹窗】参数:', modelStore.params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 搜索表单配置 ====================
|
// ==================== 搜索表单配置 ====================
|
||||||
@ -959,7 +1097,12 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
[tabKey, tabCol, stnm, qid],
|
[tabKey, tabCol, stnm, qid],
|
||||||
async () => {
|
async () => {
|
||||||
if (!tabKey.value || !tabCol.value) return
|
console.log('【Watch触发】tabKey:', tabKey.value, 'tabCol:', tabCol.value, 'stnm:', stnm.value, 'qid:', qid.value)
|
||||||
|
|
||||||
|
if (!tabKey.value || !tabCol.value) {
|
||||||
|
console.log('【Watch触发】跳过:tabKey 或 tabCol 为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
dataLoading.value = true
|
dataLoading.value = true
|
||||||
try {
|
try {
|
||||||
@ -979,8 +1122,12 @@ watch(
|
|||||||
delete params.stnmContains
|
delete params.stnmContains
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('【Watch触发】调用 fetchPieData,参数:', params)
|
||||||
const result = await fetchPieData(params)
|
const result = await fetchPieData(params)
|
||||||
|
|
||||||
|
console.log('【Watch触发】✅ fetchPieData 返回结果:', result.length, '条')
|
||||||
|
console.log('【Watch触发】数据内容:', result)
|
||||||
|
|
||||||
// 特殊处理 other 类型
|
// 特殊处理 other 类型
|
||||||
if (qid.value === 'other' && result.length > 0) {
|
if (qid.value === 'other' && result.length > 0) {
|
||||||
const introRes = await fetchIntroduce({
|
const introRes = await fetchIntroduce({
|
||||||
@ -1003,11 +1150,33 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('【Watch触发】更新 pieData,数据量:', result.length)
|
||||||
pikData.value = result
|
pikData.value = result
|
||||||
pieData.value = result
|
pieData.value = result
|
||||||
pieCode.value = []
|
pieCode.value = []
|
||||||
|
|
||||||
|
console.log('【Watch触发】pieData.value 更新后的值:', pieData.value)
|
||||||
|
|
||||||
|
// 关键:等待 DOM 更新
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
// 关键:如果图表未初始化,先初始化;否则直接更新
|
||||||
|
if (!chartInitialized.value) {
|
||||||
|
console.log('【Watch触发】图表未初始化,开始初始化图表')
|
||||||
|
// 延迟初始化,确保容器完全渲染
|
||||||
|
setTimeout(() => {
|
||||||
|
initChart()
|
||||||
|
}, 200)
|
||||||
|
} else {
|
||||||
|
// 图表已初始化,直接更新数据
|
||||||
|
console.log('【Watch触发】图表已初始化,更新数据')
|
||||||
|
updateChart()
|
||||||
|
chartInstance.value?.resize()
|
||||||
|
console.log('【图表更新】数据变化,重新渲染')
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取饼图数据失败:', error)
|
console.error('【API】获取饼图数据失败:', error)
|
||||||
message.error('获取饼图数据失败')
|
message.error('获取饼图数据失败')
|
||||||
} finally {
|
} finally {
|
||||||
dataLoading.value = false
|
dataLoading.value = false
|
||||||
@ -1038,10 +1207,32 @@ onMounted(() => {
|
|||||||
qid.value = 'all'
|
qid.value = 'all'
|
||||||
}
|
}
|
||||||
|
|
||||||
initChart()
|
// 关键:不再在 onMounted 中初始化图表
|
||||||
|
// 图表初始化由 watch 监听数据加载后触发,避免竞态条件
|
||||||
|
console.log('【生命周期】onMounted 触发,等待数据加载后初始化图表')
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize)
|
window.addEventListener('resize', handleResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听 Tab 切换,确保图表在 Tab 激活时正确渲染
|
||||||
|
watch(tabIndex, async (newTab, oldTab) => {
|
||||||
|
console.log('【Tab切换】从', oldTab, '切换到', newTab)
|
||||||
|
|
||||||
|
// 等待 DOM 更新
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (chartInstance.value && chartInitialized.value) {
|
||||||
|
console.log('【Tab切换】重新调整图表尺寸')
|
||||||
|
chartInstance.value.resize()
|
||||||
|
updateChart()
|
||||||
|
} else if (!chartInitialized.value) {
|
||||||
|
console.log('【Tab切换】图表未初始化,等待数据加载后初始化')
|
||||||
|
// 不在此处初始化,由 watch([tabKey, tabCol...]) 处理
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
chartInstance.value?.dispose()
|
chartInstance.value?.dispose()
|
||||||
window.removeEventListener('resize', handleResize)
|
window.removeEventListener('resize', handleResize)
|
||||||
@ -1108,36 +1299,8 @@ onUnmounted(() => {
|
|||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
|
||||||
<!-- 详情弹窗 -->
|
<!-- 详情弹窗已改用全局 MapModal 组件,在 AppMain.vue 中统一管理 -->
|
||||||
<a-modal
|
<!-- 无需在此处添加 a-modal,点击表格行会自动触发 modelStore.modalVisible -->
|
||||||
v-if="mapModal && modalData.sttp"
|
|
||||||
:open="mapModal"
|
|
||||||
:title="modalData.titleName ? `${modalData.titleName} 详情信息` : '详情信息'"
|
|
||||||
:width="1200"
|
|
||||||
:footer="null"
|
|
||||||
:maskClosable="false"
|
|
||||||
class="tabsModal"
|
|
||||||
style="padding-bottom: 0"
|
|
||||||
@cancel="handleModalCancel"
|
|
||||||
>
|
|
||||||
<!-- TODO: 集成ModalTabs组件 -->
|
|
||||||
<!-- <ModalTabs v-if="modalData" :tabs="handleTabs(modalData)" :params="modalData" /> -->
|
|
||||||
|
|
||||||
<!-- 临时替代方案 -->
|
|
||||||
<div class="modal-content">
|
|
||||||
<a-descriptions bordered :column="2">
|
|
||||||
<a-descriptions-item label="电站编码">
|
|
||||||
{{ modalData.stcd }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="电站类型">
|
|
||||||
{{ modalData.sttp }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
<p style="margin-top: 16px; color: #999;">
|
|
||||||
TODO: 请确认 ModalTabs 组件路径后启用上方注释代码
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<SidePanelItem title="沿程水质变化" :datetimePicker="datetimePicker">
|
<SidePanelItem title="沿程水质变化" :iconmap="iconmap" :datetimePicker="datetimePicker">
|
||||||
<div class="chart-container" ref="chartRef"></div>
|
<div class="chart-container" ref="chartRef"></div>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</template>
|
</template>
|
||||||
@ -17,7 +17,11 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'waterQuality'
|
name: 'waterQuality'
|
||||||
});
|
});
|
||||||
|
const iconmap = ref({
|
||||||
|
show: true,
|
||||||
|
value: '注:最新数据时间为2026-05-14 23:00',
|
||||||
|
icon: 'iconfont icon-time',
|
||||||
|
});
|
||||||
// ==================== 响应式数据 ====================
|
// ==================== 响应式数据 ====================
|
||||||
const chartRef = ref<HTMLElement | null>(null);
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
let chartInstance: echarts.ECharts | null = null;
|
let chartInstance: echarts.ECharts | null = null;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<!-- SidePanelItem.vue -->
|
<!-- SidePanelItem.vue -->
|
||||||
<template>
|
<template>
|
||||||
<SidePanelItem title="沿程水温变化" :prompt="prompts">
|
<SidePanelItem title="沿程水温变化" :prompt="prompts" :select="select" :datetimePicker="datetimePicker">
|
||||||
<div ref="chartRef" class="chart-container"></div>
|
<div ref="chartRef" class="chart-container"></div>
|
||||||
</SidePanelItem>
|
</SidePanelItem>
|
||||||
</template>
|
</template>
|
||||||
@ -15,7 +15,23 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
|||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'yanchengshuiwenChangeMod'
|
name: 'yanchengshuiwenChangeMod'
|
||||||
});
|
});
|
||||||
|
// 选择器配置
|
||||||
|
const select = ref({
|
||||||
|
show: true,
|
||||||
|
value: undefined,
|
||||||
|
options: [],
|
||||||
|
picker: undefined,
|
||||||
|
format: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// 日期选择器配置
|
||||||
|
const datetimePicker = ref({
|
||||||
|
show: true,
|
||||||
|
value: '2026-05-15 15',
|
||||||
|
format: 'YYYY-MM-DD HH',
|
||||||
|
picker: 'date' as const,
|
||||||
|
options: []
|
||||||
|
});
|
||||||
const prompts = ref({
|
const prompts = ref({
|
||||||
show: true,
|
show: true,
|
||||||
value: '注:最新数据时间为2026-04-08 23',
|
value: '注:最新数据时间为2026-04-08 23',
|
||||||
|
|||||||
@ -1,7 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||||
import HuanbaozdjcgzkzQK from "@/modules/huanbaozdjcgzkzQK/index.vue"
|
import HuanbaozdjcgzkzQK from "@/modules/huanbaozdjcgzkzQK/index.vue";
|
||||||
|
import SZYCBH from "@/modules/waterQuality/index.vue"
|
||||||
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
const wbsCode = ref('')
|
||||||
|
watch(
|
||||||
|
() => JidiSelectEventStore.selectedItem,
|
||||||
|
(newVal) => {
|
||||||
|
wbsCode.value = newVal.wbsCode
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -12,6 +24,7 @@ import HuanbaozdjcgzkzQK from "@/modules/huanbaozdjcgzkzQK/index.vue"
|
|||||||
<div class="rightContent">
|
<div class="rightContent">
|
||||||
<RightDrawer>
|
<RightDrawer>
|
||||||
<HuanbaozdjcgzkzQK />
|
<HuanbaozdjcgzkzQK />
|
||||||
|
<SZYCBH v-if="wbsCode != 'all'" />
|
||||||
</RightDrawer>
|
</RightDrawer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,8 +1,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||||
import ShuiZhiJianCeGongZuoQingKuang from "@/modules/shuizhijiancegongzuoQK/index.vue"
|
import ShuiZhiJianCeGongZuoQingKuang from "@/modules/shuizhijiancegongzuoQK/index.vue"
|
||||||
import EnvironmentalQuality from "@/modules/EnvironmentalQuality/index.vue" // 环境质量满足度
|
import EnvironmentalQuality from "@/modules/EnvironmentalQuality/index.vue" // 环境质量满足度
|
||||||
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
|
import SZYCBH from "@/modules/waterQuality/index.vue"
|
||||||
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
const wbsCode = ref('');
|
||||||
|
watch(
|
||||||
|
() => JidiSelectEventStore.selectedItem,
|
||||||
|
(newVal) => {
|
||||||
|
console.log(newVal);
|
||||||
|
wbsCode.value = newVal.wbsCode;
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -14,6 +27,8 @@ import EnvironmentalQuality from "@/modules/EnvironmentalQuality/index.vue" //
|
|||||||
<RightDrawer>
|
<RightDrawer>
|
||||||
<ShuiZhiJianCeGongZuoQingKuang />
|
<ShuiZhiJianCeGongZuoQingKuang />
|
||||||
<EnvironmentalQuality />
|
<EnvironmentalQuality />
|
||||||
|
<SZYCBH v-if="wbsCode != 'all'"></SZYCBH>
|
||||||
|
|
||||||
</RightDrawer>
|
</RightDrawer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||||
|
|
||||||
@ -7,6 +8,21 @@ import ZengZhiZhanJieShaoMod from "@/modules/zengZhiZhanJieShaoMod/index.vue"
|
|||||||
import ZZZJSYXQKTT from "@/modules/zengzhizhanjiansheyunxing/index.vue"
|
import ZZZJSYXQKTT from "@/modules/zengzhizhanjiansheyunxing/index.vue"
|
||||||
import ZZZYXSJTJ from "@/modules/zengzhizhanyunxingsjtj/index.vue"
|
import ZZZYXSJTJ from "@/modules/zengzhizhanyunxingsjtj/index.vue"
|
||||||
import FLZLLB from "@/modules/GYZLLB/index.vue"
|
import FLZLLB from "@/modules/GYZLLB/index.vue"
|
||||||
|
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||||
|
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||||
|
const wbsCode = ref('all');
|
||||||
|
watch(
|
||||||
|
() => JidiSelectEventStore.selectedItem,
|
||||||
|
(newVal) => {
|
||||||
|
console.log(newVal);
|
||||||
|
if (newVal.wbsCode == 'all') {
|
||||||
|
wbsCode.value = 'all';
|
||||||
|
} else {
|
||||||
|
wbsCode.value = newVal.wbsCode;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -17,8 +33,8 @@ import FLZLLB from "@/modules/GYZLLB/index.vue"
|
|||||||
<div class="rightContent">
|
<div class="rightContent">
|
||||||
<RightDrawer>
|
<RightDrawer>
|
||||||
<ZZZJSYXQKTT />
|
<ZZZJSYXQKTT />
|
||||||
<ZengZhiZhanJieShaoMod />
|
<ZengZhiZhanJieShaoMod v-if="wbsCode != 'all'" />
|
||||||
<ZengZhiJiHuaWanChengQingKuang />
|
<ZengZhiJiHuaWanChengQingKuang v-if="wbsCode != 'all'" />
|
||||||
<FLZLLB title="放流总量" />
|
<FLZLLB title="放流总量" />
|
||||||
<ZZZYXSJTJ />
|
<ZZZYXSJTJ />
|
||||||
</RightDrawer>
|
</RightDrawer>
|
||||||
|
|||||||
1492
package-lock.json
generated
1492
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
6
package.json
Normal file
6
package.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"cesium": "^1.140.0",
|
||||||
|
"vite-plugin-cesium": "^1.2.23"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user