diff --git a/src/components/DictionaryBox/alarmLevel.tsx b/src/components/DictionaryBox/alarmLevel.tsx new file mode 100644 index 0000000..e543c45 --- /dev/null +++ b/src/components/DictionaryBox/alarmLevel.tsx @@ -0,0 +1,39 @@ +/* + * @Author: zhoux zhouxia@supervision.ltd + * @Date: 2023-11-15 15:01:34 + * @LastEditors: zhoux zhouxia@supervision.ltd + * @LastEditTime: 2023-12-20 11:25:15 + * @FilePath: \general-ai-platform-web\src\components\DictionaryBox\isEnable.tsx + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import { ArrowUpOutlined, DownOutlined } from '@ant-design/icons'; + +type AlarmLevelBoxProps = { + icon?: 'ArrowUpOutlined' | 'default' | undefined; + color?: string; + size?: number; +}; + +const AlarmLevelBox: React.FC = (props) => { + const { icon, color, size } = props; + const finalSize = size || 14; + return ( +
+ {icon === 'ArrowUpOutlined' ? : } +
+ ); +}; + +export default AlarmLevelBox; diff --git a/src/components/TableActionCard/isDelete.tsx b/src/components/TableActionCard/isDelete.tsx index 649cb9c..b6bde41 100644 --- a/src/components/TableActionCard/isDelete.tsx +++ b/src/components/TableActionCard/isDelete.tsx @@ -2,18 +2,20 @@ * @Author: zhoux zhouxia@supervision.ltd * @Date: 2023-11-16 14:30:15 * @LastEditors: zhoux zhouxia@supervision.ltd - * @LastEditTime: 2023-11-16 14:56:27 + * @LastEditTime: 2023-12-19 16:30:51 * @FilePath: \general-ai-platform-web\src\components\BatchOperation\isBatchDelete.tsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ // import { useIntl } from '@ant-design/pro-components'; +import { DeleteOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Popconfirm } from 'antd'; import { FormattedMessage } from 'react-intl'; type IsDeleteProps = { // eslint-disable-next-line @typescript-eslint/ban-types - deleteApi: Function; + buttonType?: 'defalut' | 'deleteIcon'; + deleteApi: () => void; }; const IsDelete: React.FC = (props) => { @@ -34,9 +36,17 @@ const IsDelete: React.FC = (props) => { props.deleteApi(); }} > - + {props.buttonType === 'deleteIcon' ? ( + <> + + + ) : ( + + )} ); }; diff --git a/src/enums/status.ts b/src/enums/status.ts index af51370..d803349 100644 --- a/src/enums/status.ts +++ b/src/enums/status.ts @@ -1,3 +1,15 @@ +/* + * @Author: zhoux zhouxia@supervision.ltd + * @Date: 2023-12-08 14:50:08 + * @LastEditors: zhoux zhouxia@supervision.ltd + * @LastEditTime: 2023-12-20 13:25:59 + * @FilePath: \general-ai-platform-web\src\enums\status.ts + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ + +import { DownOutlined } from "@ant-design/icons"; + +// 分布式设备状态 export const deviceStatusEnums: Record = { allStatus: { miniName: '全部', @@ -25,7 +37,7 @@ export const deviceStatusEnums: Record = { color: 'error', }, }; - +// 资源设备~ export const resourceDeviceStatusEnums: Record = { allStatus: { miniName: '全部异常', @@ -70,3 +82,49 @@ export const resourceDeviceStatusEnums: Record = { renderType: 'dot', }, }; +// 告警等级~ +export const alarmLevelStatusEnum: Record[] = [ + { + color: 'rgba(232, 13, 13, 1)', + defaultValue: '1', + defaultLabel: '紧急', + isDelete: false, + icon: 'ArrowUpOutlined', + id: '1', + }, + { + color: 'rgba(255, 136, 0, 1)', + defaultValue: '2', + defaultLabel: '较高', + isDelete: false, + id: '2', + }, + { + color: 'rgba(68, 139, 245, 1)', + defaultValue: '3', + defaultLabel: '一般', + isDelete: false, + id: '3', + }, + { + color: 'rgba(179, 214, 0, 1)', + defaultValue: '4', + defaultLabel: '低', + isDelete: true, + id: '4', + }, + { + color: 'rgba(81, 177, 6, 1)', + defaultValue: '5', + defaultLabel: '较低', + isDelete: true, + id: '5', + }, + { + color: 'rgba(43, 183, 136, 1)', + defaultValue: '6', + defaultLabel: '非常低', + isDelete: true, + id: '6', + }, +]; diff --git a/src/enums/storage.ts b/src/enums/storage.ts new file mode 100644 index 0000000..f2ff216 --- /dev/null +++ b/src/enums/storage.ts @@ -0,0 +1,3 @@ +export const localStorageKeyEnums = { + alarmSetting_model_alarmStatusSetting: 'alarmSetting_model_alarmStatusSetting_key', +}; diff --git a/src/global.css b/src/global.css index b0bcb37..a2ddb35 100644 --- a/src/global.css +++ b/src/global.css @@ -268,11 +268,14 @@ a.ant-dropdown-trigger { padding-left: 12px; } .gn .ant-tabs > .ant-tabs-nav .ant-tabs-nav-wrap .ant-tabs-nav-list { - padding: 0 24px; + padding: 0 16px; margin-block-start: 0; } .gn .ant-tabs > .ant-tabs-nav .ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab-active { - font-weight: 700; + font-weight: 400; +} +.gn .ant-tabs .ant-tabs-tab .anticon { + margin-right: 4px; } .gn .ant-pro-table-list-toolbar-container { padding-block: 8px; @@ -347,6 +350,27 @@ a.ant-dropdown-trigger { .gn.themeBgHover:hover { background-color: #155BD4; } +.gn.algorithmSetting_project_box.ant-tabs-top > .ant-tabs-nav::before { + position: absolute; + right: 0; + left: 0; + border-bottom: 1px solid transparent; + content: ''; +} +.gn.algorithmSetting_project_box.ant-tabs .ant-tabs-ink-bar { + background: transparent; +} +.gn.algorithmSetting_project_box.ant-tabs .ant-tabs-tab { + padding: 16px 0 0px; +} +.gn.algorithmSetting_project_box.ant-tabs .ant-tabs-tab + .ant-tabs-tab { + margin: 0 0 0 12px; +} +.gn.algorithmSetting_project_box .ant-tabs-tab-active .ant-btn-default { + border: 1px solid #154DDD; + background: rgba(21, 77, 221, 0.1); + color: #154DDD; +} .ant-pro-global-header-logo img { height: 48px; } diff --git a/src/global.less b/src/global.less index f4313b2..00715f9 100644 --- a/src/global.less +++ b/src/global.less @@ -313,11 +313,11 @@ a.ant-dropdown-trigger{ margin-inline: 0; padding-block: 0; padding-inline: 6px; -} + } -.ant-list .ant-list-pagination { - margin-block-start: 10px; -} + .ant-list .ant-list-pagination { + margin-block-start: 10px; + } .ant-table-wrapper table tr th.ant-table-selection-column, .ant-table-wrapper table tr td.ant-table-selection-column, @@ -330,14 +330,18 @@ a.ant-dropdown-trigger{ .ant-tabs >.ant-tabs-nav .ant-tabs-nav-wrap{ .ant-tabs-nav-list{ - padding: 0 24px; + padding: 0 16px; margin-block-start: 0; .ant-tabs-tab-active{ - font-weight: 700 + font-weight: 400 } } } + .ant-tabs .ant-tabs-tab .anticon { + margin-right: 4px; + } + .ant-pro-table-list-toolbar-container { padding-block: 8px; } @@ -431,6 +435,35 @@ a.ant-dropdown-trigger{ &.themeBgHover:hover{ background-color: #155BD4; } + + + // 项目部署模块 + &.algorithmSetting_project_box{ + &.ant-tabs-top >.ant-tabs-nav::before { + position: absolute; + right: 0; + left: 0; + border-bottom: 1px solid transparent; + content: ''; + } + &.ant-tabs .ant-tabs-ink-bar{ + background: transparent; + } + &.ant-tabs .ant-tabs-tab{ + padding: 16px 0 0px; + } + &.ant-tabs .ant-tabs-tab+.ant-tabs-tab{ + // margin: 0; + margin:0 0 0 12px; + } + & .ant-tabs-tab-active{ + .ant-btn-default{ + border: 1px solid #154DDD; + background: rgba(21, 77, 221, 0.10); + color: #154DDD; + } + } + } } .ant-pro-global-header-logo img { height: 48px; @@ -444,6 +477,8 @@ a.ant-dropdown-trigger{ border-radius: 2px; } } + + // .p1{ // } diff --git a/src/layouts/treeAndTableList.tsx b/src/layouts/treeAndTableList.tsx index 0e7fd7a..b79f167 100644 --- a/src/layouts/treeAndTableList.tsx +++ b/src/layouts/treeAndTableList.tsx @@ -2,7 +2,7 @@ * @Author: zhoux zhouxia@supervision.ltd * @Date: 2023-11-21 13:42:31 * @LastEditors: zhoux zhouxia@supervision.ltd - * @LastEditTime: 2023-11-24 16:01:20 + * @LastEditTime: 2023-12-19 15:27:06 * @FilePath: \general-ai-platform-web\src\layouts\treeAndTableList.tsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -29,7 +29,7 @@ const TreeAndTableList: React.FC = (props) => { // 统一配置 let finalLeftCard: ProCardTypeProps = { // 左侧卡片 - headStyle: { paddingTop: 20, paddingLeft: 20, paddingRight: 20, paddingBottom: 20,borderBottom: '1px solid #E0E0E0' }, + headStyle: { paddingTop: 16, paddingLeft: 20, paddingRight: 20, paddingBottom: 16,borderBottom: '1px solid #E0E0E0' }, bodyStyle: {paddingLeft: 20, paddingRight: 20}, colSpan: '22%', }; diff --git a/src/locales/zh-CN/alarm.ts b/src/locales/zh-CN/alarm.ts index c604e0f..c77003f 100644 --- a/src/locales/zh-CN/alarm.ts +++ b/src/locales/zh-CN/alarm.ts @@ -2,7 +2,7 @@ * @Author: zhoux zhouxia@supervision.ltd * @Date: 2023-12-18 16:36:36 * @LastEditors: zhoux zhouxia@supervision.ltd - * @LastEditTime: 2023-12-18 17:46:05 + * @LastEditTime: 2023-12-19 13:48:54 * @FilePath: \general-ai-platform-web\src\locales\zh-CN\alarm.ts * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -25,5 +25,5 @@ export const alarm_setting: { [key: string]: string } = { 'alarm.setting.table.model.title': '告警等级', 'alarm.setting.table.list.update': '编辑告警项', 'alarm.setting.table.rule.required.code': '类别代码为必填项', - + 'alarm.setting.table.model.alarmStatusSetting': '告警等级' } \ No newline at end of file diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts index 3042e8d..086c8a2 100644 --- a/src/locales/zh-CN/menu.ts +++ b/src/locales/zh-CN/menu.ts @@ -7,6 +7,8 @@ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ export default { + 'menu.fabricView': '监控预览', + 'menu.fabricView.fabricView-room': '监控预览', 'menu.welcome': '欢迎', 'menu.more-blocks': '更多区块', 'menu.home': '首页', diff --git a/src/pages/Alarm/AlarmSetting/components/ColumnDrawer.tsx b/src/pages/Alarm/AlarmSetting/components/ColumnDrawer.tsx deleted file mode 100644 index 208d446..0000000 --- a/src/pages/Alarm/AlarmSetting/components/ColumnDrawer.tsx +++ /dev/null @@ -1,41 +0,0 @@ -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[]; - currentRow: API.DeviceCategory | undefined; -}; - - -const ColumnDrawer: React.FC = (props) => { - - return ( - { - props.handleDrawer(); - }} - closable={true} - > - {props.currentRow?.id && ( - - column={2} - title={props.currentRow?.id} - request={async () => ({ - data: props.currentRow || {}, - })} - params={{ - id: props.currentRow?.id, - }} - columns={props.columns as ProDescriptionsItemProps[]} - /> - )} - - ) -} -export {ColumnDrawer} - diff --git a/src/pages/Alarm/AlarmSetting/components/CreateForm.tsx b/src/pages/Alarm/AlarmSetting/components/CreateForm.tsx index c04ccd6..4fbffd3 100644 --- a/src/pages/Alarm/AlarmSetting/components/CreateForm.tsx +++ b/src/pages/Alarm/AlarmSetting/components/CreateForm.tsx @@ -1,13 +1,13 @@ import { postDeviceCategoryCreateDeviceCategory } from '@/services/device/DeviceCategory'; +import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup'; import { ModalForm, ProForm, ProFormSelect, ProFormText } from '@ant-design/pro-components'; import { FormattedMessage, useIntl } from '@umijs/max'; import { Form, message } from 'antd'; -import React, { useState } from 'react'; +import React from 'react'; import { proFormSmallItemStyleProps, proFormSmallModelWidth, } from '../../../../../config/defaultForm'; -import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup'; // TODO 需要根据接口替换API.DeviceCategory export type FormValueType = { target?: string; @@ -25,7 +25,7 @@ export type CreateFormProps = { }; const CreateForm: React.FC = (props) => { const intl = useIntl(); - const [isAuto, setIsAuto] = useState(true); + // const [isAuto, setIsAuto] = useState(true); const [form] = Form.useForm(); return ( @@ -92,7 +92,6 @@ const CreateForm: React.FC = (props) => { id: 'alarm.setting.table.list.code', defaultMessage: '$$$', })}`} - required={!isAuto} initialValue="" rules={[ { @@ -128,7 +127,7 @@ const CreateForm: React.FC = (props) => { })}`} required={false} debounceTime={1000} - request={async (keyWord) => { + request={async () => { // TODO 此处需要使用告警级别接口联调 const resp = await postDeviceGroupGetDeviceGroupFkSelect({}); return resp.data.list.map((v: any) => { diff --git a/src/pages/Alarm/AlarmSetting/components/UpdateForm.tsx b/src/pages/Alarm/AlarmSetting/components/UpdateForm.tsx index a275039..1c022a6 100644 --- a/src/pages/Alarm/AlarmSetting/components/UpdateForm.tsx +++ b/src/pages/Alarm/AlarmSetting/components/UpdateForm.tsx @@ -2,18 +2,13 @@ * @Author: zhoux zhouxia@supervision.ltd * @Date: 2023-11-01 13:56:33 * @LastEditors: zhoux zhouxia@supervision.ltd - * @LastEditTime: 2023-12-18 17:47:49 + * @LastEditTime: 2023-12-19 13:46:07 * @FilePath: \general-ai-platform-web\src\pages\Device\DeviceCategoryList\components\UpdateForm.tsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ import { putDeviceCategoryUpdateDeviceCategory } from '@/services/device/DeviceCategory'; -import { - ModalForm, - ProForm, - ProFormDateTimePicker, - ProFormSelect, - ProFormText, -} from '@ant-design/pro-components'; +import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup'; +import { ModalForm, ProForm, ProFormSelect, ProFormText } from '@ant-design/pro-components'; import { FormattedMessage, useIntl } from '@umijs/max'; import { Form, message } from 'antd'; import React from 'react'; @@ -21,7 +16,6 @@ import { proFormSmallItemStyleProps, proFormSmallModelWidth, } from '../../../../../config/defaultForm'; -import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup'; export type FormValueType = { target?: string; template?: string; @@ -134,9 +128,10 @@ const UpdateForm: React.FC = (props) => { defaultMessage: '$$$', })}`} required={false} - initialValue={props.values.level} + // TODO 在types中增加类型注释 + initialValue={props.values?.level} debounceTime={1000} - request={async (keyWord) => { + request={async () => { // TODO 此处需要使用告警级别接口联调 const resp = await postDeviceGroupGetDeviceGroupFkSelect({}); return resp.data.list.map((v: any) => { @@ -162,7 +157,6 @@ const UpdateForm: React.FC = (props) => { initialValue={props.values.remark} disabled={false} /> - ); diff --git a/src/pages/Alarm/AlarmSetting/components/alarmStatusForm.tsx b/src/pages/Alarm/AlarmSetting/components/alarmStatusForm.tsx new file mode 100644 index 0000000..bfd7c1a --- /dev/null +++ b/src/pages/Alarm/AlarmSetting/components/alarmStatusForm.tsx @@ -0,0 +1,170 @@ +import AlarmLevelBox from '@/components/DictionaryBox/alarmLevel'; +import { alarmLevelStatusEnum } from '@/enums/status'; +import { localStorageKeyEnums } from '@/enums/storage'; +import { DeleteOutlined, ExclamationCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; +import { ModalForm, ProFormText } from '@ant-design/pro-components'; +import { useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import React, { useEffect, useState } from 'react'; +import { proFormSmallModelWidth } from '../../../../../config/defaultForm'; +// TODO 需要根据接口替换API.DeviceCategory +export type FormValueType = { + target?: string; + template?: string; + type?: string; + time?: string; + frequency?: string; +} & Partial; + +export type CreateFormProps = { + alarmStatusModalOpen: boolean; + handleModal: () => void; + values: Partial; + reload: any; +}; + +/**style */ + +const tipStyle: React.CSSProperties = { + display: 'flex', + width: '100%', + cursor: 'pointer', + paddingBottom: 20, +}; +const AlarmStatusForm: React.FC = (props) => { + const intl = useIntl(); + const [form] = Form.useForm(); + const [alarmDict, setAlarmDict] = useState[]>([ + alarmLevelStatusEnum[0], + alarmLevelStatusEnum[1], + alarmLevelStatusEnum[2], + ]); + + // 新增一项 + function doAddItem() { + if (alarmDict.length >= 6) { + return; + } + setAlarmDict((data) => [...data, alarmLevelStatusEnum[alarmDict.length]]); + } + // 删除一项 + function doDeleteItem(delItem: Record) { + setAlarmDict((data) => data.filter((item) => item.id !== delItem.id)); + } + + useEffect(() => { + const currData = localStorage.getItem( + localStorageKeyEnums.alarmSetting_model_alarmStatusSetting, + ); + if (currData) { + const finalData = alarmLevelStatusEnum.filter((item) => + Object.keys(JSON.parse(currData)).includes(item.id), + ); + setAlarmDict(finalData); + } + }, []); + + return ( + + layout={'horizontal'} + width={proFormSmallModelWidth} + title={intl.formatMessage({ + id: 'alarm.setting.table.model.alarmStatusSetting', + defaultMessage: '$$$', + })} + open={props.alarmStatusModalOpen} + form={form} + autoFocusFirstInput + modalProps={{ + destroyOnClose: true, + onCancel: () => props.handleModal(), + }} + submitTimeout={2000} + onFinish={async (values) => { + console.log(values, 'values'); + localStorage.setItem( + localStorageKeyEnums.alarmSetting_model_alarmStatusSetting, + JSON.stringify(values), + ); + // postDeviceCategoryCreateDeviceCategory(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; + }} + > + {/* TODO 待讨论是否需要动态添加状态字段 */} + +
    + {alarmDict.map((item, index) => { + const currVal = index % 6; + const currLevel = alarmLevelStatusEnum[currVal]; + return ( +
  • +
    + +
    +
    + +
    + {index === alarmDict.length - 1 && index > 2 ? ( +
    { + doDeleteItem(item); + }} + > + +
    + ) : ( + <> + )} +
  • + ); + })} + {alarmDict.length < 6 ? ( +
  • { + doAddItem(); + }} + > +
    + +
    + + 添加 + {intl.formatMessage({ + id: 'alarm.setting.table.model.alarmStatusSetting', + defaultMessage: '$$$', + })} + +
  • + ) : ( +
  • +
    + +
    + + {intl.formatMessage({ + id: 'alarm.setting.table.model.alarmStatusSetting', + defaultMessage: '$$$', + })} + 设置数量已达到极限,不能再添加了 + +
  • + )} +
