zhaohy 4 months ago
parent
commit
0214356cbb
  1. 3
      hx-ai-intelligent/src/api/carbonEmissionFactorLibrary.ts
  2. 2
      hx-ai-intelligent/src/api/deviceManage.ts
  3. 3
      hx-ai-intelligent/src/config/app.config.ts
  4. 4
      hx-ai-intelligent/src/icon/common.svg
  5. 38
      hx-ai-intelligent/src/router/monitor.ts
  6. 148
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionFactorLibrary/index.vue
  7. 42
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/config.ts
  8. 401
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index copy.vue
  9. 567
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index.vue
  10. 141
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/dialogStyle.less
  11. 1104
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/index.less
  12. 156
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs.less
  13. 50
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs.vue
  14. 15
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs1.vue
  15. 415
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs1.vue
  16. 216
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs2.vue
  17. 255
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs3.vue
  18. 73
      hx-ai-intelligent/src/view/equipmentManage/group/config.ts
  19. 2
      hx-ai-intelligent/src/view/equipmentManage/group/editCal.vue
  20. 18
      hx-ai-intelligent/src/view/equipmentManage/group/editGroup.vue
  21. 27
      hx-ai-intelligent/src/view/equipmentManage/group/index.vue
  22. 44
      hx-ai-intelligent/src/view/equipmentManage/ledger/config.ts
  23. 506
      hx-ai-intelligent/src/view/equipmentManage/ledger/mock.json
  24. 44
      hx-ai-intelligent/src/view/monitor/energyMonitor/analysisGraph/index.vue
  25. 627
      hx-ai-intelligent/src/view/monitor/environmentMonitor/aggregateData/index.vue
  26. 24
      hx-ai-intelligent/src/view/monitor/environmentMonitor/index.vue
  27. 2
      lib/saas/view/system/login.vue

3
hx-ai-intelligent/src/api/carbonEmissionFactorLibrary.ts

