| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- import React, { useState } from 'react';
- import {
- Button, Table, Space,
- Form, Input, Select, message, Modal,
- Card, Row, Col, Typography, Badge
- } from 'antd';
- import {
- useQuery,
- useMutation,
- useQueryClient
- } from '@tanstack/react-query';
- import axios from 'axios';
- import dayjs from 'dayjs';
- import 'dayjs/locale/zh-cn';
- import type {
- ZichanInfo, DeviceInstance, DeviceType,
- } from '../share/monitorTypes.ts';
- import {
- DeviceProtocolType,
- } from '../share/monitorTypes.ts';
- import {
- EnableStatus, DeleteStatus,
- } from '../share/types.ts';
- import { DeviceInstanceAPI , DeviceTypeAPI, ZichanAPI} from './api/index.ts';
- const { Title } = Typography;
- // 设备管理页面
- export const DeviceInstancesPage = () => {
- const [form] = Form.useForm();
- const [formMode, setFormMode] = useState<'create' | 'edit'>('create');
- const [modalVisible, setModalVisible] = useState(false);
- const [selectedId, setSelectedId] = useState<number | null>(null);
- const [pagination, setPagination] = useState({
- current: 1,
- pageSize: 10,
- total: 0
- });
-
- // 获取设备列表
- const {
- data,
- isLoading,
- refetch
- } = useQuery({
- queryKey: ['deviceInstances', pagination.current, pagination.pageSize],
- queryFn: async () => {
- try {
- const response = await DeviceInstanceAPI.getDeviceInstances({
- page: pagination.current,
- limit: pagination.pageSize
- });
-
- setPagination(prev => ({
- ...prev,
- total: response.pagination.total
- }));
-
- return response.data;
- } catch (error) {
- message.error('获取设备列表失败');
- return [];
- }
- }
- });
-
- // 获取设备类型
- const { data: deviceTypes = [] } = useQuery({
- queryKey: ['deviceTypesAll'],
- queryFn: async () => {
- try {
- const response = await DeviceTypeAPI.getDeviceTypes({ pageSize: 100 })
- return response.data;
- } catch (error) {
- message.error('获取设备类型失败');
- return [];
- }
- }
- });
-
- // 获取可用资产
- const { data: zichanList = [] } = useQuery({
- queryKey: ['zichanListAll'],
- queryFn: async () => {
- try {
- const response = await ZichanAPI.getZichanList({ limit: 500 })
-
- // 筛选出未分配给设备的资产
- const deviceInstances = data || [];
- const usedAssetIds = deviceInstances.map((d: DeviceInstance) => d.id);
-
- return response.data.filter(
- (z: ZichanInfo) => !usedAssetIds.includes(z.id)
- );
- } catch (error) {
- message.error('获取可用资产失败');
- return [];
- }
- }
- });
-
- const queryClient = useQueryClient();
-
- // 提交表单
- const { mutate: submitForm, isPending: isSubmitting } = useMutation({
- mutationFn: async (values: Partial<DeviceInstance>) => {
- const deviceData = {
- ...values,
- };
-
- if (formMode === 'create') {
- return DeviceInstanceAPI.createDeviceInstance(deviceData);
- } else {
- return DeviceInstanceAPI.updateDeviceInstance(selectedId!, deviceData);
- }
- },
- onSuccess: () => {
- message.success(formMode === 'create' ? '创建成功' : '更新成功');
- setModalVisible(false);
- refetch();
- form.resetFields();
- },
- onError: () => {
- message.error(formMode === 'create' ? '创建失败' : '更新失败');
- }
- });
-
- // 删除设备
- const { mutate: deleteDevice, isPending: isDeleting } = useMutation({
- mutationFn: async (id: number) => {
- return DeviceInstanceAPI.deleteDeviceInstance(id);
- },
- onSuccess: () => {
- message.success('删除成功');
- refetch();
- },
- onError: () => {
- message.error('删除失败');
- }
- });
-
- // 处理表单提交
- const handleSubmit = (values: Partial<DeviceInstance>) => {
- submitForm({
- ...values,
- is_enabled: values.is_enabled ?? EnableStatus.ENABLED,
- is_deleted: DeleteStatus.NOT_DELETED
- });
- };
-
- // 处理编辑
- const handleEdit = (record: DeviceInstance) => {
- setSelectedId(record.id);
- setFormMode('edit');
- form.setFieldsValue({
- ...record
- });
- setModalVisible(true);
- };
-
- // 处理删除
- const handleDelete = (id: number) => {
- Modal.confirm({
- title: '确认删除',
- content: '确定要删除这个设备吗?',
- okText: '确认',
- cancelText: '取消',
- onOk: () => deleteDevice(id)
- });
- };
-
- // 处理添加
- const handleAdd = () => {
- setFormMode('create');
- setSelectedId(null);
- form.resetFields();
- setModalVisible(true);
- };
-
- // 处理页码变化
- const handlePageChange = (page: number, pageSize?: number) => {
- setPagination({
- ...pagination,
- current: page,
- pageSize: pageSize || pagination.pageSize
- });
- };
-
- const columns = [
- {
- title: 'ID',
- dataIndex: 'id',
- key: 'id',
- width: 80
- },
- {
- title: '设备类型',
- dataIndex: 'type_id',
- key: 'type_id',
- render: (typeId: number) => {
- const deviceType = deviceTypes.find((t: DeviceType) => t.id === typeId);
- return deviceType ? deviceType.name : `未知类型(${typeId})`;
- }
- },
- {
- title: '通信协议',
- dataIndex: 'protocol',
- key: 'protocol'
- },
- {
- title: '通信地址',
- dataIndex: 'address',
- key: 'address'
- },
- {
- title: '采集间隔(秒)',
- dataIndex: 'collect_interval',
- key: 'collect_interval'
- },
- {
- title: '最后采集时间',
- dataIndex: 'last_collect_time',
- key: 'last_collect_time',
- render: (date: string) => date ? dayjs(date).format('YYYY-MM-DD HH:mm:ss') : '-'
- },
- {
- title: '状态地址',
- dataIndex: 'status_address',
- key: 'status_address'
- },
- {
- title: '连接配置',
- dataIndex: 'connection_config',
- key: 'connection_config'
- },
- {
- title: '状态',
- dataIndex: 'is_enabled',
- key: 'is_enabled',
- render: (status: number) => (
- <Badge
- status={status === EnableStatus.ENABLED ? 'success' : 'error'}
- text={status === EnableStatus.ENABLED ? '启用' : '禁用'}
- />
- )
- },
- {
- title: '操作',
- key: 'action',
- render: (_: any, record: DeviceInstance) => (
- <Space size="middle">
- <Button type="link" onClick={() => handleEdit(record)}>编辑</Button>
- <Button type="link" danger onClick={() => handleDelete(record.id)}>删除</Button>
- </Space>
- )
- }
- ];
-
- return (
- <div>
- <Title level={2}>设备管理</Title>
- <Card>
- <Row justify="end" style={{ marginBottom: 16 }}>
- <Button type="primary" onClick={handleAdd}>
- 添加设备
- </Button>
- </Row>
-
- <Table
- columns={columns}
- dataSource={data || []}
- loading={isLoading}
- rowKey="id"
- pagination={{
- current: pagination.current,
- pageSize: pagination.pageSize,
- total: pagination.total,
- onChange: handlePageChange,
- showSizeChanger: true
- }}
- />
-
- <Modal
- title={formMode === 'create' ? '添加设备' : '编辑设备'}
- open={modalVisible}
- onCancel={() => setModalVisible(false)}
- footer={null}
- width={700}
- >
- <Form
- form={form}
- layout="vertical"
- onFinish={handleSubmit}
- >
- <Row gutter={16}>
- {formMode === 'create' && (
- <Col span={24}>
- <Form.Item
- name="id"
- label="关联资产"
- rules={[{ required: true, message: '请选择关联资产' }]}
- >
- <Select placeholder="请选择关联资产">
- {zichanList.map((zichan: ZichanInfo) => (
- <Select.Option key={zichan.id} value={zichan.id}>
- {zichan.asset_name || `资产ID: ${zichan.id}`}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
- </Col>
- )}
-
- <Col span={12}>
- <Form.Item
- name="type_id"
- label="设备类型"
- rules={[{ required: true, message: '请选择设备类型' }]}
- >
- <Select placeholder="请选择设备类型">
- {deviceTypes.map((type: DeviceType) => (
- <Select.Option key={type.id} value={type.id}>
- {type.name}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
- </Col>
-
- <Col span={12}>
- <Form.Item
- name="protocol"
- label="通信协议"
- rules={[{ required: true, message: '请选择通信协议' }]}
- >
- <Select placeholder="请选择通信协议">
- {Object.entries(DeviceProtocolType).map(([key, value]) => (
- <Select.Option key={key} value={value}>
- {value} - {key === value ? '' : key}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
- </Col>
- </Row>
-
- <Row gutter={16}>
- <Col span={12}>
- <Form.Item
- name="address"
- label="通信地址"
- rules={[{ required: true, message: '请输入通信地址' }]}
- >
- <Input placeholder="请输入通信地址" />
- </Form.Item>
- </Col>
-
- <Col span={12}>
- <Form.Item
- name="collect_interval"
- label="采集间隔(秒)"
- >
- <Input type="number" placeholder="请输入采集间隔" />
- </Form.Item>
- </Col>
- </Row>
- <Row gutter={16}>
- <Col span={12}>
- <Form.Item
- name="status_address"
- label="状态地址"
- >
- <Input placeholder="请输入状态地址" />
- </Form.Item>
- </Col>
-
- <Col span={12}>
- <Form.Item
- name="connection_config"
- label="连接配置"
- >
- <Input.TextArea rows={1} placeholder="请输入连接配置" />
- </Form.Item>
- </Col>
- </Row>
-
- <Form.Item
- name="remark"
- label="备注"
- >
- <Input.TextArea rows={4} placeholder="请输入备注信息" />
- </Form.Item>
-
- <Form.Item
- name="is_enabled"
- label="状态"
- initialValue={EnableStatus.ENABLED}
- >
- <Select>
- <Select.Option value={EnableStatus.ENABLED}>启用</Select.Option>
- <Select.Option value={EnableStatus.DISABLED}>禁用</Select.Option>
- </Select>
- </Form.Item>
-
- <Form.Item>
- <Space>
- <Button type="primary" htmlType="submit" loading={isSubmitting}>
- {formMode === 'create' ? '创建' : '保存'}
- </Button>
- <Button onClick={() => setModalVisible(false)}>取消</Button>
- </Space>
- </Form.Item>
- </Form>
- </Modal>
- </Card>
- </div>
- );
- };
|