diff --git a/config/routes.ts b/config/routes.ts index dc5c569..504786e 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-03-27 14:56:27 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-22 16:50:40 + * @LastEditTime: 2024-04-26 09:33:39 * @FilePath: \general-ai-manage\config\routes.ts * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -103,9 +103,9 @@ export const innerMenuRoutes = [ menuIcon: 'TestIcon', }, { - name: 'business-node-setting', - path: '/business/nodeSetting', - component: './Business/NodeSetting', + name: 'business-device-group', + path: '/business/deviceGroup', + component: './Business/DeviceGroup', access: 'canReadMenu', key: '1002', menuIcon: '', diff --git a/mock/device.ts b/mock/device.ts new file mode 100644 index 0000000..423c51c --- /dev/null +++ b/mock/device.ts @@ -0,0 +1,33 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-25 15:45:17 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-28 17:15:19 + * @FilePath: \general-ai-platform-web\mock\device.ts + * @Description: mock设备数据 + */ +import { mockGetDeviceListByGroup } from './pools/deviceData'; + +import { successMockApiProps } from './typing'; +import { fetchCurrPageByList } from './utils/apiMock'; + +export default { + // 设备列表 + 'GET /api/device/listByGroup': async (req: Request, res: Response) => { + const { page, pageSize } = req.query; + const resData: successMockApiProps = { + ...fetchCurrPageByList({ + ...mockGetDeviceListByGroup, + data: { ...mockGetDeviceListByGroup.data, page, pageSize: pageSize || 10 }, + }), + }; + res.json(resData); + }, + // // 设备分类 + // 'GET /api/dict/deviceType': async (req: Request, res: Response) => { + // const resData: successMockApiProps = { + // ...fetchMockSuccessFullByOther(mockGetDeviceTypeDictData), + // }; + // res.json(resData); + // }, +}; diff --git a/mock/deviceGroup.ts b/mock/deviceGroup.ts index d1eaf50..0da5dbb 100644 --- a/mock/deviceGroup.ts +++ b/mock/deviceGroup.ts @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-01-25 16:53:15 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-25 15:50:16 + * @LastEditTime: 2024-04-26 16:35:54 * @FilePath: \general-ai-platform-web\mock\deviceGroup.ts * @Description: 节点设备设置 mock */ @@ -12,6 +12,7 @@ import { mockGetDeviceGroupData3, mockGetDeviceGroupFkSelectData, mockGetDeviceGroupListData, + mockGetDeviceGroupSettingData, mockGetDeviceGroupTreeData, } from './pools/deviceGroupData'; import { successMockApiProps } from './typing'; @@ -29,6 +30,15 @@ export default { res.json(resData); }, + // 设备组网点树列表 + 'GET /api/device_group/setting_data': async (req: Request, res: Response) => { + const resData: successMockApiProps = { + ...fetchMockSuccessFullByOther(mockGetDeviceGroupSettingData), + }; + res.json(resData); + }, + + /** 未启用 */ // 设备组网点选项列表 'GET /api/device_group/getDeviceGroupFkSelect': async (req: Request, res: Response) => { const resData: successMockApiProps = { @@ -43,6 +53,7 @@ export default { }; res.json(resData); }, + // 设备组详情 'GET /api/device_group/getDeviceGroupById': async (req: Request, res: Response) => { const { id } = req.query; diff --git a/mock/dict.ts b/mock/dict.ts index 66323f5..10ad869 100644 --- a/mock/dict.ts +++ b/mock/dict.ts @@ -2,21 +2,28 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-04-17 14:01:39 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-17 14:01:47 + * @LastEditTime: 2024-04-28 14:08:45 * @FilePath: \general-ai-manage\mock\dict.ts * @Description: 字典表mock数据处理 */ -import { mockGetIndustryDictData } from './pools/dictData'; +import { mockGetDeviceTypeDictData, mockGetIndustryDictData } from './pools/dictData'; import { successMockApiProps } from './typing'; import { fetchMockSuccessFullByOther } from './utils/apiMock'; export default { - // 实时分析告警列表分页 - 'GET /api/dict/industry/': async (req: Request, res: Response) => { + // 行业分类 + 'GET /api/dict/industry': async (req: Request, res: Response) => { const resData: successMockApiProps = { ...fetchMockSuccessFullByOther(mockGetIndustryDictData), }; res.json(resData); }, + // 设备分类 + 'GET /api/dict/deviceType': async (req: Request, res: Response) => { + const resData: successMockApiProps = { + ...fetchMockSuccessFullByOther(mockGetDeviceTypeDictData), + }; + res.json(resData); + }, }; diff --git a/mock/pools/deviceData.ts b/mock/pools/deviceData.ts new file mode 100644 index 0000000..e64e2c9 --- /dev/null +++ b/mock/pools/deviceData.ts @@ -0,0 +1,35 @@ +// 节点下设备列表数据 +// 节点设备列表 +export const mockGetDeviceListByGroup = { + data: { + count: 2, + results: [ + { + id: '10001', + name: '海康威视环球摄像头', // 设备名称 + deviceType: '摄像头', // 设备类型 + isEnable: true, // 是否部署 + createTime: '2023-12-17T13:37:31.758471+08:00', + updateTime: '2024-04-25T15:22:16.530494+08:00', + deviceSite: '东区左侧', // 设备位置 + deviceModel: 'haikang_video_2024', // 设备型号 + deviceParams: '627663_aduh237298', // 设备参数 + remark: '', // 备注 + }, + { + id: '10002', + name: '海康威视环球摄像头', + deviceType: '控制器', + isEnable: false, + createTime: '2023-12-17T13:37:31.758471+08:00', + updateTime: '2024-04-25T15:22:16.530494+08:00', + deviceSite: '南区前侧', + deviceModel: 'haikang_video_2024', + deviceParams: '627663_aduh237298', + remark: '', + }, + ], + page: 1, + pageSize: 10, + }, +}; diff --git a/mock/pools/deviceGroupData.ts b/mock/pools/deviceGroupData.ts index b815405..6146b05 100644 --- a/mock/pools/deviceGroupData.ts +++ b/mock/pools/deviceGroupData.ts @@ -1,40 +1,257 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-25 15:45:31 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-29 14:44:39 + * @FilePath: \general-ai-platform-web\mock\pools\deviceGroupData.ts + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ /* * @Author: donghao donghao@supervision.ltd * @Date: 2024-01-25 16:32:31 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-25 15:51:57 + * @LastEditTime: 2024-04-28 13:21:47 * @FilePath: \general-ai-platform-web\mock\pools\deviceGroupData.ts * @Description: 节点设备设置 */ -// 设备组节点选项列表 -export const mockGetDeviceGroupFkSelectData = { - data: { - list: [ - { - name: '南京节点', - id: 1, - }, - { - name: '秦淮节点', - id: 2, - }, - { - name: '江宁节点', - id: 3, - }, - { - name: '安徽节点', - id: 4, - }, - { - name: '合肥节点', - id: 5, - }, - ], - }, -}; // 设备组节点树 +export const mockGetDeviceGroupSettingData = { + data: [ + { + name: '安徽省', + id: '340000', + groupList: [ + { + name: '合肥市', + id: '340100', + groupList: [ + { name: '瑶海区', id: '340102', groupList: [] }, + { name: '庐阳区', id: '340103', groupList: [] }, + { name: '蜀山区', id: '340104', groupList: [] }, + { name: '包河区', id: '340111', groupList: [] }, + { name: '长丰县', id: '340121', groupList: [] }, + { name: '肥东县', id: '340122', groupList: [] }, + { name: '肥西县', id: '340123', groupList: [] }, + { name: '庐江县', id: '340124', groupList: [] }, + { name: '巢湖市', id: '340181', groupList: [] }, + ], + }, + { + name: '芜湖市', + id: '340200', + groupList: [ + { name: '镜湖区', id: '340202', groupList: [] }, + { name: '弋江区', id: '340203', groupList: [] }, + { name: '鸠江区', id: '340207', groupList: [] }, + { name: '三山区', id: '340208', groupList: [] }, + { name: '芜湖县', id: '340221', groupList: [] }, + { name: '繁昌县', id: '340222', groupList: [] }, + { name: '南陵县', id: '340223', groupList: [] }, + { name: '无为县', id: '340225', groupList: [] }, + ], + }, + { + name: '蚌埠市', + id: '340300', + groupList: [ + { name: '龙子湖区', id: '340302', groupList: [] }, + { name: '蚌山区', id: '340303', groupList: [] }, + { name: '禹会区', id: '340304', groupList: [] }, + { name: '淮上区', id: '340311', groupList: [] }, + { name: '怀远县', id: '340321', groupList: [] }, + { name: '五河县', id: '340322', groupList: [] }, + { name: '固镇县', id: '340323', groupList: [] }, + ], + }, + { + name: '淮南市', + id: '340400', + groupList: [ + { name: '大通区', id: '340402', groupList: [] }, + { name: '田家庵区', id: '340403', groupList: [] }, + { name: '谢家集区', id: '340404', groupList: [] }, + { name: '八公山区', id: '340405', groupList: [] }, + { name: '潘集区', id: '340406', groupList: [] }, + { name: '凤台县', id: '340421', groupList: [] }, + { name: '寿县', id: '340422', groupList: [] }, + ], + }, + { + name: '马鞍山市', + id: '340500', + groupList: [ + { name: '花山区', id: '340503', groupList: [] }, + { name: '雨山区', id: '340504', groupList: [] }, + { name: '博望区', id: '340506', groupList: [] }, + { name: '当涂县', id: '340521', groupList: [] }, + { name: '含山县', id: '340522', groupList: [] }, + { name: '和县', id: '340523', groupList: [] }, + ], + }, + { + name: '淮北市', + id: '340600', + groupList: [ + { name: '杜集区', id: '340602', groupList: [] }, + { name: '相山区', id: '340603', groupList: [] }, + { name: '烈山区', id: '340604', groupList: [] }, + { name: '濉溪县', id: '340621', groupList: [] }, + ], + }, + { + name: '铜陵市', + id: '340700', + groupList: [ + { name: '铜官区', id: '340705', groupList: [] }, + { name: '义安区', id: '340706', groupList: [] }, + { name: '郊区', id: '340711', groupList: [] }, + { name: '枞阳县', id: '340722', groupList: [] }, + ], + }, + { + name: '安庆市', + id: '340800', + groupList: [ + { name: '迎江区', id: '340802', groupList: [] }, + { name: '大观区', id: '340803', groupList: [] }, + { name: '宜秀区', id: '340811', groupList: [] }, + { name: '怀宁县', id: '340822', groupList: [] }, + { name: '潜山市', id: '340882', groupList: [] }, + { name: '太湖县', id: '340825', groupList: [] }, + { name: '宿松县', id: '340826', groupList: [] }, + { name: '望江县', id: '340827', groupList: [] }, + { name: '岳西县', id: '340828', groupList: [] }, + { name: '桐城市', id: '340881', groupList: [] }, + ], + }, + { + name: '滁州市', + id: '341100', + groupList: [ + { name: '琅琊区', id: '341102', groupList: [] }, + { name: '南谯区', id: '341103', groupList: [] }, + { name: '来安县', id: '341122', groupList: [] }, + { name: '全椒县', id: '341124', groupList: [] }, + { name: '定远县', id: '341125', groupList: [] }, + { name: '凤阳县', id: '341126', groupList: [] }, + { name: '天长市', id: '341181', groupList: [] }, + { name: '明光市', id: '341182', groupList: [] }, + ], + }, + { + name: '阜阳市', + id: '341200', + groupList: [ + { name: '颍州区', id: '341202', groupList: [] }, + { name: '颍东区', id: '341203', groupList: [] }, + { name: '颍泉区', id: '341204', groupList: [] }, + { name: '临泉县', id: '341221', groupList: [] }, + { name: '太和县', id: '341222', groupList: [] }, + { name: '阜南县', id: '341225', groupList: [] }, + { name: '颍上县', id: '341226', groupList: [] }, + { name: '界首市', id: '341282', groupList: [] }, + ], + }, + { + name: '宿州市', + id: '341300', + groupList: [ + { name: '埇桥区', id: '341302', groupList: [] }, + { name: '砀山县', id: '341321', groupList: [] }, + { name: '萧县', id: '341322', groupList: [] }, + { name: '灵璧县', id: '341323', groupList: [] }, + { name: '泗县', id: '341324', groupList: [] }, + ], + }, + { + name: '六安市', + id: '341500', + groupList: [ + { name: '金安区', id: '341502', groupList: [] }, + { name: '裕安区', id: '341503', groupList: [] }, + { name: '叶集区', id: '341504', groupList: [] }, + { name: '霍邱县', id: '341522', groupList: [] }, + { name: '舒城县', id: '341523', groupList: [] }, + { name: '金寨县', id: '341524', groupList: [] }, + { name: '霍山县', id: '341525', groupList: [] }, + ], + }, + { + name: '亳州市', + id: '341600', + groupList: [ + { name: '谯城区', id: '341602', groupList: [] }, + { name: '涡阳县', id: '341621', groupList: [] }, + { name: '蒙城县', id: '341622', groupList: [] }, + { name: '利辛县', id: '341623', groupList: [] }, + ], + }, + { + name: '池州市', + id: '341700', + groupList: [ + { name: '贵池区', id: '341702', groupList: [] }, + { name: '东至县', id: '341721', groupList: [] }, + { name: '石台县', id: '341722', groupList: [] }, + { name: '青阳县', id: '341723', groupList: [] }, + ], + }, + { + name: '宣城市', + id: '341800', + groupList: [ + { name: '宣州区', id: '341802', groupList: [] }, + { name: '郎溪县', id: '341821', groupList: [] }, + { name: '广德县', id: '341822', groupList: [] }, + { name: '泾县', id: '341823', groupList: [] }, + { name: '绩溪县', id: '341824', groupList: [] }, + { name: '旌德县', id: '341825', groupList: [] }, + { name: '宁国市', id: '341881', groupList: [] }, + ], + }, + { + name: '黄山市', + id: '341000', + groupList: [ + { name: '屯溪区', id: '341002', groupList: [] }, + { name: '黄山区', id: '341003', groupList: [] }, + { name: '徽州区', id: '341004', groupList: [] }, + { name: '歙县', id: '341021', groupList: [] }, + { name: '休宁县', id: '341022', groupList: [] }, + { name: '黟县', id: '341023', groupList: [] }, + { name: '祁门县', id: '341024', groupList: [] }, + ], + }, + ], + }, + + { + name: '江苏省', + id: '320000', + groupList: [ + { + name: '南京市', + id: '320100', + groupList: [ + { name: '玄武区', id: '320102', groupList: [] }, + { name: '秦淮区', id: '320104', groupList: [] }, + { name: '建邺区', id: '320105', groupList: [] }, + { name: '鼓楼区', id: '320106', groupList: [] }, + { name: '浦口区', id: '320111', groupList: [] }, + { name: '栖霞区', id: '320113', groupList: [] }, + { name: '雨花台区', id: '320114', groupList: [] }, + { name: '江宁区', id: '320115', groupList: [] }, + { name: '六合区', id: '320116', groupList: [] }, + { name: '溧水区', id: '320117', groupList: [] }, + { name: '高淳区', id: '320118', groupList: [] }, + ], + }, + ], + }, + ], +}; + export const mockGetDeviceGroupTreeData = { data: { tree: [ @@ -72,17 +289,34 @@ export const mockGetDeviceGroupTreeData = { // 设备组列表分页 export const mockGetDeviceGroupListData = { data: { - list: [ + results: [ { - id: 1, + level: 1, + id: '0001', + createTime: '2023-10-17T10:43:31.254107+08:00', + updateTime: '2023-10-17T10:45:25.030034+08:00', + name: '上海节点', + address: '中国上海市浦东新区申迪北路', + fatherName: '无', + fatherId: '', + lon: 121.667987, + lat: 31.144417, + managerName: '刘芳', + managerPhone: '16526365632', + remark: '--', + // TODO 完成设备节点列表数据的构建 + }, + { + level: 1, + id: '0002', createTime: '2023-10-17T10:43:31.254107+08:00', updateTime: '2023-10-17T10:45:25.030034+08:00', name: '南京节点', code: 'DG00002', - address: '江苏省南京市南京市栖霞区紫东路南京紫东国际创意园', + address: '江苏省南京市南京市栖霞区紫东路南京紫东国际创意园', // 地址 telephone: '12345', - lon: '118.914349', - lat: '32.086019', + lon: '118.914349', // 经度 + lat: '32.086019', // 纬度 managerName: '张三', managerPhone: '111111111', isEnable: true, @@ -90,7 +324,8 @@ export const mockGetDeviceGroupListData = { remark: '', children: [ { - id: 2, + level: 2, + id: '20001', createTime: '2023-10-17T13:37:31.758471+08:00', updateTime: '2023-10-17T13:39:31.530494+08:00', name: '秦淮节点', @@ -105,10 +340,10 @@ export const mockGetDeviceGroupListData = { parentFkId: 1, remark: '', children: null, - key: '2', }, { - id: 3, + level: 2, + id: '20002', createTime: '2023-10-17T13:40:28.823372+08:00', updateTime: '2023-10-17T13:40:28.823372+08:00', name: '江宁节点', @@ -123,52 +358,42 @@ export const mockGetDeviceGroupListData = { parentFkId: 1, remark: '', children: null, - key: '3', }, ], - key: '1', + }, + ], + count: 2, + page: 1, + pageSize: 10, + }, +}; + +/** 未启用 */ +// 设备组节点选项列表 +export const mockGetDeviceGroupFkSelectData = { + data: { + list: [ + { + name: '南京节点', + id: 1, + }, + { + name: '秦淮节点', + id: 2, + }, + { + name: '江宁节点', + id: 3, }, { - id: 4, - createTime: '2023-10-17T15:02:30.725705+08:00', - updateTime: '2023-10-17T15:02:30.725705+08:00', name: '安徽节点', - code: 'DG00005', - address: '', - telephone: '', - lon: '', - lat: '', - managerName: '', - managerPhone: '', - isEnable: true, - parentFkId: 0, - remark: '', - children: [ - { - id: 5, - createTime: '2023-10-17T15:05:13.542992+08:00', - updateTime: '2023-10-17T15:08:01.071315+08:00', - name: '合肥节点', - code: 'DG00006', - address: '安徽省合肥市包河区马鞍山路130号', - telephone: '', - lon: '117.309214', - lat: '31.862594', - managerName: '', - managerPhone: '', - isEnable: true, - parentFkId: 4, - remark: '', - children: null, - key: '5', - }, - ], - key: '4', + id: 4, + }, + { + name: '合肥节点', + id: 5, }, ], - total: 0, - page: 1, - pageSize: 10, }, }; @@ -239,3 +464,107 @@ export const mockGetDeviceGroupData3 = { }, }, }; + +// 节点信息 +export const mockGetNodeInfo = [ + { + name: '南京中山陵', + address: '中国江苏省南京市玄武区明孝陵路1号', + fatherName: '南京', + fatherId: 'NJ002', + lon: 118.835383, + lat: 32.036853, + managerName: '赵刚', + managerPhone: '025-8443 5328', + remark: '中山陵是中国江苏省南京市的一处著名纪念建筑,是国父孙中山的陵墓。', + }, + { + name: '南京总统府', + address: '中国江苏省南京市玄武区长江路292号', + fatherName: '南京', + fatherId: 'NJ003', + lon: 118.796492, + lat: 32.054979, + managerName: '陈霞', + managerPhone: '025-8462 3951', + remark: + '南京总统府是中国南京市玄武区长江路292号的一座历史建筑,是中华民国时期南京国民政府的办公地点。', + }, + { + name: '东方明珠塔', + address: '中国上海市浦东新区陆家嘴环路1号', + fatherName: '上海', + fatherId: 'SH004', + lon: 121.506377, + lat: 31.239722, + managerName: '王静', + managerPhone: '021-5879 1888', + remark: '东方明珠塔是位于中国上海市浦东陆家嘴金融贸易区的一座电视塔,是上海的标志性建筑之一。', + }, + { + name: '南京雨花台', + address: '中国江苏省南京市雨花台区雨花路78号', + fatherName: '南京', + fatherId: 'NJ004', + lon: 118.748754, + lat: 31.997532, + managerName: '张磊', + managerPhone: '025-5275 0088', + remark: '雨花台是中国江苏省南京市雨花台区的一个丘陵,也是南京市的一个知名旅游景点。', + }, + { + name: '上海科技馆', + address: '中国上海市浦东新区世纪大道2000号', + fatherName: '上海', + fatherId: 'SH005', + lon: 121.537235, + lat: 31.216444, + managerName: '周洋', + managerPhone: '021-6854 6916', + remark: '上海科技馆是位于中国上海市浦东新区的一座科技展示馆,是上海市的科普教育基地之一。', + }, + { + name: '南京中华门', + address: '中国江苏省南京市秦淮区中华门', + fatherName: '南京', + fatherId: 'NJ005', + lon: 118.790325, + lat: 32.046384, + managerName: '李明', + managerPhone: '025-8357 8845', + remark: '中华门是中国江苏省南京市秦淮区的一处历史古迹,是南京古城墙的门。', + }, + { + name: '上海外滩观景台', + address: '中国上海市黄浦区中山东一路20号', + fatherName: '上海', + fatherId: 'SH006', + lon: 121.489562, + lat: 31.240737, + managerName: '王红', + managerPhone: '021-5879 8901', + remark: '上海外滩观景台位于上海市黄浦区外滩20号,是游览上海外滩天际线的最佳地点之一。', + }, + { + name: '南京中山陵石象路', + address: '中国江苏省南京市玄武区石象路', + fatherName: '南京', + fatherId: 'NJ006', + lon: 118.835168, + lat: 32.041867, + managerName: '刘军', + managerPhone: '025-8463 2211', + remark: '南京中山陵石象路是中国江苏省南京市玄武区的一条道路,沿路有许多历史建筑和景点。', + }, + { + name: '上海豫园', + address: '中国上海市黄浦区安仁街137号', + fatherName: '上海', + fatherId: 'SH007', + lon: 121.492783, + lat: 31.227565, + managerName: '张艳', + managerPhone: '021-6328 8888', + remark: '上海豫园是位于上海市黄浦区的一座古典式园林,是上海市的主要旅游景点之一。', + }, +]; diff --git a/mock/pools/dictData.ts b/mock/pools/dictData.ts index 233bf66..c350347 100644 --- a/mock/pools/dictData.ts +++ b/mock/pools/dictData.ts @@ -2,10 +2,12 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-04-17 13:58:57 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-17 14:05:50 + * @LastEditTime: 2024-04-28 14:03:58 * @FilePath: \general-ai-manage\mock\pools\dictData.ts * @Description: 字典表mock数据 */ + +// 行业分类 export const mockGetIndustryDictData = { data: { results: [ @@ -186,3 +188,12 @@ export const mockGetIndustryDictData = { ], }, }; +// 设备分类 +export const mockGetDeviceTypeDictData = { + data: { + results: [ + { id: 1002000, name: '摄像头' }, + { id: 1002002, name: '控制器' }, + ], + }, +}; diff --git a/public/home/business_arrow.svg b/public/home/business_arrow.svg new file mode 100644 index 0000000..81e46bd --- /dev/null +++ b/public/home/business_arrow.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/public/home/business_arrow_default.svg b/public/home/business_arrow_default.svg new file mode 100644 index 0000000..1be62d1 --- /dev/null +++ b/public/home/business_arrow_default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/home/business_big_logo.svg b/public/home/business_big_logo.svg new file mode 100644 index 0000000..abfc5bc --- /dev/null +++ b/public/home/business_big_logo.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/home/menu_footer_bg.png b/public/home/menu_footer_bg.png new file mode 100644 index 0000000..03d0aa5 Binary files /dev/null and b/public/home/menu_footer_bg.png differ diff --git a/src/app.css b/src/app.css index 28c310c..0058e65 100644 --- a/src/app.css +++ b/src/app.css @@ -12,6 +12,12 @@ background-color: transparent; padding-inline: 0 !important; } +.app_page_wrap .page_menu .ant-menu { + background-image: url(../public/home/menu_footer_bg.png); + background-repeat: no-repeat; + background-position: left bottom; + background-size: cover; +} .app_page_wrap .page_body { width: calc(100vw - 200px); } @@ -19,10 +25,10 @@ position: fixed; top: 0; right: 0; + z-index: 999; width: calc(100vw - 200px); min-width: 100px; height: 50px; - z-index: 999; padding: 0 24px 0 20px; background-color: #f8fafd; } diff --git a/src/app.less b/src/app.less index 9eae460..f1c874d 100644 --- a/src/app.less +++ b/src/app.less @@ -12,6 +12,17 @@ background-color: transparent; padding-inline: 0 !important; } + .page_menu { + // menu_footer_bg.png + + .ant-menu { + // background-color: red; + background-image: url(../public/home/menu_footer_bg.png); + background-repeat: no-repeat; + background-position: left bottom; + background-size: cover; + } + } .page_body { width: calc(100vw - 200px); .body_nav_bar { @@ -23,6 +34,7 @@ min-width: 100px; height: 50px; padding: 0 24px 0 20px; + background-color: #f8fafd; .avatar_box { & > img { diff --git a/src/app.tsx b/src/app.tsx index fc50d7a..44f72d4 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -145,7 +145,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) = // if (initialState?.loading) return ; return (
-
+
setCurrMenu(record)} diff --git a/src/base.less b/src/base.less index 6f5334b..9e293ff 100644 --- a/src/base.less +++ b/src/base.less @@ -39,6 +39,7 @@ text-align: left; text-transform: none; } + .head5 { color: #333333; font-weight: bold; @@ -61,6 +62,3 @@ text-align: left; text-transform: none; } - -body { -} diff --git a/src/components/MenuBar/index.css b/src/components/MenuBar/index.css index b3f42fd..22158f9 100644 --- a/src/components/MenuBar/index.css +++ b/src/components/MenuBar/index.css @@ -1,11 +1,11 @@ .menubar_wrap { position: fixed; - left: 0; top: 0; - height: 100vh; - display: flex; + left: 0; z-index: 999; + display: flex; width: 200px; + height: 100vh; padding: 0; background-color: #fff; border-radius: 0px 0px 32px 0px; @@ -46,7 +46,6 @@ display: flex; flex: 1; width: 100%; - padding-top: 10px; } .menubar_wrap .menu_bottom { width: 96px; diff --git a/src/components/MenuBar/index.less b/src/components/MenuBar/index.less index 5cb0639..7cdd32f 100644 --- a/src/components/MenuBar/index.less +++ b/src/components/MenuBar/index.less @@ -52,7 +52,6 @@ display: flex; flex: 1; width: 100%; - padding-top: 10px; } .menu_bottom { width: 96px; diff --git a/src/components/MenuBar/index.tsx b/src/components/MenuBar/index.tsx index ded5dd3..8270ed9 100644 --- a/src/components/MenuBar/index.tsx +++ b/src/components/MenuBar/index.tsx @@ -2,19 +2,20 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-03-27 16:03:20 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-23 10:48:58 + * @LastEditTime: 2024-04-28 09:44:23 * @FilePath: \general-ai-manage\src\components\Header\index.tsx * @Description: 内层layout菜单配置 */ import { useBusinessInfo } from '@/hooks/useBusinessInfo'; import { history, useIntl } from '@umijs/max'; +import { ReactComponent as BusinessLogoIcon } from '/public/home/business_logo.svg'; import type { MenuProps } from 'antd'; import { Menu } from 'antd'; import React, { useEffect, useState } from 'react'; -import { ReactComponent as BusinessLogoIcon } from '/public/home/business_logo.svg'; +import { ReactComponent as BusinessBigLogo } from '/public/home/business_big_logo.svg'; // import menuFooter from '/public/menuFooter.svg'; import './index.less'; @@ -104,10 +105,21 @@ const MenuBar: React.FC = ({ menuData, changeMenu }) => { return (
-
- - {getStoreBusinessInfo()?.name} +
+
{ + history.replace('/'); + }} + > + +
+
+ + {getStoreBusinessInfo()?.name} +
+ {/* // TODO 菜单需要补充路由聚焦状态 */}
= ({ menuData, changeMenu }) => { ))}
- {/*
- -
*/}
); }; diff --git a/src/components/Tree/index.ts b/src/components/Tree/index.ts new file mode 100644 index 0000000..53c59fd --- /dev/null +++ b/src/components/Tree/index.ts @@ -0,0 +1,3 @@ +import deviceGroupTree from './src/deviceGroupTree'; + +export const DeviceGroupTree = deviceGroupTree; diff --git a/src/components/Tree/src/baseTree.css b/src/components/Tree/src/baseTree.css new file mode 100644 index 0000000..e309232 --- /dev/null +++ b/src/components/Tree/src/baseTree.css @@ -0,0 +1,47 @@ +.base_tree_wrap { + font-size: 14px; +} +.base_tree_wrap > .ant-form-item { + margin-bottom: 0; +} +.base_tree_wrap > .ant-form-item .ant-input-outlined { + border: none; +} +.base_tree_wrap > .ant-form-item .ant-input:focus, +.base_tree_wrap > .ant-form-item .ant-input-focused { + border: none; + box-shadow: none; + /* 去掉聚焦时的阴影效果 */ + /* 如果需要,你也可以调整其他聚焦时的样式 */ +} +.base_tree_wrap > .ant-form-item .ant-input-outlined:focus, +.base_tree_wrap > .ant-form-item .ant-input-outlined:focus-within { + box-shadow: none; + /* 去掉聚焦时的阴影效果 */ +} +.base_tree_wrap .tree_node_1 { + width: 100%; + margin: 12px 0; + padding: 8px 17px; + background: #f5f5f5; + border-radius: 4px; + cursor: pointer; +} +.base_tree_wrap .tree_node_1 .ant-tree-switcher-noop { + opacity: 0; +} +.base_tree_wrap .tree_node_item .action_list { + display: none; +} +.base_tree_wrap .tree_node_1:hover, +.base_tree_wrap .ant-tree-treenode-selected { + color: #154ddd; + background: rgba(21, 77, 221, 0.1); + border-radius: 8px; +} +.base_tree_wrap .tree_node_item:hover .action_list { + display: block; +} +.base_tree_wrap .tree_node_item:hover .action_list .anticon-delete { + color: #e80d0d; +} diff --git a/src/components/Tree/src/baseTree.less b/src/components/Tree/src/baseTree.less new file mode 100644 index 0000000..ddc6b68 --- /dev/null +++ b/src/components/Tree/src/baseTree.less @@ -0,0 +1,53 @@ +.base_tree_wrap { + font-size: 14px; + & > .ant-form-item { + margin-bottom: 0; + .ant-input-outlined { + border: none; + } + .ant-input:focus, + .ant-input-focused { + border: none; + box-shadow: none; /* 去掉聚焦时的阴影效果 */ + /* 如果需要,你也可以调整其他聚焦时的样式 */ + } + .ant-input-outlined:focus, + .ant-input-outlined:focus-within { + box-shadow: none; /* 去掉聚焦时的阴影效果 */ + } + } + + .tree_node_1 { + width: 100%; + margin: 12px 0; + padding: 8px 17px; + background: #f5f5f5; + border-radius: 4px; + cursor: pointer; + .ant-tree-switcher-noop { + opacity: 0; + } + } + .tree_node_item { + .action_list { + display: none; + } + } + .tree_node_1:hover, + .ant-tree-treenode-selected { + color: #154ddd; + background: rgba(21, 77, 221, 0.1); + border-radius: 8px; + } + .tree_node_item:hover { + // color: #154ddd; + // background: rgba(21, 77, 221, 0.1); + // border-radius: 8px; + .action_list { + display: block; + .anticon-delete { + color: #e80d0d; + } + } + } +} diff --git a/src/components/Tree/src/baseTree.tsx b/src/components/Tree/src/baseTree.tsx new file mode 100644 index 0000000..7712e38 --- /dev/null +++ b/src/components/Tree/src/baseTree.tsx @@ -0,0 +1,247 @@ +import { formatTreeValByKey } from '@/utils/baseTree'; +import { DeleteFilled, SearchOutlined } from '@ant-design/icons'; +import { Button, Form, Input, Modal, Tree } from 'antd'; +import _debounce from 'lodash/debounce'; +import React, { useEffect, useState } from 'react'; +import { BaseTreeProps } from '../typing'; + +import { ProFormText } from '@ant-design/pro-components'; +import './baseTree.less'; +const { TreeNode } = Tree; + +const BaseTree: React.FC = (props) => { + /**state */ + // const { token } = theme.useToken(); + + const { treeData, ...defaultProps } = props; + console.log(treeData, 'treeData', defaultProps); + const [currTreeData, setCurrTreeData] = useState([ + // { title: '节点1', key: '1' }, + // { title: '节点2', key: '2', children: [{ title: '子节点1', key: '3' }] }, + ]); + + const [visible, setVisible] = useState(false); + const [editNodeKey, setEditNodeKey] = useState(null); + const [form] = Form.useForm(); + const action_add_key = ''; + + /**工具方法集 */ + // 柯里化-树的节点数值 + function formatTreeValByNodeKey( + key: 'title' | 'key' | 'children', + node: Record, + ): any { + return formatTreeValByKey(key, node, props.fieldNames); + } + + /**查询树节点 */ + // 定义一个防抖处理函数,500ms 后执行 handleChange 函数 + const debouncedHandleChange = _debounce((value) => { + // TODO 查询所有匹配的节点 + console.log('debouncedHandleChange_value:', value); + }, 500); + // 搜索节点 + function handleSearch(val) { + debouncedHandleChange(val); + } + + const handleAddNode = () => { + // setVisible(true); + // form.resetFields(); + }; + + // const getNodeByKey = (key) => { + // return currTreeData.find((node) => node.key === key); + // }; + + // const removeNodeByKey = (data, key) => { + // return data.filter((node) => { + // if (node.key === key) { + // return false; + // } + // if (node.children) { + // node.children = removeNodeByKey(node.children, key); + // } + // return true; + // }); + // }; + + // const handleEditNode = (key) => { + // setEditNodeKey(key); + // setVisible(true); + // form.setFieldsValue({ nodeTitle: getNodeByKey(key).title }); + // }; + + // const handleDeleteNode = (key) => { + // const newData = removeNodeByKey(currTreeData, key); + // setCurrTreeData(newData); + // }; + + // const handleAddChildNode = (key) => { + // setEditNodeKey(key); + // setVisible(true); + // form.resetFields(); + // }; + + // 组装节点数据 + const handleModalOk = () => { + form.validateFields().then((values) => { + const { nodeTitle } = values; + let newData; + if (editNodeKey) { + // 编辑节点标题 + newData = currTreeData.map((node) => { + if (node.key === editNodeKey) { + return { ...node, title: nodeTitle }; + } + return node; + }); + } else if (editNodeKey === null) { + // 新增根节点 + newData = [...currTreeData, { title: nodeTitle, key: Date.now().toString() }]; + } else { + // 新增子节点 + newData = currTreeData.map((node) => { + if (node.key === editNodeKey) { + return { + ...node, + children: [ + ...(node.children || []), + { title: nodeTitle, key: Date.now().toString() }, + ], + }; + } + return node; + }); + } + console.log('handleModalOk_newData', newData); + setCurrTreeData(newData); + setVisible(false); + setEditNodeKey(''); + }); + }; + + const handleModalCancel = () => { + setVisible(false); + setEditNodeKey(''); + }; + + // render 新增节点操作 + const renderAddAction = (node?: Record) => { + // console.log(node, 'renderAddAction_node'); + return props?.addRender ? ( + props?.addRender(node) + ) : ( +
+ +
+ ); + }; + + // 定义每个节点内容 递归操作 + const renderTreeNodes = (data) => { + if (Array.isArray(data) && data.length) { + return data.map((node) => { + return ( + + {formatTreeValByNodeKey('children', node) && + renderTreeNodes(formatTreeValByNodeKey('children', node))} + + + + ); + }); + } + return <>; + }; + // 渲染每个节点内容 + const renderTreeItem = (node) => { + return ( +
+ {node.title} + {!props?.hideInDelete ? ( + { + props.handleDelete(node); + }} + > + + + ) : ( + <> + )} +
+ ); + }; + + useEffect(() => { + setCurrTreeData(props.treeData); + console.log(props.treeData, 'props_treeData'); + }, [props.treeData]); + + return ( +
+ {!props?.hideInSearch ? ( + handleSearch(e.target.value)} + key="name" + name="name" + label="" + fieldProps={{ + style: { + margin: 0, + }, + prefix: , + }} + /> + ) : ( + <> + )} + { + console.log('selected', selectedKeys); + props.selectTree(selectedKeys, info); + }} + titleRender={(node) => { + if (node.title) { + return renderTreeItem(node); + } + return renderAddAction(node); + }} + {...defaultProps} + > + {renderTreeNodes(currTreeData)} + +
{renderAddAction()}
+ {/*
添加一级节点
*/} + + {/* TODO 使用ProForm */} + +
+ + + +
+
+
+ ); +}; + +export default BaseTree; diff --git a/src/components/Tree/src/deviceGroupTree.tsx b/src/components/Tree/src/deviceGroupTree.tsx new file mode 100644 index 0000000..b0568ea --- /dev/null +++ b/src/components/Tree/src/deviceGroupTree.tsx @@ -0,0 +1,72 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-26 11:11:05 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-29 16:26:05 + * @FilePath: \general-ai-manage\src\components\Tree\src\deviceGroupTree.tsx + * @Description: 设备节点树 + * @交互说明 + * 1、树形展示 + * 2、可新增、删除 + * 3、可编辑 + * 4、可拖拽 + */ +import { PlusCircleOutlined } from '@ant-design/icons'; +import React from 'react'; + +import { theme } from 'antd'; +import { DeviceGroupTreeProps } from '../typing'; +import BaseTree from './baseTree'; +const DeviceGroupTree: React.FC = (props) => { + const { token } = theme.useToken(); + console.log('token', token); + + // async function loadTree() { + // const resp = await getDeviceGroupSettingTree() + // setDeviceGroupList(resp.data) + // } + + // useEffect(()=>{ + // loadTree() + // },[]) + + // const [expandedKeys] = useState(['0-0', '0-0-0', '0-0-0-0']); + function handleAdd(node) { + // 当前节点的父节点 可以添加数据 + console.log(node, 'handleAdd_node'); + props.addTreeNode(node); + } + + return ( +
+ { + return ( +
{ + handleAdd(node); + }} + style={{ color: token.colorPrimary }} + key={node?.key || 'add'} + > + + {node?.key ? '添加子节点' : '添加节点'} +
+ ); + }} + handleDelete={(node) => { + // 提示删除 + console.log('handleDelete_node', node); + }} + selectTree={(selectedKeys, info) => { + props.selectTree(selectedKeys, info); + }} + >
+ {/* 新增节点 修改节点 */} +
+ ); +}; + +export default DeviceGroupTree; diff --git a/src/components/Tree/typing.ts b/src/components/Tree/typing.ts new file mode 100644 index 0000000..96961cc --- /dev/null +++ b/src/components/Tree/typing.ts @@ -0,0 +1,25 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-26 11:09:49 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-29 16:24:05 + * @FilePath: \general-ai-platform-web\src\components\Tree\typing.ts + * @Description: 树的类型文件 + */ + +// 增删改查基础树 +export interface BaseTreeProps extends TreeProps { + hideInAdd?: boolean; // 是否隐藏新增节点 + // hideInEdit?: boolean // 是否隐藏编辑节点 + hideInDelete?: boolean; // 是否隐藏删除节点 + hideInSearch?: boolean; // 是否隐藏筛选节点 + addRender?: React.ReactNode; // 新增操作自定义 + addText?: string | React.ReactNode; // 新增按钮文案自定义 + deleteRender?: React.ReactNode; // 删除操作自定义 + deleteText?: string | React.ReactNode; // 删除按钮文案自定义 +} +// 节点树 +export interface DeviceGroupTreeProps extends BaseTreeProps { + addTreeNode?: (arg1: Record) => void; + selectTree: (arg1: any, arg2: any) => void; +} diff --git a/src/enums/deviceGroup.ts b/src/enums/deviceGroup.ts new file mode 100644 index 0000000..9e8f4e6 --- /dev/null +++ b/src/enums/deviceGroup.ts @@ -0,0 +1,23 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-28 15:30:31 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-28 15:32:43 + * @FilePath: \general-ai-platform-web\src\enums\device.ts + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +// 告警规则 +export const deviceGroupEnums: Record[] = [ + { + label: '设备列表', + key: '1', + }, + { + label: '业务模型部署', + key: '2', + }, + { + label: '告警设置', + key: '3', + }, +]; diff --git a/src/global.css b/src/global.css index fe98fc1..1137dec 100644 --- a/src/global.css +++ b/src/global.css @@ -88,6 +88,9 @@ ol { .gn_form .ant-pro-form-group-container { gap: 0px 12px !important; } +.gn_modal_form { + margin-top: 16px; +} .gn_table_query_filter { padding: 20px 0; } @@ -114,14 +117,12 @@ ol { margin-right: 0; } .gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item .ant-steps-item-container { + position: relative; display: flex; align-items: center; justify-content: center; margin: 8px 0; } -.gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item .ant-steps-item-tail { - display: none; -} .gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item .ant-steps-item-icon { margin: 0 8px; } @@ -137,6 +138,21 @@ ol { color: #666666; font-size: 12px; } +.gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item .ant-steps-item-tail { + position: absolute; + top: auto; + left: calc(100% - 30px); + width: 16px; + height: 16px; + margin: 0; + padding: 0; + background: url('../public/home/business_arrow_default.svg') no-repeat; + background-size: cover; + border: none; +} +.gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item .ant-steps-item-tail:after { + background: transparent; +} .gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item-finish { background: #e5edff; border: 1px solid #154ddd; @@ -153,6 +169,10 @@ ol { .gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item-finish .ant-steps-item-description { color: #154ddd; } +.gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item-finish .ant-steps-item-tail { + background: url('../public/home/business_arrow.svg') no-repeat; + background-size: cover; +} .gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item-active { background: #e5edff; border: 1px solid #154ddd; @@ -163,10 +183,15 @@ ol { .gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item-active .ant-steps-item-description { color: #154ddd; } +.gn_model_steps_form .ant-modal-content .ant-modal-body .ant-steps .ant-steps-item-active .ant-steps-item-tail { + background: url('../public/home/business_arrow.svg') no-repeat; + background-size: cover; +} /* Descriptions */ .gn_table_descriptions { padding: 16px 16px 0; background: #ffffff; + border: 1px solid rgba(21, 77, 221, 0.1); border-radius: 8px; } /* ProTable ProList */ @@ -188,6 +213,21 @@ ol { padding: 0; } /* 主题样式 */ +.ant-btn-primary, +.ant-btn-primary:not(:disabled):not(.ant-btn-disabled):hover { + background-color: #154ddd; +} +.ant-btn-default:not(:disabled):not(.ant-btn-disabled):hover, +.ant-btn-link { + color: #154ddd; +} +:where(.css-dev-only-do-not-override-42nv3w).ant-btn-default:not(:disabled):not( + .ant-btn-disabled + ):hover { + color: #154ddd; + background: #ffffff; + border-color: #154ddd; +} /* 单行文本溢出显示省略号 */ .single_line { overflow: hidden; diff --git a/src/global.less b/src/global.less index 37f1a3f..f9b5053 100644 --- a/src/global.less +++ b/src/global.less @@ -114,6 +114,9 @@ ol { gap: 0px 12px !important; } } +.gn_modal_form { + margin-top: 16px; +} // 筛选表单 .gn_table_query_filter { @@ -147,14 +150,13 @@ ol { } .ant-steps-item-container { + position: relative; display: flex; align-items: center; justify-content: center; margin: 8px 0; } - .ant-steps-item-tail { - display: none; - } + .ant-steps-item-icon { margin: 0 8px; } @@ -170,6 +172,25 @@ ol { color: #666666; font-size: 12px; } + + .ant-steps-item-tail { + // display: none; + position: absolute; + top: auto; + left: calc(100% - 30px); + width: 16px; + height: 16px; + margin: 0; + padding: 0; + // background-color: red; + background: url('../public/home/business_arrow_default.svg') no-repeat; + background-size: cover; + border: none; + // right: -10px; + &:after { + background: transparent; + } + } } // 已完成 @@ -188,6 +209,10 @@ ol { .ant-steps-item-description { color: #154ddd; } + .ant-steps-item-tail { + background: url('../public/home/business_arrow.svg') no-repeat; + background-size: cover; + } } // 当前选中 .ant-steps-item-active { @@ -199,6 +224,10 @@ ol { .ant-steps-item-description { color: #154ddd; } + .ant-steps-item-tail { + background: url('../public/home/business_arrow.svg') no-repeat; + background-size: cover; + } } } } @@ -208,6 +237,7 @@ ol { .gn_table_descriptions { padding: 16px 16px 0; background: #ffffff; + border: 1px solid rgba(21, 77, 221, 0.1); border-radius: 8px; } @@ -235,21 +265,21 @@ ol { } /* 主题样式 */ -// .ant-btn-primary, -// .ant-btn-primary:not(:disabled):not(.ant-btn-disabled):hover { -// background-color: @theme_color; -// } -// .ant-btn-default:not(:disabled):not(.ant-btn-disabled):hover, -// .ant-btn-link { -// color: @theme_color; -// } -// :where(.css-dev-only-do-not-override-42nv3w).ant-btn-default:not(:disabled):not( -// .ant-btn-disabled -// ):hover { -// color: @theme_color; -// background: #ffffff; -// border-color: @theme_color; -// } +.ant-btn-primary, +.ant-btn-primary:not(:disabled):not(.ant-btn-disabled):hover { + background-color: @theme_color; +} +.ant-btn-default:not(:disabled):not(.ant-btn-disabled):hover, +.ant-btn-link { + color: @theme_color; +} +:where(.css-dev-only-do-not-override-42nv3w).ant-btn-default:not(:disabled):not( + .ant-btn-disabled + ):hover { + color: @theme_color; + background: #ffffff; + border-color: @theme_color; +} /* 单行文本溢出显示省略号 */ .single_line { diff --git a/src/locales/zh-CN/device.ts b/src/locales/zh-CN/device.ts index e0a575b..36647e9 100644 --- a/src/locales/zh-CN/device.ts +++ b/src/locales/zh-CN/device.ts @@ -1,28 +1,74 @@ /* * @Author: zhoux zhouxia@supervision.ltd * @Date: 2023-11-01 13:56:33 - * @LastEditors: zhoux zhouxia@supervision.ltd - * @LastEditTime: 2023-11-21 14:23:38 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-29 17:37:55 * @FilePath: \general-ai-platform-web\src\locales\zh-CN\device.ts - * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @Description: 设备相关 */ -export const device: { [key: string]: string } = { - 'device.device.table.list.id': 'ID', - 'device.device.table.list.name': '设备名称', - 'device.device.table.list.code': '设备代码', - 'device.device.table.list.position': '位置', - 'device.device.table.list.param': '设备参数', - 'device.device.table.list.spec': '设备规格', - 'device.device.table.list.categoryFkId': '设备类别', - 'device.device.table.list.groupFkId': '设备分组', - 'device.device.table.list.isEnable': '是否启用', - 'device.device.table.list.remark': '备注', - 'device.device.table.list.createTime': '创建时间', - 'device.device.table.list.updateTime': '更新时间', - 'device.device.table.rule.required.name': '设备名称为必填项', - 'device.device.table.rule.required.code': '设备代码为必填项', - 'device.device.table.list.add': '新建设备', - 'device.device.table.list.update': '更新设备', +// 节点设置 +export const device_group: { [key: string]: string } = { + 'device_group.tree_node.name': '节点名称', + 'device_group.tree_node.rule.required.name': '请填写节点名称', + 'device_group.tree_node.fatherName': '上级节点', + 'device_group.tree_node.lon': '经度', + 'device_group.tree_node.lat': '纬度', + 'device_group.tree_node.address': '地址', + 'device_group.tree_node.lonlat': '经纬度', + 'device_group.tree_node.managerName': '负责人', + 'device_group.tree_node.managerPhone': '联系方式', + 'device_group.tree_node.remark': '简介', + 'device_group.tree_node.createForm.add': '新建节点', + // 未启用 + + 'device_group.table.list.id': 'ID', + 'device_group.table.list.name': '分组名称', + 'device_group.table.list.code': '分组代码', + 'device_group.table.list.address': '地址', + 'device_group.table.list.telephone': '电话', + 'device_group.table.list.lon': '经度', + 'device_group.table.list.lat': '纬度', + 'device_group.table.list.managerName': '负责人姓名', + 'device_group.table.list.managerPhone': '负责人联系方式', + 'device_group.table.list.isEnable': '是否启用', + 'device_group.table.list.parentFkId': '父节点', + 'device_group.table.list.remark': '备注', + 'device_group.table.list.createTime': '创建时间', + 'device_group.table.list.updateTime': '更新时间', + 'device_group.table.rule.required.name': '分组名称为必填项', + 'device_group.table.rule.required.code': '分组代码为必填项', + 'device_group.table.rule.required.managerName': '负责人姓名为必填项', + 'device_group.table.rule.required.managerPhone': '负责人联系方式为必填项', + 'device_group.table.rule.required.parentFkId': '父节点为必填项', + 'device_group.table.list.add': '新建设备分组', + 'device_group.table.list.update': '更新设备分组', + 'device_group.table.list.treeAdd': '添加根节点', +}; + +export const device_group_list: { [key: string]: string } = { + 'device_group_list.table.list.name': '设备名称', + 'device_group_list.table.list.deviceType': '设备类型', + 'device_group_list.table.list.isEnable': '模型部署', + 'device_group_list.table.list.deployed.isEnable': '已部署', + 'device_group_list.table.list.undeployed.isEnable': '未部署', + 'device_group_list.table.list.action.setModel': '基础模型配置', + 'device_group_list.table.list.action.new': '新建设备', + 'device_group_list.table.list.action.modelType': '设备分类', + + // 未启用 + 'device_group_list.table.list.code': '设备代码', + 'device_group_list.table.list.position': '位置', + 'device_group_list.table.list.param': '设备参数', + 'device_group_list.table.list.spec': '设备规格', + 'device_group_list.table.list.categoryFkId': '设备类别', + 'device_group_list.table.list.groupFkId': '设备分组', + 'device_group_list.table.list.remark': '备注', + 'device_group_list.table.list.createTime': '创建时间', + 'device_group_list.table.list.updateTime': '更新时间', + 'device_group_list.table.rule.required.name': '设备名称为必填项', + 'device_group_list.table.rule.required.code': '设备代码为必填项', + 'device_group_list.table.list.add': '新建设备', + 'device_group_list.table.list.update': '更新设备', }; export const device_category: { [key: string]: string } = { 'device.device_category.table.list.id': 'ID', @@ -36,30 +82,7 @@ export const device_category: { [key: string]: string } = { 'device.device_category.table.list.add': '新建设备类别', 'device.device_category.table.list.update': '更新设备类别', }; -export const device_group: { [key: string]: string } = { - 'device.device_group.table.list.id': 'ID', - 'device.device_group.table.list.name': '分组名称', - 'device.device_group.table.list.code': '分组代码', - 'device.device_group.table.list.address': '地址', - 'device.device_group.table.list.telephone': '电话', - 'device.device_group.table.list.lon': '经度', - 'device.device_group.table.list.lat': '纬度', - 'device.device_group.table.list.managerName': '负责人姓名', - 'device.device_group.table.list.managerPhone': '负责人联系方式', - 'device.device_group.table.list.isEnable': '是否启用', - 'device.device_group.table.list.parentFkId': '父节点', - 'device.device_group.table.list.remark': '备注', - 'device.device_group.table.list.createTime': '创建时间', - 'device.device_group.table.list.updateTime': '更新时间', - 'device.device_group.table.rule.required.name': '分组名称为必填项', - 'device.device_group.table.rule.required.code': '分组代码为必填项', - 'device.device_group.table.rule.required.managerName': '负责人姓名为必填项', - 'device.device_group.table.rule.required.managerPhone': '负责人联系方式为必填项', - 'device.device_group.table.rule.required.parentFkId': '父节点为必填项', - 'device.device_group.table.list.add': '新建设备分组', - 'device.device_group.table.list.update': '更新设备分组', - 'device.device_group.table.list.treeAdd': '添加根节点', -}; + export const device_relation: { [key: string]: string } = { 'device.device_relation.table.list.id': 'ID', 'device.device_relation.table.list.deviceParentFkId': '设备父节点', diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts index 253d18f..4d81026 100644 --- a/src/locales/zh-CN/menu.ts +++ b/src/locales/zh-CN/menu.ts @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-04-01 11:20:09 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-23 10:51:24 + * @LastEditTime: 2024-04-26 09:36:38 * @FilePath: \uighur-recognition-web2\src\locales\zh-CN\menu.ts * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -64,7 +64,7 @@ export default { 'menu.model-runtime-lib': '模型运行库', 'menu.business-info-index': '企业信息', - 'menu.business-node-setting': '节点设置', + 'menu.business-device-group': '节点设置', 'menu.business-model-index': '业务模型', // 待废弃 'menu.realTime': '实时分析', diff --git a/src/pages/Business/DeviceGroup/components/baseInfo.tsx b/src/pages/Business/DeviceGroup/components/baseInfo.tsx new file mode 100644 index 0000000..e44801c --- /dev/null +++ b/src/pages/Business/DeviceGroup/components/baseInfo.tsx @@ -0,0 +1,62 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-23 17:00:00 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-28 17:55:58 + * @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\baseInfo.tsx + * @Description: 基本信息展示 + * + */ + +import { ProDescriptions } from '@ant-design/pro-components'; +import { FormattedMessage } from '@umijs/max'; + +type BaseInfoProps = { + info: Record; +}; + +const BaseInfo: React.FC = ({ info }) => { + // 设备基本信息 + const DeviceDetailColumns = [ + { + title: , + dataIndex: 'name', + }, + { + title: , + dataIndex: 'fatherName', + }, + { + title: , + dataIndex: 'address', + }, + { + title: , + dataIndex: 'lonlat', + render: (_, record) => { + return record?.lon + ',' + record?.lat; + }, + }, + { + title: , + dataIndex: 'managerName', + }, + { + title: ( + + ), + dataIndex: 'managerPhone', + }, + { + title: , + dataIndex: 'remark', + }, + ]; + return ( +
+ +
+ ); +}; + +export default BaseInfo; diff --git a/src/pages/Business/DeviceGroup/components/createDeviceForm.tsx b/src/pages/Business/DeviceGroup/components/createDeviceForm.tsx new file mode 100644 index 0000000..4e8ecad --- /dev/null +++ b/src/pages/Business/DeviceGroup/components/createDeviceForm.tsx @@ -0,0 +1,175 @@ +// import { postModelCategoryCreateModelCategory } from '@/services/resource/ModelCategory'; +import { ModalForm, ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components'; +import { FormattedMessage, useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import React from 'react'; +import { + proFormSmallItemStyleProps, + proFormSmallModelWidth, +} from '../../../../../config/defaultForm'; +// @ts-ignore + +export type CreateDeviceFormProps = { + createModalOpen: boolean; + handleModal: () => void; + reload: any; +}; +const CreateDeviceForm: React.FC = (props) => { + const intl = useIntl(); + // const [isAuto, setIsAuto] = useState(true); + const [form] = Form.useForm(); + + return ( + + className="gn_modal_form gn_form" + width={proFormSmallModelWidth} + title={intl.formatMessage({ + id: 'device_group.tree_node.CreateDeviceForm.add', + defaultMessage: '新建', + })} + open={props.createModalOpen} + form={form} + autoFocusFirstInput + modalProps={{ + destroyOnClose: true, + onCancel: () => props.handleModal(), + }} + submitTimeout={2000} + onFinish={async (values) => { + console.log(values, 'add_finish_values'); + // TODO 对接新增接口 + // postModelCategoryCreateModelCategory(values) + // .then(() => { + // message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' })); + // props.reload(); + // }) + // .catch(() => { + // message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' })); + // }); + props.handleModal(); + return true; + }} + > + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.name', + defaultMessage: '$$$', + })}`} + required={true} + rules={[ + { + required: true, + message: ( + + ), + }, + ]} + /> + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.fatherName', + defaultMessage: '$$$', + })}`} + disabled + /> + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.address', + defaultMessage: '$$$', + })}`} + /> + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.lon', + defaultMessage: '$$$', + })}`} + /> + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.lat', + defaultMessage: '$$$', + })}`} + /> + + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.managerName', + defaultMessage: '$$$', + })}`} + /> + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.managerPhone', + defaultMessage: '$$$', + })}`} + /> + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.remark', + defaultMessage: '$$$', + })}`} + /> + + + ); +}; +export default CreateDeviceForm; diff --git a/src/pages/Business/DeviceGroup/components/createForm.tsx b/src/pages/Business/DeviceGroup/components/createForm.tsx new file mode 100644 index 0000000..abaabd3 --- /dev/null +++ b/src/pages/Business/DeviceGroup/components/createForm.tsx @@ -0,0 +1,176 @@ +// import { postModelCategoryCreateModelCategory } from '@/services/resource/ModelCategory'; +import { ModalForm, ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components'; +import { FormattedMessage, useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import React from 'react'; +import { + proFormSmallItemStyleProps, + proFormSmallModelWidth, +} from '../../../../../config/defaultForm'; +// @ts-ignore + +export type CreateFormProps = { + createModalOpen: boolean; + handleModal: () => void; + parentInfo?: Record; + reload: any; +}; +const CreateForm: React.FC = (props) => { + const intl = useIntl(); + // const [isAuto, setIsAuto] = useState(true); + const [form] = Form.useForm(); + + return ( + + className="gn_modal_form gn_form" + width={proFormSmallModelWidth} + title={intl.formatMessage({ + id: 'device_group.tree_node.createForm.add', + defaultMessage: '新建', + })} + open={props.createModalOpen} + form={form} + autoFocusFirstInput + modalProps={{ + destroyOnClose: true, + onCancel: () => props.handleModal(), + }} + submitTimeout={2000} + onFinish={async (values) => { + console.log(values, 'add_finish_values'); + // TODO 对接新增接口 + // postModelCategoryCreateModelCategory(values) + // .then(() => { + // message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' })); + // props.reload(); + // }) + // .catch(() => { + // message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' })); + // }); + props.handleModal(); + return true; + }} + > + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.name', + defaultMessage: '$$$', + })}`} + required={true} + rules={[ + { + required: true, + message: ( + + ), + }, + ]} + /> + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.fatherName', + defaultMessage: '$$$', + })}`} + disabled + /> + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.address', + defaultMessage: '$$$', + })}`} + /> + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.lon', + defaultMessage: '$$$', + })}`} + /> + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.lat', + defaultMessage: '$$$', + })}`} + /> + + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.managerName', + defaultMessage: '$$$', + })}`} + /> + + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.managerPhone', + defaultMessage: '$$$', + })}`} + /> + } + placeholder={`${intl.formatMessage({ + id: 'common.please_input', + defaultMessage: '$$$', + })}${intl.formatMessage({ + id: 'device_group.tree_node.remark', + defaultMessage: '$$$', + })}`} + /> + + + ); +}; +export default CreateForm; diff --git a/src/pages/Business/DeviceGroup/components/deviceList.tsx b/src/pages/Business/DeviceGroup/components/deviceList.tsx new file mode 100644 index 0000000..6e412ba --- /dev/null +++ b/src/pages/Business/DeviceGroup/components/deviceList.tsx @@ -0,0 +1,246 @@ +import TableActionCard from '@/components/TableActionCard'; +import { getDeviceListByGroup } from '@/services/testApi/device'; +import { ProTable } from '@ant-design/pro-components'; +import { Access, FormattedMessage, history, useAccess } from '@umijs/max'; +import { Button } from 'antd'; +import { useRef, useState } from 'react'; + +import { proTablePaginationOptions } from '../../../../../config/defaultTable'; + +import IsDelete from '@/components/TableActionCard/isDelete'; +import CreateDeviceForm from './createDeviceForm'; + +type DeviceListProps = { + info: Record; +}; + +const DeviceList: React.FC = () => { + const access = useAccess(); + // const intl = useIntl(); + const actionRef = useRef(); + + const [createModalOpen, setCreateModalOpen] = useState(false); + // const [categoryFkIdIds, setCategoryFkIdIds] = useState([]); + // 动态设置每页数量 + const [currentPageSize, setCurrentPageSize] = useState(10); + + /**新增 编辑 删除 */ + // 新增 + const handleCreateModal = () => { + setCreateModalOpen(!createModalOpen); + }; + + function reloadList() { + actionRef.current?.reload(); + } + + const columns: ProColumns>[] = [ + { + title: , + dataIndex: 'name', + hideInSearch: true, + // width: 80, + // key: 'fixedName', + // fixed: 'left', + }, + { + title: ( + + ), + dataIndex: 'deviceType', + hideInSearch: true, + // width: 120, + }, + { + title: ( + + ), + dataIndex: 'isEnable', + hideInSearch: true, + // width: 80, + render: (dom, record) => { + return ( +
+ + + {record.isEnable ? ( + + ) : ( + + )} + +
+ ); + }, + }, + + { + title: , + dataIndex: 'option', + valueType: 'option', + fixed: 'right', + key: 'option', + render: (_, record) => [ + { + // setCurrentRow(record); + // history.push('/home/model-detail'); + // doToDetail(record); + // setShowDetail(true); + }} + > + + + ), + }, + { + key: 'updateDetail', + renderDom: ( + + ), + }, + { + key: 'destroy', + renderDom: ( + { + handleDestroy(record).then(() => {}); + }} + > + ), + }, + ]} + >, + ], + }, + ]; + + return ( +
+ [ + +
+ + +
+
, + ]} + search={false} + // scroll={{ y: proTableCommonOptions.commscrollY, x: proTableCommonOptions.commscrollX }} + options={{ fullScreen: false, setting: false, density: false, reload: false }} + actionRef={actionRef} + rowKey="key" + onDataSourceChange={(data) => { + console.log(data, 'onDataSourceChange_data'); + // let CategoryFkIdIds: any = data.map((v) => { + // return v.categoryFkId; + // }); + // setCategoryFkIdIds(CategoryFkIdIds); + }} + pagination={{ + ...proTablePaginationOptions, + pageSize: currentPageSize, + onChange: (page, pageSize) => setCurrentPageSize(pageSize), + }} + columnsState={{ + persistenceKey: 'algorithm_model_list', + persistenceType: 'localStorage', + }} + request={async (params = {}) => { + const { current, ...rest } = params; + const reqParams = { + page: current, + ...rest, + }; + let resp = await getDeviceListByGroup({ ...reqParams }); + console.log(resp, 'getDeviceListByGroup_resp'); + return { + data: resp.data?.results.map((v: Record) => { + return { ...v, key: v.id }; + }), + success: resp.success, + total: resp.data.count, + current: current, + pageSize: currentPageSize, + }; + }} + columns={columns} + /> + +
+ ); +}; + +export default DeviceList; diff --git a/src/pages/Business/DeviceGroup/index.css b/src/pages/Business/DeviceGroup/index.css new file mode 100644 index 0000000..77af702 --- /dev/null +++ b/src/pages/Business/DeviceGroup/index.css @@ -0,0 +1,37 @@ +.deviceGroup_page { + height: calc(100vh - 92px); + /* 节点列表 */ + /* 节点信息 */ +} +.deviceGroup_page .dg_content .gn_card { + height: calc(100% - 8px); +} +.deviceGroup_page .node_list > .gn_card { + box-shadow: 0px 2px 8px 0px rgba(0, 79, 178, 0.15); +} +.deviceGroup_page .node_info { + padding-left: 0; +} +.dg_deviceList_wrap .model_index_type_tag { + width: 82px; + height: 24px; + color: #52C41A; + background: #E8F7E6; + border: 1px solid #BAEEA1; + border-radius: 12px; +} +.dg_deviceList_wrap .model_index_type_tag .dot { + width: 6px; + height: 6px; + margin-right: 4px; + background: #52C41A; + border-radius: 50%; +} +.dg_deviceList_wrap .model_index_type_tag.active2 { + color: #E80D0D; + background: #FEEFEE; + border: 1px solid #F9B2AE; +} +.dg_deviceList_wrap .model_index_type_tag.active2 .dot { + background: #E80D0D; +} diff --git a/src/pages/Business/DeviceGroup/index.less b/src/pages/Business/DeviceGroup/index.less new file mode 100644 index 0000000..b17d451 --- /dev/null +++ b/src/pages/Business/DeviceGroup/index.less @@ -0,0 +1,45 @@ +.deviceGroup_page { + height: calc(100vh - 92px); + .dg_content { + .gn_card { + height: calc(100% - 8px); + } + } + /* 节点列表 */ + .node_list { + & > .gn_card { + box-shadow: 0px 2px 8px 0px rgba(0, 79, 178, 0.15); + } + } + /* 节点信息 */ + .node_info { + padding-left: 0; + } +} + +.dg_deviceList_wrap { + .model_index_type_tag { + width: 82px; + height: 24px; + color: #52c41a; + background: #e8f7e6; + border: 1px solid #baeea1; + border-radius: 12px; + + .dot { + width: 6px; + height: 6px; + margin-right: 4px; + background: #52c41a; + border-radius: 50%; + } + &.active2 { + color: #e80d0d; + background: #feefee; + border: 1px solid #f9b2ae; + .dot { + background: #e80d0d; + } + } + } +} diff --git a/src/pages/Business/DeviceGroup/index.tsx b/src/pages/Business/DeviceGroup/index.tsx new file mode 100644 index 0000000..e59db12 --- /dev/null +++ b/src/pages/Business/DeviceGroup/index.tsx @@ -0,0 +1,136 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-22 15:23:36 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-29 16:50:22 + * @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\index.tsx + * @Description: 设备节点设置 关键词 deviceGroup(dg) + * @交互说明 + * 1、节点列表的查看、添加、删除 + * 2、节点基本信息展示 + * 3、设备列表分页查看、新建、编辑、删除、设备分类、基础模型配置 + * 4、业务模型部署配置参数 + * 5、企业告警设置 + */ +import { DeviceGroupTree } from '@/components/Tree'; +import { deviceGroupEnums } from '@/enums/deviceGroup'; +import { getDeviceGroupList } from '@/services/testApi/deviceGroup'; +import { ProCard } from '@ant-design/pro-components'; +import { Button, Tabs } from 'antd'; +import { useEffect, useState } from 'react'; +import BaseInfo from './components/baseInfo'; +import CreateForm from './components/createForm'; +import DeviceList from './components/deviceList'; + +import './index.less'; + +const DeviceGroup: React.FC = () => { + /**state */ + // 节点信息 + const [deviceTreeList, setDeviceTreeList] = useState[]>([]); + const [nodeInfo, setNodeInfo] = useState>({}); // 当前节点信息 + const [createModalOpen, setCreateModalOpen] = useState(false); // 创建新增窗口是否打开 + + // 切换模块 + const [tabKey, setTabKey] = useState(deviceGroupEnums[0].key); + const [tabs] = useState([...deviceGroupEnums]); + const changeTabMode = (key: string) => { + setTabKey(key); + console.log(key); + // eslint-disable-next-line @typescript-eslint/no-use-before-define + // initList(key); + }; + /**节点列表 */ + // 设备节点树 + async function loadDeviceTree() { + const resp = await getDeviceGroupList({ page: 1, pageSize: 100 }); + console.log(resp.data, 'loadDeviceTree'); + setDeviceTreeList(resp?.data.results); + setNodeInfo(resp?.data.results[0]); + } + + // 新增 + const handleCreateModal = () => { + setCreateModalOpen(!createModalOpen); + }; + + // 节点信息展示 + + // 切换 + + // 初始化加载 + useEffect(() => { + loadDeviceTree(); + }, []); + + return ( +
+ {/* 节点列表 */} +
+ 节点列表}> +
+ { + setNodeInfo(record); + }} + addTreeNode={(node) => { + //TODO 判断是根节点还是子节点 调用新增接口 + console.log('addTreeNode_node', node); + handleCreateModal(); + }} + selectTree={(selectedKeys, info) => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + info?.node && setNodeInfo(info?.node); + // handleSelectNode(selectedKeys, info) + console.log('selectTree_selected', selectedKeys, info); + }} + > +
+
+
+ + {/* 节点信息 */} +
+ 节点信息} + extra={ + + } + > +
+ + { + changeTabMode(key); + }} + > + {tabKey === '1' && } +
+
+
+ {/* 弹窗 */} + { + // TODO 调用获取节点列表的接口 + }} + /> +
+ ); +}; + +export default DeviceGroup; diff --git a/src/pages/Business/NodeSetting/index.tsx b/src/pages/Business/NodeSetting/index.tsx deleted file mode 100644 index fc2478b..0000000 --- a/src/pages/Business/NodeSetting/index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -/* - * @Author: donghao donghao@supervision.ltd - * @Date: 2024-04-22 15:23:36 - * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-22 15:34:36 - * @FilePath: \general-ai-platform-web\src\pages\Node\NodeSetting\index.tsx - * @Description: 节点设置 - * @交互说明 - */ -const NodeSetting: React.FC = () => { - return
节点设置
; -}; - -export default NodeSetting; diff --git a/src/pages/Model/ModelDetail/index.tsx b/src/pages/Model/ModelDetail/index.tsx index 092863d..1fe0c13 100644 --- a/src/pages/Model/ModelDetail/index.tsx +++ b/src/pages/Model/ModelDetail/index.tsx @@ -45,11 +45,7 @@ const ModelDetail: React.FC = () => { /**新增 编辑 删除 */ // 新增 const handleCreateModal = () => { - if (createModalOpen) { - setCreateModalOpen(false); - } else { - setCreateModalOpen(true); - } + setCreateModalOpen(!createModalOpen); }; function reloadList() { diff --git a/src/pages/Project/BusinessInfo/components/baseInfo.tsx b/src/pages/Project/BusinessInfo/components/baseInfo.tsx index 9f6a041..a0895e5 100644 --- a/src/pages/Project/BusinessInfo/components/baseInfo.tsx +++ b/src/pages/Project/BusinessInfo/components/baseInfo.tsx @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-04-23 17:00:00 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-24 17:14:48 + * @LastEditTime: 2024-04-28 09:33:34 * @FilePath: \general-ai-platform-web\src\pages\Project\BusinessInfo\components\baseInfo.tsx * @Description: 基本信息展示 * @@ -45,7 +45,7 @@ const BaseInfo: React.FC = ({ info }) => { }, ]; return ( -
+
); diff --git a/src/services/testApi/device.ts b/src/services/testApi/device.ts new file mode 100644 index 0000000..4140541 --- /dev/null +++ b/src/services/testApi/device.ts @@ -0,0 +1,31 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-04-25 15:39:42 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-04-28 17:14:06 + * @FilePath: \general-ai-platform-web\src\services\testApi\device.ts + * @Description: 设备api + */ +// @ts-ignore +/* eslint-disable */ +import { request } from '@umijs/max'; + +/** 节点下设备分页列表 */ +export async function getDeviceListByGroup( + body: Record, // + options?: { [key: string]: any }, +) { + return request( + `/api/device/listByGroup`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + params: { + ...body, + }, + ...(options || {}), + }, + ); +} diff --git a/src/services/testApi/deviceGroup.ts b/src/services/testApi/deviceGroup.ts index b8491b6..60ff8d2 100644 --- a/src/services/testApi/deviceGroup.ts +++ b/src/services/testApi/deviceGroup.ts @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-04-25 15:39:42 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-25 15:49:38 + * @LastEditTime: 2024-04-28 11:19:40 * @FilePath: \general-ai-platform-web\src\services\testApi\deviceGroup.ts * @Description: 节点设置api */ @@ -11,26 +11,26 @@ import { request } from '@umijs/max'; /** 节点设置分页列表 */ -// export async function getDeviceGroupList( -// body: Record, // -// options?: { [key: string]: any }, -// ) { -// return request( -// `/api/device_group/list`, -// { -// method: 'GET', -// headers: { -// 'Content-Type': 'application/json', -// }, -// params: { -// ...body, -// }, -// ...(options || {}), -// }, -// ); -// } +export async function getDeviceGroupList( + body: Record, // + options?: { [key: string]: any }, +) { + return request( + `/api/device_group/getDeviceGroupList`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + params: { + ...body, + }, + ...(options || {}), + }, + ); +} -/** 获取设备组树 POST /device_group/getDeviceGroupTree */ +/** 获取设备组树 GET /device_group/getDeviceGroupTree */ export async function getDeviceGroupTree( body: Record, // options?: { [key: string]: any }, @@ -49,3 +49,23 @@ export async function getDeviceGroupTree( }, ); } + +/** 获取节点树 GET /device_group/getDeviceGroupTree */ +export async function getDeviceGroupSettingTree( + body: Record, // + options?: { [key: string]: any }, +) { + return request( + `/api/device_group/setting_data`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + params: { + ...body, + }, + ...(options || {}), + }, + ); +} diff --git a/src/services/testApi/dict.ts b/src/services/testApi/dict.ts index c91511f..5dbaada 100644 --- a/src/services/testApi/dict.ts +++ b/src/services/testApi/dict.ts @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-04-09 13:46:44 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-04-17 14:09:35 + * @LastEditTime: 2024-04-28 14:24:40 * @FilePath: \general-ai-manage\src\services\testApi\businessProject.ts * @Description: 字典表mock数据映射 */ @@ -10,12 +10,28 @@ /* eslint-disable */ import { request } from '@umijs/max'; -/** 企业项目分页列表 */ +/** 行业分类列表 */ export async function getDictIndustry( body: Record, // options?: { [key: string]: any }, ) { - return request(`/api/dict/industry/`, { + return request(`/api/dict/industry`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + params: { + ...body, + }, + ...(options || {}), + }); +} +/** 设备类型列表 */ +export async function getDictDeviceType( + body: Record, // + options?: { [key: string]: any }, +) { + return request(`/api/dict/deviceType`, { method: 'GET', headers: { 'Content-Type': 'application/json', diff --git a/src/utils/baseTree.ts b/src/utils/baseTree.ts new file mode 100644 index 0000000..58c43ff --- /dev/null +++ b/src/utils/baseTree.ts @@ -0,0 +1,13 @@ +export const formatTreeValByKey = ( + key: string, + node: Record, + fieldNames?: string, +): any => { + if (fieldNames && Object.keys(fieldNames).includes(key)) { + return node[fieldNames[key]]; + } + if (Object.keys(node).includes(key)) { + return node[key]; + } + return null; +};