feat: 初始化分布式设备模块

develop
zhoux 1 year ago
parent d78221b5c8
commit c4c145100b

@ -121,6 +121,22 @@ export default [
'access': 'canReadMenu'
}],
},
{
name: 'DCSDevice',
path: '/DCSDevice',
routes: [{
'name': 'DCSDevice-device-list',
'path': '/DCSDevice/device-list',
'component': 'DCSDevice/DeviceList',
'access': 'canReadMenu'
}, {
'name': 'DCSDevice-device-status',
'path': '/DCSDevice/device-status',
'component': 'DCSDevice/DeviceStatus',
'access': 'canReadMenu'
}],
},
{
name: 'resource',

@ -0,0 +1,20 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-12-08 10:26:34
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-12-08 10:27:48
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\DCSDevice.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// 设备列表
export const DCSDevice_list: { [key: string]: string } = {
'DCSDeviceList.device.table.list.name': '设备名称'
}
export const DCSDevice_status: { [key: string]: string } = {
}

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-10 14:44:54
* @LastEditTime: 2023-12-08 10:30:11
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\menu.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -70,5 +70,7 @@ export default {
'menu.list.staff': '人力资源',
'menu.list.staff.employee-list': '员工列表',
'menu.device.device-relation-list': '设备版本列表',
'menu.resource.algorithm-model-detail': '模型详情'
'menu.resource.algorithm-model-detail': '模型详情',
'menu.DCSDevice.DCSDevice-device-status': '设备状态',
'menu.DCSDevice.DCSDevice-device-list': '设备列表'
};

@ -0,0 +1,41 @@
import React from "react";
import {Drawer} from "antd";
import {ProColumns, ProDescriptions, ProDescriptionsItemProps} from "@ant-design/pro-components";
export type ColumnDrawProps = {
handleDrawer: (id?: any)=>void;
isShowDetail: boolean;
columns: ProColumns<API.Device>[];
currentRow: API.Device | undefined;
};
const ColumnDrawer: React.FC<ColumnDrawProps> = (props) => {
return (
<Drawer
width={500}
open={props.isShowDetail}
onClose={() => {
props.handleDrawer();
}}
closable={true}
>
{props.currentRow?.id && (
<ProDescriptions<API.Device>
column={2}
title={props.currentRow?.id}
request={async () => ({
data: props.currentRow || {},
})}
params={{
id: props.currentRow?.id,
}}
columns={props.columns as ProDescriptionsItemProps<API.Device>[]}
/>
)}
</Drawer>
)
}
export {ColumnDrawer}

@ -0,0 +1,62 @@
import { FormattedMessage} from '@umijs/max';
export const DeviceColumns = [{
title: (<FormattedMessage
id="device.device.table.list.id"
defaultMessage="$$$"/>),
dataIndex: "id",
},{
title: (<FormattedMessage
id="device.device.table.list.name"
defaultMessage="$$$"/>),
dataIndex: "name",
},{
title: (<FormattedMessage
id="device.device.table.list.code"
defaultMessage="$$$"/>),
dataIndex: "code",
},{
title: (<FormattedMessage
id="device.device.table.list.position"
defaultMessage="$$$"/>),
dataIndex: "position",
},{
title: (<FormattedMessage
id="device.device.table.list.param"
defaultMessage="$$$"/>),
dataIndex: "param",
},{
title: (<FormattedMessage
id="device.device.table.list.spec"
defaultMessage="$$$"/>),
dataIndex: "spec",
},{
title: (<FormattedMessage
id="device.device.table.list.categoryFkId"
defaultMessage="$$$"/>),
dataIndex: "category_fk_id",
},{
title: (<FormattedMessage
id="device.device.table.list.groupFkId"
defaultMessage="$$$"/>),
dataIndex: "group_fk_id",
},{
title: (<FormattedMessage
id="device.device.table.list.isEnable"
defaultMessage="$$$"/>),
dataIndex: "is_enable",
},{
title: (<FormattedMessage
id="device.device.table.list.remark"
defaultMessage="$$$"/>),
dataIndex: "remark",
},{
title: (<FormattedMessage
id="device.device.table.list.createTime"
defaultMessage="$$$"/>),
dataIndex: "create_time",
},{
title: (<FormattedMessage
id="device.device.table.list.updateTime"
defaultMessage="$$$"/>),
dataIndex: "update_time",
},]

@ -0,0 +1,233 @@
import { postDeviceCreateDevice } from '@/services/device/Device';
import { postDeviceCategoryGetDeviceCategoryFkSelect } from '@/services/device/DeviceCategory';
import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormSwitch,
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, Switch, message } from 'antd';
import React, { useState } from 'react';
import { proFormItemStyleProps, proFormModelWidth } from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Device>;
export type CreateFormProps = {
createModalOpen: boolean;
handleModal: () => void;
values: Partial<API.Device>;
reload: any;
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
const intl = useIntl();
const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.Device>();
return (
<ModalForm<API.Device>
width={proFormModelWidth}
title={intl.formatMessage({
id: 'device.device.table.list.add',
defaultMessage: '$$$',
})}
open={props.createModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
postDeviceCreateDevice(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;
}}
>
<ProForm.Group>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="name"
label={<FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.name', defaultMessage: '$$$' })}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.name"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="groupFkId"
label={<FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.groupFkId',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceGroupGetDeviceGroupFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormText
width={proFormItemStyleProps.width - 80}
name="code"
label={<FormattedMessage id="device.device.table.list.code" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.code', defaultMessage: '$$$' })}`}
required={!isAuto}
initialValue=""
disabled={isAuto}
rules={
isAuto
? []
: [
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.code"
defaultMessage="code is required"
/>
),
},
]
}
addonAfter={
<Switch
checked={isAuto}
checkedChildren={<FormattedMessage id="common.auto" defaultMessage="$$$" />}
unCheckedChildren={<FormattedMessage id="common.edit" defaultMessage="$$$" />}
onChange={setIsAuto}
/>
}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="position"
label={<FormattedMessage id="device.device.table.list.position" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.position',
defaultMessage: '$$$',
})}`}
required={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="param"
label={<FormattedMessage id="device.device.table.list.param" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.param',
defaultMessage: '$$$',
})}`}
required={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="spec"
label={<FormattedMessage id="device.device.table.list.spec" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.spec', defaultMessage: '$$$' })}`}
required={false}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="categoryFkId"
label={
<FormattedMessage id="device.device.table.list.categoryFkId" defaultMessage="$$$" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.categoryFkId',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceCategoryGetDeviceCategoryFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="remark"
label={<FormattedMessage id="device.device.table.list.remark" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.remark',
defaultMessage: '$$$',
})}`}
required={false}
/>
<ProFormSwitch
width={proFormItemStyleProps.column2Width}
name="isEnable"
label={<FormattedMessage id="device.device.table.list.isEnable" defaultMessage="$$$" />}
initialValue={true}
/>
</ProForm.Group>
</ModalForm>
);
};
export default CreateForm;

@ -0,0 +1,272 @@
import { putDeviceUpdateDevice } from '@/services/device/Device';
import { postDeviceCategoryGetDeviceCategoryFkSelect } from '@/services/device/DeviceCategory';
import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup';
import {
ModalForm,
ProForm,
ProFormDateTimePicker,
ProFormSelect,
ProFormSwitch,
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import { proFormItemStyleProps, proFormModelWidth } from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Device>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.Device>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.Device>();
return (
<ModalForm<API.Device>
width={proFormModelWidth}
title={intl.formatMessage({
id: 'device.device.table.list.update',
defaultMessage: '$$$',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
putDeviceUpdateDevice(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;
}}
>
<ProForm.Group>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="id"
label="id"
disabled={true}
initialValue={props.values.id}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="name"
label={<FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.name', defaultMessage: '$$$' })}`}
required={true}
initialValue={props.values.name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.name"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="code"
label={<FormattedMessage id="device.device.table.list.code" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.code', defaultMessage: '$$$' })}`}
required={true}
initialValue={props.values.code}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.code"
defaultMessage="code is required"
/>
),
},
]}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="position"
label={<FormattedMessage id="device.device.table.list.position" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.position',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.position}
disabled={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="param"
label={<FormattedMessage id="device.device.table.list.param" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.param',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.param}
disabled={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="spec"
label={<FormattedMessage id="device.device.table.list.spec" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.spec', defaultMessage: '$$$' })}`}
required={false}
initialValue={props.values.spec}
disabled={false}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="categoryFkId"
label={
<FormattedMessage id="device.device.table.list.categoryFkId" defaultMessage="$$$" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.categoryFkId',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.categoryFkId}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceCategoryGetDeviceCategoryFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="groupFkId"
label={<FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.groupFkId',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.groupFkId}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceGroupGetDeviceGroupFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="remark"
label={<FormattedMessage id="device.device.table.list.remark" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.remark',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.remark}
disabled={false}
/>
<ProFormSwitch
width={proFormItemStyleProps.column2Width}
name="isEnable"
label={<FormattedMessage id="device.device.table.list.isEnable" defaultMessage="$$$" />}
initialValue={props.values.isEnable}
disabled={false}
/>
<ProFormDateTimePicker
width={proFormItemStyleProps.column2Width}
name="createTime"
label={<FormattedMessage id="device.device.table.list.createTime" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.createTime',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.createTime}
disabled={true}
/>
<ProFormDateTimePicker
width={proFormItemStyleProps.column2Width}
name="updateTime"
label={<FormattedMessage id="device.device.table.list.updateTime" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.updateTime',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.updateTime}
disabled={true}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -0,0 +1,53 @@
import {useIntl} from '@umijs/max';
import React, {useState, useRef, useCallback, useEffect} from 'react';
import {Form, Modal} from 'antd';
import WebRTCStreamer from "@/components/WebRtcPlayer";
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Device>;
export type VideoModalProps = {
modalOpen: boolean;
handleModal: () => void;
values: Partial<API.Device>;
reload: any;
videoServerParam: API.RtspRes;
};
const VideoModal: React.FC<VideoModalProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.ActionDetection>();
const [videoInit, setVideoInit] = useState(false);
useEffect(()=>{
setVideoInit(false)
if (props.modalOpen) {
setVideoInit(true)
} else {
console.log('***********')
setVideoInit(false)
}
}, [props.modalOpen])
return (
<Modal title="播放视频" open={props.modalOpen}
width={1280}
onOk={props.handleModal} onCancel={props.handleModal}
footer={null}>
{videoInit && (<WebRTCStreamer is_open={props.modalOpen} stream_url={props.values.param} server_url={props.videoServerParam.host || ''}></WebRTCStreamer>)}
</Modal>
)
}
export default VideoModal;

@ -0,0 +1,706 @@
import IsBatchDelete from '@/components/BatchOperation/isBatchDelete';
import TableActionCard from '@/components/TableActionCard';
import IsDelete from '@/components/TableActionCard/isDelete';
import TreeAndTableList, { ProCardTypeProps } from '@/layouts/treeAndTableList';
import { ColumnDrawer as DeviceCategoryColumnDrawer } from '@/pages/Device/DeviceCategoryList/components/ColumnDrawer';
import { DeviceCategoryColumns } from '@/pages/Device/DeviceCategoryList/components/Columns';
import { ColumnDrawer as DeviceGroupColumnDrawer } from '@/pages/Device/DeviceGroupList/components/ColumnDrawer';
import { DeviceGroupColumns } from '@/pages/Device/DeviceGroupList/components/Columns';
import {
deleteDeviceDeleteDevice,
deleteDeviceDeleteDeviceByIds,
postDeviceCloseRtspCamera,
postDeviceGetDeviceList,
postDeviceOpenRtspCamera,
} from '@/services/device/Device';
import {
postDeviceCategoryGetDeviceCategoryById,
postDeviceCategoryGetDeviceCategoryFkSelect,
postDeviceCategoryGetDeviceCategoryNames,
} from '@/services/device/DeviceCategory';
import {
postDeviceGroupGetDeviceGroupById,
postDeviceGroupGetDeviceGroupFkSelect,
postDeviceGroupGetDeviceGroupNames,
postDeviceGroupGetDeviceGroupTree,
} from '@/services/device/DeviceGroup';
import { PlusOutlined, RedoOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProFormSelect, ProTable } from '@ant-design/pro-components';
import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max';
import { Button, Tree, message } from 'antd';
import { DataNode } from 'antd/es/tree';
import React, { useEffect, useRef, useState } from 'react';
import { proTableCommonOptions, proTablePaginationOptions } from '../../../../config/defaultTable';
import { ColumnDrawer } from './components/ColumnDrawer';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
import VideoModal from './components/VideoModal';
const DeviceList: React.FC = () => {
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
const [videoModalOpen, setVideoModalOpen] = useState<boolean>(false);
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [showDetail, setShowDetail] = useState<boolean>(false);
/**
* @en-US International configuration
* @zh-CN
* */
const access = useAccess();
const intl = useIntl();
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentRow, setCurrentRow] = useState<API.Device>();
const [selectedRowsState, setSelectedRows] = useState<API.Device[]>([]);
const [category_fk_id_open, set_category_fk_id_open] = useState(false);
const [category_fk_id, set_category_fk_id] = useState<API.DeviceCategory>();
const [category_fk_id_column_open, set_category_fk_id_column_open] = useState(false);
const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
const [categoryFkIdMap, setCategoryFkIdMap] = useState<{ [key: number]: string }>({});
const [group_fk_id_open, set_group_fk_id_open] = useState(false);
const [group_fk_id, set_group_fk_id] = useState<API.DeviceGroup>();
const [group_fk_id_column_open, set_group_fk_id_column_open] = useState(false);
const [groupFkIdIds, setGroupFkIdIds] = useState([]);
const [groupFkIdMap, setGroupFkIdMap] = useState<{ [key: number]: string }>({});
const [hasInit, setHasInit] = useState<boolean>(false);
const [nodeTreeData, setNodeTreeData] = React.useState<DataNode[]>([]);
const [selectNodes, setSelectNodes] = React.useState<any[]>([]);
const [videoOpening, setVideoOpening] = useState<boolean>(false);
const [videoServerParam, setVideoServerParam] = useState<API.RtspRes>({});
useEffect(() => {
postDeviceGroupGetDeviceGroupTree()
.then((resp) => {
setNodeTreeData(resp.data.tree);
setHasInit(true);
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
});
}, []);
const handleVideoModal = () => {
if (videoModalOpen) {
setVideoModalOpen(false);
if (videoServerParam?.pid || 0) {
postDeviceCloseRtspCamera({ pid: videoServerParam.pid }).then((resp) => {
console.log(resp);
});
}
setCurrentRow(undefined);
setVideoServerParam({});
} else {
setVideoModalOpen(true);
}
};
const handle_category_fk_id = (id: any) => {
if (category_fk_id_open) {
set_category_fk_id(undefined);
set_category_fk_id_open(false);
} else {
postDeviceCategoryGetDeviceCategoryById({ id: id }).then((resp) => {
set_category_fk_id(resp.data.deviceCategory);
set_category_fk_id_open(true);
});
}
};
const handle_category_fk_id_column_open = () => {
if (category_fk_id_column_open) {
set_category_fk_id_column_open(false);
} else {
postDeviceCategoryGetDeviceCategoryNames({ ids: categoryFkIdIds }).then((resp) => {
let a: any = {};
resp.data.list.forEach((v: any) => {
if (v.id) {
a[v.id] = v.name;
}
});
setCategoryFkIdMap(a);
});
set_category_fk_id_column_open(true);
}
};
const handle_group_fk_id = (id: any) => {
if (group_fk_id_open) {
set_group_fk_id(undefined);
set_group_fk_id_open(false);
} else {
postDeviceGroupGetDeviceGroupById({ id: id }).then((resp) => {
set_group_fk_id(resp.data.deviceGroup);
set_group_fk_id_open(true);
});
}
};
const handle_group_fk_id_column_open = () => {
if (group_fk_id_column_open) {
set_group_fk_id_column_open(false);
} else {
postDeviceGroupGetDeviceGroupNames({ ids: groupFkIdIds }).then((resp) => {
let a: any = {};
resp.data.list.forEach((v: any) => {
if (v.id) {
a[v.id] = v.name;
}
});
setGroupFkIdMap(a);
});
set_group_fk_id_column_open(true);
}
};
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
const handleCreateModal = () => {
if (createModalOpen) {
setCreateModalOpen(false);
setCurrentRow(undefined);
} else {
setCreateModalOpen(true);
}
};
const handleColumnDrawer = () => {
if (showDetail) {
setShowDetail(false);
setCurrentRow(undefined);
} else {
setShowDetail(true);
}
};
const handleDestroy = async (selectedRow: API.Device) => {
deleteDeviceDeleteDevice({ id: selectedRow.id })
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
actionRef.current?.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
});
};
const columns: ProColumns<API.Device>[] = [
{
title: <FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />,
dataIndex: 'name',
width: '150',
sorter: true,
render: (dom, entity) => {
return (
<a
onClick={() => {
setCurrentRow(entity);
setShowDetail(true);
}}
>
{dom}
</a>
);
},
// renderFormItem: () => {
// return (
// <>
// <ProFormText
// width="md"
// labelCol={{ span: 4 }}
// wrapperCol={{ span: 22 }}
// name="name"
// placeholder={`${intl.formatMessage({
// id: 'common.please_input',
// defaultMessage: '$$$',
// })}`}
// required={false}
// />
// </>
// );
// },
key: 'fixedName',
fixed: 'left',
},
// {
// title: <FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />,
// dataIndex: 'name',
// hideInSearch: true,
// },
{
title: <FormattedMessage id="device.device.table.list.code" defaultMessage="$$$" />,
dataIndex: 'code',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.position" defaultMessage="$$$" />,
dataIndex: 'position',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.param" defaultMessage="$$$" />,
dataIndex: 'param',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.spec" defaultMessage="$$$" />,
dataIndex: 'spec',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.categoryFkId" defaultMessage="$$$" />,
dataIndex: 'categoryFkId',
hideInSearch: false,
render: (text, record) => {
if (category_fk_id_column_open) {
return (
<a
onClick={() => {
handle_category_fk_id(record.categoryFkId);
}}
>
{record?.categoryFkId ? categoryFkIdMap[record.categoryFkId] : undefined}
</a>
);
} else {
return (
<a
onClick={() => {
handle_category_fk_id(record.categoryFkId);
}}
>
{record.categoryFkId}
</a>
);
}
},
renderFormItem: () => {
return (
// value 和 onchange 会通过 form 自动注入。
<ProFormSelect
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceCategoryGetDeviceCategoryFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
);
},
},
{
title: <FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />,
dataIndex: 'groupFkId',
hideInSearch: false,
render: (text, record) => {
if (group_fk_id_column_open) {
return (
<a
onClick={() => {
handle_group_fk_id(record.groupFkId);
}}
>
{record?.groupFkId ? groupFkIdMap[record.groupFkId] : undefined}
</a>
);
} else {
return (
<a
onClick={() => {
handle_group_fk_id(record.groupFkId);
}}
>
{record.groupFkId}
</a>
);
}
},
renderFormItem: () => {
return (
// value 和 onchange 会通过 form 自动注入。
<ProFormSelect
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceGroupGetDeviceGroupFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
);
},
},
{
title: <FormattedMessage id="device.device.table.list.isEnable" defaultMessage="$$$" />,
dataIndex: 'isEnable',
filters: true,
onFilter: true,
hideInSearch: true,
valueType: 'switch',
},
{
title: <FormattedMessage id="device.device.table.list.remark" defaultMessage="$$$" />,
dataIndex: 'remark',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.createTime" defaultMessage="$$$" />,
dataIndex: 'createTime',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="device.device.table.list.updateTime" defaultMessage="$$$" />,
dataIndex: 'updateTime',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
{
key: 'update',
renderDom: (
<Button
key="update"
type="link"
size="small"
onClick={() => {
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="pages.searchTable.update" defaultMessage="Update" />
</Button>
),
},
{
key: 'destroy',
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
}}
></IsDelete>
),
},
{
key: 'video',
renderDom: (
<Button
key="video"
type="link"
size="small"
onClick={() => {
setVideoOpening(true);
if (record.param) {
postDeviceOpenRtspCamera({ url: record.param })
.then((resp) => {
setVideoServerParam(resp.data);
setVideoOpening(false);
setVideoModalOpen(true);
console.log(resp.data);
setCurrentRow(record);
})
.catch(() => {
setVideoOpening(false);
message.error(
intl.formatMessage({
id: 'common.open_failure',
defaultMessage: '$$$',
}),
);
});
} else {
setVideoOpening(false);
message.error(
intl.formatMessage({ id: 'common.open_failure', defaultMessage: '$$$' }),
);
}
}}
>
<FormattedMessage id="common.open_video" defaultMessage="$$$" />
</Button>
),
},
]}
></TableActionCard>,
],
},
];
return (
<PageContainer>
<TreeAndTableList
leftCard={
{
title: '网点选择',
extra: (
<>
<Button
icon={<RedoOutlined />}
onClick={() => {
setSelectNodes([]);
actionRef.current?.reload();
}}
>
</Button>
</>
),
} as ProCardTypeProps
}
leftDom={
hasInit && (
<Tree
checkable={false}
defaultExpandAll={true}
selectedKeys={selectNodes}
treeData={nodeTreeData}
onSelect={(selectKeys) => {
setSelectNodes(selectKeys);
actionRef.current?.reload();
}}
checkStrictly={false}
/>
)
}
rightDom={
<ProTable<API.Device>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: '$$$',
})}
loading={{
tip: intl.formatMessage({
id: 'common.video_opening',
defaultMessage: '$$$',
}),
spinning: videoOpening,
}}
options={{ fullScreen: true, setting: true, density: true, reload: true }}
actionRef={actionRef}
rowKey="key"
scroll={{ x: 2000, y: proTableCommonOptions.commscrollY }}
search={{
labelWidth: proTableCommonOptions.searchLabelWidth,
}}
onDataSourceChange={(data) => {
let CategoryFkIdIds: any = data.map((v) => {
return v.categoryFkId;
});
setCategoryFkIdIds(CategoryFkIdIds);
let GroupFkIdIds: any = data.map((v) => {
return v.groupFkId;
});
setGroupFkIdIds(GroupFkIdIds);
}}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'device_list',
persistenceType: 'localStorage',
}}
tableAlertOptionRender={() => {
return (
<>
{selectedRowsState?.length > 0 && (
<IsBatchDelete
deleteApi={() => {
// TODO 需联调批量删除接口
deleteDeviceDeleteDeviceByIds({
ids: selectedRowsState.map((v: API.Device) => {
return v.id as number;
}),
}).then(() => {
actionRef.current?.reloadAndRest?.();
});
}}
/>
)}
</>
);
}}
toolBarRender={() => [
<Access
accessible={access.canUpdate(history.location.pathname)}
key={`${history.location.pathname}-add`}
>
<Button
type="primary"
key="category_fk_id_show"
onClick={() => {
handle_category_fk_id_column_open();
}}
>
{category_fk_id_column_open ? (
<FormattedMessage id="common.hide" defaultMessage="$$$" />
) : (
<FormattedMessage id="common.show" defaultMessage="$$$" />
)}
<FormattedMessage
id="device.device.table.list.categoryFkId"
defaultMessage="$$$"
/>
</Button>
<Button
type="primary"
key="group_fk_id_show"
onClick={() => {
handle_group_fk_id_column_open();
}}
>
{group_fk_id_column_open ? (
<FormattedMessage id="common.hide" defaultMessage="$$$" />
) : (
<FormattedMessage id="common.show" defaultMessage="$$$" />
)}
<FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />
</Button>
<Button
type="primary"
key="primary"
onClick={() => {
setCreateModalOpen(true);
}}
>
<PlusOutlined />{' '}
<FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
</Button>
</Access>,
]}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams: any = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (selectNodes.length) {
reqParams.groupFkId = selectNodes[0];
}
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
let resp = await postDeviceGetDeviceList({ ...reqParams });
return {
data: resp.data.list.map((v: API.Device) => {
return { ...v, key: v.id };
}),
success: resp.success,
total: resp.data.total,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => {
setSelectedRows(selectedRows);
},
}}
/>
}
></TreeAndTableList>
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<ColumnDrawer
handleDrawer={handleColumnDrawer}
isShowDetail={showDetail}
columns={columns}
currentRow={currentRow}
/>
<DeviceCategoryColumnDrawer
handleDrawer={handle_category_fk_id}
isShowDetail={category_fk_id_open}
columns={DeviceCategoryColumns}
currentRow={category_fk_id}
/>
<DeviceGroupColumnDrawer
handleDrawer={handle_group_fk_id}
isShowDetail={group_fk_id_open}
columns={DeviceGroupColumns}
currentRow={group_fk_id}
/>
<VideoModal
modalOpen={videoModalOpen}
handleModal={handleVideoModal}
values={currentRow || {}}
videoServerParam={videoServerParam}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default DeviceList;

