feat: 节点设备树、节点设备模块的联调完成

develop2
donghao 11 months ago
parent c825f53982
commit cd816525b7

@ -2,22 +2,25 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-12-27 10:30:10
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-17 13:19:01
* @LastEditTime: 2024-05-28 16:34:50
* @FilePath: \general-ai-platform-web\src\components\TableActionCard\isConfirmModal.tsx
* @Description:
*/
import { useIntl } from '@umijs/max';
import modal from 'antd/es/modal';
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
import './isConfirmModal.less';
import { ReactComponent as QuestionIcon } from '/public/icons/questionIcon.svg';
type IsConfirmModalProps = {
modalProps: ModalType;
confirmButton: string | React.ReactNode;
};
const IsConfirmModal: React.FC<IsConfirmModalProps> = (props) => {
const IsConfirmModal: React.FC<IsConfirmModalProps> = forwardRef((props, ref) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const intl = useIntl();
const confirmRef = useRef(null);
const confirm = () => {
modal.confirm({
width: 560,
@ -37,8 +40,13 @@ const IsConfirmModal: React.FC<IsConfirmModalProps> = (props) => {
});
};
// 使用 useImperativeHandle 来定义父组件可以调用的方法
useImperativeHandle(ref, () => ({
confirm,
}));
return (
<div className="isConfirmModal_wrap">
<div className="isConfirmModal_wrap" ref={confirmRef}>
<span
onClick={(e) => {
e.stopPropagation();
@ -49,6 +57,6 @@ const IsConfirmModal: React.FC<IsConfirmModalProps> = (props) => {
</span>
</div>
);
};
});
export default IsConfirmModal;

@ -22,7 +22,7 @@
.base_tree_wrap .ant-tree .ant-tree-switcher .ant-tree-switcher-icon {
font-size: 12px;
}
.base_tree_wrap .tree_node_1 {
.base_tree_wrap .tree_node_0 {
width: 100%;
margin: 12px 0;
padding: 8px 17px;
@ -30,16 +30,16 @@
border-radius: 4px;
cursor: pointer;
}
.base_tree_wrap .tree_node_1 .ant-tree-switcher-noop {
.base_tree_wrap .tree_node_0 .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 .tree_node_0:hover,
.base_tree_wrap .ant-tree-treenode-selected {
font-weight: bold;
color: #154ddd;
font-weight: bold;
background: rgba(21, 77, 221, 0.1);
border-radius: 8px;
}

@ -20,7 +20,7 @@
font-size: 12px;
}
.tree_node_1 {
.tree_node_0 {
width: 100%;
margin: 12px 0;
padding: 8px 17px;
@ -36,7 +36,7 @@
display: none;
}
}
.tree_node_1:hover,
.tree_node_0:hover,
.ant-tree-treenode-selected {
color: #154ddd;
font-weight: bold;

@ -1,6 +1,6 @@
import { formatTreeValByKey } from '@/utils/baseTree';
import { SearchOutlined } from '@ant-design/icons';
import { Button, Form, Input, Modal, Tree } from 'antd';
import { Button, Tree } from 'antd';
import _debounce from 'lodash/debounce';
import React, { useEffect, useState } from 'react';
import { BaseTreeProps } from '../typing';
@ -13,16 +13,18 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
/**state */
// const { token } = theme.useToken();
const { treeData, ...defaultProps } = props;
const { treeData, searchChange, ...defaultProps } = props;
const [currSeleted, setCurrSeleted] = useState<any[]>([]);
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 [visible, setVisible] = useState(false);
// const [editNodeKey, setEditNodeKey] = useState(null);
// const [form] = Form.useForm();
const action_add_key = '';
/**工具方法集 */
@ -37,19 +39,14 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
/**查询树节点 */
// 定义一个防抖处理函数500ms 后执行 handleChange 函数
const debouncedHandleChange = _debounce((value) => {
// TODO 查询所有匹配的节点
searchChange(value);
console.log('debouncedHandleChange_value:', value);
}, 500);
}, 1000);
// 搜索节点
function handleSearch(val) {
debouncedHandleChange(val);
}
const handleAddNode = () => {
// setVisible(true);
// form.resetFields();
};
// const getNodeByKey = (key) => {
// return currTreeData.find((node) => node.key === key);
// };
@ -84,47 +81,47 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
// };
// 组装节点数据
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 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('');
};
// const handleModalCancel = () => {
// // setVisible(false);
// setEditNodeKey('');
// };
// render 新增节点操作
const renderAddAction = (node?: Record<string, any>) => {
@ -132,7 +129,7 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
return props?.addRender ? (
props?.addRender(node)
) : (
<div onClick={handleAddNode}>
<div>
<Button></Button>
</div>
);
@ -141,18 +138,24 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
// 定义每个节点内容 递归操作
const renderTreeNodes = (data) => {
if (Array.isArray(data) && data.length) {
return data.map((node, index) => {
return data.map((node) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id, children, ...restData } = node;
console.log('restData', restData);
return (
<TreeNode
{...node}
title={formatTreeValByNodeKey('title', node)}
key={formatTreeValByNodeKey('key', node) + index}
className={`tree_node_item tree_node_${node.level}`}
key={formatTreeValByNodeKey('key', node)}
className={`tree_node_item tree_node_${!node?.parent ? 0 : 1}`}
>
{formatTreeValByNodeKey('children', node) &&
renderTreeNodes(formatTreeValByNodeKey('children', node))}
<TreeNode key={formatTreeValByNodeKey('key', node) + action_add_key}></TreeNode>
{/* 此处不可以赋值id、children */}
<TreeNode
{...restData}
key={formatTreeValByNodeKey('key', node) + action_add_key}
></TreeNode>
</TreeNode>
);
});
@ -163,11 +166,12 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
const renderTreeItem = (node) => {
return (
<div className="flex w-full">
<span className="w-[140px]">{node.title}</span>
<span className="w-[130px]">{node.title}</span>
{!props?.hideInDelete ? (
<span
className="action_list"
onClick={() => {
onClick={(e) => {
e.stopPropagation();
props.handleDelete(node);
}}
>
@ -183,6 +187,8 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
useEffect(() => {
setCurrTreeData(props.treeData);
// TODO 后续改从业务层获取 默认选项
setCurrSeleted([props?.treeData[0]?.id]);
console.log(props.treeData, 'props_treeData');
}, [props.treeData]);
@ -209,8 +215,10 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
)}
<div style={{ maxHeight: 'calc(100vh - 210px)', overflowY: 'auto', overflowX: 'hidden' }}>
<Tree
selectedKeys={currSeleted}
defaultExpandAll
onSelect={(selectedKeys, info) => {
setCurrSeleted(selectedKeys);
console.log('selected', selectedKeys);
props.selectTree(selectedKeys, info);
}}
@ -224,12 +232,12 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
>
{renderTreeNodes(currTreeData)}
</Tree>
<div className="tree_node_1">{renderAddAction()}</div>
<div className="tree_node_0">{renderAddAction()}</div>
</div>
{/* <div onClick={handleAddNode}>添加一级节点</div> */}
{/* TODO 使用ProForm */}
<Modal
{/* <Modal
title={editNodeKey ? '编辑节点' : '新增节点'}
open={visible}
onOk={handleModalOk}
@ -244,7 +252,7 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
<Input />
</Form.Item>
</Form>
</Modal>
</Modal> */}
</div>
);
};

@ -2,14 +2,15 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-26 11:11:05
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-16 13:36:53
* @LastEditTime: 2024-05-29 14:19:24
* @FilePath: \general-ai-manage\src\components\Tree\src\deviceGroupTree.tsx
* @Description:
* @
* 1
* 2
* 3
* 4
*
*
*/
import { PlusCircleOutlined } from '@ant-design/icons';
import { theme } from 'antd';
@ -33,15 +34,22 @@ const DeviceGroupTree: React.FC<DeviceGroupTreeProps> = (props) => {
props.addTreeNode(node);
}
// function handleDelete(node) {
// // 当前节点的父节点 可以添加数据
// console.log(node, 'handleAdd_node');
// }
return (
<div className="deviceGroup_tree_wrap">
<BaseTree
searchChange={props.searchChange}
treeData={props.dataSource}
fieldNames={{ title: 'name', key: 'id', children: 'children' }}
addRender={(node) => {
return (
<div
onClick={() => {
onClick={(e) => {
e.stopPropagation();
handleAdd(node);
}}
style={{ color: token.colorPrimary }}
@ -54,6 +62,7 @@ const DeviceGroupTree: React.FC<DeviceGroupTreeProps> = (props) => {
}}
handleDelete={(node) => {
// 提示删除
props.deleteTreeNode(node);
console.log('handleDelete_node', node);
}}
selectTree={(selectedKeys, info) => {

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-10 15:34:33
* @LastEditTime: 2024-05-29 16:06:49
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\device.ts
* @Description:
*/
@ -18,7 +18,9 @@ export const device_group: { [key: string]: string } = {
'device_group.tree_node.managerName': '负责人',
'device_group.tree_node.managerPhone': '联系方式',
'device_group.tree_node.remark': '简介',
'device_group.tree_node.createForm.add': '新建节点',
'device_group.tree_node.form.action.add': '新建节点',
'device_group.tree_node.form.action.update': '编辑节点',
// 未启用
'device_group.table.list.id': 'ID',
'device_group.table.list.name': '分组名称',
@ -49,6 +51,8 @@ export const device_group_list: { [key: string]: string } = {
'device_group_list.table.list.rule.required.name': '请填写设备名称',
'device_group_list.table.list.deviceSite': '设备位置',
'device_group_list.table.list.deviceType': '设备分类',
'device_group_list.table.list.rule.required.deviceType': '请选择设备分类',
'device_group_list.table.list.deviceModel': '设备型号',
'device_group_list.table.list.deviceParams': '设备参数',
'device_group_list.table.list.remark': '备注',
@ -58,7 +62,8 @@ export const device_group_list: { [key: string]: string } = {
'device_group_list.table.list.action.setModel': '基础模型配置',
'device_group_list.table.list.action.new': '新建设备',
'device_group_list.table.list.action.deviceType': '设备分类',
'device_group_list.table.list.add': '新建设备',
'device_group_list.form.action.add': '新建设备',
'device_group_list.form.action.edit': '编辑设备',
'device_group_list.table.list.action.setDeviceType': '新建设备分类',
// 未启用
'device_group_list.table.list.code': '设备代码',

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-24 14:37:22
* @LastEditTime: 2024-05-29 17:04:34
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\alarmSetForm.tsx
* @Description:
* @

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-23 17:00:00
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-28 17:55:58
* @LastEditTime: 2024-05-28 16:45:52
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\baseInfo.tsx
* @Description:
*
@ -24,32 +24,37 @@ const BaseInfo: React.FC<BaseInfoProps> = ({ info }) => {
},
{
title: <FormattedMessage id="device_group.tree_node.fatherName" defaultMessage="上级节点" />,
dataIndex: 'fatherName',
dataIndex: 'parent_name',
// TODO 需要接口返回上级节点的名称
// render: (_, record) => {
// if(record?.lon && record?.lat){
// return record?.lon + ',' + record?.lat;
// }
// return '-'
// },
},
{
title: <FormattedMessage id="device_group.tree_node.address" defaultMessage="地址" />,
dataIndex: 'address',
dataIndex: 'addr',
},
{
title: <FormattedMessage id="device_group.tree_node.lonlat" defaultMessage="经纬度" />,
dataIndex: 'lonlat',
render: (_, record) => {
return record?.lon + ',' + record?.lat;
},
dataIndex: 'lola',
},
{
title: <FormattedMessage id="device_group.tree_node.managerName" defaultMessage="负责人" />,
dataIndex: 'managerName',
dataIndex: 'contact',
},
{
title: (
<FormattedMessage id="device_group.tree_node.managerPhone" defaultMessage="联系方式" />
),
dataIndex: 'managerPhone',
dataIndex: 'phone',
},
{
title: <FormattedMessage id="device_group.tree_node.remark" defaultMessage="简介" />,
dataIndex: 'remark',
dataIndex: 'comment',
},
];
return (

@ -1,4 +1,6 @@
import { getDictDeviceType } from '@/services/testApi/dict';
import { apiDeviceClassification } from '@/services/business/device';
import { apiEntityNodesDeviceAdd } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import {
ModalForm,
ProForm,
@ -7,8 +9,8 @@ import {
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form } from 'antd';
import React from 'react';
import { Form, message } from 'antd';
import React, { useEffect } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
@ -18,6 +20,8 @@ import {
export type CreateDeviceFormProps = {
createModalOpen: boolean;
handleModal: () => void;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
reload: any;
};
const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
@ -25,12 +29,26 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
// const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.ModelCategory>();
// test 测试数据
useEffect(() => {
if (props.createModalOpen) {
form.setFieldsValue({
name: 'video_2024_000',
addr: '江苏省南京市雨花台区新华汇B4栋',
// classification: null, // 设备分类的suid
device_model: '设备型号2024_001', // 设备型号
param: 'device_2024_05_24', // 设备参数
comment:
'测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注',
});
}
}, [props.createModalOpen]);
return (
<ModalForm<API.ModelCategory>
className="gn_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device_group_list.table.list.add',
id: 'device_group_list.form.action.add',
defaultMessage: '新建',
})}
open={props.createModalOpen}
@ -44,15 +62,23 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
onFinish={async (values) => {
console.log(values, 'add_finish_values');
// TODO 对接新增接口
// postModelCategoryCreateModelCategory(values)
// .then(() => {
// message.success(intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }));
// props.reload();
// })
// .catch(() => {
// message.error(intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }));
// });
props.handleModal();
let resp = await apiEntityNodesDeviceAdd({
...values,
entity_id: props.commInfo.id,
node_id: props.nodeInfo.id,
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
@ -85,7 +111,7 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="deviceSite"
name="addr"
label={
<FormattedMessage
id="device_group_list.table.list.deviceSite"
@ -103,7 +129,7 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormSelect
width={proFormSmallItemStyleProps.column2Width}
name="deviceType"
name="classification"
label={
<FormattedMessage
id="device_group_list.table.list.deviceType"
@ -120,15 +146,27 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
showSearch
debounceTime={500}
request={async () => {
const { data } = await getDictDeviceType();
const { data } = await apiDeviceClassification();
return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v.name, value: v.id };
return { ...v, label: v.name, value: v.suid };
});
}}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device_group_list.table.list.rule.required.deviceType"
defaultMessage="必选"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="deviceModel"
name="device_model"
label={
<FormattedMessage
id="device_group_list.table.list.deviceModel"
@ -146,7 +184,7 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText
width={proFormSmallItemStyleProps.width}
name="deviceParams"
name="param"
label={
<FormattedMessage
id="device_group_list.table.list.deviceParams"
@ -164,7 +202,7 @@ const CreateDeviceForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="remark"
name="comment"
label={
<FormattedMessage id="device_group_list.table.list.remark" defaultMessage="备注" />
}

@ -1,7 +1,9 @@
// import { postModelCategoryCreateModelCategory } from '@/services/resource/ModelCategory';
import { apiEntityNodesAdd } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { ModalForm, ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form } from 'antd';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
@ -13,6 +15,7 @@ export type CreateFormProps = {
createModalOpen: boolean;
handleModal: () => void;
parentInfo?: Record<string, any>;
commInfo: Record<string, any>;
reload: any;
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
@ -20,12 +23,28 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
// const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.ModelCategory>();
// test 测试数据
// useEffect(() => {
// if (props.createModalOpen) {
// form.setFieldsValue({
// // parent: '',
// addr: '江苏省南京市雨花台区新华汇B4栋',
// lon: '108.39829462',
// lat: '32.10234761',
// contact: ' 负责人',
// phone: '18716394627',
// comment:
// '测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介测试一下简介',
// });
// }
// }, [props.createModalOpen]);
return (
<ModalForm<API.ModelCategory>
className="gn_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device_group.tree_node.createForm.add',
id: 'device_group.tree_node.form.action.add',
defaultMessage: '新建',
})}
open={props.createModalOpen}
@ -37,17 +56,24 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'add_finish_values');
// TODO 对接新增接口
// postModelCategoryCreateModelCategory(values)
// .then(() => {
// message.success(intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }));
// props.reload();
// })
// .catch(() => {
// message.error(intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }));
// });
props.handleModal();
let resp = await apiEntityNodesAdd({
...values,
entity_id: props.commInfo.id,
lola: values.lon + ',' + values.lat,
parent: props.parentInfo?.id,
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
@ -78,13 +104,13 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="fatherName"
name="parent_name"
label={
<FormattedMessage id="device_group.tree_node.fatherName" defaultMessage="上级节点" />
}
// TODO 此处在联调时确定下上级节点数据获取来源
placeholder={
!props.parentInfo?.fatherId
!props.parentInfo?.name
? `${intl.formatMessage({
id: 'common.empty',
defaultMessage: '$$$',
@ -97,12 +123,12 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
defaultMessage: '$$$',
})}`
}
initialValue={props?.parentInfo?.fatherName}
initialValue={props?.parentInfo?.name}
disabled
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="address"
name="addr"
label={<FormattedMessage id="device_group.tree_node.address" defaultMessage="地址" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
@ -140,7 +166,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="managerName"
name="contact"
label={
<FormattedMessage id="device_group.tree_node.managerName" defaultMessage="负责人" />
}
@ -154,7 +180,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="managerPhone"
name="phone"
label={
<FormattedMessage id="device_group.tree_node.managerPhone" defaultMessage="联系方式" />
}
@ -168,7 +194,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="remark"
name="comment"
label={<FormattedMessage id="device_group.tree_node.remark" defaultMessage="简介" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',

@ -2,45 +2,49 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-28 11:45:44
* @LastEditTime: 2024-05-29 16:35:16
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\deviceList.tsx
* @Description: deviceGroupdg
* @
* 1
* 2
* 3
* 4
*
* 1
* 2
* 3
*
*
*/
import InnerPageBack from '@/components/Back/innerPageBack';
import { isSuccessApi } from '@/utils/forApi';
import TableActionCard from '@/components/TableActionCard';
import {
apiDeviceClassification,
apiDeviceClassificationAdd,
apiDeviceClassificationDelete,
} from '@/services/business/device';
import TableActionCard from '@/components/TableActionCard';
import { getDeviceListByGroup } from '@/services/testApi/device';
import {
apiEntityNodesDeviceDelete,
apiEntityNodesDeviceInfo,
apiEntityNodesDeviceList,
} from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { ProTable } from '@ant-design/pro-components';
import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max';
import { Button, message } from 'antd';
import { useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../../config/defaultTable';
import CategorizeUpdate from '@/components/CategorizeUpdate';
import IsDelete from '@/components/TableActionCard/isDelete';
import CreateDeviceForm from './createDeviceForm';
import UpdateDeviceForm from './updateDeviceForm';
import ModelSetting from './modelSetting';
type DeviceListProps = {
info: Record<string, any>;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
};
const DeviceList: React.FC<DeviceListProps> = () => {
const DeviceList: React.FC<DeviceListProps> = (props) => {
/**state */
const access = useAccess();
// eslint-disable-next-line react-hooks/rules-of-hooks
@ -48,6 +52,8 @@ const DeviceList: React.FC<DeviceListProps> = () => {
const actionRef = useRef<ActionType>();
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false); // 编辑窗口是否打开
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
// 动态设置每页数量
@ -68,11 +74,30 @@ const DeviceList: React.FC<DeviceListProps> = () => {
const handleCreateModal = () => {
setCreateModalOpen(!createModalOpen);
};
// 编辑
const handleUpdateModal = () => {
setUpdateModalOpen(!updateModalOpen);
};
// 设备节点信息
async function loadDetail(record) {
const resp = await apiEntityNodesDeviceInfo({ device_id: record?.id });
if (isSuccessApi(resp) && resp?.data) {
setCurrentRow({ ...resp?.data, device_id: record?.id });
}
}
function reloadList() {
actionRef.current?.reload();
}
// 筛选查询
useEffect(() => {
if (actionRef && props?.nodeInfo) {
reloadList();
}
}, [actionRef, props.nodeInfo]);
const columns: ProColumns<Record<string, any>>[] = [
{
title: <FormattedMessage id="device_group_list.table.list.name" defaultMessage="设备名称" />,
@ -86,10 +111,11 @@ const DeviceList: React.FC<DeviceListProps> = () => {
title: (
<FormattedMessage id="device_group_list.table.list.deviceType" defaultMessage="设备类型" />
),
dataIndex: 'deviceType',
dataIndex: 'classification',
hideInSearch: true,
// width: 120,
},
// TODO 待定模型部署使用什么字段
{
title: (
<FormattedMessage id="device_group_list.table.list.isEnable" defaultMessage="模型部署" />
@ -144,9 +170,6 @@ const DeviceList: React.FC<DeviceListProps> = () => {
onClick={() => {
setCurrentRow(record);
setIsSettingOpen(true);
// history.push('/home/model-detail');
// doToDetail(record);
// setShowDetail(true);
}}
>
<FormattedMessage
@ -164,12 +187,8 @@ const DeviceList: React.FC<DeviceListProps> = () => {
type="link"
size="small"
onClick={() => {
// TODO 编辑在新增联调后实现
// setCurrentRow(record);
// history.push('/home/model-detail');
// doToDetail(record);
// setShowDetail(true);
// setUpdateModalOpen(true);
loadDetail(record);
setUpdateModalOpen(true);
}}
>
<FormattedMessage id="pages.searchTable.update" defaultMessage="编辑" />
@ -181,7 +200,16 @@ const DeviceList: React.FC<DeviceListProps> = () => {
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
console.log('删除成功');
apiEntityNodesDeviceDelete({ device_id: record.id }).then(() => {
message.success(
intl.formatMessage({
id: 'common.action.success',
defaultMessage: '$$$',
}),
);
reloadList();
});
}}
></IsDelete>
),
@ -244,10 +272,6 @@ const DeviceList: React.FC<DeviceListProps> = () => {
rowKey="id"
onDataSourceChange={(data) => {
console.log(data, 'onDataSourceChange_data');
// let CategoryFkIdIds: any = data.map((v) => {
// return v.categoryFkId;
// });
// setCategoryFkIdIds(CategoryFkIdIds);
}}
pagination={{
...proTablePaginationOptions,
@ -262,9 +286,13 @@ const DeviceList: React.FC<DeviceListProps> = () => {
const { current, ...rest } = params;
const reqParams = {
pageNo: current,
node_id: props.nodeInfo.id,
...rest,
};
let resp = await getDeviceListByGroup({ ...reqParams });
if (!reqParams.node_id) {
return { data: [], success: true };
}
let resp = await apiEntityNodesDeviceList({ ...reqParams });
console.log(resp, 'getDeviceListByGroup_resp');
return {
data: resp.data?.data,
@ -295,6 +323,17 @@ const DeviceList: React.FC<DeviceListProps> = () => {
<CreateDeviceForm
createModalOpen={createModalOpen}
handleModal={handleCreateModal}
commInfo={props.commInfo}
nodeInfo={props.nodeInfo}
reload={reloadList}
/>
<UpdateDeviceForm
updateModalOpen={updateModalOpen}
handleModal={handleUpdateModal}
values={currentRow}
commInfo={props.commInfo}
nodeInfo={props.nodeInfo}
reload={reloadList}
/>
<CategorizeUpdate

@ -0,0 +1,216 @@
import { apiDeviceClassification } from '@/services/business/device';
import { apiEntityNodesDeviceEdit } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
// @ts-ignore
export type UpdateDeviceFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
values: Record<string, any>;
reload: any;
};
const UpdateDeviceForm: React.FC<UpdateDeviceFormProps> = (props) => {
const intl = useIntl();
// const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<Record<string, any>>({});
// function resetForm() {
// form.resetFields();
// }
// useEffect(() => {
// // if (props.updateModalOpen && props.values?.id) {
// // } else {
// // resetForm();
// // }
// }, [props.updateModalOpen, props.values]);
return (
<ModalForm<API.ModelCategory>
className="gn_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device_group_list.form.action.edit',
defaultMessage: '编辑',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'update_finish_values');
let resp = await apiEntityNodesDeviceEdit({
...values,
entity_id: props.commInfo.id,
node_id: props.nodeInfo.id,
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="name"
label={
<FormattedMessage id="device_group_list.table.list.name" defaultMessage="设备名称" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.name',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device_group_list.table.list.rule.required.name"
defaultMessage="名称必填"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="addr"
label={
<FormattedMessage
id="device_group_list.table.list.deviceSite"
defaultMessage="设备位置"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceSite',
defaultMessage: '$$$',
})}`}
/>
<ProFormSelect
width={proFormSmallItemStyleProps.column2Width}
name="classification"
label={
<FormattedMessage
id="device_group_list.table.list.deviceType"
defaultMessage="设备分类"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceType',
defaultMessage: '$$$',
})}`}
showSearch
debounceTime={500}
request={async () => {
const { data } = await apiDeviceClassification();
return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v.name, value: v.suid };
});
}}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device_group_list.table.list.rule.required.deviceType"
defaultMessage="必选"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="device_model"
label={
<FormattedMessage
id="device_group_list.table.list.deviceModel"
defaultMessage="设备型号"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceModel',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="param"
label={
<FormattedMessage
id="device_group_list.table.list.deviceParams"
defaultMessage="设备参数"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceParams',
defaultMessage: '$$$',
})}`}
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="comment"
label={
<FormattedMessage id="device_group_list.table.list.remark" defaultMessage="备注" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.remark',
defaultMessage: '$$$',
})}`}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateDeviceForm;

@ -0,0 +1,233 @@
import { apiDeviceClassification } from '@/services/business/device';
import { apiEntityNodesDeviceEdit } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useEffect } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
// @ts-ignore
export type UpdateDeviceFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
values: Record<string, any>;
reload: any;
};
const UpdateDeviceForm: React.FC<UpdateDeviceFormProps> = (props) => {
const intl = useIntl();
// const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.ModelCategory>();
function resetForm() {
form.resetFields();
}
useEffect(() => {
if (props.updateModalOpen && props.values?.device_id) {
form.setFieldsValue({ ...props.values });
console.log(props.values, 'useEffect_values');
} else {
resetForm();
}
}, [props.updateModalOpen, props.values]);
// test 测试数据
// useEffect(() => {
// if (props.updateModalOpen) {
// form.setFieldsValue({
// name: 'video_2024_000',
// addr: '江苏省南京市雨花台区新华汇B4栋',
// // classification: null, // 设备分类的suid
// device_model: '设备型号2024_001', // 设备型号
// param: 'device_2024_05_24', // 设备参数
// comment:
// '测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注',
// });
// }
// }, [props.updateModalOpen]);
return (
<ModalForm<API.ModelCategory>
className="gn_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device_group_list.form.action.edit',
defaultMessage: '编辑',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'add_finish_values');
// TODO 对接新增接口
let resp = await apiEntityNodesDeviceEdit({
...values,
device_id: props.values.device_id,
entity_id: props.commInfo.id,
node_id: props.nodeInfo.id,
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="name"
label={
<FormattedMessage id="device_group_list.table.list.name" defaultMessage="设备名称" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.name',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device_group_list.table.list.rule.required.name"
defaultMessage="名称必填"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="addr"
label={
<FormattedMessage
id="device_group_list.table.list.deviceSite"
defaultMessage="设备位置"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceSite',
defaultMessage: '$$$',
})}`}
/>
<ProFormSelect
width={proFormSmallItemStyleProps.column2Width}
name="classification"
label={
<FormattedMessage
id="device_group_list.table.list.deviceType"
defaultMessage="设备分类"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceType',
defaultMessage: '$$$',
})}`}
showSearch
debounceTime={500}
request={async () => {
const { data } = await apiDeviceClassification();
return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v.name, value: v.suid };
});
}}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device_group_list.table.list.rule.required.deviceType"
defaultMessage="必选"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="device_model"
label={
<FormattedMessage
id="device_group_list.table.list.deviceModel"
defaultMessage="设备型号"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceModel',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="param"
label={
<FormattedMessage
id="device_group_list.table.list.deviceParams"
defaultMessage="设备参数"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceParams',
defaultMessage: '$$$',
})}`}
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="comment"
label={
<FormattedMessage id="device_group_list.table.list.remark" defaultMessage="备注" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.remark',
defaultMessage: '$$$',
})}`}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateDeviceForm;

@ -0,0 +1,214 @@
import { apiEntityNodesEdit } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { ModalForm, ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useEffect } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
// @ts-ignore
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
commInfo: Record<string, any>;
values: Record<string, any>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
// const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.ModelCategory>();
function resetForm() {
form.resetFields();
}
useEffect(() => {
if (props.updateModalOpen && props.values?.id) {
const { lola } = props.values;
let lon, lat;
if (lola) {
const lolaArr = lola.split(',');
lon = lolaArr[0];
lat = lolaArr[1];
}
form.setFieldsValue({ ...props.values, lon, lat });
console.log(props.values, 'useEffect_values');
} else {
resetForm();
}
}, [props.updateModalOpen, props.values]);
return (
<ModalForm<API.ModelCategory>
className="gn_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device_group.tree_node.form.action.update',
defaultMessage: '编辑',
})}
initialValues={props.values}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
let resp = await apiEntityNodesEdit({
...values,
entity_id: props.commInfo.id,
lola: values.lon + ',' + values.lat,
parent: props.values.parent,
node_id: props.values.node_id,
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="name"
label={<FormattedMessage id="device_group.tree_node.name" defaultMessage="名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.name',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device_group.tree_node.rule.required.name"
defaultMessage="名称必填"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="parent_name"
label={
<FormattedMessage id="device_group.tree_node.fatherName" defaultMessage="上级节点" />
}
// TODO 此处在联调时确定下上级节点数据获取来源
placeholder={
!props.values?.parent_name
? `${intl.formatMessage({
id: 'common.empty',
defaultMessage: '$$$',
})}`
: `${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.fatherName',
defaultMessage: '$$$',
})}`
}
disabled
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="addr"
label={<FormattedMessage id="device_group.tree_node.address" defaultMessage="地址" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.address',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="lon"
label={<FormattedMessage id="device_group.tree_node.lon" defaultMessage="经度" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.lon',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="lat"
label={<FormattedMessage id="device_group.tree_node.lat" defaultMessage="纬度" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.lat',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="contact"
label={
<FormattedMessage id="device_group.tree_node.managerName" defaultMessage="负责人" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.managerName',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="phone"
label={
<FormattedMessage id="device_group.tree_node.managerPhone" defaultMessage="联系方式" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.managerPhone',
defaultMessage: '$$$',
})}`}
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="comment"
label={<FormattedMessage id="device_group.tree_node.remark" defaultMessage="简介" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group.tree_node.remark',
defaultMessage: '$$$',
})}`}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-27 13:47:38
* @LastEditTime: 2024-05-29 15:15:23
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\index.tsx
* @Description: deviceGroupdg
* @
@ -12,29 +12,47 @@
* 4
* 5
*/
import { DeviceGroupTree } from '@/components/Tree';
import { deviceGroupEnums } from '@/enums/device';
import { useBusinessInfo } from '@/hooks/useBusinessInfo';
import { isSuccessApi } from '@/utils/forApi';
import { getDeviceGroupList } from '@/services/testApi/deviceGroup';
import IsConfirmModal from '@/components/TableActionCard/isConfirmModal';
import {
apiEntityNodes,
apiEntityNodesDelete,
apiEntityNodesInfo,
} from '@/services/business/entity';
import { ProCard } from '@ant-design/pro-components';
import { Button, Tabs } from 'antd';
import { useEffect, useState } from 'react';
import { useIntl } from '@umijs/max';
import { Button, Tabs, message } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import AlarmSetForm from './components/alarmSetForm';
import BaseInfo from './components/baseInfo';
import CreateForm from './components/createForm';
import DeviceList from './components/deviceList';
import ModelDeploy from './components/modelDeploy';
import UpdateForm from './components/updateForm';
import './index.less';
const DeviceGroup: React.FC = () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const intl = useIntl();
const { getStoreBusinessInfo } = useBusinessInfo();
/**state */
// 节点信息
const [deviceTreeList, setDeviceTreeList] = useState<Record<string, any>[]>([]);
const [nodeInfo, setNodeInfo] = useState<Record<string, any>>({}); // 当前节点信息
const [commInfo] = useState<Record<string, any>>({ ...getStoreBusinessInfo() }); // 通用信息
// const [parentInfo, setParentInfo] = useState<Record<string, any>>({}); // 通用信息
const [currTreeInfo, setCurrTreeInfo] = useState<Record<string, any>>({});
const [actionType, setActionType] = useState<string>('');
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false); // 创建新增窗口是否打开
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false); // 编辑窗口是否打开
const comfirmModalRef = useRef(null);
// 切换模块
const [tabKey, setTabKey] = useState<string>(deviceGroupEnums[0].key);
const [tabs] = useState<any>([...deviceGroupEnums]);
@ -44,14 +62,37 @@ const DeviceGroup: React.FC = () => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
// initList(key);
};
/**节点列表 */
/**节点设置 */
// 设备节点信息
async function loadDeviceDetail(record, isParent = false) {
const resp = await apiEntityNodesInfo({ node_id: record?.id });
if (isSuccessApi(resp) && resp?.data) {
// console.log(resp.data, 'loadDeviceDetail_resp');
if (isParent) {
// setParentInfo(resp?.data);
} else {
setNodeInfo({ ...resp?.data, node_id: record?.id });
}
}
}
// 设备节点树
async function loadDeviceTree() {
const resp = await getDeviceGroupList({ pageNo: 1, pageSize: 100 });
async function loadDeviceTree(otherParams = {}) {
console.log('loadDeviceTree_commInfo', commInfo);
const resp = await apiEntityNodes({ entity_id: commInfo.id, ...otherParams });
console.log(resp.data, 'loadDeviceTree');
if (isSuccessApi(resp)) {
setDeviceTreeList(resp?.data.data);
setNodeInfo(resp?.data.data[0]);
}
if (
isSuccessApi(resp) &&
resp?.data &&
resp?.data?.data &&
Array.isArray(resp?.data.data) &&
resp?.data.data.length
) {
const currNodeInfo = resp?.data.data[0];
loadDeviceDetail(currNodeInfo);
}
}
@ -59,6 +100,10 @@ const DeviceGroup: React.FC = () => {
const handleCreateModal = () => {
setCreateModalOpen(!createModalOpen);
};
// 编辑
const handleUpdateModal = () => {
setUpdateModalOpen(!updateModalOpen);
};
// 节点信息展示
// 切换
@ -68,6 +113,19 @@ const DeviceGroup: React.FC = () => {
loadDeviceTree();
}, []);
useEffect(() => {
switch (actionType) {
case 'deleteNode':
if (currTreeInfo) {
comfirmModalRef?.current?.confirm();
}
break;
case 'addNode':
handleCreateModal();
break;
}
}, [currTreeInfo, actionType]);
return (
<div className="flex deviceGroup_page">
{/* 节点列表 */}
@ -76,19 +134,30 @@ const DeviceGroup: React.FC = () => {
<div className="dg_tree_box">
<DeviceGroupTree
dataSource={deviceTreeList}
changeNode={(record) => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
record?.id && setNodeInfo(record);
searchChange={(record) => {
console.log(record, 'searchChange');
loadDeviceTree({ name: record });
}}
addTreeNode={(node) => {
//TODO 判断是根节点还是子节点 调用新增接口
console.log('addTreeNode_node', node);
handleCreateModal();
// 判断是根节点还是子节点
console.log(node, 'addTreeNode');
if (node) {
setCurrTreeInfo({ ...node, id: Number(node.key) });
} else {
setCurrTreeInfo({});
}
setActionType('addNode');
}}
deleteTreeNode={(node) => {
// 是否确认删除
setCurrTreeInfo(node);
setActionType('deleteNode');
console.log('deleteTreeNode_node', node, comfirmModalRef);
}}
selectTree={(selectedKeys, info) => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
info?.node && info?.node?.id && setNodeInfo(info?.node);
// handleSelectNode(selectedKeys, info)
if (selectedKeys && Array.isArray(selectedKeys) && selectedKeys.length) {
loadDeviceDetail({ id: selectedKeys[0] });
}
console.log('selectTree_selected', selectedKeys, info);
}}
></DeviceGroupTree>
@ -105,8 +174,7 @@ const DeviceGroup: React.FC = () => {
<Button
type="primary"
onClick={() => {
//TODO 打开修改节点信息弹窗
// handleUpdateModal();
handleUpdateModal();
}}
>
@ -123,7 +191,7 @@ const DeviceGroup: React.FC = () => {
changeTabMode(key);
}}
></Tabs>
{tabKey === '1' && <DeviceList info={nodeInfo}></DeviceList>}
{tabKey === '1' && <DeviceList commInfo={commInfo} nodeInfo={nodeInfo}></DeviceList>}
{tabKey === '2' && <ModelDeploy info={nodeInfo}></ModelDeploy>}
{tabKey === '3' && (
<AlarmSetForm
@ -151,11 +219,52 @@ const DeviceGroup: React.FC = () => {
<CreateForm
createModalOpen={createModalOpen}
handleModal={handleCreateModal}
parentInfo={nodeInfo}
parentInfo={currTreeInfo}
commInfo={commInfo}
reload={() => {
// TODO 调用获取节点列表的接口
loadDeviceTree();
}}
/>
<UpdateForm
values={nodeInfo}
updateModalOpen={updateModalOpen}
handleModal={handleUpdateModal}
commInfo={commInfo}
reload={() => {
loadDeviceTree();
}}
/>
{/* UpdateForm */}
{/* 是否删除节点 */}
<IsConfirmModal
ref={comfirmModalRef}
modalProps={{
content: `确定删除${currTreeInfo.name}及相关信息吗?删除后将无法找回,请谨慎
.`,
onOk: () => {
console.log('删除成功');
apiEntityNodesDelete({ node_id: currTreeInfo.id })
.then(() => {
message.success(
intl.formatMessage({
id: 'common.action.success',
defaultMessage: '$$$',
}),
);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
loadDeviceTree();
})
.catch(() => {
message.error(
intl.formatMessage({
id: 'common.action.failure',
defaultMessage: '$$$',
}),
);
});
},
}}
></IsConfirmModal>
</div>
);
};

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-07 14:02:00
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-28 11:10:35
* @LastEditTime: 2024-05-28 14:30:32
* @FilePath: \general-ai-manage\src\pages\ModelIndex\ModelIndex.tsx
* @Description:
* @
@ -45,7 +45,6 @@ const ModelIndex: React.FC = () => {
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
// 设置分类
const [industryOpen, setIndustryOpen] = useState<boolean>(false);
// const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-23 13:50:50
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-28 10:09:31
* @LastEditTime: 2024-05-28 14:16:29
* @FilePath: \general-ai-platform-web\src\services\Business\entity.ts
* @Description: api
*/
@ -202,3 +202,84 @@ export async function apiEntityNodesInfo(body: any, options?: { [key: string]: a
},
);
}
/** 节点企业设备 */
// 添加企业设备
export async function apiEntityNodesDeviceAdd(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/entity/nodes/device/add`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 修改企业设备
export async function apiEntityNodesDeviceEdit(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/entity/nodes/device/edit`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 企业设备信息
export async function apiEntityNodesDeviceInfo(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/entity/nodes/device/info`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 删除企业设备
export async function apiEntityNodesDeviceDelete(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/entity/nodes/device/delete`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 企业设备列表
export async function apiEntityNodesDeviceList(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/entity/nodes/device/list`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}

Loading…
Cancel
Save