@ -8,6 +8,9 @@ export enum carbonEmissionFactorLibrary {
getCarbonFactorTree = '/carbon-smart/api/carbon/emission/type/getCarbonFactorTree', getCarbonFactorTree = '/carbon-smart/api/carbon/emission/type/getCarbonFactorTree',
creat = '/carbon-smart/api/carbon/emission/type/creatOrUpdate', creat = '/carbon-smart/api/carbon/emission/type/creatOrUpdate',
delTreeNode = '/carbon-smart/api/carbon/emission/type/del', delTreeNode = '/carbon-smart/api/carbon/emission/type/del',
// 单位管理
dictionaryUnitManagement = '/carbon-smart/api/carbon/emission/factor/dictionaryUnitManagement',
findOutermost = '/carbon-smart/api/carbon/emission/factor/findOutermost',
} }
// 碳排管理-碳排统计接口 // 碳排管理-碳排统计接口
export enum energyConsumption { export enum energyConsumption {

2
hx-ai-intelligent/src/api/deviceManage.ts

@ -26,4 +26,6 @@ export enum group {
computeGroupNum = `${BASE_URL}/deviceGroup/computeGroupNum`, // 分组删除 computeGroupNum = `${BASE_URL}/deviceGroup/computeGroupNum`, // 分组删除
formula = `${BASE_URL}/deviceGroup/formula`, // 编辑公式 formula = `${BASE_URL}/deviceGroup/formula`, // 编辑公式
queryFormula = `${BASE_URL}/deviceGroup/queryFormula`, // 公式查询 queryFormula = `${BASE_URL}/deviceGroup/queryFormula`, // 公式查询
dropGroupFilter = `${BASE_URL}/deviceGroup/dropGroupFilter`, // 分组列表查询
dropGroupInfoFilter = `${BASE_URL}/deviceGroup/dropGroupInfoFilter`, // 计算列表查询
} }

3
hx-ai-intelligent/src/config/app.config.ts

@ -27,6 +27,7 @@ export const appConfig = {
themeConfig: { themeConfig: {
bgImageUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/login/background.png`, bgImageUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/login/background.png`,
logoLessUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/headerIcon.png`, logoLessUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/headerIcon.png`,
logoUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/headerIcon.png`,
}, },
// userCustomRouterGuard: (to, from, next, whiteNameList, authorizationStore, appConfig) => { // userCustomRouterGuard: (to, from, next, whiteNameList, authorizationStore, appConfig) => {
// console.log({ to, from, next, whiteNameList, authorizationStore, appConfig }, 'routeConfig'); // console.log({ to, from, next, whiteNameList, authorizationStore, appConfig }, 'routeConfig');
@ -102,7 +103,7 @@ export const appConfig = {
updatePassWordInfo: { updatePassWordInfo: {
title: '修改密码', title: '修改密码',
subtitle: 'huaxing平台', subtitle: 'huaxing平台',
api: '/api/web/objs/User/changePassword', api: '/carbon-smart/api/user/password',
}, },
// headerBellInfo: { // headerBellInfo: {
// isShow: true, // isShow: true,

4
hx-ai-intelligent/src/icon/common.svg

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14.3564453125" height="15.0081787109375" viewBox="0 0 14.3564453125 15.0081787109375" fill="none">
<path d="M14.1739 3.70025C14.1361 3.65398 14.0991 3.60771 14.0571 3.56927C13.9468 3.46744 13.8241 3.37991 13.6919 3.30873C11.7357 2.26657 9.78168 1.22155 7.82619 0.17939C7.65994 0.0891889 7.4793 0.0284937 7.2923 1.16683e-07L7.11007 0C6.6559 0.0904063 6.26508 0.352371 5.86004 0.565929C4.08665 1.49755 2.31626 2.43531 0.54908 3.37911C0.273361 3.52656 0.0597992 3.76005 0.0099678 4.11741C0.00854492 4.13022 0.00356293 4.14161 0 4.153L0 4.30463C0.0284805 4.46764 0.0761719 4.62212 0.177967 4.75167C0.213558 4.79581 0.247017 4.84208 0.287598 4.87839C0.395794 4.97306 0.505424 5.06418 0.63142 5.13181C2.60185 6.1818 4.56944 7.23606 6.54201 8.2825C6.70858 8.3722 6.88014 8.45904 7.07235 8.47755C7.2674 8.49749 7.45034 8.46118 7.62261 8.37006L13.6037 5.19445C13.6706 5.15815 13.7403 5.12754 13.803 5.08554C13.9902 4.96381 14.1653 4.82357 14.2636 4.60432C14.3063 4.51107 14.3248 4.405 14.3561 4.30463L14.3561 4.153C14.3248 3.98785 14.2764 3.82982 14.1732 3.70026L14.1739 3.70025ZM13.5004 6.55054C13.2896 6.50635 13.0699 6.53759 12.8797 6.63881C12.501 6.8424 12.1251 7.05525 11.7429 7.25386C10.2444 8.03264 8.74237 8.80714 7.24318 9.5845C7.20047 9.60585 7.16488 9.60941 7.12074 9.58663L1.61023 6.69862C1.3144 6.53849 0.971592 6.48783 0.642097 6.55553C0.300404 6.62601 0.0633507 6.9314 0.0156593 7.31936C0.0128059 7.34072 0.00497818 7.36207 0.000705719 7.38343L0.000705719 7.5799C0.0291786 7.73936 0.0768776 7.89027 0.173687 8.01983C0.266228 8.14156 0.373005 8.24264 0.501858 8.31098C2.51998 9.39372 4.53954 10.4779 6.5605 11.5549C6.72209 11.6404 6.89009 11.7258 7.07874 11.7422C7.2681 11.7592 7.44748 11.7251 7.61619 11.6375C9.69198 10.5626 11.7678 9.48912 13.8407 8.40922C14.1183 8.264 14.2771 8.00702 14.3397 7.68312C14.3461 7.65963 14.3504 7.63472 14.3561 7.61051L14.3561 7.42828C14.3369 7.36207 14.3248 7.2916 14.2998 7.22896C14.1532 6.83814 13.877 6.62387 13.5004 6.55126L13.5004 6.55054ZM13.5019 9.80944C13.2908 9.7652 13.0708 9.79644 12.8804 9.89771C12.496 10.1042 12.1159 10.3177 11.73 10.5199C10.238 11.2944 8.74591 12.0646 7.25386 12.8391C7.20773 12.8661 7.15042 12.8653 7.10508 12.837C5.27916 11.8774 3.45181 10.9207 1.62446 9.96106C1.35194 9.82084 1.04443 9.7632 0.739628 9.7952C0.383698 9.82367 0.108913 10.1049 0.0313225 10.495C0.0206451 10.5441 0.0099678 10.5918 0.000720978 10.6402L0.000720978 10.8366C0.0291862 10.9933 0.0754585 11.1427 0.168713 11.2709C0.26268 11.3983 0.373734 11.5008 0.507553 11.572C2.52355 12.654 4.54025 13.7361 6.55837 14.811C6.73064 14.9035 6.91217 14.9889 7.10935 15.0082L7.24888 15.0082C7.41069 14.9797 7.56661 14.9243 7.71016 14.8444C7.89952 14.7412 8.09955 14.6586 8.29104 14.559C10.1333 13.6008 11.9749 12.6412 13.8151 11.6823C14.107 11.53 14.2757 11.273 14.3412 10.9335L14.3561 10.868L14.3561 10.6857C14.3369 10.6195 14.3248 10.5491 14.2999 10.4864C14.1554 10.0949 13.8777 9.88134 13.5019 9.81015L13.5019 9.80944Z" fill="#4388FB" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

38
hx-ai-intelligent/src/router/monitor.ts

@ -5,25 +5,25 @@ const equipment = {
meta: { title: '监控中心', icon: 'jiankongzhongxin', index: 1 }, meta: { title: '监控中心', icon: 'jiankongzhongxin', index: 1 },
redirect: { name: 'EnvironmentMonitor' }, redirect: { name: 'EnvironmentMonitor' },
children: [ children: [
// { {
// path: 'environmentMonitor', path: 'environmentMonitor',
// name: 'EnvironmentMonitor', name: 'EnvironmentMonitor',
// meta: { title: '环境监测', hideChildren: true, icon: 'huanjingjiance' }, meta: { title: '环境监测', hideChildren: true, icon: 'huanjingjiance' },
// component: Base, component: Base,
// redirect: { name: 'EnvironmentMonitorIndex' }, redirect: { name: 'EnvironmentMonitorIndex' },
// children: [ children: [
// { {
// path: 'index', path: 'index',
// name: 'EnvironmentMonitorIndex', name: 'EnvironmentMonitorIndex',
// component: () => import('/@/view/monitor/environmentMonitor/index.vue'), component: () => import('/@/view/monitor/environmentMonitor/index.vue'),
// meta: { meta: {
// title: '环境监测', title: '环境监测',
// keepAlive: true, keepAlive: true,
// // backApi: [], // backApi: [],
// }, },
// }, },
// ], ],
// }, },
{ {
path: 'deviceMonitor', path: 'deviceMonitor',
name: 'DeviceMonitor', name: 'DeviceMonitor',

148
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionFactorLibrary/index.vue

@ -36,16 +36,17 @@
:expanded-keys="expandedKeys" :expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent" :auto-expand-parent="autoExpandParent"
@expand="onExpand"> @expand="onExpand">
<template #title="{ emissionName }"> <template #title="data">
<span v-if="emissionName && selectTreeDataValue && emissionName.indexOf(selectTreeDataValue) > -1"> <div class="treeRow">
{{ emissionName.substring(0, emissionName.indexOf(selectTreeDataValue)) }} <div>
<span v-if="data.emissionName && selectTreeDataValue && data.emissionName.indexOf(selectTreeDataValue) > -1">
{{ data.emissionName.substring(0, data.emissionName.indexOf(selectTreeDataValue)) }}
<span style="color: #f50" >{{ selectTreeDataValue }}</span> <span style="color: #f50" >{{ selectTreeDataValue }}</span>
{{ emissionName.substring(emissionName.indexOf(selectTreeDataValue) + selectTreeDataValue.length) }} {{ data.emissionName.substring(data.emissionName.indexOf(selectTreeDataValue) + selectTreeDataValue.length) }}
</span> </span>
<span v-else>{{ emissionName }}</span> <span v-else>{{ data.emissionName }}</span>
</template> </div>
</a-tree> <a-popover placement="rightTop" trigger="focus">
<a-popover v-if="showOperation" placement="rightTop" trigger="focus">
<template #content> <template #content>
<div style="display: flex;flex-direction: column;"> <div style="display: flex;flex-direction: column;">
<a-button type="text" @click="editTreeNodeData">编辑</a-button> <a-button type="text" @click="editTreeNodeData">编辑</a-button>
@ -55,8 +56,11 @@
<a-button type="text" @click="deleteTreeNode">删除</a-button> <a-button type="text" @click="deleteTreeNode">删除</a-button>
</div> </div>
</template> </template>
<MoreOutlined style="position: absolute;right: 0;top: 16%;font-size: 25px;cursor: pointer;" /> <MoreOutlined class="actionMore" />
</a-popover> </a-popover>
</div>
</template>
</a-tree>
<div class="addTreeNode"> <div class="addTreeNode">
<a-button type="primary" style="width:100%;" @click="addTreeNodeData">新增</a-button> <a-button type="primary" style="width:100%;" @click="addTreeNodeData">新增</a-button>
</div> </div>
@ -92,6 +96,66 @@
<a-button type="primary" @click="onEdit">确定</a-button> <a-button type="primary" @click="onEdit">确定</a-button>
</template> </template>
</a-drawer> </a-drawer>
<!-- 单位管理 -->
<a-drawer
:width="500"
:visible="unitManagement"
v-if="unitManagement"
:body-style="{ paddingBottom: '80px' }"
:footer-style="{ textAlign: 'right' }"
destroyOnClose
title="单位管理"
@close="closeUnitManag">
<div class="addButton">
<a-button type="primary">新增分组</a-button>
<a-button type="primary">新增单位</a-button>
</div>
<div class="treePart">
<div style="width: 100%;height: 7%;display: flex;justify-content: center;align-items: center;">
<a-select
ref="select"
:value="unitTreeParams.cnValue"
style="width: 96%"
placeholder="选择分组"
@change="handleChange"
>
<a-select-option v-for="(item, index) in groupData" :key="index" :value="item.cnValue">
{{ item.cnValue }}
</a-select-option>
</a-select>
</div>
<a-tree
:expandedKeys="unitExpandedKeys"
:selectedKeys="unitSelectedKeys"
:tree-data="unitTreeData"
v-if="unitTreeData && unitTreeData.length > 0"
>
<template #title="data">
<div class="treeRow">
<div>
<span>{{ data.cnValue }}</span>
</div>
<a-popover placement="rightTop" trigger="focus">
<template #content>
<div style="display: flex;flex-direction: column;">
<a-button type="text" @click="editTreeNodeData">编辑</a-button>
<a-button type="text" @click="addTreeNodeData">新增子节点</a-button>
<a-button type="text">上移</a-button>
<a-button type="text">下移</a-button>
<a-button type="text" @click="deleteTreeNode">删除</a-button>
</div>
</template>
<MoreOutlined class="actionMore" />
</a-popover>
</div>
</template>
</a-tree>
</div>
<template #footer>
<a-button style="margin-right: 8px" @click="closeUnitManag">取消</a-button>
<a-button type="primary" @click="onEdit">确定</a-button>
</template>
</a-drawer>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -116,6 +180,7 @@ import { log } from 'node:console';
let formData = ref({}); let formData = ref({});
const formRef = ref(); const formRef = ref();
const visible = ref(false); const visible = ref(false);
const unitManagement = ref(false);
const searchValue = ref<string>(''); const searchValue = ref<string>('');
const searchValue2 = ref<string>(''); const searchValue2 = ref<string>('');
const disabled = ref(false); const disabled = ref(false);
@ -428,7 +493,9 @@ import { log } from 'node:console';
formData.value = {}; formData.value = {};
userAuthList.value.splice(0); userAuthList.value.splice(0);
}; };
const closeUnitManag = () => {
unitManagement.value = false;
};
const onEdit = () => { const onEdit = () => {
formRef.value?.triggerSubmit().then(() => { formRef.value?.triggerSubmit().then(() => {
console.log(formData.value, 'formData.value'); console.log(formData.value, 'formData.value');
@ -497,6 +564,20 @@ import { log } from 'node:console';
api: carbonEmissionFactorLibrary.del, api: carbonEmissionFactorLibrary.del,
dynamicParams: { ids: 'id[]' }, dynamicParams: { ids: 'id[]' },
}, },
{
label: '单位管理',
type: 'primary',
name: 'userAdd',
handle: () => {
unitManagement.value = true,
fetch(carbonEmissionFactorLibrary.findOutermost).then((res) => {
groupData.value = res.data
});
fetch(carbonEmissionFactorLibrary.dictionaryUnitManagement, unitTreeParams.value).then((res) => {
unitTreeData.value = res.data
});
},
},
], ],
columns: [ columns: [
{ {
@ -679,6 +760,22 @@ import { log } from 'node:console';
// pagination: { defaultPageSize: 10 }, // pagination: { defaultPageSize: 10 },
rowKey: 'id', rowKey: 'id',
}); });
//
const unitExpandedKeys = ref<string[]>();
const unitSelectedKeys = ref<string[]>([]);
const unitTreeParams = ref({
grp: 'MEASUREMENT_UNIT'
})
const groupData = ref([])
const unitTreeData = ref<TreeProps['treeData']>(genData);
const handleChange = (value: string) => {
unitTreeParams.value.cnValue = value
fetch(carbonEmissionFactorLibrary.dictionaryUnitManagement, unitTreeParams.value).then((res) => {
unitTreeData.value = res.data
});
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.main { .main {
@ -696,7 +793,6 @@ import { log } from 'node:console';
// box-shadow: @ns-content-box-shadow; // box-shadow: @ns-content-box-shadow;
flex: 1; flex: 1;
} }
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.top{ .top{
@ -727,4 +823,34 @@ import { log } from 'node:console';
padding-bottom: 10px; padding-bottom: 10px;
border-bottom: 1px solid #e9e9e9; border-bottom: 1px solid #e9e9e9;
} }
.treeRow {
display: flex;
justify-content: space-between;
align-items: center;
}
.addButton{
width: 70%;
height: 5vh;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.treePart{
width: 70%;
height: 100%;
display: flex;
border: 1px solid #bfbfbf;
margin-left: 10%;
flex-direction: column;
}
.actionMore {
display: none;
}
:deep(.ant-tree-node-content-wrapper) {
&:hover {
.actionMore {
display: block;
}
}
}
</style> </style>

42
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/config.ts

@ -78,3 +78,45 @@ export const tableColumns = [
width: 130 width: 130
}, },
]; ];
export const columns = [
{
title: '序号',
customRender: (text: any) => {
return text.index + 1;
},
},
{
title: '因子值',
dataIndex: 'energyType',
},
{
title: '计量单位',
className: 'unit',
dataIndex: 'unit',
},
{
title: '更新时间',
className: 'unit',
dataIndex: 'unit',
},
{
title: '启用时间',
className: 'unit',
dataIndex: 'unit',
},
{
title: '结束时间',
className: 'unit',
dataIndex: 'unit',
},
{
title: '数据来源',
className: 'unit',
dataIndex: 'unit',
},
{
title: '操作',
key: 'action',
width: 130
},
];

401
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index copy.vue

@ -0,0 +1,401 @@
<!-- @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
v-if="gData && gData.length > 0"
class="draggable-tree"
style="padding: 0 16px !important;"
show-line
block-node
:tree-data="gData"
:checkedKeys="checkedTreeNodeKeys"
:selectedKeys="selectedKeys"
@check="checkTreeNode"
@select="onSelect"
: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>
</div>
</div>
<div class="right">
<a-table :columns="columns" :data-source="tableData" bordered :pagination="false">
<template #bodyCell="{ column, text }">
<template v-if="column.dataIndex === 'name'">
<a>{{ text }}</a>
</template>
</template>
<template #title>Header</template>
</a-table>
</div>
<!-- 新增树节点 -->
<ns-modal :visible="treeNodeAdd" :title="operationTree" @ok="handleOk" @cancel="handleCancel">
<ns-input
v-model:value="addTreeNode"
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"
: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 { Modal } from 'ant-design-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 { carbonEmissionFactorLibrary } from '/@/api/carbonEmissionFactorLibrary';
import type {
AntTreeNodeDragEnterEvent,
AntTreeNodeDropEvent,
TreeProps,
} from 'ant-design-vue/es/tree';
import { log } from 'node:console';
defineOptions({ name: 'QuickCalculation' });
const selectTreeDataValue = ref<string>('');
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 casData = ref([]);
const treeData = ref([]);
const userAuthList = ref([]);
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result;
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 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 checkedIds = ref([])
const emissionType = ref()
const checkTreeNode = (checkedKeys, info) => {
checkedIds.value = []
info.checkedNodes.forEach(item=>{
checkedIds.value.push(item.id)
})
sessionStorage.setItem('checkedTreeNode', checkedIds.value);
emissionType.value = checkedIds.value.join(',')
}
// /
const addTreeNode =ref()
const handleOk = (e: MouseEvent) => {
editTreeNode.value.emissionName = addTreeNode.value
http.post(carbonEmissionFactorLibrary.creat,editTreeNode.value).then(() => {
getOrgTree()
NsMessage.success('操作成功');
addTreeNode.value = ''
treeNodeAdd.value = false;
});
};
const handleCancel = () => {
addTreeNode.value = ''
treeNodeAdd.value = false;
};
//
const getOrgTree = (params?) => {
fetch(carbonEmissionFactorLibrary.getCarbonFactorTree, params).then((res) => {
gData.value = res.data
//
const selectedNodes = [];
checkedTreeNodeKeys.value.forEach(key => {
const [parentId, childId] = key.split('-').map(Number);
if (parentId >= 0 && childId >= 0 && gData.value[parentId]?.children?.[childId]) {
selectedNodes.push(gData.value[parentId]);
}
});
});
};
getOrgTree();
//
const editTreeNode = ref({})
const onSelect = (selectedKeys: string[], info: any) => {
if(info.selected){
editTreeNode.value = {
id:info.selectedNodes[0].id,
level:info.selectedNodes[0].level,
dataNumber:info.selectedNodes[0].dataNumber,
sortNumber:info.selectedNodes[0].sortNumber,
parentEmissionId:info.selectedNodes[0].parentEmissionId,
}
}
};
const onSearch = () => {
console.log(searchValue.value);
getOrgTree({ orgName: searchValue.value, orgId });
};
const tableFetch = (params) => {
console.log(params, 'sdfasfasdfasdfasdf');
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 columns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Cash Assets',
className: 'column-money',
dataIndex: 'money',
},
{
title: 'Address',
dataIndex: 'address',
},
];
const tableData = [
{
key: '1',
name: 'John Brown',
money: '¥300,000.00',
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
money: '¥1,256,000.00',
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
money: '¥120,000.00',
address: 'Sidney No. 1 Lake Park',
},
];
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 });
});
};
</script>
<style lang="less" scoped>
.main {
background-color: @ns-content-bg;
display: flex;
height: 100%;
}
.left {
width: 300px;
// max-height: calc(100vh - 96px);
margin-right: @ns-gap;
min-width: fit-content;
> div {
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;
}
::v-deep .ant-table-container{
padding: 0px 16px;
}
.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>
<style scoped>
th.column-money,
td.column-money {
text-align: right !important;
}
</style>

567
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index.vue

@ -1,16 +1,14 @@
<!-- @format -->
<template> <template>
<div class="main"> <div class="main">
<div class="left"> <div class="left">
<div class="top"> <div class="top">
<a-form style="width: 100%;margin: 0 auto;"> <a-form style="width: 100%;margin: 0 auto;">
<div class="ns-form-title"><span>排放分类</span></div> <div class="ns-form-title"><span>因子分类</span></div>
<div style="padding: 0 16px !important;width: 100%;"> <div style="padding: 0 16px !important;width: 100%;">
<a-row> <a-row>
<a-col :span="24" style="margin-bottom: 16px;"> <a-col :span="24" style="margin-bottom: 16px;">
<a-input-search <a-input-search
v-model:value="selectTreeDataValue" v-model:value="searchValue"
placeholder="请输入关键词" placeholder="请输入关键词"
@search="onSearchTreeData" @search="onSearchTreeData"
/> />
@ -19,45 +17,54 @@
</div> </div>
</a-form> </a-form>
<a-tree <a-tree
v-if="gData && gData.length > 0"
class="draggable-tree"
style="padding: 0 16px !important;"
draggable
show-line
checkable
block-node
:tree-data="gData"
:checkedKeys="checkedTreeNodeKeys"
:selectedKeys="selectedKeys"
@dragenter="onDragEnter"
@drop="onDrop"
@check="checkTreeNode"
@select="onSelect"
:expanded-keys="expandedKeys" :expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent" :auto-expand-parent="autoExpandParent"
@expand="onExpand"> :tree-data="gData"
<template #title="{ emissionName }"> @expand="onExpand"
<span v-if="emissionName && selectTreeDataValue && emissionName.indexOf(selectTreeDataValue) > -1"> style="padding: 0 16px !important;"
{{ emissionName.substring(0, emissionName.indexOf(selectTreeDataValue)) }} >
<span style="color: #f50">{{ selectTreeDataValue }}</span> <template #title="{ title }">
{{ emissionName.substring(emissionName.indexOf(selectTreeDataValue) + selectTreeDataValue.length) }} <span v-if="title.indexOf(searchValue) > -1">
{{ title.substring(0, title.indexOf(searchValue)) }}
<span style="color: #f50">{{ searchValue }}</span>
{{ title.substring(title.indexOf(searchValue) + searchValue.length) }}
</span> </span>
<span v-else>{{ emissionName }}</span> <span v-else>{{ title }}</span>
</template> </template>
</a-tree> </a-tree>
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<ns-view-list-table v-bind="tableConfig" :model="data" ref="mainRef" :scroll="{ x: 2000}"/> <a-table
:columns="columns"
:data-source="tableData"
bordered
:pagination="false">
<template #bodyCell="{ column, text, record }">
<template v-if="column.key === 'action'">
<span>
<a @click="editData(record)">编辑</a>
<a-divider type="vertical" />
<a @click="delData(record)">删除</a>
</span>
</template>
</template>
<template #title>
<div class="ns-table-title"><span>排放因子库</span></div>
<div class="buttonGroup">
<a-button type="primary" @click="addNewData">新增</a-button>
</div> </div>
<!-- 新增树节点 --> </template>
<ns-modal :visible="treeNodeAdd" :title="operationTree" @ok="handleOk" @cancel="handleCancel"> </a-table>
<ns-input <a-pagination
v-model:value="addTreeNode" :current="queryParams.pageNum"
class="input" :total="total"
placeholder="请输入排放类型"/> :page-size="queryParams.pageSize"
</ns-modal> style="display: flex;justify-content: center;margin-top: 16px;"
<!-- 新增数据库数据 --> :show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" />
<!-- 新增/编辑 -->
<a-drawer <a-drawer
:width="500" :width="500"
:visible="visible" :visible="visible"
@ -65,72 +72,74 @@
:footer-style="{ textAlign: 'right' }" :footer-style="{ textAlign: 'right' }"
destroyOnClose destroyOnClose
@close="onClose"> @close="onClose">
<ns-form <a-form
ref="formRef" ref="formRef"
:model="formData" :model="formState"
class="form" :rules="rules"
:wrapperCol="{ span: 20 }" :label-col="labelCol"
formLayout="vertical" /> :wrapper-col="wrapperCol"
>
<a-form-item ref="name" label="能源种类" name="energyType">
<a-input v-model:value="formState.energyType" placeholder="请输入能源种类" />
</a-form-item>
<a-form-item label="计量单位" name="unit">
<a-cascader v-model:value="formState.unit" :options="options" />
</a-form-item>
<a-form-item label="自动采集节点" name="collectionNode">
<a-tree-select
v-model:value="formState.collectionNode"
:tree-line="true"
:tree-data="treeData"
tree-node-filter-prop="title"
>
</a-tree-select>
</a-form-item>
<a-form-item label="计算碳排" name="isComputeCarbon">
<a-radio-group v-model:value="formState.isComputeCarbon" @change="changeRadio">
<a-radio :value="0"></a-radio>
<a-radio :value="1"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排放类型" name="emissionType">
<a-select v-model:value="formState.emissionType" placeholder="请选择排放类型">
<a-select-option v-for="(item, index) in emissionTypeDic" :key="index" :value="item.cnValue">
{{ item.cnValue }}
</a-select-option>
</a-select>
</a-form-item>
</a-form>
<template #footer> <template #footer>
<a-button style="margin-right: 8px" @click="onClose">取消</a-button> <a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="onEdit">确定</a-button> <a-button type="primary" @click="onSubmit">确定</a-button>
</template> </template>
</a-drawer> </a-drawer>
</div> </div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Modal } from 'ant-design-vue'; import { ref, watch } from 'vue';
import { computed, createVNode, defineComponent, reactive, ref, watchEffect,watch } from 'vue'; import type { TreeProps } from 'ant-design-vue';
import { Pagination } from 'ant-design-vue';
import { columns } from '../config';
import { http } from '/nerv-lib/util/http'; import { http } from '/nerv-lib/util/http';
import { NsMessage, NsModal } from '/nerv-lib/component'; defineOptions({
import { carbonEmissionFactorLibrary } from '/@/api/carbonEmissionFactorLibrary'; energyType: 'quickCalculation', // name
import type { components: {
AntTreeNodeDragEnterEvent, 'a-pagination': Pagination,
AntTreeNodeDropEvent, },
TreeProps,
} from 'ant-design-vue/es/tree';
import { log } from 'node:console';
defineOptions({ name: 'QuickCalculation' });
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 casData = ref([]);
const treeData = ref([]);
const userAuthList = ref([]);
const orgId = ref(''); const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!); const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result; orgId.value = result;
const dynamicDisabled = computed(() => {
return formRef.value?.validateResult && userAuthList.value?.length;
});
const fetch = (api, params = { orgId } ) => { const fetch = (api, params = { orgId } ) => {
return http.post(api, params); return http.post(api, params);
}; };
//
//
const x = 3; const x = 3;
const y = 2; const y = 2;
const z = 1; const z = 1;
const genData: TreeProps['treeData'] = []; const genData: TreeProps['treeData'] = [];
const checkedTreeNodeKeys = ref<string[]>(['0-0']);
const generateData = (_level: number, _preKey?: string, _tns?: TreeProps['treeData']) => { const generateData = (_level: number, _preKey?: string, _tns?: TreeProps['treeData']) => {
const preKey = _preKey || '0'; const preKey = _preKey || '0';
@ -154,70 +163,7 @@ import { log } from 'node:console';
}); });
}; };
generateData(z); 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 dataList: TreeProps['treeData'] = [];
const generateList = (data: TreeProps['treeData']) => { const generateList = (data: TreeProps['treeData']) => {
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
@ -249,13 +195,16 @@ import { log } from 'node:console';
return parentKey; return parentKey;
}; };
const expandedKeys = ref<(string | number)[]>([]); const expandedKeys = ref<(string | number)[]>([]);
const searchValue = ref<string>('');
const autoExpandParent = ref<boolean>(true); const autoExpandParent = ref<boolean>(true);
const gData = ref<TreeProps['treeData']>(genData);
const onExpand = (keys: string[]) => { const onExpand = (keys: string[]) => {
expandedKeys.value = keys; expandedKeys.value = keys;
autoExpandParent.value = false; autoExpandParent.value = false;
}; };
watch(selectTreeDataValue, value => {
watch(searchValue, value => {
const expanded = dataList const expanded = dataList
.map((item: TreeProps['treeData'][number]) => { .map((item: TreeProps['treeData'][number]) => {
if (item.title.indexOf(value) > -1) { if (item.title.indexOf(value) > -1) {
@ -265,273 +214,64 @@ import { log } from 'node:console';
}) })
.filter((item, i, self) => item && self.indexOf(item) === i); .filter((item, i, self) => item && self.indexOf(item) === i);
expandedKeys.value = expanded; expandedKeys.value = expanded;
selectTreeDataValue.value = value; searchValue.value = value;
autoExpandParent.value = true; autoExpandParent.value = true;
}); });
// //
const onSearchTreeData = (selectTreeDataValue: string) => { const total = ref<number>()
console.log('use value', selectTreeDataValue); const queryParams = ref({
console.log('or use this.value', value.value); pageNum: 1,
}; pageSize: 10,
//
const checkedIds = ref([])
const emissionType = ref()
const checkTreeNode = (checkedKeys, info) => {
checkedTreeNodeKeys.value = checkedKeys
checkedIds.value = []
info.checkedNodes.forEach(item=>{
checkedIds.value.push(item.id)
}) })
sessionStorage.setItem('checkedTreeNode', checkedIds.value); const tableData = [
emissionType.value = checkedIds.value.join(',')
mainRef.value?.nsTableRef.reload();
}
// /
const addTreeNode =ref()
const handleOk = (e: MouseEvent) => {
editTreeNode.value.emissionName = addTreeNode.value
http.post(carbonEmissionFactorLibrary.creat,editTreeNode.value).then(() => {
getOrgTree()
NsMessage.success('操作成功');
addTreeNode.value = ''
treeNodeAdd.value = false;
});
};
const handleCancel = () => {
addTreeNode.value = ''
treeNodeAdd.value = false;
};
//
const getOrgTree = (params?) => {
fetch(carbonEmissionFactorLibrary.getCarbonFactorTree, params).then((res) => {
gData.value = res.data
//
const selectedNodes = [];
checkedTreeNodeKeys.value.forEach(key => {
const [parentId, childId] = key.split('-').map(Number);
if (parentId >= 0 && childId >= 0 && gData.value[parentId]?.children?.[childId]) {
selectedNodes.push(gData.value[parentId]);
}
});
// id
getDefaultIds(selectedNodes)
});
};
const defaultIds = ref([])
const getDefaultIds = (selectedNodes) => {
selectedNodes.forEach(items => {
defaultIds.value.push(items.id)
if(items.children){
getDefaultIds(items.children)
}
})
emissionType.value = defaultIds.value.join(',')
checkedIds.value = defaultIds.value
sessionStorage.setItem('checkedTreeNode', checkedIds.value);
}
getOrgTree();
//
const editTreeNode = ref({})
const onSelect = (selectedKeys: string[], info: any) => {
if(info.selected){
editTreeNode.value = {
id:info.selectedNodes[0].id,
level:info.selectedNodes[0].level,
dataNumber:info.selectedNodes[0].dataNumber,
sortNumber:info.selectedNodes[0].sortNumber,
parentEmissionId:info.selectedNodes[0].parentEmissionId,
}
}
};
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 });
});
};
const tableConfig = ref({
title: '数据库',
api: carbonEmissionFactorLibrary.getTableList,
params: {
orgId,
emissionType
},
headerActions: [
{
label: '新增',
name: 'userAdd',
type: 'primary',
handle: () => {
opMap.value.type = 'add';
setTimeout(() => {
formData.value = {
carbonEmissionPrefix:'t',
numberOfReferences:'10'
};
userAuthList.value.splice(0);
});
opMap.value.fuc = (formData: any) => {
formData.emissionType = formData.emissionType[formData.emissionType.length - 1]
return http.post(carbonEmissionFactorLibrary.creatOrUpdate, 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.del,
dynamicParams: { ids: 'id[]' },
},
],
columns: [
{
title: 'id',
customRender: (text: any) => {
return text.index + 1;
},
},
{
title: '排放源',
dataIndex: 'emissionSources',
},
{
title: '排放类型',
dataIndex: 'emissionTypeColumn',
},
{
title: '排放气体',
dataIndex: 'emissionGas',
},
{
title: '排放环节',
dataIndex: 'emissionProcess',
},
{ {
title: '排放因子', key: '1',
dataIndex: 'emissionFactors', name: 'John Brown',
money: '¥300,000.00',
address: 'New York No. 1 Lake Park',
}, },
{ {
title: '排放因子单位', key: '2',
dataIndex: 'emissionFactorUnits', name: 'Jim Green',
money: '¥1,256,000.00',
address: 'London No. 1 Lake Park',
}, },
{ {
title: '数据来源', key: '3',
dataIndex: 'dataSources', name: 'Joe Black',
money: '¥120,000.00',
address: 'Sidney No. 1 Lake Park',
}, },
{ ];
title: '数据库', //
dataIndex: 'carbonDatabase', const onChange = (pageNumber: number,size: number) => {
}, queryParams.value.pageNum = pageNumber;
{ queryParams.value.pageSize = size;
title: '参考文献', // getTableList()
dataIndex: 'reference', };
}, // /
{ const formRef = ref();
title: '引用数量', const labelCol = { span: 5 };
dataIndex: 'numberOfReferences', const wrapperCol = { span: 19 };
}, const formState = ref({})
], const visible = ref(false);
columnActions: {
title: '操作',
actions: [
{
label: '编辑',
name: 'userEdit',
handle: (record: any) => {
userAuthList.value.splice(0);
setTimeout(() => {
console.log(record.id);
http.post(carbonEmissionFactorLibrary.findById,{ id: record.id } ).then((res) => { // form
formData.value = res.data; const rules: Record<string, Rule[]> = {
}); energyType: [{ required: true, message: '请输入能源种类', trigger: 'change' }],
}, 10); isComputeCarbon: [{ required: true, message: '请选择是否计算碳排', trigger: 'change' }]
opMap.value.type = 'edit'; };
opMap.value.fuc = (formData: any) => { //
return http.post(carbonEmissionFactorLibrary.creatOrUpdate, formData).then(() => { const editData = (record) =>{
mainRef.value?.nsTableRef.reload(); visible.value = true
};
//
const onClose = () => {
visible.value = false; visible.value = false;
NsMessage.success('操作成功'); formRef.value.resetFields();
});
}; };
visible.value = true;
},
},
{
label: '删除',
name: 'userDelete',
dynamicParams: { ids: 'id[]' },
confirm: true,
isReload: true,
api: carbonEmissionFactorLibrary.del,
},
],
},
rowKey: 'id',
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.main { .main {
background-color: @ns-content-bg; background-color: @ns-content-bg;
@ -540,13 +280,10 @@ import { log } from 'node:console';
} }
.left { .left {
width: 300px; width: 300px;
// max-height: calc(100vh - 96px);
margin-right: @ns-gap; margin-right: @ns-gap;
min-width: fit-content; min-width: fit-content;
> div { > div {
border-radius: @ns-border-radius;
background-color: @white; background-color: @white;
// box-shadow: @ns-content-box-shadow;
flex: 1; flex: 1;
} }
@ -565,12 +302,14 @@ import { log } from 'node:console';
.right { .right {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
height: 100%;
background: #ffffff;
}
::v-deep .ant-table-container{
padding: 0px 16px;
} }
.top { .top {
overflow: auto; overflow: auto;
// height: 50%;
// border-bottom: 5px solid rgb(229, 235, 240);
// overflow-y: auto;
} }
.ns-form-title{ .ns-form-title{
font-weight: bold; font-weight: bold;
@ -580,4 +319,24 @@ import { log } from 'node:console';
padding-bottom: 10px; padding-bottom: 10px;
border-bottom: 1px solid #e9e9e9; border-bottom: 1px solid #e9e9e9;
} }
::v-deep .ant-table-title{
display: flex;
height: 100%;
align-items: center;
}
.ns-table-title{
font-weight: bold;
}
.buttonGroup{
margin-left: 1vw;
width: 5vw;
display: flex;
justify-content: space-around;
}
</style>
<style scoped>
th.column-money,
td.column-money {
text-align: right !important;
}
</style> </style>

141
hx-ai-intelligent/src/view/equipmentControl/lightingManage/dialogStyle.less

@ -0,0 +1,141 @@
.out-dialog {
position: fixed;
right: 496px;
width: 500px;
height: 100%;
top: 0;
bottom: 0;
margin: auto;
box-sizing: border-box;
color: rgb(255, 83, 0);
background: black;
display: flex;
padding: 25px;
flex-direction: column;
.content {
overflow-y: scroll;
.div-operation {
display: inline-block;
width: 3px;
height: 13px;
opacity: 1;
border-radius: 1px;
background: rgba(67, 136, 251, 1);
}
.text-operation {
display: inline-block;
color: rgba(255, 255, 255, 1);
font-size: 16px;
font-weight: 700;
margin-left: 5px;
}
.j-box {
background-color: #000;
opacity: 1;
z-index: 99999;
overflow-y: scroll;
.journal {
padding: 1% 3%;
width: 100%;
height: 150px;
background-color: rgba(0, 0, 0);
border-radius: 12px;
border: 2px solid transparent;
border-image: linear-gradient(to bottom, #0077ff, #00f6ff, #000000) 1;
}
.imgText {
display: flex;
align-items: center;
justify-content: space-between;
.ztzm {
display: flex;
align-items: center;
}
.cxbtn {
color: rgba(255, 255, 255, 1);
border: none;
border-radius: 6px;
width: 59.79px;
height: 32px;
opacity: 1;
background: linear-gradient(
180deg,
rgba(255, 187, 0, 1) 0%,
rgba(255, 112, 3, 1) 91.21%,
rgba(255, 129, 3, 1) 100%
);
}
}
.btn-box {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-row-gap: 15px;
.btn-item {
text-align: center;
display: flex;
align-content: space-between;
.left {
width: 70px;
height: 35px;
line-height: 35px;
border-radius: 4px;
background: linear-gradient(
180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%
);
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
}
.right {
width: 140px;
height: 35px;
line-height: 35px;
span {
vertical-align: middle;
}
img {
padding: 0 5px;
}
}
}
}
}
}
.button-box {
width: 100%;
box-sizing: border-box;
padding: 10px;
height: 60px;
position: absolute;
background-color: transparent;
bottom: 0;
left: 0;
right: 0;
.execute, .cancel {
margin-right: 10px;
width: 74px;
height: 40px;
opacity: 1;
cursor: pointer;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
border: 0;
margin-left: 10px;
}
.execute {
background: rgb(67, 136, 251);
color: white;
}
.cancel {
background: white;
color: black;
}
}
}

1104
hx-ai-intelligent/src/view/equipmentControl/lightingManage/index.less

File diff suppressed because it is too large

156
hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs.less

@ -1,156 +0,0 @@
// 页面容器
.lighting-box {
// width: 100%;
// height: 100%;
position: relative;
// background: linear-gradient(#badaff, #8cabeb, #7095de);
// 照明设备功能总容器
.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 {
// transform: scale(1.05);
// }
.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 {
// transform: scale(1.05);
// }
}
}
}
}
// 总容器与抽屉按钮
.ns-content-main {
position: relative;
// 抽屉打开按钮
.drawer-box-in {
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-box-out {
width: 30px;
height: 40px;
border-radius: 2px;
position: fixed;
right: 496px;
top: 0;
bottom: 0;
margin: auto;
background: rgba(0, 0 ,0 ,0.5);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
}

50
hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs.vue

@ -3,19 +3,19 @@
<div class="lighting-img-box"> <div class="lighting-img-box">
<!-- 左上角区域切换 --> <!-- 左上角区域切换 -->
<div class="btn-box"> <div class="btn-box">
<button class="btn-item">1F</button> <button class="btn-item" @click=changeArea(1)>1F</button>
<button class="btn-item">2F</button> <button class="btn-item" @click=changeArea(2)>2F</button>
<button class="btn-item">站台</button> <button class="btn-item" @click=changeArea(3)>站台</button>
</div> </div>
<!-- 楼层区域 --> <!-- 楼层区域 -->
<div class="area"> <div class="area">
<div <div
v-for="(item, index) in treeData" v-for="(item, index) in treeData"
:class="computedClass(item.id)" :class="computedClass(String(item.id))"
@click="getArea(item.id)" @click="getArea(item)"
:key="index"> :key="index">
<div v-for="(v, i) in item.children" :key="i" class="light-group"> <div v-for="(v, i) in item.children" :key="i" class="light-group">
<div class="group-shadow group-shadow1" :class="computedClass(v.id)" @click.stop="getArea(v.id)"></div> <div class="group-shadow group-shadow1" :class="computedClass(v.id)" @click.stop="getArea(v)"></div>
</div> </div>
</div> </div>
</div> </div>
@ -40,16 +40,18 @@
placement="right" placement="right"
:body-style="{ background: 'rgba(0, 0, 0)', opacity: 0.8 }" :body-style="{ background: 'rgba(0, 0, 0)', opacity: 0.8 }"
:closable="false" :closable="false"
id="Odrawer" id="drawer"
:maskStyle="{ 'background-color': 'rgba(0, 0, 0, 0)' }"> :maskStyle="{ 'background-color': 'rgba(0, 0, 0, 0)' }">
<a-tabs v-model:activeKey="activeKey"> <a-tabs v-model:activeKey="activeKey">
<a-tab-pane key="1" tab="控制面板"> <a-tab-pane key="1" tab="控制面板">
<tabs1 @changeArea="getArea" :treeData="treeData"></tabs1> <tabs1 @changeArea="getArea" :treeData="treeData"></tabs1>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" tab="计划列表" force-render> <a-tab-pane key="2" tab="计划列表" force-render>
<tabs2></tabs2>
</a-tab-pane>
<a-tab-pane key="3" tab="日志">
<tabs3></tabs3>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="3" tab="日志"></a-tab-pane>
</a-tabs> </a-tabs>
</a-drawer> </a-drawer>
</div> </div>
@ -61,15 +63,17 @@ import { ref } from 'vue';
import { treeData } from './treeData' import { treeData } from './treeData'
import light from './light.vue'; import light from './light.vue';
import tabs1 from './tabs1.vue' import tabs1 from './tabs1.vue'
import tabs2 from './tabs2.vue'
import tabs3 from './tabs3.vue'
// ICON // ICON
import { import {
DoubleLeftOutlined, DoubleLeftOutlined,
DoubleRightOutlined DoubleRightOutlined
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
// - - // - -
let area = ref(['1']) const area = ref(['1'])
// - // - -
const bulbs = ref([ const bulbs = ref([
{ {
styleText: { left: '190px', bottom: '200px' }, styleText: { left: '190px', bottom: '200px' },
@ -121,6 +125,16 @@ const bulbs = ref([
}, },
]) ])
// -
const changeArea = (area: number) => {
if (area == 1) {
console.log('1F')
} else if (area == 2) {
console.log('2F')
} else if (area == 3) {
console.log('站台')
}
}
// - // -
const getArea = (result: any) => { const getArea = (result: any) => {
// //
@ -132,16 +146,14 @@ const getArea = (result: any) => {
area.value[0] = String(result) area.value[0] = String(result)
} }
} }
// -
// - // -
const computedClass = (number: number) => { const computedClass = (string: string) => {
if (area.value.indexOf(number) != -1) { if (area.value.indexOf(string) != -1) {
return `isActive area-item area${number}` return `isActive area-item area${string}`
} else { } else {
return `area-item area${number}` return `area-item area${string}`
} }
} }
// - tab // - tab
let activeKey = ref('1'); let activeKey = ref('1');
// - // -
@ -153,7 +165,7 @@ const toggleDrawer = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import "./indexs.less"; @import "./index.less";
.isActive { .isActive {
border: 3px solid white !important; border: 3px solid white !important;
} }

15
hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs1.vue

@ -1162,16 +1162,11 @@
selectedButton.value = null; selectedButton.value = null;
showControlMode.value = false; showControlMode.value = false;
showControlScene.value = false; showControlScene.value = false;
selectedButton3.value = null; selectedButton3.value = '';
selectedButton4.value = null; selectedButton4.value = '';
}; };
//
const logModalVisible = ref(false);
const handlerefClick1 = () => {
console.log(1111);
executevisible.value = true;
};
let trindex = ref('-1'); let trindex = ref('-1');
const handleRowClick = (index: any) => { const handleRowClick = (index: any) => {
@ -1192,9 +1187,7 @@
}; };
// //
const addvisible = ref<boolean>(false); const addvisible = ref<boolean>(false);
const addModal = () => {
addvisible.value = true;
};
// 穿 // 穿
interface MockData { interface MockData {
key: string; key: string;

415
hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs1.vue

@ -12,7 +12,7 @@
<div class="area"> <div class="area">
<template v-if="!showAllButtonsArea"> <template v-if="!showAllButtonsArea">
<button v-for="(button, index) in limitedButtons1" :key="index" <button v-for="(button, index) in limitedButtons1" :key="index"
:class="{ btn: true, selected: button.selected }" @click="selectButton(button, index)"> :class="{ btn: true, selected: button.selected }" @click="selectButton(button)">
{{ button.label }} {{ button.label }}
</button> </button>
<div style="margin-top: 10px"> <div style="margin-top: 10px">
@ -20,8 +20,8 @@
</div> </div>
</template> </template>
<template v-else> <template v-else>
<button v-for="(button, index) in props.treeData" :key="index" <button v-for="(button, index) in props.treeData" :key="index" :class="{ btn: true, selected: button.selected }"
:class="{ btn: true, selected: button.selected }" @click="selectButton(button)"> @click="selectButton(button)">
{{ button.label }} {{ button.label }}
</button> </button>
<div style="margin-top: 10px"> <div style="margin-top: 10px">
@ -36,7 +36,7 @@
<div class="circuit-tab"></div> <div class="circuit-tab"></div>
<span class="circuit-text">照明回路</span> <span class="circuit-text">照明回路</span>
<div class="btn2"> <div class="btn2">
<button class="openplan" :class="{ enabled2: isPlanEnabled2, disabled2: !isPlanEnabled2 }" @click="togglePlan2"> <button class="openPlan" :class="{ enabled2: isPlanEnabled2, disabled2: !isPlanEnabled2 }" @click="togglePlan2">
{{ isPlanEnabled2 ? '启用面板' : '禁用面板' }} {{ isPlanEnabled2 ? '启用面板' : '禁用面板' }}
</button> </button>
<a-switch v-model:checked="selectAllCheckbox" :disabled="singleSelection" :class="{ <a-switch v-model:checked="selectAllCheckbox" :disabled="singleSelection" :class="{
@ -49,7 +49,7 @@
</button> </button>
</div> </div>
</div> </div>
<div class="btnarea" v-if="selectedButton"> <div class="btnArea" v-if="selectedButton">
<template v-if="!showAllButtons"> <template v-if="!showAllButtons">
<button v-for="(button2, index) in limitedButtons2" :key="index" <button v-for="(button2, index) in limitedButtons2" :key="index"
:class="{ btn: true, selected: button2.selected }" class="zmhlbtn" @click="toggleSelection(button2)"> :class="{ btn: true, selected: button2.selected }" class="zmhlbtn" @click="toggleSelection(button2)">
@ -80,7 +80,7 @@
<!-- 控制模式按钮部分 --> <!-- 控制模式按钮部分 -->
<div class="control-mode-btn-area" v-show="showControlMode"> <div class="control-mode-btn-area" v-show="showControlMode">
<button v-for="(button3, index) in controlType" :key="index" <button v-for="(button3, index) in controlType" :key="index"
:class="{ btn: true, selected: button3.type === thisButtonType }" @click="selectButton3(button3)"> :class="{ btn: true, selected: button3.type == thisButton.type }" @click="selectButton3(button3)">
{{ button3.name }} {{ button3.name }}
</button> </button>
</div> </div>
@ -119,7 +119,7 @@
:style="{ height: '50px' }"> :style="{ height: '50px' }">
<td>{{ row.num }}</td> <td>{{ row.num }}</td>
<td>{{ row.light }}</td> <td>{{ row.light }}</td>
<td>{{ row.tempruter }}</td> <td>{{ row.temperature }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -130,170 +130,71 @@
<button class="flushed" @click="refresh">刷新</button> <button class="flushed" @click="refresh">刷新</button>
<button class="execute" @click="showModal">执行</button> <button class="execute" @click="showModal">执行</button>
</div> </div>
<!-- <a-modal :v-if="cxlist.length === 0" v-model:visible="executevisible" width="500px" height="792px" okText="执行"
:closable="false" @ok="handleOk2" :mask="false" :bodyStyle="{ <div class="out-dialog" v-if="executeVisible">
opacity: 1, <div class="content" v-if="executeVisible">
background: ' rgba(0,0,0)',
color: 'rgba(255,83,0)',
boxSizing: 'borderBox',
display: 'flex',
flexDirection: 'column',
position: 'fixed',
right: '496px',
top: '0',
}">
<div :v-if="cxlist.length === 0" style="height: 792px">
<div> <div>
<div class="div-operation"></div> <div class="div-operation"></div>
<span class="text-operation">变更内容 </span> <span class="text-operation">变更内容 </span>
</div> </div>
<div class="jbox" v-for="item in cxlist" :key="item.id"> <div class="j-box" v-for="item in cxList" :key="item.id">
<div class="journal" style="margin-top: 20px"> <div class="journal" style="margin-top: 20px">
<div class="imgText"> <div class="imgText">
<div class="zjzm"> <div class="zjzm">
<img class="titleimg" src="/asset/image//bulbLogo/21961.png" alt="" />&nbsp; <img class="title-img" src="/asset/image//bulbLogo/21961.png" alt="" />&nbsp;
<span class="titletext" style="font-size: 20px; font-weight: 500; color: rgba(255, 255, 255, 1)">{{ <span class="title-text" style="font-size: 20px; font-weight: 500; color: rgba(255, 255, 255, 1)">{{ item.name }}</span>
item.name }}</span>
</div> </div>
<button class="cxbtn" @click="delbtn(item.id)">撤销</button> <button class="cxbtn" @click="delBtn(item.id)">撤销</button>
</div> </div>
<div class="control-btn"> <div class="btn-box">
<button style=" <div class="btn-item">
width: 96px; <div class="left">控制模式</div>
height: 40px; <div class="right">
border-radius: 4px; <span>手动</span>
background: linear-gradient(
180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%
);
border: 1px solid rgba(95, 154, 251, 1);
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
">
控制模式
</button>
<span style="
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
margin-left: 12px;
margin-right: 8px;
">手动</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" /> <img src="/asset/image/bulbLogo/22406.png" alt="" />
<span style=" <span>自动</span>
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
margin-left: 8px;
margin-right: 40px;
">自动</span>
</div> </div>
<div class="light-btn"> </div>
<button style=" <div class="btn-item">
width: 68px; <div class="left">
height: 40px;
border-radius: 4px;
background: linear-gradient(
180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%
);
border: 1px solid rgba(95, 154, 251, 1);
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
">
亮度 亮度
</button> </div>
<span style=" <div class="right">
color: rgba(255, 255, 255, 1); <span>100lux</span>
font-size: 14px;
font-weight: 400;
margin-left: 12px;
margin-right: 8px;
">100lux</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" /> <img src="/asset/image/bulbLogo/22406.png" alt="" />
<span style=" <span>30lux</span>
color: rgba(243, 97, 99, 1);
font-size: 14px;
font-weight: 400;
margin-left: 8px;
">30lux</span>
</div> </div>
<div class="control-area-btn"> </div>
<button style=" <div class="btn-item">
width: 96px; <div class="left">
height: 40px;
border-radius: 4px;
background: linear-gradient(
180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%
);
border: 1px solid rgba(95, 154, 251, 1);
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
">
控制场景 控制场景
</button> </div>
<span style=" <div class="right">
color: rgba(255, 255, 255, 1); <span>手动</span>
font-size: 14px;
font-weight: 400;
margin-left: 12px;
margin-right: 8px;
">手动</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" /> <img src="/asset/image/bulbLogo/22406.png" alt="" />
<span style=" <span>自动</span>
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
margin-left: 8px;
margin-right: 40px;
">自动</span>
</div> </div>
<div class="temp-btn"> </div>
<button style=" <div class="btn-item">
width: 68px; <div class="left">
height: 40px;
border-radius: 4px;
background: linear-gradient(
180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%
);
border: 1px solid rgba(95, 154, 251, 1);
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
">
色温 色温
</button> </div>
<span style=" <div class="right">
color: rgba(255, 255, 255, 1); <span>4000k</span>
font-size: 14px;
font-weight: 400;
margin-left: 12px;
margin-right: 8px;
">4000k</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" /> <img src="/asset/image/bulbLogo/22406.png" alt="" />
<span style=" <span>3800k</span>
color: rgba(255, 255, 255, 1); </div>
font-size: 14px; </div>
font-weight: 400; </div>
margin-left: 8px; </div>
">3800k</span>
</div> </div>
</div> </div>
<div style="width: 100%; height: 60px;"></div>
<div class="button-box">
<button class="cancel" @click="executeVisible = false">取消</button>
<button class="execute">执行</button>
</div> </div>
</div> </div>
</a-modal> -->
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -307,19 +208,23 @@ import {
// //
onMounted(() => { onMounted(() => {
const tree = props.treeData const data = props.treeData[0]
// //
tree[0].selected = true data.selected = true
// //
buttons2.value = tree[0].children buttons2.value = data.children
}) })
// =================================================================== // ===================================================================
const props = defineProps({ const props = defineProps({
// > // >
treeData: { treeData: {
type: Array type: Array,
default: []
}, },
line: {
type: Array
}
}); });
const emit = defineEmits(['changeArea']); const emit = defineEmits(['changeArea']);
@ -336,20 +241,13 @@ const togglePlan = () => {
const showAllButtonsArea = ref(false); const showAllButtonsArea = ref(false);
// - - 1 // - - 1
const selectedButton = ref('1'); const selectedButton = ref('1');
// - // - -
const selectButton = (button: any, index: number) => { const selectButton = (button: any) => {
// //
selectedButton.value = button; selectedButton.value = button;
// //
props.treeData.forEach(item => { initMenu(1)
item.selected = false
})
button.selected = true button.selected = true
// 1
buttons2.value.forEach(item => {
item.selected = false
})
showControlMode.value = false
buttons2.value = button.children buttons2.value = button.children
// area // area
emit('changeArea', []); emit('changeArea', []);
@ -375,16 +273,7 @@ const togglePlan2 = () => {
isPlanEnabled2.value = !isPlanEnabled2.value; isPlanEnabled2.value = !isPlanEnabled2.value;
// - // -
if (isPlanEnabled2.value) { if (isPlanEnabled2.value) {
item.selected = false;
item.stop = true item.stop = true
let level1 = String(selectedButton.value.id)
let arr = [level1]
buttons2.value.forEach(item => {
if (item.selected) {
arr.push(item.id)
}
})
emit('changeArea', arr)
// - // -
} else { } else {
item.stop = false item.stop = false
@ -410,10 +299,8 @@ const toggleAllSelection = () => {
// //
if (selectAllCheckbox.value) { if (selectAllCheckbox.value) {
buttons2.value.forEach((item) => { buttons2.value.forEach((item) => {
if (!item.stop) {
item.selected = true; item.selected = true;
arr.push(item.id) arr.push(item.id)
}
}); });
// //
} else { } else {
@ -431,7 +318,7 @@ const toggleSelection = (button: any) => {
zmhlid.value = button.id zmhlid.value = button.id
// / // /
if (button.stop) { if (button.stop) {
return isPlanEnabled2.value = true isPlanEnabled2.value = true
} else { } else {
isPlanEnabled2.value = false isPlanEnabled2.value = false
} }
@ -455,17 +342,22 @@ const toggleSelection = (button: any) => {
arr.push(item.id) arr.push(item.id)
} }
}); });
console.log(arr)
emit('changeArea', arr) emit('changeArea', arr)
} }
// //
if (button.selected) { if (button.selected) {
//
showControlMode.value = true showControlMode.value = true
thisButtonType.value = button.type
thisButton.value = button thisButton.value = button
if (button.type == 3) {
showControlScene.value = true
} else { } else {
showControlScene.value = false
}
} else {
//
showControlMode.value = false showControlMode.value = false
thisButton.value = null thisButton.value = { type: '0' }
} }
}; };
@ -479,16 +371,12 @@ const buttons2 = ref([]);
// ======================================================================= // =======================================================================
// - // -
const showControlMode = ref(false); const showControlMode = ref(false);
const thisButtonType = ref(null) const thisButton = ref({ type: '0' })
const thisButton = ref(null)
// -
const selectedButton3 = ref('');
// - // -
const selectButton3 = (button3) => { const selectButton3 = (button3) => {
thisButton.value.type = button3.type thisButton.value.type = button3.type
thisButtonType.value = button3.type
showControlScene.value = button3.name === '手动'; showControlScene.value = button3.name === '手动';
selectedButton4.value = ''; // selectedButton4.value = null; //
}; };
// ======================================================================= // =======================================================================
@ -502,7 +390,7 @@ const controlSceneButtons = ref([
{ label: '客流高峰', selected: false }, { label: '客流高峰', selected: false },
]); ]);
// - // -
const selectedButton4 = ref(''); const selectedButton4 = ref(null);
// - // -
const selectButton4 = (button4) => { const selectButton4 = (button4) => {
selectedButton4.value = button4.label; selectedButton4.value = button4.label;
@ -510,33 +398,112 @@ const selectButton4 = (button4) => {
// ======================================================================== // ========================================================================
// - // -
const lightSource = ref([{ num: '8/10', light: '100', tempruter: '4200' }]); const lightSource = ref([{ num: '8/10', light: '100', temperature: '4200' }]);
let trIndex = ref('-1');
const handleRowClick = (index: any) => { const handleRowClick = (index: any) => {
trindex.value = index; trIndex.value = index;
if (index === trindex.value) { if (index === trIndex.value) {
console.log('tri'); console.log('tri');
} }
//
logModalVisible.value = true;
}; };
// ======================================================================== // ========================================================================
const cxList = ref([
{
id: '1',
name: '站厅照明 1区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
{
id: '2',
name: '站厅照明 2区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
{
id: '3',
name: '站厅照明 3区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
]);
// const cxList = cxList.value.concat(cxList.value)
//
const delBtn = (id: any) => {
console.log(id);
cxList.value.pop(id);
console.log(cxList.value.length);
if (cxList.value.length === 0) {
executeVisible.value = false;
}
};
// ========================================================================
// 5
const initMenu = (tier: number) => {
// 1 = -
if (tier == 1) {
//
buttons2.value.forEach(item => {
item.selected = false
})
//
props.treeData.forEach(item => {
item.selected = false
})
//
showControlMode.value = false;
//
showControlScene.value = false;
//
selectedButton4.value = null;
} else if (tier == 2) {
//
showControlScene.value = false;
//
selectedButton4.value = null;
}
}
//
const refresh = () => { const refresh = () => {
selectedButton.value = {}; executeVisible.value = false
selectedButton.value = '1';
emit('changeArea', []);
emit('changeArea', [1]);
showControlMode.value = false; showControlMode.value = false;
showControlScene.value = false; showControlScene.value = false;
selectedButton3.value = null;
selectedButton4.value = null; selectedButton4.value = null;
}; };
// //
const executevisible = ref<boolean>(false); const executeVisible = ref<boolean>(false);
const showModal = () => { const showModal = () => {
executevisible.value = true; executeVisible.value = true;
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import "./dialogStyle.less";
// //
.drawer-item { .drawer-item {
@ -614,7 +581,7 @@ const executevisible = ref<boolean>(false);
cursor: not-allowed; cursor: not-allowed;
} }
.openplan.enabled2 { .openPlan.enabled2 {
border: none; border: none;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
@ -627,7 +594,7 @@ const executevisible = ref<boolean>(false);
color: white; color: white;
} }
.openplan.disabled2 { .openPlan.disabled2 {
border: none; border: none;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
@ -639,7 +606,7 @@ const executevisible = ref<boolean>(false);
background-color: red; background-color: red;
} }
.openplan:disabled { .openPlan:disabled {
cursor: not-allowed; cursor: not-allowed;
} }
@ -714,7 +681,7 @@ const executevisible = ref<boolean>(false);
} }
.area, .area,
.btnarea, .btnArea,
.control-mode-btn-area, .control-mode-btn-area,
.control-scene-btn-area { .control-scene-btn-area {
margin-left: -17px; margin-left: -17px;
@ -828,7 +795,6 @@ const executevisible = ref<boolean>(false);
position: fixed; position: fixed;
bottom: 0; bottom: 0;
right: 0; right: 0;
margin-bottom: 10px;
} }
.execute { .execute {
@ -836,6 +802,7 @@ const executevisible = ref<boolean>(false);
width: 74px; width: 74px;
height: 40px; height: 40px;
opacity: 1; opacity: 1;
cursor: pointer;
border-radius: 4px; border-radius: 4px;
background: rgba(67, 136, 251, 1); background: rgba(67, 136, 251, 1);
font-size: 14px; font-size: 14px;
@ -848,6 +815,7 @@ const executevisible = ref<boolean>(false);
.flushed { .flushed {
width: 74px; width: 74px;
height: 40px; height: 40px;
cursor: pointer;
opacity: 1; opacity: 1;
border-radius: 4px; border-radius: 4px;
font-size: 14px; font-size: 14px;
@ -857,50 +825,6 @@ const executevisible = ref<boolean>(false);
border: 1px solid rgba(193, 197, 204, 1); border: 1px solid rgba(193, 197, 204, 1);
} }
.tabreboot,
.tabdelete {
border: none;
background-color: rgba(0, 0, 0, 0);
font-size: 14px;
font-weight: 400;
letter-spacing: 0;
line-height: 20px;
color: rgba(67, 136, 251, 1);
}
.tabreboot {
margin-right: 8px;
}
.add {
width: 74px;
height: 40px;
opacity: 1;
border-radius: 4px;
background: rgba(67, 136, 251, 1);
border: rgba(67, 136, 251, 1);
font-size: 14px;
font-weight: 400;
color: white;
}
.divadd {
width: 100%;
height: 64px;
display: flex;
justify-content: flex-end;
align-items: center;
position: fixed;
bottom: 0;
right: 0;
margin-bottom: 10px;
margin-right: 20px;
}
.atable {
margin-top: 20px;
}
:deep(.ant-table-pagination) { :deep(.ant-table-pagination) {
visibility: hidden; visibility: hidden;
} }
@ -1006,9 +930,12 @@ const executevisible = ref<boolean>(false);
display: flex; display: flex;
align-items: center; align-items: center;
} }
.zmhlbtn { .zmhlbtn {
position: relative; position: relative;
} }
//
.anticon-stop { .anticon-stop {
position: absolute; position: absolute;
right: 3px; right: 3px;

216
hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs2.vue

@ -0,0 +1,216 @@
<template>
<div class="div-add">
<button class="add" @click="addModal">添加</button>
</div>
<table class="custom-table table1">
<thead>
<tr :style="{ background: 'rgba(35,45,69)' }">
<th>序号</th>
<th>执行时间</th>
<th>计划名称</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in dataSource" :key="index">
<td>{{ row.key }}</td>
<td>{{ row.data }}</td>
<td>{{ row.planName }}</td>
<td v-if="row.status === '待执行'">
<button
style="
font-size: 12px;
background: rgba(57, 215, 187, 0.1);
color: rgb(57, 215, 187);
border: 1px solid rgb(57, 215, 187);
">
{{ row.status }}
</button>
</td>
<td v-if="row.status !== '待执行'">
<button
style="
font-size: 12px;
background: rgba(243, 97, 99, 0.1);
border: 1px solid rgba(243, 97, 99);
color: rgba(243, 97, 99);
">
{{ row.status }}
</button>
</td>
<td>
<button class="tabReboot" @click="handleRefClick1">重启</button>
<button class="tabDelete">删除</button>
</td>
</tr>
</tbody>
</table>
<div class="out-dialog" v-if="addVisible">
<div class="content" v-if="addVisible">
<div class="div-operation"></div>
<span class="text-operation">计划库</span>
</div>
<div style="margin-top: 20px">
<a-transfer
v-model:target-keys="targetKeys"
:data-source="mockData"
show-search
:filter-option="filterOption"
:render="(item) => item.title"
@change="handleChange"
:style="{ color: 'rgba(255,255,255,1)' }"
@search="handleSearch"
:listStyle="{ border: '2px solid rgba(25,74,125,1)', height: 'calc(100vh - 200px)' }" />
</div>
<div style="width: 100%; height: 60px;"></div>
<div class="button-box">
<button class="cancel" @click="addVisible = false">取消</button>
<button class="execute">确定</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
//
onMounted(() => {
})
//
const dataSource = ref([
{
key: '1',
data: '2024-05-01',
planName: '劳动节',
status: '暂停中',
},
{
key: '2',
data: '2024-05-01',
planName: '国庆节',
status: '待执行',
},
{
key: '3',
data: '2024-05-01',
planName: '元旦',
status: '待执行',
},
]);
const addVisible = ref<boolean>(false);
//
const handleRefClick1 = () => {
alert(111)
};
const addModal = () => {
addVisible.value = true;
};
const handleChange = (keys: string[], direction: string, moveKeys: string[]) => {
console.log(keys, direction, moveKeys);
};
const handleSearch = (dir: string, value: string) => {
console.log('search:', dir, value);
};
// 穿
interface MockData {
key: string;
title: string;
description: string;
chosen: boolean;
}
const mockData = ref([
{
key: '1',
title: '计划再开',
},
{
key: '2',
title: '检修模式',
},
{
key: '3',
title: '设备变更',
},
]);
const targetKeys = ref<string[]>([]);
const filterOption = (inputValue: string, option: MockData) => {
console.log(option.description);
return option.description.indexOf(inputValue) > -1;
};
</script>
<style lang="less" scoped>
@import "./dialogStyle.less";
//
.div-add {
height: 64px;
display: flex;
justify-content: flex-end;
align-items: center;
position: fixed;
bottom: 0;
right: 0;
margin-right: 20px;
.add {
width: 74px;
height: 40px;
opacity: 1;
border-radius: 4px;
background: rgba(67, 136, 251, 1);
border: rgba(67, 136, 251, 1);
font-size: 14px;
font-weight: 400;
color: rgba(255, 255, 255, 1);
}
}
//
.custom-table {
border-collapse: collapse;
width: 416px;
height: 60px;
color: rgba(255, 255, 255, 1);
}
.custom-table th,
.custom-table td {
border: 1px solid rgba(163, 192, 243, 1);
text-align: left;
padding: 8px;
text-align: center;
}
.table1 {
margin-top: 20px;
width: 100%;
border: 1px solid rgba(255, 255, 255);
border-radius: 5px;
background: rgba(255, 255, 255, 0.1);
//
.tabReboot,
.tabDelete {
border: none;
background-color: rgba(0, 0, 0, 0);
font-size: 14px;
font-weight: 400;
letter-spacing: 0;
line-height: 20px;
color: rgba(67, 136, 251, 1);
}
.tabReboot {
margin-right: 8px;
}
}
::v-deep(.ant-transfer) {
// hover
.ant-transfer-list-content-item:hover {
background: black;
}
}
</style>

255
hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs3.vue

@ -0,0 +1,255 @@
<template>
<table class="custom-table table1">
<thead>
<tr :style="{ background: 'rgba(35,45,69)' }">
<th>序号</th>
<th>执行时间</th>
<th>操作内容</th>
<th>操作人</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in dataSource1" :key="index" @click="handleRowClick(row.key)"
:class="row.key === trIndex ? 'isTrIndex' : ''">
<td>{{ row.key }}</td>
<td>{{ row.data }}</td>
<td>{{ row.planName }}</td>
<td>{{ row.status }}</td>
</tr>
</tbody>
</table>
<div class="out-dialog" v-if="logModalVisible">
<div class="content" v-if="logModalVisible">
<div>
<div class="div-operation"></div>
<span class="text-operation">变更内容 </span>
</div>
<div class="jbox" v-for="item in cxList" :key="item.id">
<div class="journal" style="margin-top: 20px">
<div class="imgText">
<div class="zjzm">
<img class="title-img" src="/asset/image//bulbLogo/21961.png" alt="" />&nbsp;
<span class="title-text" style="font-size: 20px; font-weight: 500; color: rgba(255, 255, 255, 1)">{{
item.name }}</span>
</div>
</div>
<div class="btn-box">
<div class="btn-item">
<div class="left">控制模式</div>
<div class="right">
<span>手动</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>自动</span>
</div>
</div>
<div class="btn-item">
<div class="left">
亮度
</div>
<div class="right">
<span>100lux</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>30lux</span>
</div>
</div>
<div class="btn-item">
<div class="left">
控制场景
</div>
<div class="right">
<span>手动</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>自动</span>
</div>
</div>
<div class="btn-item">
<div class="left">
色温
</div>
<div class="right">
<span>4000k</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>3800k</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="height: 60px;"></div>
<div class="button-box">
<button class="cancel" @click="logModalVisible = false">取消</button>
</div>
</div>
<div class="div-add">
<button class="add">刷新</button>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
//
onMounted(() => {
})
// ===================================================================
const props = defineProps({
// >
treeData: {
type: Array
},
});
const emit = defineEmits(['changeArea']);
//
const dataSource1 = ref([
{
key: '1',
data: '2024-05-01',
planName: '计划再开',
status: '张三111',
},
{
key: '2',
data: '2024-05-01',
planName: '检修模式',
status: '李四12',
},
{
key: '3',
data: '2024-05-01',
planName: '设备变更',
status: '王五33',
},
]);
const cxList = ref([
{
id: '1',
name: '站厅照明 1区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
{
id: '2',
name: '站厅照明 2区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
{
id: '3',
name: '站厅照明 3区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
]);
let trIndex = ref('-1');
const logModalVisible = ref(false);
const handleRowClick = (index: any) => {
trIndex.value = index;
if (index === trIndex.value) {
console.log('tri');
}
//
logModalVisible.value = true;
};
</script>
<style lang="less" scoped>
@import "./dialogStyle.less";
//
.div-add {
height: 64px;
display: flex;
justify-content: flex-end;
align-items: center;
position: fixed;
bottom: 0;
right: 0;
margin-right: 20px;
.add {
width: 74px;
height: 40px;
opacity: 1;
border-radius: 4px;
background: rgba(67, 136, 251, 1);
border: rgba(67, 136, 251, 1);
font-size: 14px;
font-weight: 400;
color: rgba(255, 255, 255, 1);
}
}
//
.custom-table {
border-collapse: collapse;
width: 416px;
height: 60px;
color: rgba(255, 255, 255, 1);
}
.custom-table th,
.custom-table td {
border: 1px solid rgba(163, 192, 243, 1);
text-align: left;
padding: 8px;
text-align: center;
}
.table1 {
margin-top: 20px;
width: 100%;
border: 1px solid rgba(255, 255, 255);
border-radius: 5px;
background: rgba(255, 255, 255, 0.1);
.tabReboot,
.tabDelete {
border: none;
background-color: rgba(0, 0, 0, 0);
font-size: 14px;
font-weight: 400;
letter-spacing: 0;
line-height: 20px;
color: rgba(67, 136, 251, 1);
}
.tabReboot {
margin-right: 8px;
}
.isTrIndex {
background: rgba(67, 136, 251, 1);
}
}
::v-deep(.ant-transfer) {
// hover
.ant-transfer-list-content-item:hover {
background: black;
}
}
</style>

73
hx-ai-intelligent/src/view/equipmentManage/group/config.ts

@ -1,8 +1,9 @@
import { NsSelect } from './../../../../../lib/component/form/select/index';
import { dateUtil } from '/nerv-lib/util/date-util'; import { dateUtil } from '/nerv-lib/util/date-util';
import data from './mock.json'; import data from './mock.json';
import { http } from '/nerv-lib/util'; import { http } from '/nerv-lib/util';
import { ref } from 'vue'; import { ref } from 'vue';
import { group } from '/@/api/deviceManage'; import { device, group } from '/@/api/deviceManage';
import { dict } from '/@/api'; import { dict } from '/@/api';
import { origanizemanage } from '/@/api/origanizemanage'; import { origanizemanage } from '/@/api/origanizemanage';
const tableCalKeyMap = [ const tableCalKeyMap = [
@ -122,7 +123,7 @@ export const formSchema = [
immediate: true, immediate: true,
// resultField: 'data.COUNT_POINT', // resultField: 'data.COUNT_POINT',
labelField: 'cnValue', labelField: 'cnValue',
valueField: 'cnValue', valueField: 'dicKey',
}, },
rules: [ rules: [
{ {
@ -198,7 +199,7 @@ export const treeConfig = (orgId) => {
immediate: true, immediate: true,
// resultField: 'data.ENERGY_TYPE', // resultField: 'data.ENERGY_TYPE',
labelField: 'cnValue', labelField: 'cnValue',
valueField: 'cnValue', valueField: 'dicKey',
placeholder: '请选择能耗种类', placeholder: '请选择能耗种类',
autoSelectFirst: true, autoSelectFirst: true,
}, },
@ -303,9 +304,22 @@ export const tableConfig = (el, elGroup, elFormula, defaultParams) => {
schemas: [ schemas: [
{ {
field: 'orgName', field: 'orgName',
component: 'NsInput', component: 'NsSelectApi',
defaultParams: defaultParams.value,
componentProps: { componentProps: {
placeholder: '请选择公司', placeholder: '请选择公司',
mode: 'multiple',
api: group.dropGroupFilter,
resultField: 'data',
params: { filterField: 'ORG' },
labelField: 'orgName',
valueField: 'orgId',
filterOption: (input: string, option: any) => {
return option.deviceName.toLowerCase().indexOf(input.toLowerCase()) >= 0;
},
showSearch: true,
dropdownReload: true,
allowClear: true,
}, },
}, },
{ {
@ -433,11 +447,23 @@ export const tableConfigCal = (el, elGroup, elFormula, defaultParams) => {
formConfig: { formConfig: {
schemas: [ schemas: [
{ {
field: 'name', field: 'orgIds',
label: '公司', component: 'NsSelectApi',
component: 'NsInput', defaultParams: defaultParams.value,
componentProps: { componentProps: {
placeholder: '请选择公司', placeholder: '请选择公司',
mode: 'multiple',
api: group.dropGroupInfoFilter,
resultField: 'data',
params: { filterField: 'ORG' },
labelField: 'orgName',
valueField: 'orgId',
filterOption: (input: string, option: any) => {
return option.deviceName.toLowerCase().indexOf(input.toLowerCase()) >= 0;
},
showSearch: true,
dropdownReload: true,
allowClear: true,
}, },
}, },
{ {
@ -455,17 +481,40 @@ export const tableConfigCal = (el, elGroup, elFormula, defaultParams) => {
}, },
}, },
{ {
field: 'provider', field: 'deviceStatus',
component: 'NsInput', component: 'NsSelectApi',
componentProps: { componentProps: {
placeholder: '请输入设备状态', placeholder: '请选择设备状态',
api: () => dict({ params: { dicKey: 'DEVICE_STATUS' } }),
immediate: true,
labelField: 'cnValue',
valueField: 'dicKey',
}, },
}, },
{ {
field: 'deviceNameType', field: 'deviceNameType',
component: 'NsInput', component: 'NsSelectApi',
defaultParams: defaultParams.value,
componentProps: { componentProps: {
placeholder: '请输入设备型号', placeholder: '请选择设备型号',
mode: 'multiple',
api: (params: any) => {
return http.post(group.dropGroupInfoFilter, params).then((res: any) => {
const result = [...new Set(res.data)];
return { data: result };
});
},
resultField: 'data',
params: { filterField: 'DEVICE_TYPE' },
// labelField: 'orgName',
// valueField: 'orgId',
filterOption: (input: string, option: any) => {
return option.deviceName.toLowerCase().indexOf(input.toLowerCase()) >= 0;
},
showSearch: true,
dropdownReload: true,
allowClear: true,
}, },
}, },
{ {

2
hx-ai-intelligent/src/view/equipmentManage/group/editCal.vue

@ -104,7 +104,7 @@
item['key'] = item.id.toString(); item['key'] = item.id.toString();
return item; return item;
}); });
targetKeys.value = res.data.linkGroups?.map((item) => { targetKeys.value = res.data.linkDeviceInfos?.map((item) => {
return item.id.toString(); return item.id.toString();
}); });
}); });

18
hx-ai-intelligent/src/view/equipmentManage/group/editGroup.vue

@ -7,6 +7,7 @@
:cancel="() => (visible = false)" :cancel="() => (visible = false)"
placement="right"> placement="right">
<ns-form <ns-form
ref="editGroupRef"
:schemas="schemas(inputDisabled)" :schemas="schemas(inputDisabled)"
:model="model" :model="model"
formLayout="vertical" formLayout="vertical"
@ -15,7 +16,7 @@
<template #addonAfter="data"> <template #addonAfter="data">
<template v-if="data.field === 'groupName'"> <template v-if="data.field === 'groupName'">
<div class="iconOP"> <div class="iconOP">
<EditOutlined v-if="inputDisabled" @click="() => (inputDisabled = false)" /> <EditOutlined v-if="inputDisabled" @click="editGroup" />
<CheckOutlined v-else @click="op" /> <CheckOutlined v-else @click="op" />
</div> </div>
</template> </template>
@ -53,6 +54,7 @@
const emit = defineEmits(['sure']); const emit = defineEmits(['sure']);
const props = defineProps({ params: Object }); const props = defineProps({ params: Object });
const visible = ref(false); const visible = ref(false);
const editGroupRef = ref();
const model = ref({}); const model = ref({});
const inputDisabled = ref(true); const inputDisabled = ref(true);
const selectedRowKeys = ref([]); const selectedRowKeys = ref([]);
@ -63,6 +65,7 @@
}; };
const startCararcter = 65; const startCararcter = 65;
//
const addGroup = () => { const addGroup = () => {
opType = true; opType = true;
getCode(); getCode();
@ -71,20 +74,31 @@
model.value = { groupName: '' }; model.value = { groupName: '' };
// if(mockDataSource.value.length) // if(mockDataSource.value.length)
}; };
const op = () => { const op = () => {
inputDisabled.value = !inputDisabled.value; inputDisabled.value = !inputDisabled.value;
add(); add();
}; };
//
const editGroup = () => {
if (!selectedRowKeys.value?.length) {
NsMessage.warn('请先选择需要编辑的分组');
return;
}
inputDisabled.value = false;
};
//
const add = () => { const add = () => {
const finalParams = { ...props.params, ...model.value }; const finalParams = { ...props.params, ...model.value };
if (opType) { if (opType) {
delete finalParams.id; delete finalParams.id;
} }
editGroupRef.value.triggerSubmit().then(() => {
http.post(group.saveComputeGroup, finalParams).then(() => { http.post(group.saveComputeGroup, finalParams).then(() => {
getTableData(); getTableData();
NsMessage.success('操作成功'); NsMessage.success('操作成功');
}); });
});
}; };
const delGroup = (id) => { const delGroup = (id) => {

27
hx-ai-intelligent/src/view/equipmentManage/group/index.vue

@ -16,7 +16,14 @@
<template #title="data"> <template #title="data">
<div class="treeRow"> <div class="treeRow">
<div> <div>
<ns-icon :name="data.pointType !== '计算节点' ? 'fenzujiedian' : 'jisuanjiedian'" /> <ns-icon
:name="
data?.id === 'all'
? 'common'
: data.pointType === 'GROUPING_NODE'
? 'fenzujiedian'
: 'jisuanjiedian'
" />
<span style="padding-left: 8px">{{ data.pointName }}</span> <span style="padding-left: 8px">{{ data.pointName }}</span>
</div> </div>
<a-dropdown> <a-dropdown>
@ -64,7 +71,12 @@
const treeRef = ref(); const treeRef = ref();
const defaultType = ref(true); const defaultType = ref(true);
const result = JSON.parse(sessionStorage.getItem('ORGID')!); const result = JSON.parse(sessionStorage.getItem('ORGID')!);
const defaultParams = ref({ orgId: result, energyType: '用电量', id: '', hxDeviceGroupId: '' }); const defaultParams = ref({
orgId: result,
energyType: 'ELECTRICITY_USAGE',
id: '',
hxDeviceGroupId: '',
});
const config = tableConfig(editDrawerRef, editGroupRef, editFormulaRef, defaultParams); const config = tableConfig(editDrawerRef, editGroupRef, editFormulaRef, defaultParams);
const configCal = tableConfigCal(editDrawerCalRef, editGroupRef, editFormulaRef, defaultParams); const configCal = tableConfigCal(editDrawerCalRef, editGroupRef, editFormulaRef, defaultParams);
@ -165,7 +177,7 @@
defaultParams.value.energyType = energyType; defaultParams.value.energyType = energyType;
defaultParams.value.id = id; defaultParams.value.id = id;
defaultParams.value.hxDeviceGroupId = id; defaultParams.value.hxDeviceGroupId = id;
defaultType.value = pointType === '分组节点'; defaultType.value = pointType === 'GROUPING_NODE';
defaultType.value defaultType.value
? tableRef.value?.nsTableRef.reload() ? tableRef.value?.nsTableRef.reload()
: tableCalRef.value?.nsTableRef.reload(); : tableCalRef.value?.nsTableRef.reload();
@ -215,9 +227,16 @@
} }
} }
.treeRow { .common-style {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
.treeRow {
.common-style;
> div:first-child {
.common-style;
}
}
</style> </style>

44
hx-ai-intelligent/src/view/equipmentManage/ledger/config.ts

@ -138,9 +138,21 @@ export const tableConfig = (orgId) => {
{ {
field: 'deviceName', field: 'deviceName',
label: '设备名称', label: '设备名称',
component: 'NsInput', component: 'NsSelectApi',
componentProps: { componentProps: {
placeholder: '请输入设备名称', placeholder: '请选择设备名称',
api: device.dropArea,
resultField: 'data',
params: { orgId, filterField: 'DEVICE_NAME_FACTORY' },
labelField: 'deviceName',
valueField: 'deviceName',
filterOption: (input: string, option: any) => {
return option.deviceName.toLowerCase().indexOf(input.toLowerCase()) >= 0;
},
showSearch: true,
immediate: true,
dropdownReload: true,
allowClear: true,
}, },
}, },
{ {
@ -166,7 +178,7 @@ export const tableConfig = (orgId) => {
loadData: (selectedOptions, options) => { loadData: (selectedOptions, options) => {
const targetOption = selectedOptions[selectedOptions.length - 1]; const targetOption = selectedOptions[selectedOptions.length - 1];
if (!selectedOptions.length) { if (!selectedOptions.length) {
http.post(device.dropArea, { orgId }).then((res) => { http.post(device.dropArea, { orgId, filterField: 'DEVICE_AREA' }).then((res) => {
options.value = res.data?.map((item) => { options.value = res.data?.map((item) => {
return { label: item, value: item, children: [], isLeaf: false }; return { label: item, value: item, children: [], isLeaf: false };
}); });
@ -175,7 +187,9 @@ export const tableConfig = (orgId) => {
const value = targetOption?.value; const value = targetOption?.value;
if (targetOption) { if (targetOption) {
targetOption.loading = true; targetOption.loading = true;
http.post(device.dropArea, { device1Area: value, orgId }).then((res) => { http
.post(device.dropArea, { device1Area: value, orgId, filterField: 'DEVICE_AREA' })
.then((res) => {
targetOption.loading = false; targetOption.loading = false;
targetOption.children = res.data?.map((item) => { targetOption.children = res.data?.map((item) => {
return { label: item, value: item, children: [], isLeaf: true }; return { label: item, value: item, children: [], isLeaf: true };
@ -188,15 +202,21 @@ export const tableConfig = (orgId) => {
{ {
field: 'manufacturer', field: 'manufacturer',
label: '设备厂商', label: '设备厂商',
component: 'NsInput', component: 'NsSelectApi',
componentProps: { componentProps: {
placeholder: '请输入设备厂商', placeholder: '请选择设备厂商',
options: [ api: device.dropArea,
{ resultField: 'data',
label: '全部', params: { orgId, filterField: 'DEVICE_NAME_FACTORY' },
value: '', labelField: 'manufacturer',
}, valueField: 'manufacturer',
], filterOption: (input: string, option: any) => {
return option.manufacturer.toLowerCase().indexOf(input.toLowerCase()) >= 0;
},
showSearch: true,
immediate: true,
dropdownReload: true,
allowClear: true,
}, },
}, },
{ {

506
hx-ai-intelligent/src/view/equipmentManage/ledger/mock.json

@ -1,506 +0,0 @@
{
"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
}
]
}

44
hx-ai-intelligent/src/view/monitor/energyMonitor/analysisGraph/index.vue

@ -48,6 +48,8 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, ref, inject, watch } from 'vue'; import { defineComponent, onMounted, ref, inject, watch } from 'vue';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';
export default defineComponent({ export default defineComponent({
name: 'AnalysisGraph', name: 'AnalysisGraph',
@ -413,17 +415,45 @@
}); });
// //
const downloadChart = () => { const downloadChart = async () => {
if (chartInstance) { // if (chartInstance) {
const base64 = chartInstance.getDataURL({ // const base64 = chartInstance.getDataURL({
// type: 'png',
// backgroundColor: '#fff',
// });
// const link = document.createElement('a');
// link.href = base64;
// link.download = 'chart.png';
// link.click();
// }
const zip = new JSZip();
const chartInstances = [chartInstance, chartRight1, chartRight2];
const imagePromises = chartInstances.map((chart: any, index) => {
return new Promise((resolve) => {
const base64 = chart.getDataURL({
type: 'png', type: 'png',
backgroundColor: '#fff', backgroundColor: '#fff',
}); });
const link = document.createElement('a'); // Base64
link.href = base64; const binary = atob(base64.split(',')[1]);
link.download = 'chart.png'; const array = [];
link.click(); for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
} }
const uint8Array = new Uint8Array(array);
resolve({ name: `chart${index + 1}.png`, data: uint8Array });
});
});
const images = await Promise.all(imagePromises);
images.forEach((image: any) => {
zip.file(image.name, image.data);
});
zip.generateAsync({ type: 'blob' }).then((content) => {
saveAs(content, 'charts.zip'); // 使 FileSaver.js ZIP
});
}; };
return { return {

627
hx-ai-intelligent/src/view/monitor/environmentMonitor/aggregateData/index.vue

File diff suppressed because one or more lines are too long

24
hx-ai-intelligent/src/view/monitor/environmentMonitor/index.vue

@ -0,0 +1,24 @@
<template>
<a-tabs v-model:activeKey="activeKey" style="height: 5%">
<a-tab-pane key="1" tab="综合数据" />
<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>
<!-- <ns-view-list-table v-bind="tableConfig" v-if="activeKey == '1'" /> -->
<aggregate-data ref="aggregateDataRef" v-if="activeKey == '1'" style="height: 85%" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { tableConfig } from './config';
import aggregateData from './aggregateData/index.vue';
const aggregateDataRef = ref();
var activeKey = ref('1');
defineOptions({
name: 'EnvironmentMonitorIndex', // name
});
</script>
<style lang="less" scoped></style>

2
lib/saas/view/system/login.vue

@ -129,7 +129,7 @@
accountNo: userName.value.trim(), accountNo: userName.value.trim(),
password: password.value.trim(), password: password.value.trim(),
}); });
validator(null, value.code) validator(null, value?.code)
.then(() => { .then(() => {
// //
rememberFunc(data); rememberFunc(data);

Loading…
Cancel
Save