@ -0,0 +1,41 @@
import React from "react";
import {Drawer} from "antd";
import {ProColumns, ProDescriptions, ProDescriptionsItemProps} from "@ant-design/pro-components";
export type ColumnDrawProps = {
handleDrawer: (id?: any)=>void;
isShowDetail: boolean;
columns: ProColumns<API.Device>[];
currentRow: API.Device | undefined;
};
const ColumnDrawer: React.FC<ColumnDrawProps> = (props) => {
return (
<Drawer
width={500}
open={props.isShowDetail}
onClose={() => {
props.handleDrawer();
}}
closable={true}
>
{props.currentRow?.id && (
<ProDescriptions<API.Device>
column={2}
title={props.currentRow?.id}
request={async () => ({
data: props.currentRow || {},
})}
params={{
id: props.currentRow?.id,
}}
columns={props.columns as ProDescriptionsItemProps<API.Device>[]}
/>
)}
</Drawer>
)
}
export {ColumnDrawer}

@ -0,0 +1,62 @@
import { FormattedMessage} from '@umijs/max';
export const DeviceColumns = [{
title: (<FormattedMessage
id="device.device.table.list.id"
defaultMessage="$$$"/>),
dataIndex: "id",
},{
title: (<FormattedMessage
id="device.device.table.list.name"
defaultMessage="$$$"/>),
dataIndex: "name",
},{
title: (<FormattedMessage
id="device.device.table.list.code"
defaultMessage="$$$"/>),
dataIndex: "code",
},{
title: (<FormattedMessage
id="device.device.table.list.position"
defaultMessage="$$$"/>),
dataIndex: "position",
},{
title: (<FormattedMessage
id="device.device.table.list.param"
defaultMessage="$$$"/>),
dataIndex: "param",
},{
title: (<FormattedMessage
id="device.device.table.list.spec"
defaultMessage="$$$"/>),
dataIndex: "spec",
},{
title: (<FormattedMessage
id="device.device.table.list.categoryFkId"
defaultMessage="$$$"/>),
dataIndex: "category_fk_id",
},{
title: (<FormattedMessage
id="device.device.table.list.groupFkId"
defaultMessage="$$$"/>),
dataIndex: "group_fk_id",
},{
title: (<FormattedMessage
id="device.device.table.list.isEnable"
defaultMessage="$$$"/>),
dataIndex: "is_enable",
},{
title: (<FormattedMessage
id="device.device.table.list.remark"
defaultMessage="$$$"/>),
dataIndex: "remark",
},{
title: (<FormattedMessage
id="device.device.table.list.createTime"
defaultMessage="$$$"/>),
dataIndex: "create_time",
},{
title: (<FormattedMessage
id="device.device.table.list.updateTime"
defaultMessage="$$$"/>),
dataIndex: "update_time",
},]