+ + ); +}; +export default AlarmStatusForm; diff --git a/src/pages/Alarm/AlarmSetting/index.tsx b/src/pages/Alarm/AlarmSetting/index.tsx index 3553a3a..f3de489 100644 --- a/src/pages/Alarm/AlarmSetting/index.tsx +++ b/src/pages/Alarm/AlarmSetting/index.tsx @@ -1,33 +1,37 @@ import IsBatchDelete from '@/components/BatchOperation/isBatchDelete'; +import AlarmLevelBox from '@/components/DictionaryBox/alarmLevel'; import TableActionCard from '@/components/TableActionCard'; import IsDelete from '@/components/TableActionCard/isDelete'; +import { alarmLevelStatusEnum } from '@/enums/status'; import { deleteDeviceCategoryDeleteDeviceCategory, deleteDeviceCategoryDeleteDeviceCategoryByIds, postDeviceCategoryGetDeviceCategoryList, } from '@/services/device/DeviceCategory'; -import { PlusOutlined, SettingOutlined } from '@ant-design/icons'; +import { EditOutlined, PlusOutlined, SettingOutlined } from '@ant-design/icons'; import type { ActionType, ProColumns } from '@ant-design/pro-components'; import { PageContainer, ProTable } from '@ant-design/pro-components'; import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max'; -import { Button, message } from 'antd'; +import { Button, Space, message } from 'antd'; import React, { 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 AlarmStatusForm from './components/alarmStatusForm'; const DeviceCategoryList: React.FC = () => { /** * @en-US Pop-up window of new window * @zh-CN 新建窗口的弹窗 * */ const [createModalOpen, setCreateModalOpen] = useState(false); + // 告警状态设置 + const [alarmStatusModalOpen, setAlarmStatusModalOpen] = useState(true); + /** * @en-US The pop-up window of the distribution update window * @zh-CN 分布更新窗口的弹窗 * */ const [updateModalOpen, setUpdateModalOpen] = useState(false); - const [showDetail, setShowDetail] = useState(false); /** * @en-US International configuration * @zh-CN 国际化配置 @@ -40,12 +44,12 @@ const DeviceCategoryList: React.FC = () => { const [currentRow, setCurrentRow] = useState(); const [selectedRowsState, setSelectedRows] = useState([]); - /** // TODO - 1. 告警级别设置 - 2. 告警列表-告警级别渲染 - 3. 项目部署-告警模块 + 1. 告警列表-告警级别渲染-操作按钮 2h + // TODO 讨论 + 1. 告警状态设置 + 2. 项目部署告警添加 */ const handleUpdateModal = () => { @@ -64,12 +68,11 @@ const DeviceCategoryList: React.FC = () => { setCreateModalOpen(true); } }; - const handleColumnDrawer = () => { - if (showDetail) { - setShowDetail(false); - setCurrentRow(undefined); + const handleAlarmStatusModal = () => { + if (alarmStatusModalOpen) { + setAlarmStatusModalOpen(false); } else { - setShowDetail(true); + setAlarmStatusModalOpen(true); } }; const handleDestroy = async (selectedRow: API.DeviceCategory) => { @@ -96,23 +99,28 @@ const DeviceCategoryList: React.FC = () => { hideInSearch: true, }, { - title: ( - - ), + title: , dataIndex: 'category', hideInSearch: true, }, { - title: ( - - ), - dataIndex: 'level', - hideInSearch: true, + title: , + dataIndex: 'level', + hideInSearch: true, + render: (text, record, index) => { + console.log(text, record, index, 'level_record'); + const currVal = index % 6; + const currLevel = alarmLevelStatusEnum[currVal]; + return ( + + + {currLevel.defaultLabel} + + ); }, + }, { - title: ( - - ), + title: , dataIndex: 'createTime', sorter: true, hideInSearch: true, @@ -130,23 +138,34 @@ const DeviceCategoryList: React.FC = () => { { key: 'update', renderDom: ( - + { setUpdateModalOpen(true); setCurrentRow(record); }} - > - - + /> ), }, { key: 'destroy', renderDom: ( { handleDestroy(record).then(() => {}); }} @@ -206,14 +225,15 @@ const DeviceCategoryList: React.FC = () => { accessible={access.canUpdate(history.location.pathname)} key={`${history.location.pathname}-add`} > - , ]} @@ -257,7 +278,12 @@ const DeviceCategoryList: React.FC = () => { }, }} /> - + { handleModal={handleUpdateModal} reload={actionRef.current?.reload} /> - - ); }; diff --git a/src/pages/ComputePowerAllocation/ComputePowerAllocation.tsx b/src/pages/ComputePowerAllocation/ComputePowerAllocation.tsx index 1fa19f0..876e094 100644 --- a/src/pages/ComputePowerAllocation/ComputePowerAllocation.tsx +++ b/src/pages/ComputePowerAllocation/ComputePowerAllocation.tsx @@ -2,7 +2,8 @@ /* eslint-disable react/no-unknown-property */ import { PageContainer, ProCard } from '@ant-design/pro-components'; import { Image } from 'antd'; -import React from 'react'; +import { fabric } from 'fabric'; +import React, { useEffect, useRef, useState } from 'react'; // type import { ComputePowerPoolItem } from './typing'; @@ -61,9 +62,104 @@ const InfoPreview: React.FC<{ const OccupyProportion: React.FC<{ pools: ComputePowerPoolItem[]; }> = ({ pools }) => { + + const poolDefault = { + + buttonOptions: { + width: 20, + height: 40, + fill: 'white', // 填充颜色 + strokeWidth: 2, // 边框宽度 + left: 0, + top: 0, + selectable: false, + } + } + const [clipPathData, setClipPathData] = useState({ + width: 1000, // 宽 + height: 80, // 高 + }); + const canvasRef = useRef(null); + const [cvs, setCanvas] = useState(null); + const [rect1Witdh, setRect1Witdh] = useState(pools[0].proportion/100 * clipPathData.width); + + useEffect(() => { + const canvasObject = new fabric.Canvas(canvasRef.current); + const rect1 = new fabric.Rect({ + top: 3, // 矩形左上角在y轴的位置 + left: 0, // 矩形左上角在x轴的位置 + width: rect1Witdh, // 矩形的宽 + height: 32, // 矩形的高 + fill: '#FAA90B', // 填充色 + stroke: 'transparent', // 边框颜色 + strokeWidth: 2, // 边框宽度 + rx: 15, // 圆角的横向半径 + ry: 15, // 圆角的纵向半径 + selectable: false, + }); + // 创建矩形对象 + const bgRect1 = new fabric.Rect({ + width: 20, + height: 40, + fill: 'white', // 填充颜色 + strokeWidth: 2, // 边框宽度 + left: 0, + top: 0, + selectable: false, + hasControls: false, + }); + // 添加背景图片到矩形 + fabric.Image.fromURL('/images/computePowerAllocation/slideBtn1.png', function (img) { + // 设置图片的宽度和高度为矩形的宽度和高度 + img.set({ width: bgRect1.width, height: bgRect1.height, selectable: false ,hasControls: false}); + // 将图片置于矩形的底部 + // bgRect1.set({ originX: 'center', originY: 'center' }); + canvasObject.add( + new fabric.Group([bgRect1, img], { + width: 20, + height: 40, + left: rect1Witdh - 10, + top: 0, + lockMovementY: true, + hasControls: false, + // selectable: false, + }), + ); + // 更新Canvas以应用更改 + canvasObject.renderAll(); + + }); + canvasObject.add(rect1); + canvasObject.on('object:moving', (event) => { + // 获取事件的目标对象 + const targetObject = event.target; + console.log(targetObject,'targetObject', canvasObject.item(0)) + canvasObject.item(0).set({ + width: targetObject?.left + 10 + }) + // set_category_fk_id_open(false); + + // 检查目标对象是否为组合对象 + setRect1Witdh(targetObject?.left) + canvasObject.renderAll(); + }); + canvasObject.renderAll(); + + setCanvas(canvasObject); + return () => { + canvasObject.dispose(); + }; + }, []); + return (
-
+
+ {/* */} + +
    - +
  • - +
