<!-- eslint-disable vue/v-on-event-hyphenation --> <template> <div class="parent-container"> <div class="ns-tree-title"> <span>数据点位</span> </div> <a-select ref="select" v-model:value="selectedValue" placeholder="请选择能耗类型" style="width: 100%; margin-bottom: 10px" :options="options1" @change="changeEnergyType" /> <a-radio-group v-model:value="mode" @change="changeMode" style="padding-bottom: 10px; width: 100%"> <a-radio-button value="0" style="width: 50%; text-align: center" :disabled="shebei"> 设备 </a-radio-button> <a-radio-button value="1" style="width: 50%; text-align: center">节点</a-radio-button> </a-radio-group> <a-input v-model:value="deviceName" placeholder="请输入设备名称" v-if="mode == '0'" @change="changeMode" /> <a-input v-model:value="pointName" placeholder="请输入节点名称" v-else @change="changeMode" /> <a-spin :spinning="treeLoading"> <a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys" v-model:checkedKeys="checkedKeys" checkable :height="300" style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px" :tree-data="treeData2"> <!-- <template #title="{ title }"> <span v-if="title.indexOf(mode == '0' ? deviceName : pointName) > -1"> {{ title.substr(0, title.indexOf(mode == '0' ? deviceName : pointName)) }} <span style="color: #f50">{{ mode == '0' ? deviceName : pointName }}</span> {{ title.substr( title.indexOf(mode == '0' ? deviceName : pointName) + (mode == '0' ? deviceName : pointName).length, ) }} </span> <span v-else>{{ title }}</span> </template> --> </a-tree> </a-spin> <div class="fixed-bottom"> <a-divider /> <a-select v-model:value="dateTypeValue" placeholder="请选择日期类型" style="width: 100%; margin-bottom: 10px" :options="options2" /> <a-range-picker style="width: 100%; margin-bottom: 10px" @change="onChangeDate" v-model:value="dateValue" :picker="dateTypeValue" /> <a-button type="primary" style="width: 100%; margin-bottom: 10px" @click="getSelect"> 查询 </a-button> </div> </div> </template> <script lang="ts"> import type { TreeSelectProps, SelectProps } from 'ant-design-vue'; import { defineComponent, ref, onMounted, inject } from 'vue'; import dayjs, { Dayjs } from 'dayjs'; import { http } from '/nerv-lib/util'; import { device, group } from '/@/api/deviceManage'; import { energyMonitor } from '/@/api/monitor'; import { dict } from '/@/api'; export default defineComponent({ // eslint-disable-next-line vue/multi-word-component-names name: 'Tree', setup() { const value = ref<string>(); const deviceName = ref<string>(); const pointName = ref<string>(); const treeLoading = ref(false); const shebei = ref(false); // 树打开节点 const expandedKeys = ref<string[]>([]); // 树勾选节点 const selectedKeys = ref<string[]>([]); // 树点击节点 const checkedKeys = ref<string[]>([]); // 能耗类型list const options1 = ref<SelectProps['options']>([]); // 日期类型list const options2 = ref<SelectProps['options']>([]); const mode = ref<String>('0'); // 能耗类型 const selectedValue = ref<string | number | null | undefined>(); // 日期类型 const dateTypeValue = ref<string | undefined>('month'); // 时间 const dateValue = ref<[Dayjs, Dayjs] | undefined>([dayjs(), dayjs()]); // 页面初始化参数 const getOptionsList = async () => { try { const options = await dict({ params: { dicKey: 'ENERGY_TYPE' } }); options.data.data.forEach((item: any) => { (item.value = item.dicKey), (item.label = item.cnValue); }); options1.value = options.data.data; // 根据返回数据的结构来更新 options1.value if (options1.value) { selectedValue.value = options1.value[0].value; } } catch (error) { console.error('Failed to fetch options:', error); } options2.value = [ { value: 'date', label: '日', }, { value: 'month', label: '月', }, { value: 'year', label: '年', }, ]; }; interface PageData { // 图表 表格数据 graphTableList: any[]; // 图表 表格表头 graphTableColumns: any[]; // 图表 图表数据 graphGraphList: any[]; // 分析 表格数据 analysisTableList: any[]; // 分析 图表数据 analysisGraphList: any[]; } const pageData = inject<PageData>('pageData'); if (!pageData) { throw new Error('pageData is not provided'); } // 选择能耗类型 const changeEnergyType = () => { if (selectedValue.value == '碳排量') { shebei.value = true; mode.value = '1'; } else { shebei.value = false; } changeMode(); }; const startDate = ref<String>(); const endDate = ref<String>(); const onChangeDate = (val: RangeValue, dateStrings: any) => { if (dateStrings && dateStrings.length === 2) { dateValue.value = val; startDate.value = dateStrings[0]; endDate.value = dateStrings[1]; } }; const getSelect = () => { // const date = dateValue.value; // let year = 0; // let month = 0; // if (date) { // year = date.year(); // month = date.month() + 1; // } else { // return; // } let startTime = ''; let endTime = ''; if (startDate.value && endDate.value) { if (dateTypeValue.value == 'month') { startTime = startDate.value + '-01'; const [year, month] = endDate.value.split('-').map(Number); // 创建下一个月的第一天 const date = new Date(year, month, 1); // 减去一天得到当月的最后一天 // date.setDate(date.getDate() - 1); endTime = date.toISOString().split('T')[0]; // endTime = endDate.value + '-01'; } else if (dateTypeValue.value == 'year') { startTime = startDate.value + '-01-01'; endTime = endDate.value + '-12-31'; } else { startTime = startDate.value + ''; endTime = endDate.value + ''; } } else { // 获取当天的时间 const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, '0'); // getMonth() 返回的月份是0-11 const day = String(today.getDate()).padStart(2, '0'); startTime = year + '-' + month + '-' + day; endTime = year + '-' + month + '-' + day; } // 图表数据 http .post(energyMonitor.getDeviceOrNodeEnergyGraph, { deviceName: deviceName.value, energyType: selectedValue.value, orgId: orgId.value, dateType: dateTypeValue.value == 'year' ? 0 : 1, //0 年 1月 deviceInfoCodes: mode.value == '0' ? checkedKeys.value : [], // 设备需要传 device_info_code energyQueryType: mode.value, // 0 设备 1 节点 nodeIds: mode.value == '1' ? checkedKeys.value : [], startTime: startTime, endTime: endTime, }) .then((res) => { let selectedValueName = ''; options1.value?.forEach((item) => { if (item.value == selectedValue.value) { selectedValueName = item.label; } }); res.data.tableList.forEach((item) => { item.selectedValueName = selectedValueName; }); pageData.graphTableList = res.data.tableList; pageData.graphTableColumns = res.data.tableHeaderList; pageData.graphGraphList = res.data.graghData; }); // 分析数据 http .post(energyMonitor.getDeviceOrNodeEnergyAnalyse, { deviceName: deviceName.value, energyType: selectedValue.value, orgId: orgId.value, dateType: dateTypeValue.value == 'year' ? 0 : 1, //0 年 1月 deviceInfoCodes: mode.value == '0' ? checkedKeys.value : [], // 设备需要传 device_info_code energyQueryType: mode.value, // 0 设备 1 节点 nodeIds: mode.value == '1' ? checkedKeys.value : [], startTime: startTime, endTime: endTime, }) .then((res) => { pageData.analysisTableList = res.data.dataList; pageData.analysisGraphList = res.data.dataList; }); }; const orgId = ref(''); const result = JSON.parse(sessionStorage.getItem('ORGID')!); orgId.value = result; const treeData2 = ref<TreeSelectProps['treeData']>([]); // 切换树结构 const changeMode = () => { treeLoading.value = true; if (mode.value == '0') { http .post(group.queryDeviceToEnergy, { deviceName: deviceName.value, energyType: selectedValue.value, orgId: orgId.value, // pageNum: 1, // pageSize: 9999, }) .then((res) => { let val = '999999999'; let label = '所有设备'; let records = res.data; records.forEach((item: any) => { (item.title = item.deviceNum), (item.key = item.deviceCode); }); let a: TreeSelectProps['treeData'] = [{ title: label, key: val, children: records }]; treeData2.value = a; expandedKeys.value = [val]; checkedKeys.value.push(records[0].deviceCode, records[1].deviceCode); getSelect(); }) .finally(() => { treeLoading.value = false; }); } else { http .post(group.queryDeviceGroupTree, { pointName: pointName.value, energyType: selectedValue.value, orgId: orgId.value, }) .then((res) => { treeData2.value = []; treeData2.value = formatTreeData(pointName.value ? res.data[0].searchList : res.data); expandedKeys.value = getAllKeys(treeData2.value); }) .finally(() => { treeLoading.value = false; }); } }; const getAllKeys = (data: any) => { let keys: any[] = []; data.forEach((item: any) => { if (item.children) { keys.push(item.key); keys = keys.concat(getAllKeys(item.children)); } }); return keys; }; const formatTreeData = (data: any) => { return data.map((item: any) => ({ title: item.pointName, key: item.id, children: item.children ? formatTreeData(item.children) : [], })); }; type RangeValue = [Dayjs, Dayjs]; const dates = ref<RangeValue>(); const hackValue = ref<RangeValue>(); const disabledDate = (current: Dayjs) => { if (!dates.value || (dates.value as any).length === 0) { return false; } const tooLate = dates.value[0] && current.diff(dates.value[0], 'days') > 2; const tooEarly = dates.value[1] && dates.value[1].diff(current, 'days') > 2; return tooEarly || tooLate; }; const onOpenChange = (open: boolean) => { if (open) { dates.value = [] as any; hackValue.value = [] as any; } else { hackValue.value = undefined; } }; const onCalendarChange = (val: RangeValue) => { dates.value = val; }; onMounted(() => { getOptionsList(); changeMode(); // debugger; // await checkedKeys.value.push( // treeData2.value[0].children[0].deviceCode, // treeData2.value[0].children[1].deviceCode, // ); // debugger; getSelect(); }); return { value, deviceName, pointName, treeData2, expandedKeys, selectedKeys, checkedKeys, options1, options2, mode, selectedValue, dateTypeValue, dateValue, getOptionsList, getSelect, changeMode, disabledDate, onCalendarChange, onOpenChange, hackValue, treeLoading, changeEnergyType, shebei, onChangeDate, }; }, }); </script> <style lang="less" scoped> .ns-tree-title { user-select: text; margin-bottom: 5px; padding-bottom: 10px; padding-top: 10px; border-bottom: 1px solid #e9e9e9; > span { padding-left: 10px; line-height: 20px; } } .parent-container { position: relative; height: 100%; } .fixed-bottom { position: absolute; bottom: 0; width: 100%; margin-bottom: 10px; } </style>