@ -0,0 +1,233 @@
import { postDeviceCreateDevice } from '@/services/device/Device';
import { postDeviceCategoryGetDeviceCategoryFkSelect } from '@/services/device/DeviceCategory';
import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormSwitch,
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, Switch, message } from 'antd';
import React, { useState } from 'react';
import { proFormItemStyleProps, proFormModelWidth } from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Device>;
export type CreateFormProps = {
createModalOpen: boolean;
handleModal: () => void;
values: Partial<API.Device>;
reload: any;
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
const intl = useIntl();
const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.Device>();
return (
<ModalForm<API.Device>
width={proFormModelWidth}
title={intl.formatMessage({
id: 'device.device.table.list.add',
defaultMessage: '$$$',
})}
open={props.createModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
postDeviceCreateDevice(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;
}}
>
<ProForm.Group>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="name"
label={<FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.name', defaultMessage: '$$$' })}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.name"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="groupFkId"
label={<FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.groupFkId',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceGroupGetDeviceGroupFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormText
width={proFormItemStyleProps.width - 80}
name="code"
label={<FormattedMessage id="device.device.table.list.code" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.code', defaultMessage: '$$$' })}`}
required={!isAuto}
initialValue=""
disabled={isAuto}
rules={
isAuto
? []
: [
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.code"
defaultMessage="code is required"
/>
),
},
]
}
addonAfter={
<Switch
checked={isAuto}
checkedChildren={<FormattedMessage id="common.auto" defaultMessage="$$$" />}
unCheckedChildren={<FormattedMessage id="common.edit" defaultMessage="$$$" />}
onChange={setIsAuto}
/>
}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="position"
label={<FormattedMessage id="device.device.table.list.position" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.position',
defaultMessage: '$$$',
})}`}
required={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="param"
label={<FormattedMessage id="device.device.table.list.param" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.param',
defaultMessage: '$$$',
})}`}
required={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="spec"
label={<FormattedMessage id="device.device.table.list.spec" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.spec', defaultMessage: '$$$' })}`}
required={false}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="categoryFkId"
label={
<FormattedMessage id="device.device.table.list.categoryFkId" defaultMessage="$$$" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.categoryFkId',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceCategoryGetDeviceCategoryFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="remark"
label={<FormattedMessage id="device.device.table.list.remark" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.remark',
defaultMessage: '$$$',
})}`}
required={false}
/>
<ProFormSwitch
width={proFormItemStyleProps.column2Width}
name="isEnable"
label={<FormattedMessage id="device.device.table.list.isEnable" defaultMessage="$$$" />}
initialValue={true}
/>
</ProForm.Group>
</ModalForm>
);
};
export default CreateForm;

@ -0,0 +1,272 @@
import { putDeviceUpdateDevice } from '@/services/device/Device';
import { postDeviceCategoryGetDeviceCategoryFkSelect } from '@/services/device/DeviceCategory';
import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup';
import {
ModalForm,
ProForm,
ProFormDateTimePicker,
ProFormSelect,
ProFormSwitch,
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import { proFormItemStyleProps, proFormModelWidth } from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Device>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.Device>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.Device>();
return (
<ModalForm<API.Device>
width={proFormModelWidth}
title={intl.formatMessage({
id: 'device.device.table.list.update',
defaultMessage: '$$$',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
putDeviceUpdateDevice(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;
}}
>
<ProForm.Group>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="id"
label="id"
disabled={true}
initialValue={props.values.id}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="name"
label={<FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.name', defaultMessage: '$$$' })}`}
required={true}
initialValue={props.values.name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.name"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="code"
label={<FormattedMessage id="device.device.table.list.code" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.code', defaultMessage: '$$$' })}`}
required={true}
initialValue={props.values.code}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.device.table.rule.required.code"
defaultMessage="code is required"
/>
),
},
]}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="position"
label={<FormattedMessage id="device.device.table.list.position" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.position',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.position}
disabled={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="param"
label={<FormattedMessage id="device.device.table.list.param" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.param',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.param}
disabled={false}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="spec"
label={<FormattedMessage id="device.device.table.list.spec" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({ id: 'device.device.table.list.spec', defaultMessage: '$$$' })}`}
required={false}
initialValue={props.values.spec}
disabled={false}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="categoryFkId"
label={
<FormattedMessage id="device.device.table.list.categoryFkId" defaultMessage="$$$" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.categoryFkId',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.categoryFkId}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceCategoryGetDeviceCategoryFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormSelect
width={proFormItemStyleProps.column2Width}
name="groupFkId"
label={<FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.groupFkId',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.groupFkId}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceGroupGetDeviceGroupFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
<ProFormText
width={proFormItemStyleProps.column2Width}
name="remark"
label={<FormattedMessage id="device.device.table.list.remark" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.remark',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.remark}
disabled={false}
/>
<ProFormSwitch
width={proFormItemStyleProps.column2Width}
name="isEnable"
label={<FormattedMessage id="device.device.table.list.isEnable" defaultMessage="$$$" />}
initialValue={props.values.isEnable}
disabled={false}
/>
<ProFormDateTimePicker
width={proFormItemStyleProps.column2Width}
name="createTime"
label={<FormattedMessage id="device.device.table.list.createTime" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.createTime',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.createTime}
disabled={true}
/>
<ProFormDateTimePicker
width={proFormItemStyleProps.column2Width}
name="updateTime"
label={<FormattedMessage id="device.device.table.list.updateTime" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device.device.table.list.updateTime',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.updateTime}
disabled={true}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -0,0 +1,53 @@
import {useIntl} from '@umijs/max';
import React, {useState, useRef, useCallback, useEffect} from 'react';
import {Form, Modal} from 'antd';
import WebRTCStreamer from "@/components/WebRtcPlayer";
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Device>;
export type VideoModalProps = {
modalOpen: boolean;
handleModal: () => void;
values: Partial<API.Device>;
reload: any;
videoServerParam: API.RtspRes;
};
const VideoModal: React.FC<VideoModalProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.ActionDetection>();
const [videoInit, setVideoInit] = useState(false);
useEffect(()=>{
setVideoInit(false)
if (props.modalOpen) {
setVideoInit(true)
} else {
console.log('***********')
setVideoInit(false)
}
}, [props.modalOpen])
return (
<Modal title="播放视频" open={props.modalOpen}
width={1280}
onOk={props.handleModal} onCancel={props.handleModal}
footer={null}>
{videoInit && (<WebRTCStreamer is_open={props.modalOpen} stream_url={props.values.param} server_url={props.videoServerParam.host || ''}></WebRTCStreamer>)}
</Modal>
)
}
export default VideoModal;

@ -0,0 +1,706 @@
import IsBatchDelete from '@/components/BatchOperation/isBatchDelete';
import TableActionCard from '@/components/TableActionCard';
import IsDelete from '@/components/TableActionCard/isDelete';
import TreeAndTableList, { ProCardTypeProps } from '@/layouts/treeAndTableList';
import { ColumnDrawer as DeviceCategoryColumnDrawer } from '@/pages/Device/DeviceCategoryList/components/ColumnDrawer';
import { DeviceCategoryColumns } from '@/pages/Device/DeviceCategoryList/components/Columns';
import { ColumnDrawer as DeviceGroupColumnDrawer } from '@/pages/Device/DeviceGroupList/components/ColumnDrawer';
import { DeviceGroupColumns } from '@/pages/Device/DeviceGroupList/components/Columns';
import {
deleteDeviceDeleteDevice,
deleteDeviceDeleteDeviceByIds,
postDeviceCloseRtspCamera,
postDeviceGetDeviceList,
postDeviceOpenRtspCamera,
} from '@/services/device/Device';
import {
postDeviceCategoryGetDeviceCategoryById,
postDeviceCategoryGetDeviceCategoryFkSelect,
postDeviceCategoryGetDeviceCategoryNames,
} from '@/services/device/DeviceCategory';
import {
postDeviceGroupGetDeviceGroupById,
postDeviceGroupGetDeviceGroupFkSelect,
postDeviceGroupGetDeviceGroupNames,
postDeviceGroupGetDeviceGroupTree,
} from '@/services/device/DeviceGroup';
import { PlusOutlined, RedoOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProFormSelect, ProTable } from '@ant-design/pro-components';
import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max';
import { Button, Tree, message } from 'antd';
import { DataNode } from 'antd/es/tree';
import React, { useEffect, useRef, useState } from 'react';
import { proTableCommonOptions, proTablePaginationOptions } from '../../../../config/defaultTable';
import { ColumnDrawer } from './components/ColumnDrawer';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
import VideoModal from './components/VideoModal';
const DeviceList: React.FC = () => {
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
const [videoModalOpen, setVideoModalOpen] = useState<boolean>(false);
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [showDetail, setShowDetail] = useState<boolean>(false);
/**
* @en-US International configuration
* @zh-CN
* */
const access = useAccess();
const intl = useIntl();
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentRow, setCurrentRow] = useState<API.Device>();
const [selectedRowsState, setSelectedRows] = useState<API.Device[]>([]);
const [category_fk_id_open, set_category_fk_id_open] = useState(false);
const [category_fk_id, set_category_fk_id] = useState<API.DeviceCategory>();
const [category_fk_id_column_open, set_category_fk_id_column_open] = useState(false);
const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
const [categoryFkIdMap, setCategoryFkIdMap] = useState<{ [key: number]: string }>({});
const [group_fk_id_open, set_group_fk_id_open] = useState(false);
const [group_fk_id, set_group_fk_id] = useState<API.DeviceGroup>();
const [group_fk_id_column_open, set_group_fk_id_column_open] = useState(false);
const [groupFkIdIds, setGroupFkIdIds] = useState([]);
const [groupFkIdMap, setGroupFkIdMap] = useState<{ [key: number]: string }>({});
const [hasInit, setHasInit] = useState<boolean>(false);
const [nodeTreeData, setNodeTreeData] = React.useState<DataNode[]>([]);
const [selectNodes, setSelectNodes] = React.useState<any[]>([]);
const [videoOpening, setVideoOpening] = useState<boolean>(false);
const [videoServerParam, setVideoServerParam] = useState<API.RtspRes>({});
useEffect(() => {
postDeviceGroupGetDeviceGroupTree()
.then((resp) => {
setNodeTreeData(resp.data.tree);
setHasInit(true);
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
});
}, []);
const handleVideoModal = () => {
if (videoModalOpen) {
setVideoModalOpen(false);
if (videoServerParam?.pid || 0) {
postDeviceCloseRtspCamera({ pid: videoServerParam.pid }).then((resp) => {
console.log(resp);
});
}
setCurrentRow(undefined);
setVideoServerParam({});
} else {
setVideoModalOpen(true);
}
};
const handle_category_fk_id = (id: any) => {
if (category_fk_id_open) {
set_category_fk_id(undefined);
set_category_fk_id_open(false);
} else {
postDeviceCategoryGetDeviceCategoryById({ id: id }).then((resp) => {
set_category_fk_id(resp.data.deviceCategory);
set_category_fk_id_open(true);
});
}
};
const handle_category_fk_id_column_open = () => {
if (category_fk_id_column_open) {
set_category_fk_id_column_open(false);
} else {
postDeviceCategoryGetDeviceCategoryNames({ ids: categoryFkIdIds }).then((resp) => {
let a: any = {};
resp.data.list.forEach((v: any) => {
if (v.id) {
a[v.id] = v.name;
}
});
setCategoryFkIdMap(a);
});
set_category_fk_id_column_open(true);
}
};
const handle_group_fk_id = (id: any) => {
if (group_fk_id_open) {
set_group_fk_id(undefined);
set_group_fk_id_open(false);
} else {
postDeviceGroupGetDeviceGroupById({ id: id }).then((resp) => {
set_group_fk_id(resp.data.deviceGroup);
set_group_fk_id_open(true);
});
}
};
const handle_group_fk_id_column_open = () => {
if (group_fk_id_column_open) {
set_group_fk_id_column_open(false);
} else {
postDeviceGroupGetDeviceGroupNames({ ids: groupFkIdIds }).then((resp) => {
let a: any = {};
resp.data.list.forEach((v: any) => {
if (v.id) {
a[v.id] = v.name;
}
});
setGroupFkIdMap(a);
});
set_group_fk_id_column_open(true);
}
};
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
const handleCreateModal = () => {
if (createModalOpen) {
setCreateModalOpen(false);
setCurrentRow(undefined);
} else {
setCreateModalOpen(true);
}
};
const handleColumnDrawer = () => {
if (showDetail) {
setShowDetail(false);
setCurrentRow(undefined);
} else {
setShowDetail(true);
}
};
const handleDestroy = async (selectedRow: API.Device) => {
deleteDeviceDeleteDevice({ id: selectedRow.id })
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
actionRef.current?.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
});
};
const columns: ProColumns<API.Device>[] = [
{
title: <FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />,
dataIndex: 'name',
width: '150',
sorter: true,
render: (dom, entity) => {
return (
<a
onClick={() => {
setCurrentRow(entity);
setShowDetail(true);
}}
>
{dom}
</a>
);
},
// renderFormItem: () => {
// return (
// <>
// <ProFormText
// width="md"
// labelCol={{ span: 4 }}
// wrapperCol={{ span: 22 }}
// name="name"
// placeholder={`${intl.formatMessage({
// id: 'common.please_input',
// defaultMessage: '$$$',
// })}`}
// required={false}
// />
// </>
// );
// },
key: 'fixedName',
fixed: 'left',
},
// {
// title: <FormattedMessage id="device.device.table.list.name" defaultMessage="$$$" />,
// dataIndex: 'name',
// hideInSearch: true,
// },
{
title: <FormattedMessage id="device.device.table.list.code" defaultMessage="$$$" />,
dataIndex: 'code',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.position" defaultMessage="$$$" />,
dataIndex: 'position',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.param" defaultMessage="$$$" />,
dataIndex: 'param',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.spec" defaultMessage="$$$" />,
dataIndex: 'spec',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.categoryFkId" defaultMessage="$$$" />,
dataIndex: 'categoryFkId',
hideInSearch: false,
render: (text, record) => {
if (category_fk_id_column_open) {
return (
<a
onClick={() => {
handle_category_fk_id(record.categoryFkId);
}}
>
{record?.categoryFkId ? categoryFkIdMap[record.categoryFkId] : undefined}
</a>
);
} else {
return (
<a
onClick={() => {
handle_category_fk_id(record.categoryFkId);
}}
>
{record.categoryFkId}
</a>
);
}
},
renderFormItem: () => {
return (
// value 和 onchange 会通过 form 自动注入。
<ProFormSelect
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceCategoryGetDeviceCategoryFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
);
},
},
{
title: <FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />,
dataIndex: 'groupFkId',
hideInSearch: false,
render: (text, record) => {
if (group_fk_id_column_open) {
return (
<a
onClick={() => {
handle_group_fk_id(record.groupFkId);
}}
>
{record?.groupFkId ? groupFkIdMap[record.groupFkId] : undefined}
</a>
);
} else {
return (
<a
onClick={() => {
handle_group_fk_id(record.groupFkId);
}}
>
{record.groupFkId}
</a>
);
}
},
renderFormItem: () => {
return (
// value 和 onchange 会通过 form 自动注入。
<ProFormSelect
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}`}
required={false}
showSearch
debounceTime={1000}
request={async (keyWord) => {
const resp = await postDeviceGroupGetDeviceGroupFkSelect({
keyword: keyWord?.keyWords || '',
});
return resp.data.list.map((v: any) => {
return {
label: v.name,
value: v.id,
};
});
}}
/>
);
},
},
{
title: <FormattedMessage id="device.device.table.list.isEnable" defaultMessage="$$$" />,
dataIndex: 'isEnable',
filters: true,
onFilter: true,
hideInSearch: true,
valueType: 'switch',
},
{
title: <FormattedMessage id="device.device.table.list.remark" defaultMessage="$$$" />,
dataIndex: 'remark',
hideInSearch: true,
},
{
title: <FormattedMessage id="device.device.table.list.createTime" defaultMessage="$$$" />,
dataIndex: 'createTime',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="device.device.table.list.updateTime" defaultMessage="$$$" />,
dataIndex: 'updateTime',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
{
key: 'update',
renderDom: (
<Button
key="update"
type="link"
size="small"
onClick={() => {
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="pages.searchTable.update" defaultMessage="Update" />
</Button>
),
},
{
key: 'destroy',
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
}}
></IsDelete>
),
},
{
key: 'video',
renderDom: (
<Button
key="video"
type="link"
size="small"
onClick={() => {
setVideoOpening(true);
if (record.param) {
postDeviceOpenRtspCamera({ url: record.param })
.then((resp) => {
setVideoServerParam(resp.data);
setVideoOpening(false);
setVideoModalOpen(true);
console.log(resp.data);
setCurrentRow(record);
})
.catch(() => {
setVideoOpening(false);
message.error(
intl.formatMessage({
id: 'common.open_failure',
defaultMessage: '$$$',
}),
);
});
} else {
setVideoOpening(false);
message.error(
intl.formatMessage({ id: 'common.open_failure', defaultMessage: '$$$' }),
);
}
}}
>
<FormattedMessage id="common.open_video" defaultMessage="$$$" />
</Button>
),
},
]}
></TableActionCard>,
],
},
];
return (
<PageContainer>
<TreeAndTableList
leftCard={
{
title: '网点选择',
extra: (
<>
<Button
icon={<RedoOutlined />}
onClick={() => {
setSelectNodes([]);
actionRef.current?.reload();
}}
>
</Button>
</>
),
} as ProCardTypeProps
}
leftDom={
hasInit && (
<Tree
checkable={false}
defaultExpandAll={true}
selectedKeys={selectNodes}
treeData={nodeTreeData}
onSelect={(selectKeys) => {
setSelectNodes(selectKeys);
actionRef.current?.reload();
}}
checkStrictly={false}
/>
)
}
rightDom={
<ProTable<API.Device>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: '$$$',
})}
loading={{
tip: intl.formatMessage({
id: 'common.video_opening',
defaultMessage: '$$$',
}),
spinning: videoOpening,
}}
options={{ fullScreen: true, setting: true, density: true, reload: true }}
actionRef={actionRef}
rowKey="key"
scroll={{ x: 2000, y: proTableCommonOptions.commscrollY }}
search={{
labelWidth: proTableCommonOptions.searchLabelWidth,
}}
onDataSourceChange={(data) => {
let CategoryFkIdIds: any = data.map((v) => {
return v.categoryFkId;
});
setCategoryFkIdIds(CategoryFkIdIds);
let GroupFkIdIds: any = data.map((v) => {
return v.groupFkId;
});
setGroupFkIdIds(GroupFkIdIds);
}}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'device_list',
persistenceType: 'localStorage',
}}
tableAlertOptionRender={() => {
return (
<>
{selectedRowsState?.length > 0 && (
<IsBatchDelete
deleteApi={() => {
// TODO 需联调批量删除接口
deleteDeviceDeleteDeviceByIds({
ids: selectedRowsState.map((v: API.Device) => {
return v.id as number;
}),
}).then(() => {
actionRef.current?.reloadAndRest?.();
});
}}
/>
)}
</>
);
}}
toolBarRender={() => [
<Access
accessible={access.canUpdate(history.location.pathname)}
key={`${history.location.pathname}-add`}
>
<Button
type="primary"
key="category_fk_id_show"
onClick={() => {
handle_category_fk_id_column_open();
}}
>
{category_fk_id_column_open ? (
<FormattedMessage id="common.hide" defaultMessage="$$$" />
) : (
<FormattedMessage id="common.show" defaultMessage="$$$" />
)}
<FormattedMessage
id="device.device.table.list.categoryFkId"
defaultMessage="$$$"
/>
</Button>
<Button
type="primary"
key="group_fk_id_show"
onClick={() => {
handle_group_fk_id_column_open();
}}
>
{group_fk_id_column_open ? (
<FormattedMessage id="common.hide" defaultMessage="$$$" />
) : (
<FormattedMessage id="common.show" defaultMessage="$$$" />
)}
<FormattedMessage id="device.device.table.list.groupFkId" defaultMessage="$$$" />
</Button>
<Button
type="primary"
key="primary"
onClick={() => {
setCreateModalOpen(true);
}}
>
<PlusOutlined />{' '}
<FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
</Button>
</Access>,
]}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams: any = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (selectNodes.length) {
reqParams.groupFkId = selectNodes[0];
}
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
let resp = await postDeviceGetDeviceList({ ...reqParams });
return {
data: resp.data.list.map((v: API.Device) => {
return { ...v, key: v.id };
}),
success: resp.success,
total: resp.data.total,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => {
setSelectedRows(selectedRows);
},
}}
/>
}
></TreeAndTableList>
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<ColumnDrawer
handleDrawer={handleColumnDrawer}
isShowDetail={showDetail}
columns={columns}
currentRow={currentRow}
/>
<DeviceCategoryColumnDrawer
handleDrawer={handle_category_fk_id}
isShowDetail={category_fk_id_open}
columns={DeviceCategoryColumns}
currentRow={category_fk_id}
/>
<DeviceGroupColumnDrawer
handleDrawer={handle_group_fk_id}
isShowDetail={group_fk_id_open}
columns={DeviceGroupColumns}
currentRow={group_fk_id}
/>
<VideoModal
modalOpen={videoModalOpen}
handleModal={handleVideoModal}
values={currentRow || {}}
videoServerParam={videoServerParam}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default DeviceList;
Loading…
Cancel
Save