@@ -121,12 +225,12 @@ const OccupyProportion: React.FC<{ display: 'flex', paddingLeft: 0, paddingBottom: 24, - margin: 0 + margin: 0, }} > {pools.map((item, index) => { return ( -
  • +
  • {item.type != 2 ? ( - 预计处理效率:{item.PretreatmentEfficiency} 帧/秒 + 预计处理效率: + {item.PretreatmentEfficiency} 帧/秒 ) : ( <> @@ -171,8 +276,6 @@ const ComputePowerAllocation: React.FC = () => { paddingTop: 0, paddingBottom: 0, margin: 0, - - }} gutter={24} wrap @@ -196,7 +299,9 @@ const ComputePowerAllocation: React.FC = () => { } + placeholder={ + + } />
    { const [tabs, setTabs] = useState([]); const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra'); const [modelVersionData, setModelVersionData] = useState([]); - const [projectData, setProjectData] = useState>({}); + const [projectData, setProjectData] = useState>({}); const [targetKeys, setTargetKeys] = useState([]); const [projectConfigId, setProjectConfigId] = useState(0); const handleUpdateModal = () => { @@ -197,8 +202,8 @@ const AlgorithmSetting: React.FC = () => { key={item.configId} style={{ padding: 0, fontWeight: 700 }} onClick={() => { - setProjectData(item) - console.log(item,'setProjectData_item', projectData) + setProjectData(item); + console.log(item, 'setProjectData_item', projectData); setProjectConfigId(item.configId); handleUpdateModal(); }} @@ -213,10 +218,13 @@ const AlgorithmSetting: React.FC = () => { // console.log(88, model_data); // setProjectData({...projectData, [v.id]: v}) return { - label: `项目:${v.name}`, + label: , key: v.id, children: ( + style={{ + padding: '0px 16px 16px' + }} className="gn" ghost={true} itemCardProps={{ @@ -241,7 +249,7 @@ const AlgorithmSetting: React.FC = () => { console.log(action, rows, 'toolBarRender'); // TODO 需要对接接口 const isProcess: boolean = false; - return isProcess ? ( + const currNode = isProcess ? ( ); + return [currNode]; }} dataSource={model_data} /> @@ -354,9 +363,9 @@ const AlgorithmSetting: React.FC = () => {
    { columns={columns} > - { changeProjectTab(key); }, - }} - > + }} */} + + + 项目 + + ), + children: ( + { + changeProjectTab(key); + }} + > + ), + }, + { + key: '2', + label: ( + <> + + 告警 + + ), + children: (告警部分), + }, + ]} + />
    } > diff --git a/src/utils/storage.js b/src/utils/storage.js new file mode 100644 index 0000000..602378a --- /dev/null +++ b/src/utils/storage.js @@ -0,0 +1,78 @@ +// TODO 改为ts格式 +/** + * Set storage + * + * @param name + * @param content + * @param maxAge + */ +export const setStore = (name, content, maxAge = null) => { + if (!global.window || !name) { + return + } + + if (typeof content !== 'string') { + content = JSON.stringify(content) + } + + const storage = global.window.localStorage + + storage.setItem(name, content) + if (maxAge && !isNaN(parseInt(maxAge))) { + const timeout = parseInt(new Date().getTime() / 1000) + storage.setItem(`${name}_expire`, timeout + maxAge) + } + } + + /** + * Get storage + * + * @param name + * @returns {*} + */ + export const getStore = name => { + if (!global.window || !name) { + return + } + + const content = window.localStorage.getItem(name) + const _expire = window.localStorage.getItem(`${name}_expire`) + + if (_expire) { + const now = parseInt(new Date().getTime() / 1000) + if (now > _expire) { + return + } + } + + try { + return JSON.parse(content) + } catch (e) { + return content + } + } + + /** + * Clear storage + * + * @param name + */ + export const clearStore = name => { + if (!global.window || !name) { + return + } + + window.localStorage.removeItem(name) + window.localStorage.removeItem(`${name}_expire`) + } + + /** + * Clear all storage + */ + export const clearAll = () => { + if (!global.window || !name) { + return + } + + window.localStorage.clear() + } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index a9ad888..9fe8cd8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,5 @@ } }, - "include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx"] + "include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx", "src/utils/storage.js"] }