Compare commits
27 Commits
main
...
6b93422b08
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b93422b08 | ||
|
|
30286253e7 | ||
|
|
a0d928feaa | ||
|
|
50ca1daca4 | ||
|
|
fb1980d73a | ||
|
|
ab17c4a1f9 | ||
|
|
aab4c9a600 | ||
|
|
0855659d74 | ||
|
|
3abdde797b | ||
|
|
d004a06ec1 | ||
|
|
76248c0f70 | ||
|
|
6e294e13eb | ||
|
|
7a9bea2f8e | ||
|
|
77052ae284 | ||
|
|
33eb153885 | ||
|
|
a3a5b63ea5 | ||
|
|
7a20eb8603 | ||
|
|
dc29be2718 | ||
|
|
f28b224c91 | ||
|
|
bfd6282a99 | ||
|
|
64cfd47d50 | ||
|
|
796d2fcf63 | ||
|
|
287dc9262b | ||
|
|
f39fb299c4 | ||
|
|
9ad9446cae | ||
|
|
1d4b76492d | ||
|
|
a16b26370f |
@@ -43,6 +43,20 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ns-content-main) {
|
||||
.ant-tabs-content {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
// :deep(.ant-menu-item),
|
||||
// :deep(.ant-menu-submenu-title) {
|
||||
// &:not(.ant-menu-item-selected) {
|
||||
// // &:not(.ant-menu-item-active) {
|
||||
// .anticon {
|
||||
// color: rgb(141, 150, 163);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// :deep(.ns-content) {
|
||||
// // padding-top: 80px !important;
|
||||
// }
|
||||
|
||||
5
hx-ai-intelligent/src/api/alarmSettings/deviceAlarms.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum deviceAlarms {
|
||||
getTableList = '/carbon-smart/api/AlarmEquipment/selectAlarmEquipment', //设备告警分页
|
||||
addOrUpNewData = '/carbon-smart/api/AlarmEquipment/creatOrUpdate', //设备告警添加 修海
|
||||
del = '/carbon-smart/api/AlarmEquipment/delete', //设备告警删除
|
||||
}
|
||||
12
hx-ai-intelligent/src/api/carbonEmissionFactorLibrary.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export enum carbonEmissionFactorLibrary {
|
||||
getTableList = '/carbon-smart/api/carbon/emission/factor/queryCarbonFactorPage',
|
||||
addNewData = '/carbon-smart/api/carbon/emission/factor/creatOrUpdate',
|
||||
editUser = '/carbon-smart/api/user/edit',
|
||||
frozen = '/carbon-smart/api/user/frozen',
|
||||
resetPwd = '/carbon-smart/api/user/resetPwd',
|
||||
del = '/carbon-smart/api/user/del',
|
||||
batchDel = '/carbon-smart/api/user/batchDel',
|
||||
getCarbonFactorTree = '/carbon-smart/api/carbon/emission/type/getCarbonFactorTree',
|
||||
queryDeptTree = '/carbon-smart/api/user/queryDeptTree',
|
||||
queryUserPerList = '/carbon-smart/api/user/queryUserPerList',
|
||||
}
|
||||
@@ -3,9 +3,11 @@ export enum device {
|
||||
queryDeviceTree = `${BASE_URL}/deviceInfo/queryDeviceTree`, // 左侧树
|
||||
queryDevicePage = `${BASE_URL}/deviceInfo/queryDevicePage`, // 列表
|
||||
dropArea = `${BASE_URL}/deviceInfo/dropArea`, // 查询下拉区域
|
||||
queryDevicePoint = `${BASE_URL}/deviceInfo/queryDevicePoint`, // 获取设备点位
|
||||
}
|
||||
|
||||
export enum group {
|
||||
queryDeviceGroupTree = `${BASE_URL}/deviceGroup/queryDeviceGroupTree`, // 左侧树
|
||||
creatOrUpdate = `${BASE_URL}/deviceGroup/creatOrUpdate`, // 左侧树节点新增编辑
|
||||
del = `${BASE_URL}/deviceGroup/del`, // 左侧树节点新增编辑
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { get } from 'lodash-es';
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
|
||||
/***
|
||||
*配置接口 格式 module:Array<resource>
|
||||
*/
|
||||
@@ -6,4 +9,32 @@ export const apiModule = {
|
||||
};
|
||||
|
||||
export const BASE_URL = '/carbon-smart';
|
||||
export const dict = `${BASE_URL}/client/dict/listByKey`;
|
||||
|
||||
interface dictHttpConfig {
|
||||
api?: string;
|
||||
keyField?: string;
|
||||
params: object;
|
||||
transform?: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典数据(首次获取,后续读缓存)
|
||||
*/
|
||||
|
||||
export const dict = async ({
|
||||
api = `${BASE_URL}/client/dict/listByKey`,
|
||||
params = {},
|
||||
keyField = 'dicKey',
|
||||
transform = (res: any) => res,
|
||||
}: dictHttpConfig) => {
|
||||
const dictMap = JSON.parse(sessionStorage.getItem('dictMap') || '{}') as Object;
|
||||
const key = get(params, keyField) as keyof typeof dictMap;
|
||||
|
||||
if (!dictMap.hasOwnProperty(key)) {
|
||||
const res = await http.post(api, params);
|
||||
const options = get(transform(res), `data.${key}`);
|
||||
dictMap[key] = options;
|
||||
sessionStorage.setItem('dictMap', JSON.stringify(dictMap));
|
||||
}
|
||||
return Promise.resolve({ data: { data: get(dictMap, key) } });
|
||||
};
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<template>
|
||||
<ns-modal
|
||||
ref="modalRef"
|
||||
centered
|
||||
v-bind="extraModalConfig"
|
||||
destroyOnClose
|
||||
v-model:visible="visible"
|
||||
:title="title"
|
||||
:okButtonProps="buttonProps"
|
||||
@ok="handleOk">
|
||||
<ns-form ref="formRef" :schemas="schemas" :model="formData" formLayout="formVertical" />
|
||||
<ns-form ref="formRef" :schemas="schemas" :model="formData" formLayout="vertical" />
|
||||
</ns-modal>
|
||||
</template>
|
||||
|
||||
@@ -21,6 +22,7 @@
|
||||
api: string | object | Function;
|
||||
data?: object;
|
||||
extraModalConfig?: object;
|
||||
success?: Function;
|
||||
};
|
||||
const route = useRoute();
|
||||
const { httpRequest } = useApi();
|
||||
@@ -59,14 +61,15 @@
|
||||
formRef.value
|
||||
.triggerSubmit()
|
||||
.then((data: any) => {
|
||||
const { api } = props;
|
||||
const { api, success } = props;
|
||||
const requestConfig: HttpRequestConfig = { method: 'POST' };
|
||||
const { params } = route;
|
||||
|
||||
httpRequest({ api, params: data, pathParams: params, requestConfig })
|
||||
.then(() => {
|
||||
.then((res) => {
|
||||
NsMessage.success('操作成功', 1, () => {
|
||||
toggle();
|
||||
success && success(res);
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
1
hx-ai-intelligent/src/icon/biaoge.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720144479404" class="icon" viewBox="0 0 1142 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2572" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.84375" height="16"><path d="M1102.769231 39.384615v945.23077H39.384615V39.384615h1063.384616m0-39.384615H39.384615a39.384615 39.384615 0 0 0-39.384615 39.384615v945.23077a39.384615 39.384615 0 0 0 39.384615 39.384615h1063.384616a39.384615 39.384615 0 0 0 39.384615-39.384615V39.384615a39.384615 39.384615 0 0 0-39.384615-39.384615z" fill="#4D4D4D" p-id="2573"></path><path d="M39.384615 393.846154h1063.384616v39.384615H39.384615zM39.384615 590.769231h1063.384616v39.384615H39.384615zM39.384615 787.692308h1063.384616v39.384615H39.384615zM39.384615 196.923077h1063.384616v39.384615H39.384615z" fill="#B3B3B3" p-id="2574"></path><path d="M315.076923 196.923077v787.692308H275.692308V196.923077zM590.769231 196.923077v787.692308h-39.384616V196.923077zM866.461538 196.923077v787.692308h-39.384615V196.923077z" fill="#B3B3B3" p-id="2575"></path><path d="M39.384615 39.384615h1063.384616v157.538462H39.384615z" fill="#05AFC8" p-id="2576"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
hx-ai-intelligent/src/icon/bingtu.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720145764410" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4680" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M495.611479 159.364238C285.562631 159.364238 115.284768 329.642102 115.284768 539.690949S285.562631 920.01766 495.611479 920.01766 875.93819 749.739797 875.93819 539.690949H518.216336c-12.484662 0-22.604857-10.120194-22.604857-22.604856V159.364238z" fill="#839BFB" p-id="4681"></path><path d="M562.860927 495.046358h368.459161c0-215.978102-175.085916-391.064018-391.064017-391.064018v368.459161c0 12.484662 10.120194 22.604857 22.604856 22.604857z" fill="#839BFB" fill-opacity=".6" p-id="4682"></path></svg>
|
||||
|
After Width: | Height: | Size: 838 B |
10
hx-ai-intelligent/src/icon/fenzujiedian.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8.98974609375" height="8.14453125" viewBox="0 0 8.98974609375 8.14453125" fill="none">
|
||||
<path d="M7.93101 4.53462L6.23624 4.53462L5.52032 3.46466L6.49265 1.79796L5.44381 0L3.32621 0L2.27236 1.79796L3.29704 3.54617L2.62652 4.54987L1.05875 4.54987L0 6.34726L1.05875 8.1452L3.17144 8.1452L4.06128 6.62695L4.93729 6.62695L5.81886 8.13029L7.93102 8.13029L8.98978 6.33258L7.93101 4.53462ZM3.19734 4.59392L3.8643 3.59569L5.00553 3.59569L5.73168 4.68208L4.88461 6.1274L4.09644 6.1274L3.19734 4.59392Z" fill="url(#linear_fill_60_2513)" >
|
||||
</path>
|
||||
<defs>
|
||||
<linearGradient id="linear_fill_60_2513" x1="4.494873046875" y1="0" x2="4.494873046875" y2="8.14453125" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#4DACE6" />
|
||||
<stop offset="1" stop-color="#2A93D5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 888 B |
12
hx-ai-intelligent/src/icon/gaojingguanli.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="36px" height="36px" viewBox="0 0 36 36" enable-background="new 0 0 36 36" xml:space="preserve"> <image id="image0" width="36" height="36" x="0" y="0"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAATLoWrAAAAIGNIUk0AAHomAACAhAAA+gAAAIDo
|
||||
AAB1MAAA6mAAADqYAAAXcJy6UTwAAAASUExURQAAAI2Vo46Wo4uXo42Wo////3MrvScAAAAEdFJO
|
||||
UwCAv0BHJ479AAAAAWJLR0QF+G/pxwAAAAd0SU1FB+gHBAISL9sg4ewAAABSSURBVCjPY2CgCxBU
|
||||
cVJGFRFxAQIUMUYXMBBAV+Ti4ogQYXZxQVfGBBNygAuZwIQQOlXwCDnBhVzgAL+QA8vQFcIELi4Y
|
||||
nsQUcnHBEMMiREsAALpDPLVxCYzSAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI0LTA3LTA0VDAyOjE4
|
||||
OjQ3KzAwOjAwPdooNQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNC0wNy0wNFQwMjoxODo0NyswMDow
|
||||
MEyHkIkAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjQtMDctMDRUMDI6MTg6NDcrMDA6MDAbkrFW
|
||||
AAAAAElFTkSuQmCC" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
hx-ai-intelligent/src/icon/huanjingjiance.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720061440927" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11363" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M659.925333 128a74.666667 74.666667 0 0 1 71.338667 52.618667L754.56 256H821.333333c64.8 0 117.333333 52.533333 117.333334 117.333333v426.666667c0 64.8-52.533333 117.333333-117.333334 117.333333H202.666667c-64.8 0-117.333333-52.533333-117.333334-117.333333V373.333333c0-64.8 52.533333-117.333333 117.333334-117.333333h66.773333l23.296-75.381333A74.666667 74.666667 0 0 1 364.074667 128h295.850666zM512 405.333333c-88.362667 0-160 71.637333-160 160 0 88.362667 71.637333 160 160 160 88.362667 0 160-71.637333 160-160 0-88.362667-71.637333-160-160-160z m0 256a96 96 0 1 0 0-192 96 96 0 0 0 0 192z" p-id="11364"></path></svg>
|
||||
|
After Width: | Height: | Size: 954 B |
1
hx-ai-intelligent/src/icon/jiankongzhongxin.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720061108318" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10061" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M512 12L94.71 138v314.92C94.71 657.7 263.86 880.16 512 1012c248.14-131.84 417.29-354.3 417.29-559.08V138z m209.91 510H562v159.91H462V522H302.09V422H462V262.09h100V422h159.91z" p-id="10062"></path></svg>
|
||||
|
After Width: | Height: | Size: 535 B |
10
hx-ai-intelligent/src/icon/jisuanjiedian.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="9.1005859375" height="9.099609375" viewBox="0 0 9.1005859375 9.099609375" fill="none">
|
||||
<path d="M7.01762 4.69157L2.30136 4.69157C2.04227 4.66303 1.84615 4.44409 1.84615 4.18343C1.84615 3.92276 2.04227 3.70384 2.30136 3.67525L7.01762 3.67525C7.27673 3.70384 7.47285 3.92276 7.47285 4.18343C7.47285 4.44409 7.27673 4.66303 7.01762 4.69157ZM7.01762 6.69587L2.30136 6.69587C2.04227 6.6673 1.84615 6.44837 1.84615 6.18771C1.84615 5.92704 2.04227 5.70809 2.30136 5.67952L7.01762 5.67952C7.27673 5.70809 7.47285 5.92704 7.47285 6.18771C7.47285 6.44837 7.27673 6.6673 7.01762 6.69587ZM9.09498 8.33346L9.09498 1.98149C9.09498 1.21918 8.46167 1.27564 8.46167 1.27564L4.88941 1.27564C4.77006 1.27634 4.65399 1.23653 4.56021 1.16271C4.56021 1.16271 4.40816 0.880585 4.12926 0.428757C3.87605 -0.0795288 3.54708 0.00531769 3.54708 0.00531769L0.785301 0.00531769C0 0.00531769 0 0.824379 0 0.824379L0 8.27722C0 9.2087 0.633301 9.09628 0.633301 9.09628L8.53744 9.09628C9.19643 9.09547 9.09498 8.33345 9.09498 8.33345L9.09498 8.33346Z" fill="url(#linear_fill_60_2485)" >
|
||||
</path>
|
||||
<defs>
|
||||
<linearGradient id="linear_fill_60_2485" x1="4.55029296875" y1="0" x2="4.55029296875" y2="9.099609375" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#4DACE6" />
|
||||
<stop offset="1" stop-color="#2A93D5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
4
hx-ai-intelligent/src/icon/tanpaiguanli.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14.5244140625" height="14.5294189453125" viewBox="0 0 14.5244140625 14.5294189453125" fill="none">
|
||||
<path d="M6.61912 12.2301C6.6032 12.5346 6.44482 12.8138 6.19166 12.9837L3.73703 14.4259C3.46877 14.5639 3.15036 14.5639 2.8821 14.4259L0.427467 12.9837C0.174295 12.8138 0.0159187 12.5346 0 12.2301L0 9.34584C0.0162582 9.04147 0.174555 8.76241 0.427467 8.59227L2.88209 7.15012C3.15031 7.01189 3.46881 7.01189 3.73703 7.15012L6.19165 8.59337C6.44482 8.76326 6.6032 9.04247 6.61912 9.34694L6.61912 12.2301ZM14.5239 12.2301C14.508 12.5346 14.3497 12.8138 14.0965 12.9837L11.6419 14.4259C11.3736 14.5639 11.0552 14.5639 10.7869 14.4259L8.33231 12.9837C8.079 12.814 7.92058 12.5347 7.90484 12.2301L7.90484 9.34584C7.92075 9.04137 8.07913 8.76217 8.33231 8.59227L10.7869 7.14902C11.0551 7.01079 11.3736 7.01079 11.6419 7.14902L14.0965 8.59117C14.3495 8.76118 14.5079 9.04031 14.524 9.34475L14.5239 12.2301ZM10.5842 5.18465C10.5683 5.48912 10.4099 5.76833 10.1567 5.93822L7.70211 7.38147C7.43394 7.51988 7.11535 7.51988 6.84718 7.38147L4.39256 5.93822C4.13938 5.76833 3.981 5.48912 3.96508 5.18465L3.96508 2.30036C3.98117 1.99594 4.13951 1.7168 4.39256 1.54678L6.84718 0.103527C7.11544 -0.0345116 7.43386 -0.0345116 7.70212 0.103527L10.1567 1.54568C10.41 1.71546 10.5685 1.99473 10.5842 2.29926L10.5842 5.18465Z" fill="#8D96A3" >
|
||||
</path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
hx-ai-intelligent/src/icon/xiazai.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720430904326" class="icon" viewBox="0 0 1354 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3403" xmlns:xlink="http://www.w3.org/1999/xlink" width="21.15625" height="16"><path d="M1034.83248 645.406063l-191.508238 191.508238a53.622507 53.622507 0 0 1-75.964301 0l-191.508238-191.508238a53.622507 53.622507 0 0 1 0-75.964301 53.622507 53.622507 0 0 1 75.965301 0l102.775054 102.775054V303.884205a53.622507 53.622507 0 1 1 107.245014 0v368.332611l95.753119-102.775054a53.622507 53.622507 0 0 1 75.965301 0 53.622507 53.622507 0 0 1 1.276988 75.964301z m262.364587-175.548385a365.141641 365.141641 0 0 0-97.030108-98.94609 378.546518 378.546518 0 0 0-29.364729-123.202867 397.697341 397.697341 0 0 0-89.369178-127.671825 404.719277 404.719277 0 0 0-133.418773-91.28516A408.549242 408.549242 0 0 0 792.894706 0.026a400.251318 400.251318 0 0 0-225.977921 67.665377 410.464224 410.464224 0 0 0-97.669102 91.285161 261.088598 261.088598 0 0 0-63.836412-7.65993 247.044727 247.044727 0 0 0-176.18738 70.857348 245.129745 245.129745 0 0 0-72.134336 202.360139 324.925011 324.925011 0 0 0-84.263225 72.77333A308.965158 308.965158 0 0 0 0.053 702.22054a310.242146 310.242146 0 0 0 97.029107 228.531898 331.307952 331.307952 0 0 0 105.969025 69.58136 330.030964 330.030964 0 0 0 127.670826 23.619782h656.233963A360.034688 360.034688 0 0 0 1242.298572 919.261544a360.034688 360.034688 0 0 0 81.071254-116.181932 354.288741 354.288741 0 0 0 27.449748-138.523725 344.713829 344.713829 0 0 0-54.260501-194.699209z" fill="#5656FB" p-id="3404"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
50
hx-ai-intelligent/src/router/alarmManagement.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
|
||||
const alarmManagement = {
|
||||
path: '/alarmManagement',
|
||||
name: 'AlarmManagement',
|
||||
meta: { title: '告警管理', icon: 'gaojingguanli', index: 4 },
|
||||
redirect: { name: 'alarmManagement' },
|
||||
children: [
|
||||
{
|
||||
path: 'alarmOverview',
|
||||
name: 'AlarmOverview',
|
||||
meta: { title: '告警总览', hideChildren: true, icon: 'gaojingguanli' },
|
||||
component: Base,
|
||||
redirect: { name: 'alarmOverviewIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'alarmOverviewIndex',
|
||||
// component: () => import('/nerv-lib/saas/view/menuManage/index.vue'),
|
||||
component: () => import('/@/view/alarmManagement/alarmOverview/index.vue'),
|
||||
meta: {
|
||||
title: '告警总览',
|
||||
keepAlive: true,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'alarmSettings',
|
||||
name: 'AlarmSettings',
|
||||
meta: { title: '告警设置', hideChildren: true, icon: 'gaojingguanli' },
|
||||
component: Base,
|
||||
redirect: { name: 'alarmSettingsIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'alarmSettingsIndex',
|
||||
// component: () => import('/nerv-lib/saas/view/menuManage/index.vue'),
|
||||
component: () => import('/@/view/alarmManagement/alarmSettings/index.vue'),
|
||||
meta: {
|
||||
title: '告警设置',
|
||||
keepAlive: true,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
export default alarmManagement;
|
||||
50
hx-ai-intelligent/src/router/carbonEmissionManage.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
|
||||
const equipment = {
|
||||
path: '/carbonEmissionManage',
|
||||
name: 'CarbonEmissionManage',
|
||||
meta: { title: '碳排管理', icon: 'tanpaiguanli', index: 1 },
|
||||
redirect: { name: 'CarbonEmissionStatistics' },
|
||||
children: [
|
||||
{
|
||||
path: 'carbonEmissionStatistics',
|
||||
name: 'CarbonEmissionStatistics',
|
||||
meta: { title: '碳排统计', hideChildren: true, icon: 'tanpaiguanli' },
|
||||
component: Base,
|
||||
redirect: { name: 'CarbonEmissionStatisticsIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'CarbonEmissionStatisticsIndex',
|
||||
// component: () => import('/nerv-lib/saas/view/menuManage/index.vue'),
|
||||
component: () => import('/@/view/carbonEmissionManage/carbonEmissionStatistics/index.vue'),
|
||||
meta: {
|
||||
title: '碳排统计',
|
||||
keepAlive: true,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'carbonEmissionFactorLibrary',
|
||||
name: 'CarbonEmissionFactorLibrary',
|
||||
meta: { title: '碳排因子库', hideChildren: true, icon: 'tanpaiguanli' },
|
||||
component: Base,
|
||||
redirect: { name: 'CarbonEmissionFactorLibraryIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'CarbonEmissionFactorLibraryIndex',
|
||||
// component: () => import('/nerv-lib/saas/view/menuManage/index.vue'),
|
||||
component: () => import('/@/view/carbonEmissionManage/carbonEmissionFactorLibrary/index.vue'),
|
||||
meta: {
|
||||
title: '碳排因子库',
|
||||
keepAlive: true,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
export default equipment;
|
||||
86
hx-ai-intelligent/src/router/monitor.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
|
||||
const equipment = {
|
||||
path: '/monitor',
|
||||
name: 'Monitor',
|
||||
meta: { title: '监控中心', icon: 'jiankongzhongxin', index: 1 },
|
||||
redirect: { name: 'EnvironmentMonitor' },
|
||||
children: [
|
||||
// {
|
||||
// path: 'environmentMonitor',
|
||||
// name: 'EnvironmentMonitor',
|
||||
// meta: { title: '环境监测', hideChildren: true, icon: 'huanjingjiance' },
|
||||
// component: Base,
|
||||
// redirect: { name: 'EnvironmentMonitorIndex' },
|
||||
// children: [
|
||||
// {
|
||||
// path: 'index',
|
||||
// name: 'EnvironmentMonitorIndex',
|
||||
// component: () => import('/@/view/monitor/environmentMonitor/index.vue'),
|
||||
// meta: {
|
||||
// title: '环境监测',
|
||||
// keepAlive: true,
|
||||
// // backApi: [],
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
path: 'deviceMonitor',
|
||||
name: 'DeviceMonitor',
|
||||
meta: { title: '设备监测', hideChildren: true, icon: 'huanjingjiance' },
|
||||
component: Base,
|
||||
redirect: { name: 'DeviceMonitorIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'DeviceMonitorIndex',
|
||||
component: () => import('/@/view/monitor/deviceMonitor/index.vue'),
|
||||
meta: {
|
||||
title: '设备监测',
|
||||
keepAlive: true,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'energyMonitor',
|
||||
name: 'EnergyMonitor',
|
||||
meta: { title: '能耗监测', hideChildren: true, icon: 'huanjingjiance' },
|
||||
component: Base,
|
||||
redirect: { name: 'EnergyMonitorIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'EnergyMonitorIndex',
|
||||
component: () => import('/@/view/monitor/energyMonitor/index.vue'),
|
||||
meta: {
|
||||
title: '能耗监测',
|
||||
keepAlive: true,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// path: 'group',
|
||||
// name: 'Group',
|
||||
// meta: { title: '分组管理', hideChildren: true, icon: 'shebeiguanli' },
|
||||
// component: Base,
|
||||
// redirect: { name: 'GroupIndex' },
|
||||
// children: [
|
||||
// {
|
||||
// path: 'index',
|
||||
// name: 'GroupIndex',
|
||||
// component: () => import('/@/view/monitor/group/index.vue'),
|
||||
// meta: {
|
||||
// title: '分组管理',
|
||||
// keepAlive: true,
|
||||
// // backApi: [],
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
};
|
||||
export default equipment;
|
||||
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<div class="box-top">
|
||||
<div v-for="index in 3" :key="index" class="box-top-item">
|
||||
<div class="item-box">
|
||||
<div class="item-box-left">
|
||||
<div class="item-box-left-title">设备告警 (今日处理 / 总数) </div>
|
||||
<div class="iem-box-left-number">
|
||||
10 / 13
|
||||
<span
|
||||
style="
|
||||
color: #04d919;
|
||||
font-size: 14px;
|
||||
margin-left: 5px;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
"
|
||||
>+10%</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-box-right">
|
||||
<img width="54px" height="54px" src="../../../../src/icon/gaojingguanli.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: 4; width: 100%">2</div>
|
||||
<div style="flex: 4; width: 100%">3</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'; // 从 Vue 中导入 ref、onMounted 和 watchEffect
|
||||
|
||||
defineOptions({
|
||||
name: 'alarmOverview', // 与页面路由name一致缓存才可生效
|
||||
});
|
||||
|
||||
const info = ref({});
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// border: 1px solid red;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
background-color: #f0f1f4;
|
||||
box-sizing: border-box;
|
||||
.box-top {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 5px;
|
||||
.box-top-item {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
gap: 5px;
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
.item-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
.item-box-left {
|
||||
flex: 9;
|
||||
height: 100%;
|
||||
padding: 0px !important;
|
||||
.item-box-left-title {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 14px;
|
||||
color: #aaaaaa;
|
||||
font-kerning: normal;
|
||||
font-family: '微软雅黑', sans-serif;
|
||||
}
|
||||
.iem-box-left-number {
|
||||
color: #000000;
|
||||
font-weight: 700;
|
||||
font-family: 'Arial Negreta', 'Arial Normal', 'Arial', sans-serif;
|
||||
font-style: normal;
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
.item-box-right {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,287 @@
|
||||
<!-- 配置设备告警 -->
|
||||
<template>
|
||||
<ns-view-list-table v-if="show" ref="mainRef" class="table" v-bind="tableConfig">
|
||||
<template #bodyCell="{ record, column }">
|
||||
<template v-if="column.dataIndex === 'enableRules'">
|
||||
<a-switch
|
||||
:checked="record.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': record.enableRules === 1 ? true : false,
|
||||
'grey-background': record.enableRules === 1 ? false : true,
|
||||
}"
|
||||
@click="clickSwitch({ enableRules: record.enableRules, record: record })" />
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'equipmentInfo'">
|
||||
{{
|
||||
record?.enableRules
|
||||
? record.enableRules + '>' + record.deviceType + '>' + record.deviceName
|
||||
: '-'
|
||||
}}
|
||||
</template>
|
||||
</template>
|
||||
</ns-view-list-table>
|
||||
<!-- 新增or编辑界面 -->
|
||||
<editConfigureEnergyAlarm ref="editConfigureEnergyAlarms" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, createVNode } from 'vue';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import data from '../notificationManagementMock.json';
|
||||
import { NsMessage, NsModal } from '/nerv-lib/component';
|
||||
import editConfigureEnergyAlarm from './editConfigureEnergyAlarm.vue';
|
||||
import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
export default {
|
||||
components: { editConfigureEnergyAlarm },
|
||||
|
||||
setup() {
|
||||
//设备告警数据
|
||||
const configureDeviceAlarmsData = ref({});
|
||||
const show = ref(false);
|
||||
const tableConfig = ref({});
|
||||
const mainRef = ref({});
|
||||
const editConfigureEnergyAlarms = ref({});
|
||||
const mockData = ref(data.listData);
|
||||
const clickSwitch = (data: any) => {
|
||||
NsModal.confirm({
|
||||
title: '启用状态',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
content: '确定' + (data.record.enableRules === 1 ? '关闭' : '启用') + '吗?',
|
||||
onOk: () => {
|
||||
http
|
||||
.post(deviceAlarms.addOrUpNewData, {
|
||||
id: data.record.id,
|
||||
enableRules: data.record.enableRules === 1 ? 0 : 1,
|
||||
})
|
||||
.then(() => {
|
||||
NsMessage.success('操作成功');
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
const doWnload = (url: any) => {
|
||||
const a = document.createElement('a');
|
||||
document.body.appendChild(a);
|
||||
a.href = encodeURI(url);
|
||||
//设置下载的文件名
|
||||
// a.download = fileName.value;
|
||||
//触发a标签的点击事件,进行下载
|
||||
a.click();
|
||||
};
|
||||
const setconfigureDeviceAlarmsData = (value: any) => {
|
||||
configureDeviceAlarmsData.value = value;
|
||||
show.value = true;
|
||||
tableConfig.value = {
|
||||
title: '告警规则',
|
||||
api: deviceAlarms.getTableList,
|
||||
value: mockData.value,
|
||||
headerActions: [
|
||||
{
|
||||
label: '新增',
|
||||
name: 'RoleTypeAdd',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
editConfigureEnergyAlarms.value.toggle();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导入',
|
||||
name: 'groupImport',
|
||||
type: 'primary',
|
||||
extra: {
|
||||
// api: props.postImportApi, // 导入接口名
|
||||
title: '设备信息', // 弹窗title
|
||||
templateName: 'whiteListUser', // 所使用的文件名称
|
||||
indexName: '设备id', // 匹配类型字段
|
||||
message: [
|
||||
{ label: '1、若必填项未填写,则不能进行导入操作' },
|
||||
{ label: `2、当重复时,则更新数据。` },
|
||||
{ label: '3、数据将从模版的第五行进行导入。' },
|
||||
{ label: '4、文件导入勿超过5MB。' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导出',
|
||||
name: 'groupExports',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
doWnload('/hx-ai-intelligent/asset/file/whiteListUser.xlsx');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '批量删除',
|
||||
type: 'primary',
|
||||
name: 'userBatchDel',
|
||||
dynamicDisabled: (data: any) => {
|
||||
return data.list.length === 0;
|
||||
},
|
||||
confirm: true,
|
||||
isReload: true,
|
||||
isClearCheck: true,
|
||||
// api: origanizemanage.batchDel,
|
||||
dynamicParams: { userIds: 'userId[]' },
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '规则id',
|
||||
dataIndex: 'ruleId',
|
||||
},
|
||||
{
|
||||
title: '设备信息/节点信息',
|
||||
dataIndex: 'equipmentInfo',
|
||||
},
|
||||
{
|
||||
title: '对比类型',
|
||||
dataIndex: 'valueType',
|
||||
},
|
||||
{
|
||||
title: '告警点位',
|
||||
dataIndex: 'devicePoint',
|
||||
},
|
||||
{
|
||||
title: '判断条件',
|
||||
dataIndex: 'ruleType',
|
||||
},
|
||||
{
|
||||
title: '异常描述',
|
||||
dataIndex: 'abnormalDescription',
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '启用通知',
|
||||
dataIndex: 'enableRules',
|
||||
},
|
||||
],
|
||||
// rowSelection: null, 选择按钮
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
editConfigureEnergyAlarms.value.toggle(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
confirm: true,
|
||||
handle: () => {
|
||||
// mockData.value.splice(0, 1);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
formConfig: {
|
||||
title: value.errorCode,
|
||||
schemas: [
|
||||
{
|
||||
field: 'provider',
|
||||
label: '设备名称',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入设备名称',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '设备点位',
|
||||
component: 'nsSelectApi',
|
||||
componentProps: {
|
||||
api: '/api/community/objs/DictItem',
|
||||
params: {
|
||||
pageSize: 100,
|
||||
code: 'MZ',
|
||||
},
|
||||
placeholder: '请选择设备点位',
|
||||
resultField: 'data',
|
||||
labelField: 'dictName',
|
||||
valueField: 'dictValue',
|
||||
immediate: true,
|
||||
autoSelectFirst: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'payWay',
|
||||
label: '启用状态',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择启用状态',
|
||||
options: [
|
||||
{
|
||||
label: '启用',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '关闭',
|
||||
value: '0',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '异常描述',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入异常描述关键字',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
params: { id: value.id },
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'id',
|
||||
};
|
||||
};
|
||||
return {
|
||||
configureDeviceAlarmsData,
|
||||
show,
|
||||
clickSwitch,
|
||||
doWnload,
|
||||
tableConfig,
|
||||
editConfigureEnergyAlarms,
|
||||
setconfigureDeviceAlarmsData,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,421 @@
|
||||
<template>
|
||||
<ns-drawer
|
||||
v-model:visible="visible"
|
||||
width="520"
|
||||
:title="infoObject?.id ? '编辑告警规则' : '新增告警规则'"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
:ok="btnClick"
|
||||
:cancel="handleClose"
|
||||
placement="right">
|
||||
<div style="padding: 18px; width: 100%; overflow: hidden">
|
||||
<a-form ref="formRef" :model="infoObject" :rules="rules">
|
||||
<a-form-item ref="site" label="站点" name="site">
|
||||
<a-tree-select
|
||||
v-model:value="infoObject.site"
|
||||
show-search
|
||||
style="width: 100%"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
placeholder="请选择站点"
|
||||
allow-clear
|
||||
tree-default-expand-all
|
||||
:tree-data="zdTreeData"
|
||||
tree-node-filter-prop="label">
|
||||
<!-- 特殊处理情况 -->
|
||||
<!-- <template #title="{ value: val, label }">
|
||||
<b v-if="val === 'parent 1-1'" style="color: #08c">sss</b>
|
||||
<template v-else>{{ label }}</template>
|
||||
</template> -->
|
||||
</a-tree-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="数据来源" name="sbtype">
|
||||
<a-cascader
|
||||
v-model:value="infoObject.sbtype"
|
||||
:options="sbOptions"
|
||||
:show-search="{ filter }"
|
||||
placeholder="请选择数据来源" />
|
||||
</a-form-item>
|
||||
<a-form-item label="设备节点" name="jdDevice">
|
||||
<a-tree-select
|
||||
v-model:value="infoObject.jdDevice"
|
||||
style="width: 100%"
|
||||
placeholder="请选择设备节点"
|
||||
:tree-line="true && { showLeafIcon: false }"
|
||||
:tree-data="jdTreeData" />
|
||||
</a-form-item>
|
||||
<a-form-item label="启用规则" name="delivery">
|
||||
<a-switch
|
||||
v-model:checked="infoObject.delivery"
|
||||
:class="{
|
||||
'blue-background': infoObject.delivery,
|
||||
'grey-background': !infoObject.delivery,
|
||||
}" />
|
||||
</a-form-item>
|
||||
<a-form-item label="异常描述" name="desc">
|
||||
<a-textarea
|
||||
v-model:value="infoObject.desc"
|
||||
style="height: 32px"
|
||||
:autoSize="{ minRows: 1, maxRows: 1 }"
|
||||
show-count
|
||||
:maxlength="30" />
|
||||
</a-form-item>
|
||||
<a-form-item label="规则类型" name="resource">
|
||||
<a-radio-group v-model:value="infoObject.resource">
|
||||
<a-radio value="1">且 (and) </a-radio>
|
||||
<a-radio value="2">或 (or) </a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="对比类型1" name="qzType">
|
||||
<a-cascader
|
||||
v-model:value="infoObject.sbtype"
|
||||
:options="sbOptions"
|
||||
placeholder="请选择数据来源" />
|
||||
</a-form-item>
|
||||
<template v-for="index in infoObject.alarmList?.length" :key="index">
|
||||
<div style="width: 100%; display: flex; margin-left: 42px; padding: 12px">
|
||||
<span style="line-height: 32px">{{ `逻辑${index}:` }}</span>
|
||||
<a-select
|
||||
v-model:value="infoObject.alarmList[index - 1].logic"
|
||||
style="width: 70px; margin-left: 12px"
|
||||
:options="ljOptions"
|
||||
@change="handleQzChange" />
|
||||
<span style="line-height: 32px; margin-left: 32px">{{ `数值${index}:` }}</span>
|
||||
<a-input
|
||||
style="width: 65px; margin-left: 6px"
|
||||
type="number"
|
||||
v-model:value="infoObject.alarmList[index - 1].num" />
|
||||
<div
|
||||
style="width: 70px; align-items: center; cursor: pointer"
|
||||
@click="deleteAlarmList(index - 1)">
|
||||
<img
|
||||
style="width: 14px; margin: 0 12px"
|
||||
src="https://files.axshare.com/gsc/4T0UQR/5a/e6/81/5ae6813d499c422383c7a15dd956523f/images/设备规则/u72.svg?pageId=cbce6e61-bc6a-4283-802d-993fce6151c0" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
infoObject.alarmList[index - 1].num === null ||
|
||||
infoObject.alarmList[index - 1].logic === null
|
||||
"
|
||||
style="width: 100%; color: #ff4d4f; text-align: center; margin-bottom: 5px">
|
||||
请选择正确的逻辑{{ index }} 或 输入正确的数值{{ index }}
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-if="infoObject.alarmList?.length < 2"
|
||||
style="width: 100%; color: #ff4d4f; text-align: center; margin-bottom: 5px">
|
||||
逻辑至少2条
|
||||
</div>
|
||||
<div style="width: 100%; margin-top: 12px; display: flex; justify-content: flex-end">
|
||||
<a-button type="primary" @click="addAlarmList"> 新增</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</div>
|
||||
</ns-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { ref, toRaw } from 'vue';
|
||||
import type { CascaderProps, TreeSelectProps, SelectProps } from 'ant-design-vue';
|
||||
import type { ShowSearchType } from 'ant-design-vue/es/cascader';
|
||||
import { device } from '/@/api/deviceManage';
|
||||
import { http } from '/nerv-lib/util';
|
||||
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
|
||||
const visible = ref(false);
|
||||
//表单数据
|
||||
const infoObject = ref({
|
||||
id: null,
|
||||
site: null,
|
||||
jdDevice: null,
|
||||
resource: null,
|
||||
desc: null,
|
||||
sbtype: null,
|
||||
delivery: null,
|
||||
alarmList: [{ logic: null, num: null }],
|
||||
});
|
||||
//删除的逻辑列表
|
||||
const delAlarmList = ref([]);
|
||||
const formRef = ref();
|
||||
//站点数
|
||||
const zdTreeData = ref<TreeSelectProps['treeData']>([
|
||||
{
|
||||
label: '铁路总局(T01)',
|
||||
value: 'T01',
|
||||
children: [
|
||||
{
|
||||
label: '济阳站(T0101)',
|
||||
value: 'T0101',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
//设备类型树
|
||||
const sbOptions: CascaderProps['options'] = [
|
||||
{
|
||||
value: '3',
|
||||
label: '3.电梯',
|
||||
children: [
|
||||
{
|
||||
value: '301',
|
||||
label: '301.扶梯',
|
||||
},
|
||||
{
|
||||
value: '302',
|
||||
label: '301.直梯',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '4',
|
||||
label: '4.冷热源',
|
||||
children: [
|
||||
{
|
||||
value: '401',
|
||||
label: '402.冷水机组',
|
||||
},
|
||||
{
|
||||
value: '402',
|
||||
label: '403.热泵机组',
|
||||
},
|
||||
{
|
||||
value: '403',
|
||||
label: '403.锅炉',
|
||||
},
|
||||
{
|
||||
value: '404',
|
||||
label: '404.水处理机组',
|
||||
},
|
||||
{
|
||||
value: '405',
|
||||
label: '405.板式热交换机组',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
//节点数据
|
||||
const jdTreeData = ref([
|
||||
{
|
||||
title: 'parent 1',
|
||||
value: 'parent 1',
|
||||
children: [
|
||||
{
|
||||
title: 'parent 1-0',
|
||||
value: 'parent 1-0',
|
||||
children: [
|
||||
{
|
||||
title: 'my leaf',
|
||||
value: 'leaf1',
|
||||
},
|
||||
{
|
||||
title: 'your leaf',
|
||||
value: 'leaf2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-1',
|
||||
value: 'parent 1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
//设备点位
|
||||
const dwOptions = ref<SelectProps['options']>([
|
||||
{ value: '电压 (U)', label: '电压 (U)', code: '1' },
|
||||
{ value: '电流 (I)', label: '电流 (I)', code: '2' },
|
||||
{ value: '电流 (I)', label: 'a相电流 (Ia)', code: '3' },
|
||||
]);
|
||||
const filter: ShowSearchType['filter'] = (inputValue: any, path: any) => {
|
||||
return path.some(
|
||||
(option: any) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1,
|
||||
);
|
||||
};
|
||||
//取值类型
|
||||
const qzOptions = ref<SelectProps['options']>([
|
||||
{ value: '实时值', label: '实时值', code: '1' },
|
||||
{ value: '平均值', label: '平均值', code: '2' },
|
||||
]);
|
||||
//逻辑
|
||||
const ljOptions = ref<SelectProps['options']>([
|
||||
{ value: '1', label: '≥' },
|
||||
{ value: '2', label: '>' },
|
||||
{ value: '3', label: '≤' },
|
||||
{ value: '4', label: '<' },
|
||||
{ value: '5', label: '=' },
|
||||
]);
|
||||
//设备点位方法
|
||||
const filterOption = (input: string, option: any) => {
|
||||
console.log('搜索', option.value);
|
||||
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
const handleFocus = () => {
|
||||
console.log('点击');
|
||||
};
|
||||
const handleChange = (value: string) => {
|
||||
console.log(`selected ${value}`);
|
||||
console.log('选择', infoObject.value.sbAdress);
|
||||
//获得code
|
||||
dwOptions.value.forEach((item) => {
|
||||
if (item.value === value) {
|
||||
console.log('符合', item.code);
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleQzChange = (value: string) => {
|
||||
//获得code
|
||||
qzOptions.value.forEach((item) => {
|
||||
if (item.value === value) {
|
||||
console.log('符合', item.code);
|
||||
}
|
||||
});
|
||||
};
|
||||
const emit = defineEmits(['editObject']);
|
||||
//父调子 页面显示方法
|
||||
const toggle = (value: any) => {
|
||||
//获取设备类型
|
||||
http.post(device.queryDeviceTree, null).then((res) => {
|
||||
console.log(res, '请求出来的数据');
|
||||
NsMessage.success('操作成功');
|
||||
});
|
||||
//判断 是新增 还是修改
|
||||
if (value) {
|
||||
infoObject.value = value;
|
||||
} else {
|
||||
infoObject.value = {
|
||||
id: null,
|
||||
site: null,
|
||||
jdDevice: null,
|
||||
resource: null,
|
||||
desc: null,
|
||||
sbtype: null,
|
||||
delivery: null,
|
||||
alarmList: [{ logic: null, num: null }],
|
||||
};
|
||||
}
|
||||
|
||||
visible.value = !visible.value;
|
||||
};
|
||||
//表单 判断规格
|
||||
const rules: Record<string, Rule[]> = {
|
||||
site: [{ required: true, message: '请选择站点', trigger: 'change' }],
|
||||
sbtype: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
||||
delivery: [{ required: true, message: '请选择启用规则', trigger: 'change' }],
|
||||
jdDevice: [{ required: true, message: '请选择设备名称', trigger: 'change' }],
|
||||
sbAdress: [{ required: true, message: '请选择设备点位', trigger: 'change' }],
|
||||
qzType: [{ required: true, message: '请选择取值类型', trigger: 'change' }],
|
||||
resource: [{ required: true, message: '请选择规则类型', trigger: 'change' }],
|
||||
desc: [{ required: true, message: '请输入异常描述', trigger: 'blur' }],
|
||||
alarm: [{ required: true, message: '请选择逻辑', trigger: 'blur' }],
|
||||
number: [{ required: true, message: '请输入数值', trigger: 'blur' }],
|
||||
};
|
||||
// 开关选择
|
||||
const changeSwitch = () => {
|
||||
console.log(infoObject.value.selectSwitch, '开关');
|
||||
};
|
||||
// 确认按钮
|
||||
const btnClick = () => {
|
||||
console.log(infoObject.value, '数据');
|
||||
|
||||
infoObject.value.alarmList.forEach((item) => {
|
||||
if (item.logic === null || item.num === null) {
|
||||
// NsMessage.error('请选择逻辑和数值');
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (infoObject.value.alarmList.length < 2) {
|
||||
NsMessage.error('请选择逻辑和数值');
|
||||
return;
|
||||
}
|
||||
//数据是否验证通过
|
||||
formRef.value.validate().then(() => {
|
||||
console.log('values', infoObject, toRaw(infoObject));
|
||||
delAlarmList.value = [];
|
||||
});
|
||||
//调用接口
|
||||
// http
|
||||
// .post(props.api, data)
|
||||
// .then(() => {
|
||||
// isLoading.value = false;
|
||||
// NsMessage.success('操作成功', 1, () => {
|
||||
// navigateBack();
|
||||
// });
|
||||
// })
|
||||
// .catch(() => {
|
||||
// isLoading.value = false;
|
||||
// });
|
||||
};
|
||||
//取消按钮
|
||||
const handleClose = () => {
|
||||
// 清楚校验错误信息
|
||||
formRef.value.resetFields();
|
||||
//对象清空
|
||||
infoObject.value = {
|
||||
id: null,
|
||||
site: null,
|
||||
resource: null,
|
||||
desc: null,
|
||||
sbtype: null,
|
||||
delivery: null,
|
||||
alarmList: [{ alarm: null, number: null }],
|
||||
};
|
||||
visible.value = false;
|
||||
delAlarmList.value = [];
|
||||
};
|
||||
// 新增逻辑列表
|
||||
const addAlarmList = () => {
|
||||
if (infoObject.value.alarmList) {
|
||||
infoObject.value.alarmList.push({ logic: null, num: null });
|
||||
} else {
|
||||
infoObject.value.alarmList = [{ logic: null, num: null }];
|
||||
}
|
||||
};
|
||||
// 删除 逻辑列表、
|
||||
const deleteAlarmList = (index: number) => {
|
||||
if (infoObject.value.alarmList[index]?.id) {
|
||||
delAlarmList.value.push(infoObject.value.alarmList[index]);
|
||||
}
|
||||
infoObject.value.alarmList.splice(index, 1);
|
||||
};
|
||||
defineExpose({
|
||||
toggle,
|
||||
handleClose,
|
||||
dwOptions,
|
||||
formRef,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.drawerContainer {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
/deep/ .ant-form-item-label {
|
||||
z-index: 20;
|
||||
text-align: right;
|
||||
width: 23%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<ns-drawer
|
||||
v-model:visible="visible"
|
||||
width="520"
|
||||
:title="infoObject?.id ? '修改能源告警' : '新增能源告警'"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
:ok="btnClick"
|
||||
:cancel="handleClose"
|
||||
placement="right">
|
||||
<ns-form ref="formRef" :schemas="schemas" :model="infoObject" formLayout="vertical" />
|
||||
<div style="margin-left: 52px">
|
||||
应用规则:
|
||||
<a-switch
|
||||
:checked="infoObject?.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': infoObject?.enableRules === 1 ? true : false,
|
||||
'grey-background': infoObject?.enableRules === 1 ? false : true,
|
||||
}"
|
||||
style="margin-left: 6px"
|
||||
@change="changeSwitch" />
|
||||
</div>
|
||||
</ns-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { http } from '/nerv-lib/util';
|
||||
// import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
|
||||
const visible = ref(false);
|
||||
//表单数据
|
||||
const infoObject = ref({
|
||||
id: null,
|
||||
accountNo: null,
|
||||
enableRules: 0,
|
||||
});
|
||||
const formRef = ref();
|
||||
const emit = defineEmits(['editObject']);
|
||||
const toggle = (value: any) => {
|
||||
//判断 是新增 还是修改
|
||||
if (value) {
|
||||
infoObject.value = value;
|
||||
} else {
|
||||
infoObject.value = {
|
||||
id: null,
|
||||
accountNo: null,
|
||||
enableRules: 0,
|
||||
};
|
||||
}
|
||||
visible.value = !visible.value;
|
||||
};
|
||||
const schemas = [
|
||||
{
|
||||
field: 'basicInfo',
|
||||
label: '',
|
||||
displayFormItem: false,
|
||||
class: 'ns-form-item-full',
|
||||
component: 'NsChildForm',
|
||||
componentProps: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'alarmTitle',
|
||||
label: '告警标题',
|
||||
component: 'NsInput',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '告警标题不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
placeholder: '请输入告警标题',
|
||||
maxLength: 20,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'repetitions',
|
||||
label: '重复次数',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '重复次数不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择重复次数',
|
||||
|
||||
options: [
|
||||
{
|
||||
label: '单次',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '重复',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '累计',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
label: '优先级',
|
||||
component: 'NsSelect',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '优先级不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择优先级',
|
||||
options: [
|
||||
{
|
||||
label: '紧急',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '一般',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
label: '监测频率',
|
||||
component: 'NsSelect',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '监测频率不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择监测频率',
|
||||
componentProps: {
|
||||
api: '/api/community/objs/DictItem',
|
||||
params: {
|
||||
pageSize: 100,
|
||||
code: 'MZ',
|
||||
},
|
||||
placeholder: '请选择设备点位',
|
||||
resultField: 'data',
|
||||
labelField: 'dictName',
|
||||
valueField: 'dictValue',
|
||||
immediate: true,
|
||||
autoSelectFirst: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
//开关
|
||||
const changeSwitch = () => {
|
||||
switch (infoObject.value.enableRules) {
|
||||
case 1:
|
||||
infoObject.value.enableRules = 0;
|
||||
break;
|
||||
case 0:
|
||||
infoObject.value.enableRules = 1;
|
||||
break;
|
||||
}
|
||||
};
|
||||
const btnClick = () => {
|
||||
//表单校验
|
||||
formRef.value.triggerSubmit().then(() => {
|
||||
//调用接口
|
||||
// http.post(deviceAlarms.addOrUpNewData, infoObject.value).then(() => {
|
||||
// NsMessage.success('操作成功');
|
||||
// visible.value = false;
|
||||
// emit('editObject', null);
|
||||
// });
|
||||
});
|
||||
};
|
||||
const handleClose = () => {
|
||||
// 清楚校验错误信息
|
||||
formRef.value.formElRef.clearValidate();
|
||||
console.log(infoObject.value);
|
||||
visible.value = false;
|
||||
NsMessage.success('操作成功');
|
||||
};
|
||||
defineExpose({
|
||||
toggle,
|
||||
handleClose,
|
||||
formRef,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.drawerContainer {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,288 @@
|
||||
<!-- 配置设备告警 -->
|
||||
<template>
|
||||
<ns-view-list-table v-if="show" ref="mainRef" class="table" v-bind="tableConfig">
|
||||
<template #bodyCell="{ record, column }">
|
||||
<template v-if="column.dataIndex === 'enableRules'">
|
||||
<a-switch
|
||||
:checked="record.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': record.enableRules === 1 ? true : false,
|
||||
'grey-background': record.enableRules === 1 ? false : true,
|
||||
}"
|
||||
@click="clickSwitch({ enableRules: record.enableRules, record: record })" />
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'equipmentInfo'">
|
||||
{{
|
||||
record?.enableRules
|
||||
? record.enableRules + '>' + record.deviceType + '>' + record.deviceName
|
||||
: '-'
|
||||
}}
|
||||
</template>
|
||||
</template>
|
||||
</ns-view-list-table>
|
||||
<!-- 新增or编辑界面 -->
|
||||
<editConfigureDeviceAlarm ref="editConfigureDeviceAlarms" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, createVNode } from 'vue';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import data from '../notificationManagementMock.json';
|
||||
import { NsMessage, NsModal } from '/nerv-lib/component';
|
||||
import editConfigureDeviceAlarm from '../equipmentAlarm/editConfigureDeviceAlarm.vue';
|
||||
import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
export default {
|
||||
components: { editConfigureDeviceAlarm },
|
||||
|
||||
setup() {
|
||||
//设备告警数据
|
||||
const configureDeviceAlarmsData = ref({});
|
||||
const show = ref(false);
|
||||
const tableConfig = ref({});
|
||||
const mainRef = ref({});
|
||||
const editConfigureDeviceAlarms = ref({});
|
||||
const mockData = ref(data.listData);
|
||||
const clickSwitch = (data: any) => {
|
||||
NsModal.confirm({
|
||||
title: '启用状态',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
content: '确定' + (data.record.enableRules === 1 ? '关闭' : '启用') + '吗?',
|
||||
onOk: () => {
|
||||
http
|
||||
.post(deviceAlarms.addOrUpNewData, {
|
||||
id: data.record.id,
|
||||
enableRules: data.record.enableRules === 1 ? 0 : 1,
|
||||
})
|
||||
.then(() => {
|
||||
NsMessage.success('操作成功');
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
const doWnload = (url: any) => {
|
||||
const a = document.createElement('a');
|
||||
document.body.appendChild(a);
|
||||
a.href = encodeURI(url);
|
||||
//设置下载的文件名
|
||||
// a.download = fileName.value;
|
||||
//触发a标签的点击事件,进行下载
|
||||
a.click();
|
||||
};
|
||||
const setconfigureDeviceAlarmsData = (value: any) => {
|
||||
configureDeviceAlarmsData.value = value;
|
||||
show.value = true;
|
||||
tableConfig.value = {
|
||||
title: '告警规则',
|
||||
api: deviceAlarms.getTableList,
|
||||
value: mockData.value,
|
||||
headerActions: [
|
||||
{
|
||||
label: '新增',
|
||||
name: 'RoleTypeAdd',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
editConfigureDeviceAlarms.value.toggle();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导入',
|
||||
name: 'groupImport',
|
||||
type: 'primary',
|
||||
extra: {
|
||||
// api: props.postImportApi, // 导入接口名
|
||||
title: '设备信息', // 弹窗title
|
||||
templateName: 'whiteListUser', // 所使用的文件名称
|
||||
indexName: '设备id', // 匹配类型字段
|
||||
message: [
|
||||
{ label: '1、若必填项未填写,则不能进行导入操作' },
|
||||
{ label: `2、当重复时,则更新数据。` },
|
||||
{ label: '3、数据将从模版的第五行进行导入。' },
|
||||
{ label: '4、文件导入勿超过5MB。' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导出',
|
||||
name: 'groupExports',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
doWnload('/hx-ai-intelligent/asset/file/whiteListUser.xlsx');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '批量删除',
|
||||
type: 'primary',
|
||||
name: 'userBatchDel',
|
||||
dynamicDisabled: (data: any) => {
|
||||
return data.list.length === 0;
|
||||
},
|
||||
confirm: true,
|
||||
isReload: true,
|
||||
isClearCheck: true,
|
||||
// api: origanizemanage.batchDel,
|
||||
dynamicParams: { userIds: 'userId[]' },
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '规则id',
|
||||
dataIndex: 'ruleId',
|
||||
},
|
||||
{
|
||||
title: '设备信息',
|
||||
dataIndex: 'equipmentInfo',
|
||||
},
|
||||
{
|
||||
title: '告警点位',
|
||||
dataIndex: 'devicePoint',
|
||||
},
|
||||
{
|
||||
title: '判断条件',
|
||||
dataIndex: 'ruleType',
|
||||
},
|
||||
{
|
||||
title: '取值类型',
|
||||
dataIndex: 'valueType',
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '异常描述',
|
||||
dataIndex: 'abnormalDescription',
|
||||
},
|
||||
{
|
||||
title: '启用通知',
|
||||
dataIndex: 'enableRules',
|
||||
},
|
||||
],
|
||||
// rowSelection: null, 选择按钮
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
editConfigureDeviceAlarms.value.toggle(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
confirm: true,
|
||||
handle: () => {
|
||||
// mockData.value.splice(0, 1);
|
||||
console.log(data, 'xxxxxxx');
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
formConfig: {
|
||||
title: value.errorCode,
|
||||
schemas: [
|
||||
{
|
||||
field: 'provider',
|
||||
label: '设备名称',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入设备名称',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '设备点位',
|
||||
component: 'nsSelectApi',
|
||||
componentProps: {
|
||||
api: '/api/community/objs/DictItem',
|
||||
params: {
|
||||
pageSize: 100,
|
||||
code: 'MZ',
|
||||
},
|
||||
placeholder: '请选择设备点位',
|
||||
resultField: 'data',
|
||||
labelField: 'dictName',
|
||||
valueField: 'dictValue',
|
||||
immediate: true,
|
||||
autoSelectFirst: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'payWay',
|
||||
label: '启用状态',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择启用状态',
|
||||
options: [
|
||||
{
|
||||
label: '启用',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '关闭',
|
||||
value: '0',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '异常描述',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入异常描述关键字',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
params: { id: value.id },
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'id',
|
||||
};
|
||||
};
|
||||
return {
|
||||
configureDeviceAlarmsData,
|
||||
show,
|
||||
clickSwitch,
|
||||
doWnload,
|
||||
tableConfig,
|
||||
editConfigureDeviceAlarms,
|
||||
setconfigureDeviceAlarmsData,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,489 @@
|
||||
<template>
|
||||
<ns-drawer
|
||||
v-model:visible="visible"
|
||||
width="520"
|
||||
:title="infoObject?.id ? '编辑告警规则' : '新增告警规则'"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
:ok="btnClick"
|
||||
:cancel="handleClose"
|
||||
placement="right">
|
||||
<div style="padding: 18px; width: 100%; overflow: hidden">
|
||||
<a-form ref="formRef" :model="infoObject" :rules="rules">
|
||||
<a-form-item ref="site" label="站点" name="site">
|
||||
<a-tree-select
|
||||
v-model:value="infoObject.site"
|
||||
show-search
|
||||
style="width: 100%"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
placeholder="请选择站点"
|
||||
allow-clear
|
||||
tree-default-expand-all
|
||||
:tree-data="zdTreeData"
|
||||
tree-node-filter-prop="label" />
|
||||
</a-form-item>
|
||||
<a-form-item label="设备类型" name="deviceType">
|
||||
<a-cascader
|
||||
v-model:value="infoObject.deviceType"
|
||||
:options="deviceTypeTreeData"
|
||||
:field-names="{
|
||||
children: 'children',
|
||||
label: 'deviceType',
|
||||
value: 'id',
|
||||
}"
|
||||
:show-search="{ filter }"
|
||||
@change="selectDeviceType"
|
||||
placeholder="请选择设备类型" />
|
||||
</a-form-item>
|
||||
<a-form-item label="设备名称" name="deviceName">
|
||||
<a-select
|
||||
v-model:value="infoObject.deviceName"
|
||||
:disabled="!(infoObject && infoObject.deviceType && infoObject.deviceType.length > 0)"
|
||||
style="width: 100%"
|
||||
:autoClearSearchValue="true"
|
||||
@change="selectDevice"
|
||||
placeholder="请选择设备名称">
|
||||
<template v-for="(item, index) in deviceNameTreeData" :key="index">
|
||||
<a-select-option :value="item.id">
|
||||
{{ item.deviceName }}
|
||||
</a-select-option>
|
||||
</template>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="设备点位" name="devicePoint">
|
||||
<a-select
|
||||
v-model:value="infoObject.devicePoint"
|
||||
show-search
|
||||
placeholder="请选择设备点位"
|
||||
:disabled="!infoObject?.deviceName"
|
||||
style="width: 100%"
|
||||
:options="dwOptions"
|
||||
:filter-option="filterOption"
|
||||
@focus="handleFocus"
|
||||
@change="handleChange" />
|
||||
</a-form-item>
|
||||
<a-form-item label="启用规则" name="enableRules">
|
||||
<a-switch
|
||||
:checked="infoObject.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': infoObject.enableRules === 1 ? true : false,
|
||||
'grey-background': infoObject.enableRules === 1 ? false : true,
|
||||
}"
|
||||
@click="clickSwitch" />
|
||||
</a-form-item>
|
||||
<a-form-item label="取值类型" name="valueType">
|
||||
<a-select
|
||||
v-model:value="infoObject.valueType"
|
||||
show-search
|
||||
placeholder="请选择取值类型"
|
||||
style="width: 100%"
|
||||
:options="qzOptions"
|
||||
:filter-option="filterOption"
|
||||
@change="handleQzChange" />
|
||||
</a-form-item>
|
||||
<a-form-item label="异常描述" name="abnormalDescription">
|
||||
<a-textarea
|
||||
v-model:value="infoObject.abnormalDescription"
|
||||
style="height: 32px"
|
||||
:autoSize="{ minRows: 1, maxRows: 1 }"
|
||||
show-count
|
||||
:maxlength="30" />
|
||||
</a-form-item>
|
||||
<a-form-item label="规则类型" name="ruleType">
|
||||
<a-radio-group v-model:value="infoObject.ruleType">
|
||||
<a-radio value="1">且 (and) </a-radio>
|
||||
<a-radio value="2">或 (or) </a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<template v-for="index in infoObject.alarmList?.length" :key="index">
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-left: 42px;
|
||||
padding: 12px;
|
||||
border-color: #ff4d4f !important;
|
||||
">
|
||||
<span style="line-height: 32px">{{ `逻辑${index}:` }}</span>
|
||||
<a-select
|
||||
v-model:value="infoObject.alarmList[index - 1].logic"
|
||||
style="width: 70px; margin-left: 12px"
|
||||
:options="ljOptions"
|
||||
@change="handleQzChange" />
|
||||
<span style="line-height: 32px; margin-left: 32px">{{ `数值${index}:` }}</span>
|
||||
<a-input
|
||||
style="width: 65px; margin-left: 6px"
|
||||
type="number"
|
||||
v-model:value="infoObject.alarmList[index - 1].num" />
|
||||
<div
|
||||
style="width: 70px; align-items: center; cursor: pointer"
|
||||
@click="deleteAlarmList(index - 1)">
|
||||
<img
|
||||
style="width: 14px; margin: 0 12px"
|
||||
src="https://files.axshare.com/gsc/4T0UQR/5a/e6/81/5ae6813d499c422383c7a15dd956523f/images/设备规则/u72.svg?pageId=cbce6e61-bc6a-4283-802d-993fce6151c0" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
infoObject.alarmList[index - 1].num === null ||
|
||||
infoObject.alarmList[index - 1].logic === null
|
||||
"
|
||||
style="width: 100%; color: #ff4d4f; text-align: center; margin-bottom: 5px">
|
||||
请选择正确的逻辑{{ index }} 或 输入正确的数值{{ index }}
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-if="infoObject?.alarmList?.length < 2"
|
||||
style="width: 100%; color: #ff4d4f; text-align: center; margin-bottom: 5px">
|
||||
逻辑至少2条
|
||||
</div>
|
||||
<div style="width: 100%; margin-top: 12px; display: flex; justify-content: flex-end">
|
||||
<a-button type="primary" @click="addAlarmList"> 新增</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</div>
|
||||
</ns-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { ref, toRaw, watch } from 'vue';
|
||||
import type { CascaderProps, TreeSelectProps, SelectProps } from 'ant-design-vue';
|
||||
import type { ShowSearchType } from 'ant-design-vue/es/cascader';
|
||||
import { device } from '/@/api/deviceManage';
|
||||
import { http } from '/nerv-lib/util';
|
||||
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
import { async } from '@antv/x6/lib/registry/marker/async';
|
||||
|
||||
const visible = ref(false);
|
||||
//表单数据
|
||||
const infoObject = ref({
|
||||
id: null,
|
||||
site: null,
|
||||
ruleType: null,
|
||||
abnormalDescription: null,
|
||||
deviceType: [],
|
||||
devicePoint: null,
|
||||
valueType: null,
|
||||
deviceName: null,
|
||||
enableRules: 0,
|
||||
alarmList: [{ id: null, alarm: null, number: null, isDelete: '0' }],
|
||||
});
|
||||
//删除的逻辑列表
|
||||
const delAlarmList = ref([]);
|
||||
const formRef = ref();
|
||||
//组织数
|
||||
const orgId = ref('');
|
||||
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
|
||||
orgId.value = result;
|
||||
//站点数
|
||||
const zdTreeData = ref<TreeSelectProps['treeData']>([
|
||||
{
|
||||
label: '铁路总局(T01)',
|
||||
value: 'T01',
|
||||
children: [
|
||||
{
|
||||
label: '济阳站(T0101)',
|
||||
value: 'T0101',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
//设备类型树
|
||||
let deviceTypeTreeData = ref([]);
|
||||
//设备树
|
||||
let deviceNameTreeData = ref([]);
|
||||
//选择设备类型方法
|
||||
const selectDeviceType = (value: any, selectedOptions: any) => {
|
||||
//获取该类型设备
|
||||
getDevicePage({
|
||||
orgId: orgId.value,
|
||||
code: selectedOptions[selectedOptions.length - 1].code,
|
||||
pageNum: 1,
|
||||
pageSize: 999,
|
||||
});
|
||||
};
|
||||
//选择设备方法
|
||||
const selectDevice = (value: string) => {
|
||||
console.log(`selected ${value}`);
|
||||
};
|
||||
//获取设备列表
|
||||
const getDevicePage = (value: any) => {
|
||||
http.post(device.queryDevicePage, value).then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
deviceNameTreeData.value = res.data.records;
|
||||
}
|
||||
});
|
||||
};
|
||||
//获取设备点位
|
||||
const getDevicePoint = (value: any) => {
|
||||
http.post(device.queryDevicePoint, value).then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
console.log(res, '数据');
|
||||
}
|
||||
});
|
||||
};
|
||||
//设备点位
|
||||
const dwOptions = ref<SelectProps['options']>([
|
||||
{ value: '电压 (U)', label: '电压 (U)', code: '1' },
|
||||
{ value: '电流 (I)', label: '电流 (I)', code: '2' },
|
||||
{ value: '电流 (I)', label: 'a相电流 (Ia)', code: '3' },
|
||||
]);
|
||||
const filter: ShowSearchType['filter'] = (inputValue: any, path: any) => {
|
||||
return path.some(
|
||||
(option: any) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1,
|
||||
);
|
||||
};
|
||||
//取值类型
|
||||
const qzOptions = ref<SelectProps['options']>([
|
||||
{ value: '实时值', label: '实时值', code: '1' },
|
||||
{ value: '平均值', label: '平均值', code: '2' },
|
||||
]);
|
||||
//逻辑
|
||||
const ljOptions = ref<SelectProps['options']>([
|
||||
{ value: '1', label: '≥' },
|
||||
{ value: '2', label: '>' },
|
||||
{ value: '3', label: '≤' },
|
||||
{ value: '4', label: '<' },
|
||||
{ value: '5', label: '=' },
|
||||
]);
|
||||
//设备点位方法
|
||||
const filterOption = (input: string, option: any) => {
|
||||
console.log('搜索', option.value);
|
||||
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
const handleFocus = () => {
|
||||
console.log('点击');
|
||||
};
|
||||
const handleChange = (value: string) => {
|
||||
console.log(`selected ${value}`);
|
||||
console.log('选择', infoObject.value.devicePoint);
|
||||
//获得code
|
||||
dwOptions.value.forEach((item) => {
|
||||
if (item.value === value) {
|
||||
console.log('符合', item.code);
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleQzChange = (value: string) => {
|
||||
//获得code
|
||||
qzOptions.value.forEach((item) => {
|
||||
if (item.value === value) {
|
||||
console.log('符合', item.code);
|
||||
}
|
||||
});
|
||||
};
|
||||
//开关
|
||||
const clickSwitch = () => {
|
||||
if (infoObject.value.enableRules === 1) {
|
||||
infoObject.value.enableRules = 0;
|
||||
} else {
|
||||
infoObject.value.enableRules = 1;
|
||||
}
|
||||
};
|
||||
const emit = defineEmits(['editObject']);
|
||||
|
||||
// 定义一个递归函数来查找每一级的id 设备类型回显 层级方法
|
||||
function findParentIds(tree: any, targetId: number, result: any) {
|
||||
for (let item of tree) {
|
||||
if (item.children && item.children.length > 0) {
|
||||
if (item.children.some((child: any) => child.id === targetId)) {
|
||||
result.unshift(item.id); // 将当前节点的id添加到结果数组的最前面
|
||||
findParentIds(tree, item.id, result); // 递归查找父级节点的id
|
||||
break; // 找到后可以退出循环
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 递归 获取当前 选择的设备类型 对象 用来获取设备列表
|
||||
const findNodeById = (nodes: any, id: any) => {
|
||||
for (let node of nodes) {
|
||||
if (node.id === id) {
|
||||
//获取设备树
|
||||
getDevicePage({ orgId: orgId.value, code: node.code, pageNum: 1, pageSize: 99 });
|
||||
return;
|
||||
} else if (node.children.length > 0) {
|
||||
const found = findNodeById(node.children, id);
|
||||
if (found) {
|
||||
//获取设备树
|
||||
getDevicePage({ orgId: orgId.value, code: found.code, pageNum: 1, pageSize: 99 });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // 没有找到目标节点,返回 null
|
||||
};
|
||||
//父调子 页面显示方法
|
||||
const toggle = async (value: any) => {
|
||||
//获取设备类型
|
||||
await http
|
||||
.post(device.queryDeviceTree, { orgId: orgId.value, pageNum: 1, pageSize: 10 })
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
deviceTypeTreeData.value = res.data;
|
||||
}
|
||||
});
|
||||
//判断 是新增 还是修改
|
||||
if (value) {
|
||||
infoObject.value = value;
|
||||
// 获取 选择的设备类型对象
|
||||
let selectDevice = ref([value.deviceType]);
|
||||
findNodeById(deviceTypeTreeData.value, value.deviceType);
|
||||
//获取设备点位
|
||||
getDevicePoint({ id: 1 });
|
||||
// 修改时
|
||||
findParentIds(deviceTypeTreeData.value, value.deviceType, selectDevice.value);
|
||||
infoObject.value.deviceType = selectDevice.value;
|
||||
} else {
|
||||
//获取设备树
|
||||
infoObject.value = {
|
||||
id: null,
|
||||
site: null,
|
||||
ruleType: null,
|
||||
abnormalDescription: null,
|
||||
deviceType: [],
|
||||
devicePoint: null,
|
||||
valueType: null,
|
||||
deviceName: null,
|
||||
enableRules: 0,
|
||||
alarmList: [{ id: null, alarm: null, number: null, isDelete: '0' }],
|
||||
};
|
||||
}
|
||||
|
||||
visible.value = !visible.value;
|
||||
};
|
||||
//表单 判断规格
|
||||
const rules: infoObject<string, Rule[]> = {
|
||||
site: [{ required: true, message: '请选择站点', trigger: 'change' }],
|
||||
deviceType: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
||||
enableRules: [{ required: true, message: '请选择启用规则', trigger: 'change' }],
|
||||
deviceName: [{ required: true, message: '请选择设备名称', trigger: 'change' }],
|
||||
devicePoint: [{ required: true, message: '请选择设备点位', trigger: 'change' }],
|
||||
valueType: [{ required: true, message: '请选择取值类型', trigger: 'change' }],
|
||||
ruleType: [{ required: true, message: '请选择规则类型', trigger: 'change' }],
|
||||
abnormalDescription: [{ required: true, message: '请输入异常描述', trigger: 'blur' }],
|
||||
alarm: [{ required: true, message: '请选择逻辑', trigger: 'blur' }],
|
||||
number: [{ required: true, message: '请输入数值', trigger: 'blur' }],
|
||||
};
|
||||
// 开关选择
|
||||
const changeSwitch = () => {
|
||||
console.log(infoObject.value.selectSwitch, '开关');
|
||||
};
|
||||
// 确认按钮
|
||||
const btnClick = () => {
|
||||
console.log(infoObject.value, '数据');
|
||||
infoObject.value.alarmList.forEach((item) => {
|
||||
if (item.logic === null || item.num === null) {
|
||||
// NsMessage.error('请选择逻辑和数值');
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (infoObject.value.alarmList.length < 2) {
|
||||
NsMessage.error('请选择逻辑和数值');
|
||||
return;
|
||||
}
|
||||
//数据是否验证通过
|
||||
formRef.value.validate().then(() => {
|
||||
console.log('values', infoObject.value);
|
||||
let data = toRaw(infoObject);
|
||||
//逻辑列表
|
||||
data.alarmList = [...infoObject.value.alarmList, ...delAlarmList.value];
|
||||
//设备类型 只取最后一级的id
|
||||
data.deviceType = infoObject.value.deviceType[infoObject.value.deviceType.length - 1];
|
||||
delAlarmList.value = [];
|
||||
});
|
||||
//调用接口
|
||||
// http
|
||||
// .post(props.api, data)
|
||||
// .then(() => {
|
||||
// isLoading.value = false;
|
||||
// NsMessage.success('操作成功', 1, () => {
|
||||
// navigateBack();
|
||||
// });
|
||||
// })
|
||||
// .catch(() => {
|
||||
// isLoading.value = false;
|
||||
// });
|
||||
};
|
||||
//取消按钮
|
||||
const handleClose = () => {
|
||||
// 清楚校验错误信息
|
||||
formRef.value.resetFields();
|
||||
//对象清空
|
||||
infoObject.value = {
|
||||
id: null,
|
||||
site: null,
|
||||
ruleType: null,
|
||||
abnormalDescription: null,
|
||||
deviceType: [],
|
||||
devicePoint: null,
|
||||
enableRules: 0,
|
||||
alarmList: [{ id: null, alarm: null, number: null, isDelete: '0' }],
|
||||
};
|
||||
visible.value = false;
|
||||
delAlarmList.value = [];
|
||||
};
|
||||
// 新增逻辑列表
|
||||
const addAlarmList = () => {
|
||||
if (infoObject.value.alarmList) {
|
||||
infoObject.value.alarmList.push({ logic: null, num: null });
|
||||
} else {
|
||||
infoObject.value.alarmList = [{ logic: null, num: null }];
|
||||
}
|
||||
};
|
||||
// 删除 逻辑列表、
|
||||
const deleteAlarmList = (index: number) => {
|
||||
// 确保 index 在有效范围内
|
||||
if (index < infoObject.value.alarmList.length && index >= 0) {
|
||||
const alarmItemToDelete = infoObject.value.alarmList[index];
|
||||
if (alarmItemToDelete?.id) {
|
||||
// 添加到 delAlarmList 中,并标记为已删除
|
||||
delAlarmList.value.push({ ...alarmItemToDelete, isDelete: '1' });
|
||||
}
|
||||
// 从 infoObject 中删除该元素
|
||||
infoObject.value.alarmList.splice(index, 1);
|
||||
} else {
|
||||
console.error('Invalid index: ', index);
|
||||
}
|
||||
};
|
||||
defineExpose({
|
||||
toggle,
|
||||
handleClose,
|
||||
dwOptions,
|
||||
formRef,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.drawerContainer {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
/deep/ .ant-form-item-label {
|
||||
z-index: 20;
|
||||
text-align: right;
|
||||
width: 23%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,258 @@
|
||||
<template>
|
||||
<ns-drawer
|
||||
v-model:visible="visible"
|
||||
width="520"
|
||||
:title="infoObject?.id ? '修改设备告警' : '新增设备告警'"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
:ok="btnClick"
|
||||
:cancel="handleClose"
|
||||
placement="right">
|
||||
<ns-form ref="formRef" :schemas="schemas" :model="infoObject" formLayout="vertical" />
|
||||
<div style="margin-left: 52px">
|
||||
应用规则:
|
||||
<a-switch
|
||||
:checked="infoObject?.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': infoObject?.enableRules === 1 ? true : false,
|
||||
'grey-background': infoObject?.enableRules === 1 ? false : true,
|
||||
}"
|
||||
style="margin-left: 6px"
|
||||
@change="changeSwitch" />
|
||||
</div>
|
||||
</ns-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
|
||||
const visible = ref(false);
|
||||
//表单数据
|
||||
const infoObject = ref({
|
||||
id: null,
|
||||
accountNo: null,
|
||||
enableRules: 0,
|
||||
});
|
||||
const formRef = ref();
|
||||
const emit = defineEmits(['editObject']);
|
||||
const toggle = (value: any) => {
|
||||
//判断 是新增 还是修改
|
||||
if (value) {
|
||||
infoObject.value = value;
|
||||
} else {
|
||||
infoObject.value = {
|
||||
id: null,
|
||||
accountNo: null,
|
||||
enableRules: 0,
|
||||
};
|
||||
}
|
||||
visible.value = !visible.value;
|
||||
};
|
||||
const schemas = [
|
||||
{
|
||||
field: 'basicInfo',
|
||||
label: '',
|
||||
displayFormItem: false,
|
||||
class: 'ns-form-item-full',
|
||||
component: 'NsChildForm',
|
||||
componentProps: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'alarmTitle',
|
||||
label: '告警标题',
|
||||
component: 'NsInput',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '告警标题不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
placeholder: '请输入告警标题',
|
||||
maxLength: 20,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'repetitions',
|
||||
label: '重复次数',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '重复次数不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择重复次数',
|
||||
|
||||
options: [
|
||||
{
|
||||
label: '单次',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '重复',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '累计',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'monitorTime',
|
||||
label: '检测时长',
|
||||
component: 'NsInputNumber',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
validator: (rules: any, value: any, cbfn: any) => {
|
||||
if (value && /^[0-9]*$/.test(value)) {
|
||||
cbfn();
|
||||
} else {
|
||||
cbfn('请输入正确的监测时长');
|
||||
}
|
||||
},
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
placeholder: '请输入监测时长',
|
||||
// maxLength: 30,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'monitorTimeUnit',
|
||||
label: '监测时长单位',
|
||||
component: 'NsSelect',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '监测时长单位不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择监测时长单位',
|
||||
options: [
|
||||
{
|
||||
label: '分',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '时',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '天',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
label: '优先级',
|
||||
component: 'NsSelect',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '优先级不能为空',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择优先级',
|
||||
options: [
|
||||
{
|
||||
label: '紧急',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '一般',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
//开关
|
||||
const changeSwitch = () => {
|
||||
switch (infoObject.value.enableRules) {
|
||||
case 1:
|
||||
infoObject.value.enableRules = 0;
|
||||
break;
|
||||
case 0:
|
||||
infoObject.value.enableRules = 1;
|
||||
break;
|
||||
}
|
||||
};
|
||||
const btnClick = () => {
|
||||
//表单校验
|
||||
formRef.value.triggerSubmit().then(() => {
|
||||
//调用接口
|
||||
http.post(deviceAlarms.addOrUpNewData, infoObject.value).then(() => {
|
||||
NsMessage.success('操作成功');
|
||||
visible.value = false;
|
||||
emit('editObject', null);
|
||||
});
|
||||
});
|
||||
};
|
||||
const handleClose = () => {
|
||||
// 清楚校验错误信息
|
||||
formRef.value.formElRef.clearValidate();
|
||||
console.log(infoObject.value);
|
||||
visible.value = false;
|
||||
NsMessage.success('操作成功');
|
||||
};
|
||||
defineExpose({
|
||||
toggle,
|
||||
handleClose,
|
||||
formRef,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.drawerContainer {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<a-tabs default-active-key="1" @change="callback">
|
||||
<a-tab-pane key="1" tab="通知管理">
|
||||
<ns-view-list-table v-bind="notificationConfig" ref="mainRef">
|
||||
<template #bodyCell="{ record, column }">
|
||||
<template v-if="column.dataIndex === 'enableRules'">
|
||||
<a-switch
|
||||
:checked="record.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': record.enableRules === 1 ? true : false,
|
||||
'grey-background': record.enableRules === 1 ? false : true,
|
||||
}"
|
||||
@change="clickSwitch({ enableRules: record.enableRules, record: record })" />
|
||||
</template>
|
||||
</template>
|
||||
</ns-view-list-table>
|
||||
<!-- 联系方式 -->
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="设备告警" force-render>
|
||||
<ns-view-list-table
|
||||
v-show="equipmentAlarm"
|
||||
ref="mainRefEquipmentAlarm"
|
||||
class="table"
|
||||
v-bind="equipmentAlarmConfig">
|
||||
<template #bodyCell="{ record, column }">
|
||||
<template v-if="column.dataIndex === 'enableRules'">
|
||||
<a-switch
|
||||
:checked="record.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': record.enableRules === 1 ? true : false,
|
||||
'grey-background': record.enableRules === 1 ? false : true,
|
||||
}"
|
||||
@change="clickSwitch({ enableRules: record.enableRules, record: record })" />
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'monitor'">
|
||||
{{
|
||||
record?.monitorTime && record?.monitorTimeUnit
|
||||
? record?.monitorTime + record?.monitorTimeUnit
|
||||
: '-'
|
||||
}}
|
||||
</template>
|
||||
</template>
|
||||
</ns-view-list-table>
|
||||
<a-button
|
||||
v-if="!equipmentAlarm"
|
||||
type="primary"
|
||||
style="position: absolute; right: 130px; z-index: 99; top: 80px; height: 30px"
|
||||
@click="backequipmentAlarm"
|
||||
>返回</a-button
|
||||
>
|
||||
<!-- 新增 或 编辑 设备告警 -->
|
||||
<editeEquipmentAlarm ref="editEquipmentAlarm" @editObject="editObject" />
|
||||
<!-- 配置设备告警-->
|
||||
<configureDeviceAlarms v-show="!equipmentAlarm" ref="configureDeviceAlarms" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="能源告警">
|
||||
<ns-view-list-table
|
||||
v-bind="energyAlarmConfig"
|
||||
v-show="energyAlarm"
|
||||
ref="mainEnergyAlarmConfig"
|
||||
class="table">
|
||||
<template #bodyCell="{ record, column }">
|
||||
<template v-if="column.dataIndex === 'enableRules'">
|
||||
<a-switch
|
||||
:checked="record.enableRules === 1 ? true : false"
|
||||
:class="{
|
||||
'blue-background': record.enableRules === 1 ? true : false,
|
||||
'grey-background': record.enableRules === 1 ? false : true,
|
||||
}"
|
||||
@click="clickSwitch({ enableRules: record.enableRules, record: record })" />
|
||||
</template>
|
||||
</template>
|
||||
</ns-view-list-table>
|
||||
<a-button
|
||||
v-if="!energyAlarm"
|
||||
type="primary"
|
||||
style="position: absolute; right: 130px; z-index: 99; top: 80px; height: 30px"
|
||||
@click="backenergyAlarm"
|
||||
>返回</a-button
|
||||
>
|
||||
<!-- 新增 或 编辑 能源告警 -->
|
||||
<editeEnergyAlarm ref="editeEnergyAlarm" @editObject="editObject" />
|
||||
<!-- 配置能源告警-->
|
||||
<configureEnergyAlarms v-show="!energyAlarm" ref="configureEnergyAlarms" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { notificationtableConfig } from './ts/notificationManagementConfig';
|
||||
import { equipmentAlarmTableConfig } from './ts/equipmentAlarmConfig';
|
||||
import { energyAlarmConfigs } from './ts/energyAlarmConfig';
|
||||
import { ref, createVNode } from 'vue';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { NsMessage, NsModal } from '/nerv-lib/component';
|
||||
import editeEquipmentAlarm from './equipmentAlarm/editeEquipmentAlarm.vue';
|
||||
import editeEnergyAlarm from './energyAlarm/editeEnergyAlarm.vue';
|
||||
import configureEnergyAlarms from './energyAlarm/configureEnergyAlarms.vue';
|
||||
import configureDeviceAlarms from './equipmentAlarm/configureDeviceAlarms.vue';
|
||||
import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
export default {
|
||||
name: 'AlarmSettings',
|
||||
components: {
|
||||
editeEquipmentAlarm,
|
||||
configureDeviceAlarms,
|
||||
configureEnergyAlarms,
|
||||
editeEnergyAlarm,
|
||||
},
|
||||
setup() {
|
||||
const mainRef = ref();
|
||||
const mainRefEquipmentAlarm = ref();
|
||||
const mainEnergyAlarmConfig = ref();
|
||||
const editEquipmentAlarm = ref();
|
||||
const editeEnergyAlarm = ref();
|
||||
const configureDeviceAlarms = ref();
|
||||
const configureEnergyAlarms = ref();
|
||||
const equipmentAlarm = ref(true);
|
||||
const energyAlarm = ref(true);
|
||||
const notificationConfig = notificationtableConfig(null, mainEnergyAlarmConfig, null);
|
||||
//能源告警配置
|
||||
const energyAlarmConfig = energyAlarmConfigs(
|
||||
editeEnergyAlarm,
|
||||
mainRefEquipmentAlarm,
|
||||
energyAlarm,
|
||||
configureEnergyAlarms,
|
||||
);
|
||||
//设备告警配置
|
||||
const equipmentAlarmConfig = equipmentAlarmTableConfig(
|
||||
editEquipmentAlarm,
|
||||
mainRefEquipmentAlarm,
|
||||
equipmentAlarm,
|
||||
configureDeviceAlarms,
|
||||
);
|
||||
const callback = (key: any) => {
|
||||
console.log(key);
|
||||
};
|
||||
//返回设备告警
|
||||
const backequipmentAlarm = () => {
|
||||
equipmentAlarm.value = !equipmentAlarm.value;
|
||||
configureDeviceAlarms.value.show = false;
|
||||
};
|
||||
const backenergyAlarm = () => {
|
||||
energyAlarm.value = !energyAlarm.value;
|
||||
configureEnergyAlarms.value.show = false;
|
||||
};
|
||||
const clickSwitch = (data: any) => {
|
||||
console.log(data.record.enableRules === 1 ? '关闭' : '启用');
|
||||
NsModal.confirm({
|
||||
title: '启用状态',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
content: '确定' + (data.record.enableRules === 1 ? '关闭' : '启用') + '吗?',
|
||||
onOk: () => {
|
||||
http
|
||||
.post(deviceAlarms.addOrUpNewData, {
|
||||
id: data.record.id,
|
||||
enableRules: data.record.enableRules === 1 ? 0 : 1,
|
||||
})
|
||||
.then(() => {
|
||||
NsMessage.success('操作成功');
|
||||
mainRefEquipmentAlarm.value?.nsTableRef.reload();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
// 编辑或添加成功 刷新列表
|
||||
const editObject = () => {
|
||||
mainRefEquipmentAlarm.value?.nsTableRef.reload();
|
||||
// console.log(newList.value.formFinish, '数据');
|
||||
};
|
||||
return {
|
||||
callback,
|
||||
notificationConfig,
|
||||
energyAlarmConfig,
|
||||
equipmentAlarmConfig,
|
||||
editObject,
|
||||
clickSwitch,
|
||||
editEquipmentAlarm,
|
||||
editeEnergyAlarm,
|
||||
configureDeviceAlarms,
|
||||
configureEnergyAlarms,
|
||||
equipmentAlarm,
|
||||
energyAlarm,
|
||||
backequipmentAlarm,
|
||||
backenergyAlarm,
|
||||
mainRef,
|
||||
mainRefEquipmentAlarm,
|
||||
mainEnergyAlarmConfig,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.full-height {
|
||||
height: 100%; /* 设置高度为父容器高度 */
|
||||
}
|
||||
.blue-background.ant-switch-checked {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
.blue-background.ant-switch-checked .ant-switch-handle {
|
||||
background-color: linear-gradient(
|
||||
180deg,
|
||||
rgba(1, 206, 255, 1) 0%,
|
||||
rgba(0, 150, 229, 1) 100%
|
||||
) !important;
|
||||
}
|
||||
|
||||
.grey-background.ant-switch .ant-switch-handle {
|
||||
background-color: grey !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"listData":[
|
||||
{
|
||||
"id": "d4",
|
||||
"isDel": "0",
|
||||
"officesId": "84",
|
||||
"deviceCode": "37430200143",
|
||||
"deviceName": "地听测试电表",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "1",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "",
|
||||
"types": "",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo1",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": "84566",
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "cupidatat nisi ea ad",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": null,
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null,
|
||||
"priority": "1",
|
||||
"alarmTitle": "电压异常告警",
|
||||
"errorCode": "A001",
|
||||
"monitorTime":"1",
|
||||
"repetitions":"1",
|
||||
"monitorTimeUnit": "分",
|
||||
"enableRules": "1",
|
||||
"isUse":true
|
||||
} , {
|
||||
"id": "d5",
|
||||
"isDel": "0",
|
||||
"officesId": "84",
|
||||
"deviceCode": "37430200143",
|
||||
"deviceName": "地听测试电表",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "1",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "",
|
||||
"types": "",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo2",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": "84566",
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "cupidatat nisi ea ad",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": null,
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null,
|
||||
"priority": "1",
|
||||
"alarmTitle": "电压异常告警",
|
||||
"errorCode": "A001",
|
||||
"monitorTime":"1",
|
||||
"repetitions":"1",
|
||||
"monitorTimeUnit": "分",
|
||||
"enableRules": "0",
|
||||
"isUse":true
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import data from '../notificationManagementMock.json';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
|
||||
import { ref } from 'vue';
|
||||
const tableKeyMap = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '优先级',
|
||||
dataIndex: 'priority',
|
||||
},
|
||||
{
|
||||
title: '告警标题',
|
||||
dataIndex: 'alarmTitle',
|
||||
},
|
||||
{
|
||||
title: '错误码',
|
||||
dataIndex: 'errorCode',
|
||||
},
|
||||
{
|
||||
title: '重复次数',
|
||||
dataIndex: 'repetitions',
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '监测时长',
|
||||
dataIndex: 'monitor',
|
||||
},
|
||||
{
|
||||
title: '是否启用',
|
||||
dataIndex: 'enableRules',
|
||||
},
|
||||
];
|
||||
const mockData = ref(data.listData);
|
||||
const doWnload = (url: any) => {
|
||||
const a = document.createElement('a');
|
||||
document.body.appendChild(a);
|
||||
a.href = encodeURI(url);
|
||||
//设置下载的文件名
|
||||
// a.download = fileName.value;
|
||||
//触发a标签的点击事件,进行下载
|
||||
a.click();
|
||||
};
|
||||
|
||||
export const energyAlarmConfigs = (
|
||||
editeEnergyAlarm: any,
|
||||
mainRefEquipmentAlarm: any,
|
||||
energyAlarm: any,
|
||||
configureDeviceAlarms: any,
|
||||
) => {
|
||||
return {
|
||||
title: '告警规则',
|
||||
api: deviceAlarms.getTableList,
|
||||
value: mockData.value,
|
||||
headerActions: [
|
||||
{
|
||||
label: '新增',
|
||||
name: 'RoleTypeAdd',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
editeEnergyAlarm.value.toggle();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导入',
|
||||
name: 'groupImport',
|
||||
type: 'primary',
|
||||
extra: {
|
||||
// api: props.postImportApi, // 导入接口名
|
||||
title: '设备信息', // 弹窗title
|
||||
templateName: 'whiteListUser', // 所使用的文件名称
|
||||
indexName: '设备id', // 匹配类型字段
|
||||
message: [
|
||||
{ label: '1、若必填项未填写,则不能进行导入操作' },
|
||||
{ label: `2、当重复时,则更新数据。` },
|
||||
{ label: '3、数据将从模版的第五行进行导入。' },
|
||||
{ label: '4、文件导入勿超过5MB。' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导出',
|
||||
name: 'groupExports',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
doWnload('/hx-ai-intelligent/asset/file/whiteListUser.xlsx');
|
||||
},
|
||||
},
|
||||
],
|
||||
columns: tableKeyMap,
|
||||
// rowSelection: null, 选择按钮
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
editeEnergyAlarm.value.toggle(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '配置',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
energyAlarm.value = !energyAlarm.value;
|
||||
configureDeviceAlarms.value.setconfigureDeviceAlarmsData(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
confirm: true,
|
||||
handle: (data: any) => {
|
||||
http.post(deviceAlarms.del, { id: data.id }).then(() => {
|
||||
NsMessage.success('操作成功');
|
||||
mainRefEquipmentAlarm.value?.nsTableRef.reload();
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'priority',
|
||||
label: '告警优先级',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择告警优先级',
|
||||
options: [
|
||||
{
|
||||
label: '紧急',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '一般',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'alarmTitle',
|
||||
label: '告警标题',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入告警标题关键字',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'errorCode',
|
||||
label: '错误码',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入告警错误码',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'enableRules',
|
||||
label: '启用状态',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择启用状态',
|
||||
options: [
|
||||
{
|
||||
label: '启用',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '关闭',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'id',
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,197 @@
|
||||
import data from '../notificationManagementMock.json';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { deviceAlarms } from '/@/api/alarmSettings/deviceAlarms';
|
||||
|
||||
import { ref } from 'vue';
|
||||
const tableKeyMap = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '优先级',
|
||||
dataIndex: 'priority',
|
||||
},
|
||||
{
|
||||
title: '告警标题',
|
||||
dataIndex: 'alarmTitle',
|
||||
},
|
||||
{
|
||||
title: '错误码',
|
||||
dataIndex: 'errorCode',
|
||||
},
|
||||
{
|
||||
title: '重复次数',
|
||||
dataIndex: 'repetitions',
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '监测时长',
|
||||
dataIndex: 'monitor',
|
||||
},
|
||||
{
|
||||
title: '是否启用',
|
||||
dataIndex: 'enableRules',
|
||||
},
|
||||
];
|
||||
const mockData = ref(data.listData);
|
||||
const doWnload = (url: any) => {
|
||||
const a = document.createElement('a');
|
||||
document.body.appendChild(a);
|
||||
a.href = encodeURI(url);
|
||||
//设置下载的文件名
|
||||
// a.download = fileName.value;
|
||||
//触发a标签的点击事件,进行下载
|
||||
a.click();
|
||||
};
|
||||
|
||||
export const equipmentAlarmTableConfig = (
|
||||
editEquipmentAlarm: any,
|
||||
mainRefEquipmentAlarm: any,
|
||||
equipmentAlarm: any,
|
||||
configureDeviceAlarms: any,
|
||||
) => {
|
||||
return {
|
||||
title: '告警规则',
|
||||
api: deviceAlarms.getTableList,
|
||||
value: mockData.value,
|
||||
headerActions: [
|
||||
{
|
||||
label: '新增',
|
||||
name: 'RoleTypeAdd',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
editEquipmentAlarm.value.toggle();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导入',
|
||||
name: 'groupImport',
|
||||
type: 'primary',
|
||||
extra: {
|
||||
// api: props.postImportApi, // 导入接口名
|
||||
title: '设备信息', // 弹窗title
|
||||
templateName: 'whiteListUser', // 所使用的文件名称
|
||||
indexName: '设备id', // 匹配类型字段
|
||||
message: [
|
||||
{ label: '1、若必填项未填写,则不能进行导入操作' },
|
||||
{ label: `2、当重复时,则更新数据。` },
|
||||
{ label: '3、数据将从模版的第五行进行导入。' },
|
||||
{ label: '4、文件导入勿超过5MB。' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导出',
|
||||
name: 'groupExports',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
doWnload('/hx-ai-intelligent/asset/file/whiteListUser.xlsx');
|
||||
},
|
||||
},
|
||||
],
|
||||
columns: tableKeyMap,
|
||||
// rowSelection: null, 选择按钮
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
editEquipmentAlarm.value.toggle(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '配置',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
equipmentAlarm.value = !equipmentAlarm.value;
|
||||
configureDeviceAlarms.value.setconfigureDeviceAlarmsData(data);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
confirm: true,
|
||||
handle: (data: any) => {
|
||||
http.post(deviceAlarms.del, { id: data.id }).then(() => {
|
||||
NsMessage.success('操作成功');
|
||||
mainRefEquipmentAlarm.value?.nsTableRef.reload();
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'priority',
|
||||
label: '告警优先级',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择告警优先级',
|
||||
options: [
|
||||
{
|
||||
label: '紧急',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '一般',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'alarmTitle',
|
||||
label: '告警标题',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入告警标题关键字',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'errorCode',
|
||||
label: '错误码',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入错误码关键字',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'enableRules',
|
||||
label: '启用状态',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择启用状态',
|
||||
options: [
|
||||
{
|
||||
label: '启用',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '关闭',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'id',
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,151 @@
|
||||
import { dateUtil } from '/nerv-lib/util/date-util';
|
||||
import data from '../notificationManagementMock.json';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { ref } from 'vue';
|
||||
const tableKeyMap = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '优先级',
|
||||
dataIndex: 'id',
|
||||
},
|
||||
{
|
||||
title: '告警类型',
|
||||
dataIndex: 'deviceCode',
|
||||
},
|
||||
{
|
||||
title: '告警标题',
|
||||
dataIndex: 'deviceName',
|
||||
},
|
||||
{
|
||||
title: '错误码',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '通知名单',
|
||||
dataIndex: 'position',
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '通知方式',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '启用通知',
|
||||
dataIndex: 'enableRules',
|
||||
},
|
||||
];
|
||||
const mockData = ref(data.listData);
|
||||
export const notificationtableConfig = (el) => {
|
||||
return {
|
||||
title: '告警规则',
|
||||
// api: '/carbon_emission/device/getDeviceList',
|
||||
value: mockData.value,
|
||||
headerActions: [{}],
|
||||
columns: tableKeyMap,
|
||||
// rowSelection: null, 选择按钮
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
actions: [
|
||||
{
|
||||
label: '联系方式',
|
||||
name: 'FeedBackDetail',
|
||||
dynamicParams: ['uuid', 'appealType'],
|
||||
handle: (data: any) => {
|
||||
console.log(data, '联系方式');
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'name',
|
||||
label: '告警类型',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选告警类型',
|
||||
options: [
|
||||
{
|
||||
label: '设备告警',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '网关告警',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: '能耗告警',
|
||||
value: '3',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '告警优先级',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择告警优先级',
|
||||
options: [
|
||||
{
|
||||
label: '紧急',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '一般',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '告警标题',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入告警标题关键字',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '错误码',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入告警错误码',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'payWay',
|
||||
label: '启用状态',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择启用状态',
|
||||
options: [
|
||||
{
|
||||
label: '启用',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '关闭',
|
||||
value: '0',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'id',
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,229 @@
|
||||
import { ref } from 'vue';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { origanizemanage } from '/@/api/origanizemanage';
|
||||
export const formConfig = (disabled) => {
|
||||
return ref([
|
||||
{
|
||||
field: 'field111',
|
||||
component: 'NsChildForm',
|
||||
componentProps: {
|
||||
schemas: [
|
||||
{
|
||||
label: '排放源',
|
||||
field: 'accountNo',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入排放源',
|
||||
maxLength: 20,
|
||||
disabled,
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入排放源',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'userStatus',
|
||||
label: '排放气体',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择排放气体',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择排放气体',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'userStatus',
|
||||
label: '排放环节',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择排放环节',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '排放因子',
|
||||
field: 'accountNo',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入排放因子值',
|
||||
maxLength: 20,
|
||||
disabled,
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入排放因子值',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'userStatus',
|
||||
label: '碳排前缀',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择碳排前缀',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择碳排前缀',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '碳排后缀',
|
||||
field: 'accountNo',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入碳排后缀',
|
||||
maxLength: 20,
|
||||
disabled,
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入碳排后缀',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '已引用数',
|
||||
field: 'accountNo',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
maxLength: 20,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '参考文献',
|
||||
field: 'accountNo',
|
||||
component: 'NsTextarea',
|
||||
componentProps: {
|
||||
placeholder: '请输入参考文献',
|
||||
maxLength: 20,
|
||||
disabled,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
};
|
||||
const options = ref([]);
|
||||
|
||||
const getUserPerList = (transform, params = {}) => {
|
||||
return http.post(origanizemanage.queryUserPerList, { ...params }).then((res) => {
|
||||
return res.data?.map((item) => {
|
||||
item = { ...item, ...transform(item) };
|
||||
return item;
|
||||
});
|
||||
});
|
||||
};
|
||||
export const formConfig2 = (casData: any) => {
|
||||
return ref([
|
||||
{
|
||||
field: 'information',
|
||||
component: 'NsCascader',
|
||||
componentProps: {
|
||||
placeholder: '请选择',
|
||||
displayRender: ({ labels, selectedOptions }: any) => {
|
||||
console.log(labels, selectedOptions);
|
||||
|
||||
casData.value = selectedOptions.map(({ label, value }) => {
|
||||
return { label, value };
|
||||
});
|
||||
return labels.join('/');
|
||||
},
|
||||
loadData: (selectedOptions, options) => {
|
||||
console.log(selectedOptions, options, 'selectedOptions, options');
|
||||
|
||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||
let transForm, params;
|
||||
// load options lazily
|
||||
if (!selectedOptions.length) {
|
||||
transForm = (data) => {
|
||||
data['label'] = data.orgName;
|
||||
data['value'] = data.orgId;
|
||||
data['isLeaf'] = false;
|
||||
data['level'] = 1;
|
||||
return data;
|
||||
};
|
||||
getUserPerList(transForm).then((res) => {
|
||||
options.value = [...res];
|
||||
});
|
||||
}
|
||||
const id = targetOption?.value;
|
||||
const level = targetOption?.level;
|
||||
if (targetOption) {
|
||||
targetOption.loading = true;
|
||||
}
|
||||
|
||||
if (level === 1) {
|
||||
transForm = (data) => {
|
||||
data['label'] = data.deptName;
|
||||
data['value'] = data.deptId;
|
||||
data['isLeaf'] = false;
|
||||
data['level'] = 2;
|
||||
return data;
|
||||
};
|
||||
params = { orgId: id };
|
||||
} else if (level === 2) {
|
||||
transForm = (data) => {
|
||||
data['label'] = data.roleName;
|
||||
data['value'] = data.roleId;
|
||||
data['level'] = 3;
|
||||
return data;
|
||||
};
|
||||
params = { deptId: id };
|
||||
}
|
||||
if (targetOption) {
|
||||
getUserPerList(transForm, { ...params }).then((res) => {
|
||||
targetOption.loading = false;
|
||||
targetOption.children = [...res];
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
};
|
||||
@@ -0,0 +1,619 @@
|
||||
<!-- @format -->
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="left">
|
||||
<div class="top">
|
||||
<a-form style="width: 100%;margin: 0 auto;">
|
||||
<div class="ns-form-title"><span>排放分类</span></div>
|
||||
<div style="padding: 0 16px !important;width: 100%;">
|
||||
<a-row>
|
||||
<a-col :span="24" style="margin-bottom: 16px;">
|
||||
<a-input-search
|
||||
v-model:value="selectTreeDataValue"
|
||||
placeholder="请输入关键词"
|
||||
@search="onSearchTreeData"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-form>
|
||||
<a-tree
|
||||
class="draggable-tree"
|
||||
style="padding: 0 16px !important;"
|
||||
draggable
|
||||
show-line
|
||||
checkable
|
||||
block-node
|
||||
:tree-data="gData"
|
||||
@dragenter="onDragEnter"
|
||||
@drop="onDrop"
|
||||
:expanded-keys="expandedKeys"
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
@expand="onExpand"
|
||||
>
|
||||
<template #title="{ emissionName }">
|
||||
<span v-if="emissionName && selectTreeDataValue && emissionName.indexOf(selectTreeDataValue) > -1">
|
||||
{{ emissionName.substring(0, emissionName.indexOf(selectTreeDataValue)) }}
|
||||
<span style="color: #f50">{{ selectTreeDataValue }}</span>
|
||||
{{ emissionName.substring(emissionName.indexOf(selectTreeDataValue) + selectTreeDataValue.length) }}
|
||||
</span>
|
||||
<span v-else>{{ emissionName }}</span>
|
||||
</template>
|
||||
</a-tree>
|
||||
<a-popover placement="rightTop" trigger="focus">
|
||||
<template #content>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<a-button type="text">编辑</a-button>
|
||||
<a-button type="text">新增子节点</a-button>
|
||||
<a-button type="text">删除</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<MoreOutlined style="position: absolute;right: 0;top: 16%;font-size: 25px;cursor: pointer;" />
|
||||
</a-popover>
|
||||
<div class="addTreeNode">
|
||||
<a-button type="primary" style="width:100%;" @click="addTreeNodeData">新增</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<ns-view-list-table v-bind="tableConfig" :model="data" ref="mainRef" :scroll="{ x: 2000}"/>
|
||||
</div>
|
||||
<!-- 新增树节点 -->
|
||||
<ns-modal :visible="treeNodeAdd" :title="operationTree" @ok="handleOk" @cancel="handleCancel">
|
||||
<ns-input
|
||||
v-model:value="latitude1"
|
||||
class="input"
|
||||
placeholder="请输入排放类型"
|
||||
/>
|
||||
</ns-modal>
|
||||
<!-- 新增数据库数据 -->
|
||||
<a-drawer
|
||||
:width="500"
|
||||
:visible="visible"
|
||||
:body-style="{ paddingBottom: '80px' }"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
destroyOnClose
|
||||
@close="onClose">
|
||||
<ns-form
|
||||
ref="formRef"
|
||||
:schemas="formSchema"
|
||||
:model="formData"
|
||||
class="form"
|
||||
:wrapperCol="{ span: 20 }"
|
||||
formLayout="vertical" />
|
||||
<template #footer>
|
||||
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" @click="onEdit">确定</a-button>
|
||||
</template>
|
||||
</a-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { MoreOutlined } from '@ant-design/icons-vue';
|
||||
import { computed, createVNode, defineComponent, reactive, ref, watchEffect,watch } from 'vue';
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
import { NsMessage, NsModal } from '/nerv-lib/component';
|
||||
import { formConfig, formConfig2 } from './config';
|
||||
import { carbonEmissionFactorLibrary } from '/@/api/carbonEmissionFactorLibrary';
|
||||
import type {
|
||||
AntTreeNodeDragEnterEvent,
|
||||
AntTreeNodeDropEvent,
|
||||
TreeProps,
|
||||
} from 'ant-design-vue/es/tree';
|
||||
import { log } from 'node:console';
|
||||
|
||||
defineOptions({ name: 'OrderListIndex' });
|
||||
const selectTreeDataValue = ref<string>('');
|
||||
const mainRef = ref();
|
||||
const data = reactive({});
|
||||
let formData = ref({});
|
||||
const formRef = ref();
|
||||
const visible = ref(false);
|
||||
const searchValue = ref<string>('');
|
||||
const searchValue2 = ref<string>('');
|
||||
const disabled = ref(false);
|
||||
const treeNodeAdd = ref<boolean>(false);
|
||||
const operationTree = ref<string>('新增');
|
||||
|
||||
const opMap: any = ref({
|
||||
type: 'add',
|
||||
fuc: () => {},
|
||||
record: {},
|
||||
});
|
||||
watchEffect(() => {
|
||||
disabled.value = opMap.value.type === 'edit';
|
||||
});
|
||||
const formSchema = formConfig(disabled);
|
||||
const casData = ref([]);
|
||||
const treeData = ref([]);
|
||||
const userAuthList = ref([]);
|
||||
const orgId = JSON.parse(sessionStorage.getItem('userInfo')).orgId;
|
||||
const dynamicDisabled = computed(() => {
|
||||
return formRef.value?.validateResult && userAuthList.value?.length;
|
||||
});
|
||||
const fetch = (api, params = { orgId }) => {
|
||||
return http.post(api, params);
|
||||
};
|
||||
|
||||
// 树结构
|
||||
const x = 3;
|
||||
const y = 2;
|
||||
const z = 1;
|
||||
const genData: TreeProps['treeData'] = [];
|
||||
|
||||
const generateData = (_level: number, _preKey?: string, _tns?: TreeProps['treeData']) => {
|
||||
const preKey = _preKey || '0';
|
||||
const tns = _tns || genData;
|
||||
|
||||
const children = [];
|
||||
for (let i = 0; i < x; i++) {
|
||||
const key = `${preKey}-${i}`;
|
||||
tns.push({ title: key, key });
|
||||
if (i < y) {
|
||||
children.push(key);
|
||||
}
|
||||
}
|
||||
if (_level < 0) {
|
||||
return tns;
|
||||
}
|
||||
const level = _level - 1;
|
||||
children.forEach((key, index) => {
|
||||
tns[index].children = [];
|
||||
return generateData(level, key, tns[index].children);
|
||||
});
|
||||
};
|
||||
generateData(z);
|
||||
type TreeDataItem = TreeProps['treeData'][number];
|
||||
const gData = ref<TreeProps['treeData']>(genData);
|
||||
const onDragEnter = (info: AntTreeNodeDragEnterEvent) => {
|
||||
console.log(info);
|
||||
// expandedKeys 需要展开时
|
||||
// expandedKeys.value = info.expandedKeys;
|
||||
};
|
||||
|
||||
const onDrop = (info: AntTreeNodeDropEvent) => {
|
||||
console.log(info);
|
||||
const dropKey = info.node.key;
|
||||
const dragKey = info.dragNode.key;
|
||||
const dropPos = info.node.pos.split('-');
|
||||
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
||||
const loop = (data: TreeProps['treeData'], key: string | number, callback: any) => {
|
||||
data.forEach((item, index) => {
|
||||
if (item.key === key) {
|
||||
return callback(item, index, data);
|
||||
}
|
||||
if (item.children) {
|
||||
return loop(item.children, key, callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
const data = [...gData.value];
|
||||
|
||||
// Find dragObject
|
||||
let dragObj: TreeDataItem;
|
||||
loop(data, dragKey, (item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
if (!info.dropToGap) {
|
||||
// Drop on the content
|
||||
loop(data, dropKey, (item: TreeDataItem) => {
|
||||
item.children = item.children || [];
|
||||
/// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
} else if (
|
||||
(info.node.children || []).length > 0 && // Has children
|
||||
info.node.expanded && // Is expanded
|
||||
dropPosition === 1 // On the bottom gap
|
||||
) {
|
||||
loop(data, dropKey, (item: TreeDataItem) => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
} else {
|
||||
let ar: TreeProps['treeData'] = [];
|
||||
let i = 0;
|
||||
loop(data, dropKey, (_item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
||||
ar = arr;
|
||||
i = index;
|
||||
});
|
||||
if (dropPosition === -1) {
|
||||
ar.splice(i, 0, dragObj);
|
||||
} else {
|
||||
ar.splice(i + 1, 0, dragObj);
|
||||
}
|
||||
}
|
||||
gData.value = data;
|
||||
};
|
||||
const dataList: TreeProps['treeData'] = [];
|
||||
const generateList = (data: TreeProps['treeData']) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const node = data[i];
|
||||
const key = node.key;
|
||||
dataList.push({ key, title: key });
|
||||
if (node.children) {
|
||||
generateList(node.children);
|
||||
}
|
||||
}
|
||||
};
|
||||
generateList(genData);
|
||||
|
||||
const getParentKey = (
|
||||
key: string | number,
|
||||
tree: TreeProps['treeData'],
|
||||
): string | number | undefined => {
|
||||
let parentKey;
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
const node = tree[i];
|
||||
if (node.children) {
|
||||
if (node.children.some(item => item.key === key)) {
|
||||
parentKey = node.key;
|
||||
} else if (getParentKey(key, node.children)) {
|
||||
parentKey = getParentKey(key, node.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parentKey;
|
||||
};
|
||||
const expandedKeys = ref<(string | number)[]>([]);
|
||||
const autoExpandParent = ref<boolean>(true);
|
||||
|
||||
const onExpand = (keys: string[]) => {
|
||||
expandedKeys.value = keys;
|
||||
autoExpandParent.value = false;
|
||||
};
|
||||
|
||||
watch(selectTreeDataValue, value => {
|
||||
const expanded = dataList
|
||||
.map((item: TreeProps['treeData'][number]) => {
|
||||
if (item.title.indexOf(value) > -1) {
|
||||
return getParentKey(item.key, gData.value);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((item, i, self) => item && self.indexOf(item) === i);
|
||||
expandedKeys.value = expanded;
|
||||
selectTreeDataValue.value = value;
|
||||
autoExpandParent.value = true;
|
||||
});
|
||||
// 筛选树结构中的数据
|
||||
const onSearchTreeData = (selectTreeDataValue: string) => {
|
||||
console.log('use value', selectTreeDataValue);
|
||||
console.log('or use this.value', value.value);
|
||||
};
|
||||
// 点击新增树节点
|
||||
const addTreeNodeData = () => {
|
||||
treeNodeAdd.value = true;
|
||||
};
|
||||
const handleOk = (e: MouseEvent) => {
|
||||
console.log(e);
|
||||
treeNodeAdd.value = false;
|
||||
};
|
||||
const handleCancel = () => {
|
||||
treeNodeAdd.value = false;
|
||||
};
|
||||
// 企业树
|
||||
const getOrgTree = (params?) => {
|
||||
fetch(carbonEmissionFactorLibrary.getCarbonFactorTree, params).then((res) => {
|
||||
gData.value = res
|
||||
});
|
||||
};
|
||||
getOrgTree();
|
||||
|
||||
const onSearch = () => {
|
||||
console.log(searchValue.value);
|
||||
getOrgTree({ orgName: searchValue.value, orgId });
|
||||
};
|
||||
|
||||
const tableFetch = (params) => {
|
||||
console.log(params, 'sdfasfasdfasdfasdf');
|
||||
|
||||
tableConfig.value.params = {
|
||||
...mainRef.value.params,
|
||||
...params,
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
const handleSelect = (selectedKeys: any, info: any) => {
|
||||
fetch(carbonEmissionFactorLibrary.queryDeptTree, { orgId: info.node?.orgInfo.orgId }).then((res) => {
|
||||
treeData2.value = res.data;
|
||||
});
|
||||
tableFetch({ orgId: info.node?.orgInfo.orgId });
|
||||
};
|
||||
|
||||
|
||||
const onClose = () => {
|
||||
visible.value = false;
|
||||
formData.value = {};
|
||||
userAuthList.value.splice(0);
|
||||
};
|
||||
|
||||
const onEdit = () => {
|
||||
formRef.value?.triggerSubmit().then(() => {
|
||||
console.log(formData.value, 'formData.value');
|
||||
if (!userAuthList.value.length) {
|
||||
NsMessage.error('请添加用户权限');
|
||||
return;
|
||||
}
|
||||
|
||||
opMap.value.fuc &&
|
||||
opMap.value.fuc({ ...formData.value, userRoleList: userAuthList.value, orgId });
|
||||
});
|
||||
};
|
||||
|
||||
const tableConfig = ref({
|
||||
title: '数据库',
|
||||
api: carbonEmissionFactorLibrary.getTableList,
|
||||
params: {
|
||||
orgId,
|
||||
},
|
||||
headerActions: [
|
||||
{
|
||||
label: '新增',
|
||||
name: 'userAdd',
|
||||
type: 'primary',
|
||||
handle: () => {
|
||||
opMap.value.type = 'add';
|
||||
setTimeout(() => {
|
||||
formData.value = {
|
||||
// orgName: JSON.parse(sessionStorage.getItem('userInfo')).orgName,
|
||||
};
|
||||
userAuthList.value.splice(0);
|
||||
});
|
||||
opMap.value.fuc = (formData: any) => {
|
||||
return http.post(carbonEmissionFactorLibrary.addNewData, formData).then(() => {
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
visible.value = false;
|
||||
NsMessage.success('操作成功');
|
||||
});
|
||||
};
|
||||
visible.value = true;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '导入',
|
||||
type: 'primary',
|
||||
name: 'userImport',
|
||||
handle: () => {},
|
||||
},
|
||||
{
|
||||
label: '导出',
|
||||
type: 'primary',
|
||||
name: 'userExports',
|
||||
},
|
||||
{
|
||||
label: '批量删除',
|
||||
type: 'primary',
|
||||
name: 'userBatchDel',
|
||||
dynamicDisabled: (data: any) => {
|
||||
return data.list.length === 0;
|
||||
},
|
||||
confirm: true,
|
||||
isReload: true,
|
||||
isClearCheck: true,
|
||||
api: carbonEmissionFactorLibrary.batchDel,
|
||||
dynamicParams: { userIds: 'userId[]' },
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
title: 'id',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '排放源',
|
||||
dataIndex: 'emissionSources',
|
||||
},
|
||||
{
|
||||
title: '排放类型',
|
||||
dataIndex: 'emissionType',
|
||||
},
|
||||
{
|
||||
title: '排放气体',
|
||||
dataIndex: 'emissionGas',
|
||||
},
|
||||
{
|
||||
title: '排放环节',
|
||||
dataIndex: 'emissionProcess',
|
||||
},
|
||||
{
|
||||
title: '排放因子',
|
||||
dataIndex: 'emissionFactors',
|
||||
},
|
||||
{
|
||||
title: '排放因子单位',
|
||||
dataIndex: 'emissionFactorUnits',
|
||||
},
|
||||
{
|
||||
title: '数据来源',
|
||||
dataIndex: 'dataSources',
|
||||
},
|
||||
{
|
||||
title: '数据库',
|
||||
dataIndex: 'carbonDatabase',
|
||||
},
|
||||
{
|
||||
title: '参考文献',
|
||||
dataIndex: 'reference',
|
||||
},
|
||||
{
|
||||
title: '引用数量',
|
||||
dataIndex: 'numberOfReferences',
|
||||
},
|
||||
],
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
name: 'userEdit',
|
||||
handle: (record: any) => {
|
||||
userAuthList.value.splice(0);
|
||||
setTimeout(() => {
|
||||
formData.value = record;
|
||||
userAuthList.value.push(...record.userRoleInfos);
|
||||
}, 10);
|
||||
opMap.value.type = 'edit';
|
||||
opMap.value.fuc = (formData: any) => {
|
||||
return http.post(carbonEmissionFactorLibrary.editUser, formData).then(() => {
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
visible.value = false;
|
||||
NsMessage.success('操作成功');
|
||||
});
|
||||
};
|
||||
visible.value = true;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
name: 'userDelete',
|
||||
dynamicParams: 'userId',
|
||||
confirm: true,
|
||||
isReload: true,
|
||||
api: carbonEmissionFactorLibrary.del,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'emissionSources',
|
||||
label: '排放源',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入排放源',
|
||||
maxLength: 30,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'userStatus',
|
||||
label: '排放环节',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择排放环节',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'userStatus',
|
||||
label: '排放气体',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择排放气体',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'userStatus',
|
||||
label: '数据库名称',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请选择数据库名称',
|
||||
options: [
|
||||
{
|
||||
label: '正常',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'accountNo',
|
||||
label: '文献关键字',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入文献关键字',
|
||||
maxLength: 30,
|
||||
},
|
||||
},
|
||||
],
|
||||
params: {},
|
||||
},
|
||||
// pagination: { defaultPageSize: 10 },
|
||||
rowKey: 'userId',
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
background-color: @ns-content-bg;
|
||||
display: flex;
|
||||
}
|
||||
.left {
|
||||
width: 300px;
|
||||
// max-height: calc(100vh - 96px);
|
||||
margin-right: @ns-gap;
|
||||
min-width: fit-content;
|
||||
> div {
|
||||
border-radius: @ns-border-radius;
|
||||
background-color: @white;
|
||||
// box-shadow: @ns-content-box-shadow;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.top{
|
||||
position: relative;
|
||||
.addTreeNode{
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.top {
|
||||
overflow: auto;
|
||||
// height: 50%;
|
||||
// border-bottom: 5px solid rgb(229, 235, 240);
|
||||
// overflow-y: auto;
|
||||
}
|
||||
.ns-form-title{
|
||||
font-weight: bold;
|
||||
user-select: text;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { ref } from 'vue';
|
||||
import { origanizemanage } from '/@/api/origanizemanage';
|
||||
import { http } from '/nerv-lib/saas';
|
||||
|
||||
export const mockData = ref([
|
||||
{
|
||||
id: 3,
|
||||
zhanghao: 'axb',
|
||||
name: '张三',
|
||||
sex: '男',
|
||||
phone: '123456789',
|
||||
email: '1234567889',
|
||||
relation: '1',
|
||||
role: '1',
|
||||
status: '1',
|
||||
},
|
||||
]);
|
||||
|
||||
export const mockData2 = ref([
|
||||
{
|
||||
information: '铁路局1/产品部1/产品总监1',
|
||||
},
|
||||
]);
|
||||
|
||||
export const treeData = ref([
|
||||
{
|
||||
title: '铁路总局',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{ title: '济阳站', key: '0-0-0' },
|
||||
{ title: '临沂站', key: '0-0-1' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
export const treeData2 = [
|
||||
{
|
||||
title: '全部',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{ title: '产品部', key: '0-0-0' },
|
||||
{ title: '运维部', key: '0-0-1' },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,105 @@
|
||||
import { dateUtil } from '/nerv-lib/util/date-util';
|
||||
import data from './mock.json';
|
||||
export const tableConfig = {
|
||||
title: '设备台账',
|
||||
// api: '/carbon_emission/device/getDeviceList',
|
||||
value: data.dataSource,
|
||||
params: {
|
||||
page: 0,
|
||||
pageSize: 10,
|
||||
},
|
||||
rowSelection: null,
|
||||
columns: [
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'id',
|
||||
},
|
||||
{
|
||||
title: '设备型号',
|
||||
dataIndex: 'deviceCode',
|
||||
},
|
||||
{
|
||||
title: 'SN码',
|
||||
dataIndex: 'deviceName',
|
||||
textNumber: 8,
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '设备一级区域',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备二级区域',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备详细位置',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备规格',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备厂商纳税人识别号',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '厂商联系人',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备描述',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: 'IP地址',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '生产日期',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '采购日期',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '启用日期',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备成本(元)',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '使用期限',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '额定功率',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '特殊参数',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
],
|
||||
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'createTime',
|
||||
label: '生产日期',
|
||||
component: 'NsRangePicker',
|
||||
fieldMap: ['queryStartDate', 'queryEndDate'],
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
},
|
||||
},
|
||||
],
|
||||
params: {},
|
||||
},
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'uuid',
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="能耗统计">
|
||||
<ns-view-list-table v-bind="tableConfig" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="碳排统计" force-render>Content of Tab Pane 2</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="碳排速算">Content of Tab Pane 3</a-tab-pane>
|
||||
</a-tabs>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { tableConfig } from './config';
|
||||
defineOptions({
|
||||
name: 'CarbonEmissionStatisticsIndex', // 与页面路由name一致缓存才可生效
|
||||
});
|
||||
const activeKey = ref('1');
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
{
|
||||
"data":[
|
||||
{
|
||||
"title": "家居照明",
|
||||
"key": "1",
|
||||
"children": [
|
||||
{
|
||||
"title": "灯泡",
|
||||
"key": "1-1",
|
||||
"children": [
|
||||
{
|
||||
"title": "LED灯泡",
|
||||
"key": "1-1-1",
|
||||
"children": [
|
||||
{
|
||||
"title": "E27 LED灯泡",
|
||||
"key": "1-1-1-1",
|
||||
"attr": {
|
||||
"瓦特": "7W",
|
||||
"光通量": "500lm",
|
||||
"色温": "2700K"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "E14 小灯泡",
|
||||
"key": "1-1-1-2",
|
||||
"attr": {
|
||||
"瓦特": "4W",
|
||||
"光通量": "250lm",
|
||||
"色温": "6500K"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "节能灯",
|
||||
"key": "1-1-2",
|
||||
"children": [
|
||||
{
|
||||
"title": "E27 节能灯泡",
|
||||
"key": "1-1-2-1",
|
||||
"attr": {
|
||||
"瓦特": "11W",
|
||||
"光通量": "800lm",
|
||||
"色温": "6500K"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "灯具",
|
||||
"key": "1-2",
|
||||
"children": [
|
||||
{
|
||||
"title": "吊灯",
|
||||
"key": "1-2-1",
|
||||
"children": [
|
||||
{
|
||||
"title": "水晶吊灯",
|
||||
"key": "1-2-1-1",
|
||||
"attr": {
|
||||
"尺寸": "Φ60cm",
|
||||
"适用面积": "15-20㎡"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "现代简约吊灯",
|
||||
"key": "1-2-1-2",
|
||||
"attr": {
|
||||
"尺寸": "Φ52cm",
|
||||
"适用面积": "10-15㎡"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "台灯",
|
||||
"key": "1-2-2",
|
||||
"children": [
|
||||
{
|
||||
"title": "护眼台灯",
|
||||
"key": "1-2-2-1",
|
||||
"attr": {
|
||||
"瓦特": "18W",
|
||||
"调光调色": "是"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "折叠臂台灯",
|
||||
"key": "1-2-2-2",
|
||||
"attr": {
|
||||
"瓦特": "14W",
|
||||
"调光调色": "否"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "开关插座",
|
||||
"key": "1-3",
|
||||
"children": [
|
||||
{
|
||||
"title": "智能开关",
|
||||
"key": "1-3-1",
|
||||
"children": [
|
||||
{
|
||||
"title": "触控式智能开关",
|
||||
"key": "1-3-1-1",
|
||||
"attr": {
|
||||
"控制方式": "触控/远程",
|
||||
"兼容性": "ZigBee/WiFi"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "插座",
|
||||
"key": "1-3-2",
|
||||
"children": [
|
||||
{
|
||||
"title": "多功能插座",
|
||||
"key": "1-3-2-1",
|
||||
"attr": {
|
||||
"插孔类型": "2/3插",
|
||||
"USB接口": "有"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "电梯",
|
||||
"key": "3",
|
||||
"children": [
|
||||
{
|
||||
"title": "扶梯",
|
||||
"key": "301"
|
||||
},
|
||||
{
|
||||
"title": "直梯",
|
||||
"key": "302"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "冷源源",
|
||||
"key": "4",
|
||||
"children": [
|
||||
{
|
||||
"title": "通风及空调设备",
|
||||
"key": "5",
|
||||
"children": [
|
||||
{
|
||||
"title": "组合式空调机组",
|
||||
"key": "501"
|
||||
},
|
||||
{
|
||||
"title": "新风机组",
|
||||
"key": "502"
|
||||
},
|
||||
{
|
||||
"title": "精密空调",
|
||||
"key": "503"
|
||||
},
|
||||
{
|
||||
"title": "风机盘管",
|
||||
"key": "504"
|
||||
},
|
||||
{
|
||||
"title": "VAV",
|
||||
"key": "505"
|
||||
},
|
||||
{
|
||||
"title": "室外多联机",
|
||||
"key": "506"
|
||||
},
|
||||
{
|
||||
"title": "风幕机",
|
||||
"key": "507"
|
||||
},
|
||||
{
|
||||
"title": "球喷",
|
||||
"key": "508"
|
||||
},
|
||||
{
|
||||
"title": "送风机",
|
||||
"key": "509"
|
||||
},
|
||||
{
|
||||
"title": "排风机",
|
||||
"key": "510"
|
||||
},
|
||||
{
|
||||
"title": "排风兼排烟机",
|
||||
"key": "511"
|
||||
},
|
||||
{
|
||||
"title": "通风机",
|
||||
"key": "512"
|
||||
},
|
||||
{
|
||||
"title": "风阀",
|
||||
"key": "513"
|
||||
},
|
||||
{
|
||||
"title": "风柱式空调",
|
||||
"key": "514"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "照明",
|
||||
"key": "6",
|
||||
"children": [
|
||||
{
|
||||
"title": "多功能传感器",
|
||||
"key": "701"
|
||||
},
|
||||
{
|
||||
"title": "照度传感器",
|
||||
"key": "702"
|
||||
},
|
||||
{
|
||||
"title": "噪声传感器",
|
||||
"key": "703"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dataSource":[
|
||||
{
|
||||
"id": "d4",
|
||||
"isDel": "0",
|
||||
"officesId": "84",
|
||||
"deviceCode": "37430200143",
|
||||
"deviceName": "地听测试电表",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "1",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "",
|
||||
"types": "",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": "84566",
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "cupidatat nisi ea ad",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": null,
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null
|
||||
},
|
||||
{
|
||||
"id": "d1",
|
||||
"isDel": "0",
|
||||
"officesId": "84",
|
||||
"deviceCode": "37430200144",
|
||||
"deviceName": "地听测试2",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "1",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "",
|
||||
"types": "",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": "84566",
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "802",
|
||||
"ip": "10.5.36.0",
|
||||
"port": "6000",
|
||||
"com": "",
|
||||
"slaveAddress": "123测试",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": "2024-02-28 11:26:58",
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null
|
||||
},
|
||||
{
|
||||
"id": "d2",
|
||||
"isDel": "0",
|
||||
"officesId": "84",
|
||||
"deviceCode": "1235623",
|
||||
"deviceName": "测试设备2",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "是",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "",
|
||||
"types": "",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": null,
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "cupidatat nisi ea ad",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": "2024-02-28 11:31:57",
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null
|
||||
},
|
||||
{
|
||||
"id": "d7",
|
||||
"isDel": "0",
|
||||
"officesId": "",
|
||||
"deviceCode": "0213",
|
||||
"deviceName": "测试",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "1",
|
||||
"serialNumber": "",
|
||||
"pidCode": null,
|
||||
"brand": "6da085e5-956d-4000-bd3c-ebb01a9c99a1",
|
||||
"types": "d7a8aede-b821-4ff2-953d-601a20e5a948",
|
||||
"manufacturer": "",
|
||||
"contacts": "",
|
||||
"phonenumber": null,
|
||||
"position": "",
|
||||
"activeState": "",
|
||||
"measurementDirection": "",
|
||||
"deviceMagnification": null,
|
||||
"deviceAccuracy": null,
|
||||
"frequency": "",
|
||||
"standardFrequency": "",
|
||||
"deviceHead": "",
|
||||
"constructor": "",
|
||||
"voltageType": "",
|
||||
"pt": null,
|
||||
"ct": null,
|
||||
"communicationProtocol": "",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "1",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "",
|
||||
"insertTime": "2024-03-14 20:01:53",
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": ""
|
||||
},
|
||||
{
|
||||
"id": "d3",
|
||||
"isDel": "0",
|
||||
"officesId": "84",
|
||||
"deviceCode": "81",
|
||||
"deviceName": "设备名称1111",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "1",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "6da085e5-956d-4000-bd3c-ebb01a9c99a1",
|
||||
"types": "d7a8aede-b821-4ff2-953d-601a20e5a948",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": "84566",
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "cupidatat nisi ea ad",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": "2024-03-15 17:34:24",
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null
|
||||
},
|
||||
{
|
||||
"id": "d43fdfff_02_0001",
|
||||
"isDel": "0",
|
||||
"officesId": "843fdffff213d2d3",
|
||||
"deviceCode": "00037430200143",
|
||||
"deviceName": "应感者酸严",
|
||||
"category": "1",
|
||||
"type": "1001",
|
||||
"energyCount": "esse consequat",
|
||||
"serialNumber": "69",
|
||||
"pidCode": null,
|
||||
"brand": "",
|
||||
"types": "",
|
||||
"manufacturer": "elit non in",
|
||||
"contacts": "ad reprehenderit",
|
||||
"phonenumber": "34",
|
||||
"position": "in esse commodo",
|
||||
"activeState": "1",
|
||||
"measurementDirection": "1",
|
||||
"deviceMagnification": 62,
|
||||
"deviceAccuracy": "89",
|
||||
"frequency": "anim consequat irure",
|
||||
"standardFrequency": "ut elit",
|
||||
"deviceHead": "pariatur ex velit",
|
||||
"constructor": "84566",
|
||||
"voltageType": "cillum aliquip reprehenderit",
|
||||
"pt": 61,
|
||||
"ct": 64,
|
||||
"communicationProtocol": "cupidatat nisi ea ad",
|
||||
"ip": "",
|
||||
"port": "",
|
||||
"com": "",
|
||||
"slaveAddress": "",
|
||||
"dlt": "",
|
||||
"conversionIdentifier": "48",
|
||||
"multiplicationAdjustment": "1",
|
||||
"accessMethod": "1",
|
||||
"replacementFrequency": "0",
|
||||
"dataDetail": "sit",
|
||||
"insertTime": "2024-04-29 11:12:43",
|
||||
"children": null,
|
||||
"devicePointList": null,
|
||||
"insertUser": null
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
// 页面容器
|
||||
.lighting-box {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
position: relative;
|
||||
// background: linear-gradient(#badaff, #8cabeb, #7095de);
|
||||
.drawer-box {
|
||||
width: 30px;
|
||||
height: 40px;
|
||||
border-radius: 2px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
background: rgba(0, 0 ,0 ,0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
.drawer-icon {
|
||||
|
||||
}
|
||||
}
|
||||
// 照明设备功能总容器
|
||||
.lighting-img-box {
|
||||
position: relative;
|
||||
width: 1280px;
|
||||
height: 720px;
|
||||
user-select: none;
|
||||
background-image: url(../image/bg.jpg);
|
||||
// 由于背景是俯视图,会产生有交点的透视效果,故使用透视属性
|
||||
perspective: 1000px;
|
||||
perspective-origin: 850px -160px;
|
||||
// 左上角区域切换功能
|
||||
.btn-box {
|
||||
width: 120px;
|
||||
position: sticky;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
.btn-item {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
background: rgba(39, 120, 255, 1);
|
||||
border: 1px solid rgba(51, 199, 255, 1);
|
||||
box-shadow: 0px 10px 15px rgba(0, 54, 136, 0.3);
|
||||
font-size: 18px;
|
||||
color: white;
|
||||
}
|
||||
.btn-item:hover {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
// 大区分区
|
||||
.area{
|
||||
position: absolute;
|
||||
bottom: 170px;
|
||||
left: 240px;
|
||||
width: 780px;
|
||||
height: 240px;
|
||||
transform: rotateX(79deg) rotateZ(-22deg) skew(29deg);
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
.area1 {
|
||||
width: 170px;
|
||||
background: rgba(0, 251, 91, 0.3);
|
||||
border: 2px solid rgb(0, 251, 91);
|
||||
display: flex;
|
||||
}
|
||||
.area2 {
|
||||
width: 240px;
|
||||
background: rgba(255, 165, 0, 0.3);
|
||||
border: 2px solid rgb(255, 165, 0);
|
||||
display: flex;
|
||||
}
|
||||
.area3 {
|
||||
width: 110px;
|
||||
background: rgba(255, 0, 0, 0.3);
|
||||
border: 2px solid rgb(255, 0, 0);
|
||||
}
|
||||
.area4 {
|
||||
flex: 1;
|
||||
background: rgba(80, 236, 244, 0.3);
|
||||
border: 2px solid rgb(80, 236, 244);
|
||||
}
|
||||
.area-item:hover {
|
||||
border:2px solid white;
|
||||
}
|
||||
.area-item {
|
||||
cursor: pointer;
|
||||
transition: all ease 0.2s;
|
||||
>.light-group {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display:flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.group-shadow1 {
|
||||
width: 35px;
|
||||
height: 150px;
|
||||
border-radius: 20px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.group-shadow2 {
|
||||
width: 35px;
|
||||
height: 180px;
|
||||
border-radius: 20px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.group-shadow3 {
|
||||
width: 40px;
|
||||
height: 180px;
|
||||
border-radius: 20px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.group-shadow4 {
|
||||
width: 40px;
|
||||
height: 160px;
|
||||
border-radius: 20px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
.group-shadow {
|
||||
transition: all ease 0.2s;
|
||||
}
|
||||
.group-shadow:hover {
|
||||
border: 2px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ns-content-main {
|
||||
position: relative;
|
||||
// 抽屉伸缩按钮
|
||||
.drawer-box {
|
||||
width: 30px;
|
||||
height: 40px;
|
||||
border-radius: 2px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
background: rgba(0, 0 ,0 ,0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
.drawer-icon {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<a-popover color="rgba(0, 0, 0, 0.8)">
|
||||
<template #content>
|
||||
<div class="light-tag">
|
||||
<div class="light-tag-tit">
|
||||
<div>
|
||||
<img src="/asset/image//bulbLogo/21962.png" alt="" />
|
||||
<span class="tag-text">{{ result.name }}</span>
|
||||
</div>
|
||||
<button class="right-button">{{ type == 1 ? '正常' : '关闭' }}</button>
|
||||
</div>
|
||||
<div class="light-tag-box">
|
||||
<div class="tag-box-item">
|
||||
<img src="/asset/image//bulbLogo/22496.png" alt="" />
|
||||
<span class="title">控制模式</span>
|
||||
<span class="result">自动</span>
|
||||
</div>
|
||||
<div class="tag-box-item">
|
||||
<img src="/asset/image//bulbLogo/22496.png" alt="" />
|
||||
<span class="title">亮度</span>
|
||||
<span class="result">{{ result.brightness }}</span>
|
||||
</div>
|
||||
<div class="tag-box-item">
|
||||
<img src="/asset/image//bulbLogo/22496.png" alt="" />
|
||||
<span class="title">控制场景</span>
|
||||
<span class="result">{{ result.automatic2 }}</span>
|
||||
</div>
|
||||
<div class="tag-box-item">
|
||||
<img src="/asset/image//bulbLogo/22496.png" alt="" />
|
||||
<span class="title">色温</span>
|
||||
<span class="result">{{ result.brightness3 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="icon-box" :style="styleObject">
|
||||
<img v-if="type == 1" class="icon-item" src="/asset/image/bulbLogo/22394.png" alt="">
|
||||
<img v-if="type == 2" class="icon-item" src="/asset/image/bulbLogo/22396.png" alt="">
|
||||
<img v-if="type == 3" class="icon-item" src="/asset/image/bulbLogo/22400.png" alt="">
|
||||
</div>
|
||||
</a-popover>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
defineProps({
|
||||
styleObject: Object,
|
||||
type: Number
|
||||
});
|
||||
|
||||
const result = ref({
|
||||
id: '1',
|
||||
name: '站厅照明 1区',
|
||||
manual: '手动',
|
||||
automatic: '自动',
|
||||
brightness: '100lux',
|
||||
brightness2: '30lux',
|
||||
manual2: '手动',
|
||||
automatic2: '舒适',
|
||||
brightness3: '4000k',
|
||||
brightness4: '3800k',
|
||||
});
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.icon-box {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
.icon-item {
|
||||
width: 25px;
|
||||
cursor: pointer;
|
||||
transition: all ease 0.1s;
|
||||
}
|
||||
.icon-item:active {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
// 悬浮窗外部
|
||||
.light-tag {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
// 悬浮窗标题
|
||||
.light-tag-tit {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
vertical-align: middle;
|
||||
height: 30px;
|
||||
.tag-text {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.right-button {
|
||||
width: 50px;
|
||||
height: 26px;
|
||||
background: rgba(57, 215, 187, 0.1);
|
||||
border: 1px solid rgba(57, 215, 187, 1);
|
||||
font-size: 12px;
|
||||
color: rgba(57, 215, 187, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 悬浮窗底部4格子
|
||||
.light-tag-box {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
.tag-box-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
img {
|
||||
width: 120px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.title {
|
||||
position: absolute;
|
||||
left: 60px;
|
||||
top: 13px;
|
||||
color: rgba(64, 255, 252, 1);
|
||||
}
|
||||
.result {
|
||||
line-height: 50px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
};
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -62,7 +62,12 @@ const mockData = ref(data.listData);
|
||||
export const formSchema = [
|
||||
{
|
||||
field: 'isCreate',
|
||||
component: 'NsInput',
|
||||
component: 'NsCheck',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'isCreatSon',
|
||||
component: 'NsCheck',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
@@ -71,7 +76,12 @@ export const formSchema = [
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'isCreatSon',
|
||||
field: 'id',
|
||||
component: 'NsInput',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'pid',
|
||||
component: 'NsInput',
|
||||
show: false,
|
||||
},
|
||||
@@ -95,10 +105,10 @@ export const formSchema = [
|
||||
component: 'NsSelectApi',
|
||||
componentProps: {
|
||||
placeholder: '请选择节点类型(必填)',
|
||||
api: dict,
|
||||
params: { dicKey: 'COUNT_POINT' },
|
||||
api: () => dict({ params: { dicKey: 'COUNT_POINT' } }),
|
||||
// params: { dicKey: 'COUNT_POINT' },
|
||||
immediate: true,
|
||||
resultField: 'data.COUNT_POINT',
|
||||
// resultField: 'data.COUNT_POINT',
|
||||
labelField: 'cnValue',
|
||||
valueField: 'cnValue',
|
||||
},
|
||||
@@ -118,6 +128,7 @@ export const treeConfig = (orgId) => {
|
||||
title: '能耗分组',
|
||||
},
|
||||
params: { orgId },
|
||||
showLine: { showLeafIcon: false },
|
||||
api: group.queryDeviceGroupTree,
|
||||
// api: () => {
|
||||
// return new Promise((resolve) => {
|
||||
@@ -127,7 +138,7 @@ export const treeConfig = (orgId) => {
|
||||
// });
|
||||
// },
|
||||
transform: (data) => {
|
||||
return [{ title: '全部', key: 'all', selectable: false, children: data }];
|
||||
return [{ pointName: '全部', id: 'all', selectable: false, children: data }];
|
||||
},
|
||||
formConfig: {
|
||||
schemas: [
|
||||
@@ -137,10 +148,10 @@ export const treeConfig = (orgId) => {
|
||||
component: 'NsSelectApi',
|
||||
autoSubmit: true,
|
||||
componentProps: {
|
||||
api: dict,
|
||||
params: { dicKey: 'ENERGY_TYPE' },
|
||||
api: () => dict({ params: { dicKey: 'ENERGY_TYPE' } }),
|
||||
// params: { dicKey: 'ENERGY_TYPE' },
|
||||
immediate: true,
|
||||
resultField: 'data.ENERGY_TYPE',
|
||||
// resultField: 'data.ENERGY_TYPE',
|
||||
labelField: 'cnValue',
|
||||
valueField: 'cnValue',
|
||||
placeholder: '请选择能耗种类',
|
||||
|
||||
@@ -10,20 +10,25 @@
|
||||
<NsModalFrom ref="modalFormRef" v-bind="nsModalFormConfig" />
|
||||
<div class="groupContainer">
|
||||
<div class="tree">
|
||||
<ns-tree-api v-bind="tConfig" @select="handleSelect">
|
||||
<ns-tree-api ref="treeRef" v-bind="tConfig" @select="handleSelect">
|
||||
<template #title="data">
|
||||
<div class="treeRow">
|
||||
<span>{{ data.title }}</span>
|
||||
<div>
|
||||
<ns-icon :name="data.pointType !== '计算节点' ? 'fenzujiedian' : 'jisuanjiedian'" />
|
||||
<span style="padding-left: 8px">{{ data.pointName }}</span>
|
||||
</div>
|
||||
<a-dropdown>
|
||||
<ns-icon name="actionMore" size="14" class="actionMore" />
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item
|
||||
v-for="(item, index) in actionList"
|
||||
:key="index"
|
||||
@click="item.func(data)">
|
||||
<span>{{ item.title }}</span>
|
||||
</a-menu-item>
|
||||
<template v-for="(item, index) in actionList" :key="index">
|
||||
<!-- 全部节点只需要新增子节点 -->
|
||||
<a-menu-item
|
||||
v-if="data.id !== 'all' || item.key === 'addNodeSon'"
|
||||
@click="item.func(data)">
|
||||
<span>{{ item.title }}</span>
|
||||
</a-menu-item>
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
@@ -45,6 +50,7 @@
|
||||
import { NsMessage, NsModal } from '/nerv-lib/component';
|
||||
import NsModalFrom from '/@/components/ns-modal-form.vue';
|
||||
import { group } from '/@/api/deviceManage';
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
|
||||
type opType = 'up' | 'down';
|
||||
const { getParams } = useParams();
|
||||
@@ -52,6 +58,7 @@
|
||||
const editDrawerRef = ref();
|
||||
const editGroupRef = ref();
|
||||
const editFormulaRef = ref();
|
||||
const treeRef = ref();
|
||||
const defaultType = ref(true);
|
||||
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
|
||||
const config = tableConfig(editDrawerRef, editGroupRef, editFormulaRef);
|
||||
@@ -65,6 +72,9 @@
|
||||
extraModalConfig: {
|
||||
bodyStyle: { paddingBottom: 0 },
|
||||
},
|
||||
success: () => {
|
||||
treeRef.value?.treeReload();
|
||||
},
|
||||
});
|
||||
nextTick(() => {
|
||||
console.log(modalFormRef.value, 'modal');
|
||||
@@ -74,30 +84,35 @@
|
||||
console.log(data);
|
||||
nsModalFormConfig.value.title = '新增';
|
||||
nsModalFormConfig.value.data = {
|
||||
pointName: '新增',
|
||||
isCreate: true,
|
||||
isCreatSon: false,
|
||||
orgId: result,
|
||||
};
|
||||
if (data.id !== 'all') {
|
||||
nsModalFormConfig.value.data.pid = data.id;
|
||||
nsModalFormConfig.value.data.isCreatSon = true;
|
||||
}
|
||||
modalFormRef.value?.toggle();
|
||||
};
|
||||
const editNode = (data) => {
|
||||
console.log(data);
|
||||
nsModalFormConfig.value.title = '编辑';
|
||||
nsModalFormConfig.value.data = { pointName: 123 };
|
||||
nsModalFormConfig.value.data = data;
|
||||
modalFormRef.value?.toggle();
|
||||
|
||||
data.value = { pointName: 'qwe' };
|
||||
};
|
||||
const moveNode = (data, type: opType) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
const deleteNode = (a) => {
|
||||
const deleteNode = (record) => {
|
||||
NsModal.confirm({
|
||||
centered: true,
|
||||
title: '提示',
|
||||
content: '确定删除吗?',
|
||||
onOk: () => {
|
||||
console.log(a);
|
||||
http.post(group.del, { id: record.id }).then(() => {
|
||||
treeRef.value?.treeReload();
|
||||
NsMessage.success('删除成功');
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
180
hx-ai-intelligent/src/view/monitor/deviceMonitor/config.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import { dateUtil } from '/nerv-lib/util/date-util';
|
||||
import data from './mock.json';
|
||||
export const tableConfig = {
|
||||
title: '设备台账',
|
||||
// api: '/carbon_emission/device/getDeviceList',
|
||||
value: data.dataSource,
|
||||
treeConfig: {
|
||||
header: {
|
||||
icon: 'orgLink',
|
||||
title: '设备类别',
|
||||
},
|
||||
defaultExpandAll: true,
|
||||
api: () => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(data);
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'name',
|
||||
label: '设备名称',
|
||||
component: 'NsInput',
|
||||
autoSubmit: true,
|
||||
componentProps: {
|
||||
placeholder: '请输入',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
params: {
|
||||
page: 0,
|
||||
pageSize: 10,
|
||||
},
|
||||
rowSelection: null,
|
||||
columns: [
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'id',
|
||||
},
|
||||
{
|
||||
title: '设备型号',
|
||||
dataIndex: 'deviceCode',
|
||||
},
|
||||
{
|
||||
title: 'SN码',
|
||||
dataIndex: 'deviceName',
|
||||
textNumber: 8,
|
||||
textEllipsis: true,
|
||||
},
|
||||
{
|
||||
title: '设备一级区域',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备二级区域',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备详细位置',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备规格',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备厂商纳税人识别号',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '厂商联系人',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备描述',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: 'IP地址',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '生产日期',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '采购日期',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '启用日期',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '设备成本(元)',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '使用期限',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '额定功率',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
{
|
||||
title: '特殊参数',
|
||||
dataIndex: 'position',
|
||||
},
|
||||
],
|
||||
|
||||
formConfig: {
|
||||
schemas: [
|
||||
{
|
||||
field: 'name',
|
||||
label: '设备名称',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'provider',
|
||||
label: '设备厂商',
|
||||
component: 'NsInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'payWay',
|
||||
label: '设备区域',
|
||||
component: 'NsSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择',
|
||||
options: [
|
||||
{
|
||||
label: '全部',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
label: '生产日期',
|
||||
component: 'NsRangePicker',
|
||||
fieldMap: ['queryStartDate', 'queryEndDate'],
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'createTime1',
|
||||
label: '采购日期',
|
||||
component: 'NsRangePicker',
|
||||
fieldMap: ['queryStartDate', 'queryEndDate'],
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'createTime2',
|
||||
label: '启用日期',
|
||||
component: 'NsRangePicker',
|
||||
fieldMap: ['queryStartDate', 'queryEndDate'],
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
},
|
||||
},
|
||||
],
|
||||
params: {},
|
||||
},
|
||||
// pagination: { pageSizeOptions: false },
|
||||
rowKey: 'uuid',
|
||||
};
|
||||
136
hx-ai-intelligent/src/view/monitor/deviceMonitor/graph/index.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div ref="graphChart" style="width: 100%; height: 80%"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref, watch } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { inject } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
name: 'Graph',
|
||||
|
||||
setup() {
|
||||
let data = ref<any[]>([]);
|
||||
interface PageData {
|
||||
tableList: any[];
|
||||
tableColumns: any[];
|
||||
graphList: any[];
|
||||
}
|
||||
const pageData = inject<PageData>('pageData');
|
||||
|
||||
if (!pageData) {
|
||||
throw new Error('pageData is not provided');
|
||||
}
|
||||
// 监听 pageData 的变化
|
||||
watch(
|
||||
() => pageData as PageData,
|
||||
(_newValue, _oldValue) => {
|
||||
// 执行你的逻辑代码
|
||||
draw();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
const graphChart = ref(null);
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
|
||||
const draw = () => {
|
||||
data.value = pageData.graphList;
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose();
|
||||
}
|
||||
chartInstance = echarts.init(graphChart.value);
|
||||
|
||||
var seriesList = [];
|
||||
var date = [];
|
||||
var legendList: string | any[] = [];
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
date.push(data.value[i].date);
|
||||
|
||||
for (let j = 0; j < data.value[i].data.length; j++) {
|
||||
if (seriesList.length < j + 1) {
|
||||
seriesList.push({
|
||||
name: data.value[i].data[j].name,
|
||||
data: [data.value[i].data[j].value],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
});
|
||||
} else {
|
||||
seriesList[j].data.push(data.value[i].data[j].value);
|
||||
}
|
||||
if (legendList.length == 0 || legendList.length < j + 1) {
|
||||
legendList.push(data.value[i].data[j].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
const option = {
|
||||
legend: {
|
||||
data: legendList,
|
||||
orient: 'horizontal',
|
||||
bottom: 30,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params: any) => {
|
||||
const date = params[0].name;
|
||||
const values = params
|
||||
.map((param: any) => {
|
||||
const unit = data.value.find((d) => d.date === date)?.unit || '';
|
||||
return `<tr>
|
||||
<td>${param.marker}${param.seriesName}</td>
|
||||
<td style="text-align: right;">${param.value} ${unit}</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join('');
|
||||
return `<div>${date}</div><table style="width: 100%;">${values}</table>`;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: date,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
height: 10,
|
||||
start: 0,
|
||||
end: 100,
|
||||
handleSize: '300%', // 设置滑块的大小
|
||||
bottom: 15,
|
||||
},
|
||||
],
|
||||
series: seriesList,
|
||||
};
|
||||
|
||||
chartInstance = echarts.init(graphChart.value);
|
||||
chartInstance.setOption(option);
|
||||
};
|
||||
onMounted(() => {
|
||||
draw();
|
||||
});
|
||||
// 下载图表
|
||||
const downloadChart = () => {
|
||||
if (chartInstance) {
|
||||
const base64 = chartInstance.getDataURL({
|
||||
type: 'png',
|
||||
backgroundColor: '#fff',
|
||||
});
|
||||
const link = document.createElement('a');
|
||||
link.href = base64;
|
||||
link.download = 'chart.png';
|
||||
link.click();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
draw,
|
||||
graphChart,
|
||||
downloadChart,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
19
hx-ai-intelligent/src/view/monitor/deviceMonitor/index.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- eslint-disable vue/multi-word-component-names -->
|
||||
<template>
|
||||
<page />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, provide } from 'vue';
|
||||
import page from './page.vue';
|
||||
|
||||
// 创建一个响应式对象
|
||||
const pageData = reactive({
|
||||
tableList: [],
|
||||
tableColumns: [],
|
||||
graphList: [],
|
||||
});
|
||||
|
||||
// 使用 provide 函数来提供这个响应式对象
|
||||
provide('pageData', pageData);
|
||||
</script>
|
||||
81
hx-ai-intelligent/src/view/monitor/deviceMonitor/page.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<!-- eslint-disable vue/multi-word-component-names -->
|
||||
<template>
|
||||
<a-row type="flex">
|
||||
<a-col :span="4">
|
||||
<div style="padding: 0 20px; width: 100%; height: 100%">
|
||||
<tree ref="treeRef" />
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="20">
|
||||
<div style="width: 100%; height: 100%">
|
||||
<div class="ns-right-title">
|
||||
<span>历史数据</span>
|
||||
<div class="button">
|
||||
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" />
|
||||
<ns-icon :name="iconName" size="18" style="margin-right: 10px" @click="change" />
|
||||
</div>
|
||||
</div>
|
||||
<graph ref="graphRef" v-if="isGraph" />
|
||||
<environment-table ref="tableRef" v-else />
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import tree from './tree/index.vue';
|
||||
import graph from './graph/index.vue';
|
||||
import environmentTable from './table/index.vue';
|
||||
|
||||
const iconName = ref('biaoge');
|
||||
|
||||
const treeRef = ref();
|
||||
const graphRef = ref();
|
||||
const tableRef = ref();
|
||||
|
||||
let isGraph = ref(true);
|
||||
|
||||
defineOptions({
|
||||
name: 'EnvironmentMonitorIndex', // 与页面路由name一致缓存才可生效
|
||||
});
|
||||
|
||||
const downloadChart = () => {
|
||||
if (isGraph.value) {
|
||||
if (graphRef.value) {
|
||||
graphRef.value.downloadChart();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function change() {
|
||||
isGraph.value = !isGraph.value;
|
||||
if (iconName.value == 'biaoge') {
|
||||
iconName.value = 'bingtu';
|
||||
} else {
|
||||
iconName.value = 'biaoge';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ns-right-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
user-select: text;
|
||||
margin-bottom: 5px;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
|
||||
> span {
|
||||
padding-left: 10px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
}
|
||||
</style>
|
||||
179
hx-ai-intelligent/src/view/monitor/deviceMonitor/table/index.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<a-table :columns="columns" :data-source="data" bordered />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch, ref, onMounted } from 'vue';
|
||||
import type { TableColumnType } from 'ant-design-vue';
|
||||
import { inject } from 'vue';
|
||||
|
||||
// let data: any[] = [];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'EnvironmentTable',
|
||||
setup() {
|
||||
let data = ref<any[]>([]);
|
||||
let columns = ref<TableColumnType[]>([]);
|
||||
|
||||
interface PageData {
|
||||
tableList: any[];
|
||||
tableColumns: any[];
|
||||
graphList: any[];
|
||||
}
|
||||
const pageData = inject<PageData>('pageData');
|
||||
|
||||
if (!pageData) {
|
||||
throw new Error('pageData is not provided');
|
||||
}
|
||||
// 监听 pageData 的变化
|
||||
watch(
|
||||
() => pageData as PageData,
|
||||
(_newValue, _oldValue) => {
|
||||
data.value = pageData.tableList;
|
||||
|
||||
let columnA: any[] = [...column];
|
||||
columnA.push(...pageData.tableColumns);
|
||||
columns.value = columnA;
|
||||
// pageData.graphList;
|
||||
// 执行你的逻辑代码
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
const getRowSpan = (dataIndex: string, record: any, data: any, dependents: string[] = []) => {
|
||||
let rowSpan = 1;
|
||||
for (let i = data.indexOf(record) + 1; i < data.length; i++) {
|
||||
let shouldMerge = true;
|
||||
for (const dependent of dependents) {
|
||||
if (data[i][dependent] !== record[dependent]) {
|
||||
shouldMerge = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shouldMerge && data[i][dataIndex] === record[dataIndex]) {
|
||||
rowSpan++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rowSpan;
|
||||
};
|
||||
|
||||
const column: TableColumnType[] = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'key',
|
||||
customCell: (record, rowIndex) => {
|
||||
if (rowIndex == undefined) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
const rowSpan = getRowSpan('name', record, data.value);
|
||||
if (rowIndex != 0 && data.value[rowIndex - 1].key == record.key) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'name',
|
||||
customCell: (record, rowIndex) => {
|
||||
if (rowIndex == undefined) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
const rowSpan = getRowSpan('name', record, data.value);
|
||||
if (rowIndex != 0 && data.value[rowIndex - 1].name == record.name) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备点位',
|
||||
dataIndex: 'position',
|
||||
customCell: (record, rowIndex) => {
|
||||
if (rowIndex == undefined) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
const rowSpan = getRowSpan('position', record, data.value, ['name']);
|
||||
if (
|
||||
rowIndex != 0 &&
|
||||
data.value[rowIndex - 1].name == record.name &&
|
||||
data.value[rowIndex - 1].position == record.position
|
||||
) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '计量单位',
|
||||
dataIndex: 'unit',
|
||||
customCell: (record, rowIndex) => {
|
||||
if (rowIndex == undefined) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
const rowSpan = getRowSpan('unit', record, data.value, ['name', 'position']);
|
||||
if (
|
||||
rowIndex != 0 &&
|
||||
data.value[rowIndex - 1].name == record.name &&
|
||||
data.value[rowIndex - 1].position == record.position &&
|
||||
data.value[rowIndex - 1].unit == record.unit
|
||||
) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
data.value = pageData.tableList;
|
||||
|
||||
let columnA: any[] = [...column];
|
||||
columnA.push(...pageData.tableColumns);
|
||||
columns.value = columnA;
|
||||
});
|
||||
return {
|
||||
data,
|
||||
column,
|
||||
columns,
|
||||
pageData,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
573
hx-ai-intelligent/src/view/monitor/deviceMonitor/tree/index.vue
Normal file
@@ -0,0 +1,573 @@
|
||||
<!-- eslint-disable vue/v-on-event-hyphenation -->
|
||||
<template>
|
||||
<div class="parent-container">
|
||||
<div class="ns-tree-title">
|
||||
<span>设备列表</span>
|
||||
</div>
|
||||
<a-tree-select
|
||||
v-model:value="value"
|
||||
style="width: 100%"
|
||||
:tree-line="treeLine && { showLeafIcon }"
|
||||
:tree-data="treeData1"
|
||||
@change="">
|
||||
<!-- <template #title="{ value: val, title }">
|
||||
<b v-if="val === 'parent 1-1'" style="color: #08c">sss</b>
|
||||
<template v-else>{{ title }}</template>
|
||||
</template> -->
|
||||
</a-tree-select>
|
||||
|
||||
<a-tree
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
checkable
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:tree-data="treeData2">
|
||||
<!-- <template #title="{ title, key }">
|
||||
<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
|
||||
<template v-else>{{ title }}</template>
|
||||
</template> -->
|
||||
</a-tree>
|
||||
|
||||
<div class="fixed-bottom">
|
||||
<a-divider />
|
||||
<a-select
|
||||
ref="select"
|
||||
v-model:value="selectedValue"
|
||||
placeholder="请选择点位"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:options="options1" />
|
||||
<a-select
|
||||
v-model:value="frequencyValue"
|
||||
placeholder="请选择频率"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:options="options2" />
|
||||
<a-range-picker
|
||||
:value="hackValue || dateRange"
|
||||
:disabled-date="disabledDate"
|
||||
@change="onChange"
|
||||
@openChange="onOpenChange"
|
||||
@calendarChange="onCalendarChange"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:placeholder="['请选择日期', '请选择日期']" />
|
||||
<a-button type="primary" style="width: 100%; margin-bottom: 10px" @click="getSelect">
|
||||
查询
|
||||
</a-button>
|
||||
<a-button type="primary" style="width: 100%; margin-bottom: 10px" @click="getSelect11">
|
||||
模拟不同数据查询
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { TreeSelectProps, TreeProps, SelectProps } from 'ant-design-vue';
|
||||
import { defineComponent, ref, onMounted } from 'vue';
|
||||
import { Dayjs } from 'dayjs';
|
||||
import { inject } from 'vue';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { device } from '/@/api/deviceManage';
|
||||
// import { device } from '/@/api/deviceManage';
|
||||
|
||||
const treeData2: TreeProps['treeData'] = [
|
||||
{
|
||||
title: 'AC_001(总电表)',
|
||||
key: '1',
|
||||
children: [
|
||||
{
|
||||
title: 'AC_002(暖通电表)',
|
||||
key: '2',
|
||||
},
|
||||
{
|
||||
title: 'AC_003(照明电表)',
|
||||
key: '3',
|
||||
},
|
||||
{
|
||||
title: 'AC_004(给排水电表)',
|
||||
key: '4',
|
||||
},
|
||||
{
|
||||
title: 'AC_005(通风电表)',
|
||||
key: '5',
|
||||
},
|
||||
{
|
||||
title: 'AC_006(电动门电表)',
|
||||
key: '6',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
name: 'Tree',
|
||||
setup() {
|
||||
const treeLine = ref(true);
|
||||
const showLeafIcon = ref(false);
|
||||
const value = ref<string>();
|
||||
|
||||
const orgId = ref('');
|
||||
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
|
||||
orgId.value = result;
|
||||
|
||||
const treeData1 = ref<TreeSelectProps['treeData']>([
|
||||
{
|
||||
title: '3.电梯',
|
||||
value: '3',
|
||||
children: [
|
||||
{
|
||||
title: '301.扶梯',
|
||||
value: '301',
|
||||
},
|
||||
{
|
||||
title: '302.直梯',
|
||||
value: '302',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '4.冷热源',
|
||||
value: '4',
|
||||
children: [
|
||||
{
|
||||
title: '401.冷水机组',
|
||||
value: '401',
|
||||
},
|
||||
{
|
||||
title: '402.热泵机组',
|
||||
value: '402',
|
||||
},
|
||||
{
|
||||
title: '403.锅炉',
|
||||
value: '403',
|
||||
},
|
||||
{
|
||||
title: '404.水处理机组',
|
||||
value: '404',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
http.post(device.queryDeviceTree, { orgId: orgId.value }).then((res) => {
|
||||
treeData1.value = formatTreeData(res.data);
|
||||
});
|
||||
|
||||
const formatTreeData = (data) => {
|
||||
return data.map((item) => ({
|
||||
title: item.code + '.' + item.deviceType,
|
||||
value: item.id,
|
||||
children: item.children ? formatTreeData(item.children) : [],
|
||||
}));
|
||||
};
|
||||
|
||||
const expandedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||
const selectedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||
const checkedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||
|
||||
const options1 = ref<SelectProps['options']>([]);
|
||||
const options2 = ref<SelectProps['options']>([
|
||||
{
|
||||
value: '1',
|
||||
label: '5分钟',
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '10分钟',
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: '30分钟',
|
||||
},
|
||||
{
|
||||
value: '4',
|
||||
label: '1小时',
|
||||
},
|
||||
]);
|
||||
const selectedValue = ref<string | undefined>();
|
||||
const frequencyValue = ref<string | undefined>();
|
||||
const dateRange = ref<[Dayjs, Dayjs] | undefined>();
|
||||
|
||||
const getDianWeiList = () => {
|
||||
console.log('getDianWeiList 被调用');
|
||||
options1.value = [
|
||||
{ value: '1', label: 'A 项电压' },
|
||||
{ value: '2', label: 'B 项电压' },
|
||||
{ value: '3', label: 'C 项电压' },
|
||||
{ value: '4', label: 'AB 线电压' },
|
||||
{ value: '5', label: 'BC 线电压' },
|
||||
{ value: '6', label: 'A 项电流' },
|
||||
{ value: '7', label: 'B 项电流' },
|
||||
];
|
||||
};
|
||||
|
||||
interface PageData {
|
||||
tableList: any[];
|
||||
tableColumns: any[];
|
||||
graphList: any[];
|
||||
}
|
||||
const pageData = inject<PageData>('pageData');
|
||||
if (!pageData) {
|
||||
throw new Error('pageData is not provided');
|
||||
}
|
||||
// 查询数据后放入pageData
|
||||
const getSelect = () => {
|
||||
pageData.tableList = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'AC_002(暖通电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '1',
|
||||
name: 'AC_002(暖通电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'AC_003(照明电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'AC_003(照明电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'AC_004(给排水电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
];
|
||||
pageData.tableColumns = [
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
},
|
||||
{
|
||||
title: '1:00',
|
||||
dataIndex: '1:00',
|
||||
},
|
||||
];
|
||||
pageData.graphList = [
|
||||
{
|
||||
date: '2023-12-01 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '21',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '36',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '5',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-02 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '26',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '25',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '47',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-03 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '18',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '22',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '26',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-04 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '40',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '15',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '12',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-05 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '15',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '18',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '15',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-06 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '15',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '18',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '15',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
// 测试查询 模拟不同数据
|
||||
const getSelect11 = () => {
|
||||
pageData.tableList = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'AC_002(暖通电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
'2:00': '2222',
|
||||
},
|
||||
{
|
||||
key: '1',
|
||||
name: 'AC_002(暖通电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
'2:00': '2222',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'AC_003(照明电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
'2:00': '2222',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'AC_003(照明电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
'2:00': '2222',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'AC_004(给排水电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
'2:00': '2222',
|
||||
},
|
||||
];
|
||||
pageData.tableColumns = [
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
},
|
||||
{
|
||||
title: '1:00',
|
||||
dataIndex: '1:00',
|
||||
},
|
||||
{
|
||||
title: '2:00',
|
||||
dataIndex: '2:00',
|
||||
},
|
||||
];
|
||||
pageData.graphList = [
|
||||
{
|
||||
date: '2023-12-01 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '21',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '36',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '5',
|
||||
},
|
||||
{
|
||||
name: 'AC_005(1111111)',
|
||||
value: '14',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-02 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '26',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '25',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '47',
|
||||
},
|
||||
{
|
||||
name: 'AC_005(1111111)',
|
||||
value: '28',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
type RangeValue = [Dayjs, Dayjs];
|
||||
const dates = ref<RangeValue>();
|
||||
const hackValue = ref<RangeValue>();
|
||||
|
||||
const onChange = (val: RangeValue) => {
|
||||
dateRange.value = val;
|
||||
};
|
||||
const onOpenChange = (open: boolean) => {
|
||||
if (open) {
|
||||
dates.value = [] as any;
|
||||
hackValue.value = [] as any;
|
||||
} else {
|
||||
hackValue.value = undefined;
|
||||
}
|
||||
};
|
||||
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 onCalendarChange = (val: RangeValue) => {
|
||||
dates.value = val;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDianWeiList();
|
||||
});
|
||||
|
||||
// const dateFormat = 'YYYY-MM-DD';
|
||||
|
||||
return {
|
||||
treeLine,
|
||||
showLeafIcon,
|
||||
value,
|
||||
treeData1,
|
||||
treeData2,
|
||||
expandedKeys,
|
||||
selectedKeys,
|
||||
checkedKeys,
|
||||
options1,
|
||||
options2,
|
||||
selectedValue,
|
||||
frequencyValue,
|
||||
dateRange,
|
||||
getDianWeiList,
|
||||
getSelect,
|
||||
getSelect11,
|
||||
disabledDate,
|
||||
onCalendarChange,
|
||||
onOpenChange,
|
||||
onChange,
|
||||
hackValue,
|
||||
pageData,
|
||||
};
|
||||
},
|
||||
});
|
||||
</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>
|
||||
@@ -0,0 +1,206 @@
|
||||
<template>
|
||||
<div ref="graphGraphchart" style="width: 100%; height: 80%"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const data = [
|
||||
{
|
||||
date: '2023-12-01 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '21',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '36',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '5',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-02 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '26',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '25',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '47',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-03 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '18',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '22',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '26',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-04 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '40',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '15',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '12',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2023-12-05 0:00',
|
||||
unit: 'V',
|
||||
data: [
|
||||
{
|
||||
name: 'AC_002(暖通电表)',
|
||||
value: '15',
|
||||
},
|
||||
{
|
||||
name: 'AC_003(照明电表)',
|
||||
value: '18',
|
||||
},
|
||||
{
|
||||
name: 'AC_004(给排水电表)',
|
||||
value: '15',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'GraphGraph',
|
||||
setup() {
|
||||
const graphGraphchart = ref(null);
|
||||
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
onMounted(() => {
|
||||
chartInstance = echarts.init(graphGraphchart.value);
|
||||
var seriesList = [];
|
||||
var date = [];
|
||||
var legendList: string | any[] = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
date.push(data[i].date);
|
||||
|
||||
for (let j = 0; j < data[i].data.length; j++) {
|
||||
if (seriesList.length < j + 1) {
|
||||
seriesList.push({
|
||||
name: data[i].data[j].name,
|
||||
data: [data[i].data[j].value],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
});
|
||||
} else {
|
||||
seriesList[j].data.push(data[i].data[j].value);
|
||||
}
|
||||
if (legendList.length == 0 || legendList.length < j + 1) {
|
||||
legendList.push(data[i].data[j].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
const option = {
|
||||
legend: {
|
||||
data: legendList,
|
||||
orient: 'horizontal',
|
||||
bottom: 0,
|
||||
left: 60,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params: any) => {
|
||||
const date = params[0].name;
|
||||
const values = params
|
||||
.map((param: any) => {
|
||||
const unit = data.find((d) => d.date === date)?.unit || '';
|
||||
return `<tr>
|
||||
<td>${param.marker}${param.seriesName}</td>
|
||||
<td style="text-align: right;">${param.value} ${unit}</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join('');
|
||||
return `<div>${date}</div><table style="width: 100%;">${values}</table>`;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: date,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
// dataZoom: [
|
||||
// {
|
||||
// height: 10,
|
||||
// start: 0,
|
||||
// end: 100,
|
||||
// handleSize: '300%', // 设置滑块的大小
|
||||
// bottom: 15,
|
||||
// },
|
||||
// ],
|
||||
// toolbox: {
|
||||
// show: true,
|
||||
// feature: {
|
||||
// mark: { show: true },
|
||||
// saveAsImage: { show: true },
|
||||
// },
|
||||
// },
|
||||
series: seriesList,
|
||||
};
|
||||
|
||||
chartInstance = echarts.init(graphGraphchart.value);
|
||||
chartInstance.setOption(option);
|
||||
});
|
||||
|
||||
// 下载图表
|
||||
const downloadChart = () => {
|
||||
if (chartInstance) {
|
||||
const base64 = chartInstance.getDataURL({
|
||||
type: 'png',
|
||||
backgroundColor: '#fff',
|
||||
});
|
||||
const link = document.createElement('a');
|
||||
link.href = base64;
|
||||
link.download = 'chart.png';
|
||||
link.click();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
graphGraphchart,
|
||||
downloadChart,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
88
hx-ai-intelligent/src/view/monitor/energyMonitor/index.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<!-- eslint-disable vue/multi-word-component-names -->
|
||||
<template>
|
||||
<a-tabs v-model:activeKey="activeKey" style="height: 8%">
|
||||
<a-tab-pane key="1" tab="图表" />
|
||||
<a-tab-pane key="2" tab="分析" />
|
||||
</a-tabs>
|
||||
<a-row type="flex" style="height: 92%">
|
||||
<a-col :span="4">
|
||||
<div style="padding: 0 20px; width: 100%; height: 100%">
|
||||
<tree ref="treeRef" />
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="20">
|
||||
<div style="width: 100%; height: 100%">
|
||||
<div class="ns-right-title">
|
||||
<span>统计数据</span>
|
||||
<div class="button">
|
||||
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" />
|
||||
<ns-icon :name="iconName" size="18" style="margin-right: 10px" @click="change" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="activeKey == '1'" style="height: 90%">
|
||||
<graph-graph ref="graphRef" v-if="isGraph" />
|
||||
<environment-table ref="tableRef" v-else />
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import tree from './tree/index.vue';
|
||||
import graphGraph from './graphGraph/index.vue';
|
||||
import environmentTable from './table/index.vue';
|
||||
|
||||
const iconName = ref('biaoge');
|
||||
|
||||
const treeRef = ref();
|
||||
const graphRef = ref();
|
||||
const tableRef = ref();
|
||||
|
||||
let isGraph = ref(true);
|
||||
const activeKey = ref('1');
|
||||
|
||||
defineOptions({
|
||||
name: 'EnvironmentMonitorIndex', // 与页面路由name一致缓存才可生效
|
||||
});
|
||||
|
||||
const downloadChart = () => {
|
||||
if (activeKey.value == '1' && isGraph) {
|
||||
if (graphRef.value) {
|
||||
graphRef.value.downloadChart();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function change() {
|
||||
isGraph.value = !isGraph.value;
|
||||
if (iconName.value == 'biaoge') {
|
||||
iconName.value = 'bingtu';
|
||||
} else {
|
||||
iconName.value = 'biaoge';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ns-right-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
user-select: text;
|
||||
margin-bottom: 5px;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
|
||||
> span {
|
||||
padding-left: 10px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
}
|
||||
</style>
|
||||
166
hx-ai-intelligent/src/view/monitor/energyMonitor/table/index.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<a-table :columns="columns" :data-source="data" bordered />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import type { TableColumnType } from 'ant-design-vue';
|
||||
|
||||
const data = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'AC_002(暖通电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '1',
|
||||
name: 'AC_002(暖通电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'AC_003(照明电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'AC_003(照明电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'AC_004(给排水电表)',
|
||||
position: 'A 相电压',
|
||||
unit: 'V',
|
||||
date: '2023-12-01',
|
||||
'1:00': '3626',
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'EnvironmentTable',
|
||||
setup() {
|
||||
const getRowSpan = (dataIndex: string, record, data, dependents: string[] = []) => {
|
||||
let rowSpan = 1;
|
||||
for (let i = data.indexOf(record) + 1; i < data.length; i++) {
|
||||
let shouldMerge = true;
|
||||
for (const dependent of dependents) {
|
||||
if (data[i][dependent] !== record[dependent]) {
|
||||
shouldMerge = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shouldMerge && data[i][dataIndex] === record[dataIndex]) {
|
||||
rowSpan++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rowSpan;
|
||||
};
|
||||
|
||||
const columns: TableColumnType[] = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'key',
|
||||
customCell: (record, rowIndex) => {
|
||||
const rowSpan = getRowSpan('name', record, data);
|
||||
if (rowIndex != 0 && data[rowIndex - 1].key == record.key) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'name',
|
||||
customCell: (record, rowIndex) => {
|
||||
const rowSpan = getRowSpan('name', record, data);
|
||||
if (rowIndex != 0 && data[rowIndex - 1].name == record.name) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备点位',
|
||||
dataIndex: 'position',
|
||||
customCell: (record, rowIndex) => {
|
||||
const rowSpan = getRowSpan('position', record, data, ['name']);
|
||||
if (
|
||||
rowIndex != 0 &&
|
||||
data[rowIndex - 1].name == record.name &&
|
||||
data[rowIndex - 1].position == record.position
|
||||
) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '计量单位',
|
||||
dataIndex: 'unit',
|
||||
customCell: (record, rowIndex) => {
|
||||
const rowSpan = getRowSpan('unit', record, data, ['name', 'position']);
|
||||
if (
|
||||
rowIndex != 0 &&
|
||||
data[rowIndex - 1].name == record.name &&
|
||||
data[rowIndex - 1].position == record.position &&
|
||||
data[rowIndex - 1].unit == record.unit
|
||||
) {
|
||||
return {
|
||||
rowSpan: 0,
|
||||
colSpan: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
rowSpan: rowSpan,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
},
|
||||
{
|
||||
title: '1:00',
|
||||
dataIndex: '1:00',
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
330
hx-ai-intelligent/src/view/monitor/energyMonitor/tree/index.vue
Normal file
@@ -0,0 +1,330 @@
|
||||
<!-- eslint-disable vue/v-on-event-hyphenation -->
|
||||
<template>
|
||||
<div class="parent-container">
|
||||
<div class="ns-tree-title">
|
||||
<span>数据点位</span>
|
||||
</div>
|
||||
<!-- <a-tree-select
|
||||
v-model:value="value"
|
||||
style="width: 100%"
|
||||
|
||||
:tree-line="treeLine && { showLeafIcon }"
|
||||
:tree-data="treeData1"
|
||||
>
|
||||
</a-tree-select> -->
|
||||
<a-select
|
||||
ref="select"
|
||||
v-model:value="selectedValue"
|
||||
placeholder="请选择能耗类型"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:options="options1" />
|
||||
|
||||
<a-radio-group
|
||||
v-model:value="mode"
|
||||
@change="changeMode"
|
||||
style="padding-bottom: 10px; width: 100%">
|
||||
<a-radio-button value="1" style="width: 50%; text-align: center">设备</a-radio-button>
|
||||
<a-radio-button value="2" style="width: 50%; text-align: center">节点</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-input v-model:value="value" placeholder="请输入设备名称" v-if="mode == '1'" />
|
||||
<a-input v-model:value="value" placeholder="请输入节点名称" v-else />
|
||||
<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" />
|
||||
|
||||
<div class="fixed-bottom">
|
||||
<a-divider />
|
||||
<a-select
|
||||
v-model:value="frequencyValue"
|
||||
placeholder="请选择采集频率"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:options="options2" />
|
||||
<a-range-picker
|
||||
:value="hackValue || dateRange"
|
||||
:disabled-date="disabledDate"
|
||||
@change="onChange"
|
||||
@openChange="onOpenChange"
|
||||
@calendarChange="onCalendarChange"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
:placeholder="['请选择日期', '请选择日期']" />
|
||||
<a-button type="primary" style="width: 100%; margin-bottom: 10px" @click="getSelect"
|
||||
>查询</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { TreeSelectProps, TreeProps, SelectProps } from 'ant-design-vue';
|
||||
import { defineComponent, ref, onMounted } from 'vue';
|
||||
import { Dayjs } from 'dayjs';
|
||||
|
||||
export default defineComponent({
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
name: 'Tree',
|
||||
setup() {
|
||||
// const treeLine = ref(true);
|
||||
// const showLeafIcon = ref(false);
|
||||
const value = ref<string>();
|
||||
|
||||
const treeData1 = ref<TreeSelectProps['treeData']>([
|
||||
{
|
||||
title: '3.电梯',
|
||||
value: '3',
|
||||
children: [
|
||||
{
|
||||
title: '301.扶梯',
|
||||
value: '301',
|
||||
},
|
||||
{
|
||||
title: '302.直梯',
|
||||
value: '302',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '4.冷热源',
|
||||
value: '4',
|
||||
children: [
|
||||
{
|
||||
title: '401.冷水机组',
|
||||
value: '401',
|
||||
},
|
||||
{
|
||||
title: '402.热泵机组',
|
||||
value: '402',
|
||||
},
|
||||
{
|
||||
title: '403.锅炉',
|
||||
value: '403',
|
||||
},
|
||||
{
|
||||
title: '404.水处理机组',
|
||||
value: '404',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const expandedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||
const selectedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||
const checkedKeys = ref<string[]>(['0-0-0', '0-0-1']);
|
||||
|
||||
const options1 = ref<SelectProps['options']>([]);
|
||||
const options2 = ref<SelectProps['options']>([
|
||||
{
|
||||
value: '1',
|
||||
label: '5分钟',
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '10分钟',
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: '30分钟',
|
||||
},
|
||||
{
|
||||
value: '4',
|
||||
label: '1小时',
|
||||
},
|
||||
]);
|
||||
const mode = ref<String>('1');
|
||||
const selectedValue = ref<string | undefined>();
|
||||
const frequencyValue = ref<string | undefined>();
|
||||
const dateRange = ref<[Dayjs, Dayjs] | undefined>();
|
||||
|
||||
const getDianWeiList = () => {
|
||||
console.log('getDianWeiList 被调用');
|
||||
options1.value = [
|
||||
{ value: '1', label: '用电量' },
|
||||
{ value: '2', label: '用水量' },
|
||||
{ value: '3', label: '碳排量' },
|
||||
{ value: '4', label: '标煤量' },
|
||||
];
|
||||
};
|
||||
|
||||
const getSelect = () => {};
|
||||
|
||||
const treeData2 = ref<TreeProps['treeData']>([]);
|
||||
const changeMode = () => {
|
||||
if (mode.value == '1') {
|
||||
treeData2.value = [
|
||||
{
|
||||
title: 'AC_001(总电表)',
|
||||
key: '101',
|
||||
children: [
|
||||
{
|
||||
title: 'AC_002(暖通电表)',
|
||||
key: '102',
|
||||
},
|
||||
{
|
||||
title: 'AC_003(照明电表)',
|
||||
key: '103',
|
||||
},
|
||||
{
|
||||
title: 'AC_004(给排水电表)',
|
||||
key: '104',
|
||||
},
|
||||
{
|
||||
title: 'AC_005(通风电表)',
|
||||
key: '105',
|
||||
},
|
||||
{
|
||||
title: 'AC_006(电动门电表)',
|
||||
key: '106',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
} else {
|
||||
treeData2.value = [
|
||||
{
|
||||
title: '功能分项',
|
||||
key: '1',
|
||||
children: [
|
||||
{
|
||||
title: '照明',
|
||||
key: '2',
|
||||
children: [
|
||||
{
|
||||
title: '站台照明',
|
||||
key: '3',
|
||||
},
|
||||
{
|
||||
title: '站厅照明',
|
||||
key: '4',
|
||||
},
|
||||
{
|
||||
title: '应急照明',
|
||||
key: '5',
|
||||
},
|
||||
{
|
||||
title: '广告照明',
|
||||
key: '6',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '暖通',
|
||||
key: '7',
|
||||
},
|
||||
{
|
||||
title: '排放',
|
||||
key: '8',
|
||||
},
|
||||
{
|
||||
title: '给排水',
|
||||
key: '9',
|
||||
},
|
||||
{
|
||||
title: '光伏',
|
||||
key: '10',
|
||||
},
|
||||
{
|
||||
title: '电梯',
|
||||
key: '11',
|
||||
},
|
||||
{
|
||||
title: '电动门',
|
||||
key: '12',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
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 onChange = (val: RangeValue) => {
|
||||
dateRange.value = val;
|
||||
};
|
||||
|
||||
const onCalendarChange = (val: RangeValue) => {
|
||||
dates.value = val;
|
||||
};
|
||||
onMounted(() => {
|
||||
getDianWeiList();
|
||||
changeMode();
|
||||
});
|
||||
|
||||
// const dateFormat = 'YYYY-MM-DD';
|
||||
|
||||
return {
|
||||
// treeLine,
|
||||
// showLeafIcon,
|
||||
value,
|
||||
treeData1,
|
||||
treeData2,
|
||||
expandedKeys,
|
||||
selectedKeys,
|
||||
checkedKeys,
|
||||
options1,
|
||||
options2,
|
||||
mode,
|
||||
selectedValue,
|
||||
frequencyValue,
|
||||
dateRange,
|
||||
getDianWeiList,
|
||||
getSelect,
|
||||
changeMode,
|
||||
disabledDate,
|
||||
onCalendarChange,
|
||||
onOpenChange,
|
||||
onChange,
|
||||
hackValue,
|
||||
};
|
||||
},
|
||||
});
|
||||
</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>
|
||||
@@ -26,6 +26,7 @@
|
||||
</div>
|
||||
<a-drawer
|
||||
:width="500"
|
||||
title=" "
|
||||
:visible="visible"
|
||||
:body-style="{ paddingBottom: '80px' }"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
@@ -545,7 +546,8 @@
|
||||
{
|
||||
label: '新增',
|
||||
name: 'userAdd',
|
||||
type: 'primary',
|
||||
style: { marginBottom: '16px' },
|
||||
// type: 'primary',
|
||||
handle: () => {
|
||||
addformvisible.value = true;
|
||||
},
|
||||
@@ -644,6 +646,9 @@
|
||||
:deep(.ns-table-main) {
|
||||
border-top: 0;
|
||||
padding: 0;
|
||||
.drawerTable {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
ref="formElRef"
|
||||
:model="formModel">
|
||||
<div v-if="showAction && showExpandAll" class="ns-form-title ns-title-extra-box">
|
||||
<span>查询</span>
|
||||
<span> {{ title ? title : '查询' }}</span>
|
||||
<a-button type="link" class="ns-operate-expand" @click="expandAll = !expandAll">
|
||||
<template v-if="expandAll">
|
||||
收起筛选
|
||||
@@ -107,6 +107,7 @@
|
||||
const isInitDefaultValueRef = ref(false);
|
||||
const expandRef = ref(props.expand);
|
||||
const expandAll = ref(props.expandAll);
|
||||
const title = ref(props.title);
|
||||
const formModel = computed(() => {
|
||||
return props.model;
|
||||
});
|
||||
@@ -315,6 +316,7 @@
|
||||
splitNumber,
|
||||
finish,
|
||||
expandAll,
|
||||
title,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18,4 +18,5 @@ export const formProps = {
|
||||
// 收起全部
|
||||
expandAll: PropTypes.bool.def(true), // 默认是否全部展开
|
||||
showExpandAll: PropTypes.bool.def(true), // 是否展示右上角的全部收起展开
|
||||
title: PropTypes.bool.def(false), // 是否展示右上角的全部收起展开
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
:expand="expand"
|
||||
:showExpand="showExpand"
|
||||
:expandAll="expandAll"
|
||||
:title="formConfig.title"
|
||||
:showExpandAll="showExpandAll"
|
||||
:model="formModel"
|
||||
@finish="formFinish" />
|
||||
|
||||
@@ -105,6 +105,11 @@
|
||||
};
|
||||
|
||||
getData();
|
||||
const treeReload = (params) => {
|
||||
getData(params);
|
||||
};
|
||||
|
||||
defineExpose({ treeReload });
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@gap: 16px;
|
||||
|
||||