feat: 告警设置模块静态完成

develop
zhoux 1 year ago
parent c807eb7123
commit c7db8824ef

@ -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<AlarmLevelBoxProps> = (props) => {
const { icon, color, size } = props;
const finalSize = size || 14;
return (
<div
style={{
backgroundColor: color,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: finalSize,
height: finalSize,
borderRadius: '50%',
color: 'white',
fontSize: finalSize * 0.55,
}}
>
{icon === 'ArrowUpOutlined' ? <ArrowUpOutlined /> : <DownOutlined />}
</div>
);
};
export default AlarmLevelBox;

@ -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<IsDeleteProps> = (props) => {
@ -34,9 +36,17 @@ const IsDelete: React.FC<IsDeleteProps> = (props) => {
props.deleteApi();
}}
>
<Button type="link" size="small" danger>
<FormattedMessage id="pages.searchTable.destroy" defaultMessage="Destroy" />
</Button>
{props.buttonType === 'deleteIcon' ? (
<>
<DeleteOutlined style={{
color: "rgba(232, 13, 13, 1)"
}} />
</>
) : (
<Button type="link" size="small" danger>
<FormattedMessage id="pages.searchTable.destroy" defaultMessage="Destroy" />
</Button>
)}
</Popconfirm>
);
};

@ -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<string, any> = {
allStatus: {
miniName: '全部',
@ -25,7 +37,7 @@ export const deviceStatusEnums: Record<string, any> = {
color: 'error',
},
};
// 资源设备~
export const resourceDeviceStatusEnums: Record<string, any> = {
allStatus: {
miniName: '全部异常',
@ -70,3 +82,49 @@ export const resourceDeviceStatusEnums: Record<string, any> = {
renderType: 'dot',
},
};
// 告警等级~
export const alarmLevelStatusEnum: Record<string, any>[] = [
{
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',
},
];

@ -0,0 +1,3 @@
export const localStorageKeyEnums = {
alarmSetting_model_alarmStatusSetting: 'alarmSetting_model_alarmStatusSetting_key',
};

@ -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;
}

@ -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{
// }

@ -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<TreeAndTableListProps> = (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%',
};

@ -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': '告警等级'
}

@ -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': '首页',
@ -75,5 +77,5 @@ export default {
'menu.DCSDevice.DCSDevice-device-list': '设备列表',
'menu.DCSDevice.DCSDevice-device-category-list': '设备类别',
'menu.DCSDevice.DCSDevice-device-group-list': '设备组',
'menu.Contact.Contact-contact-list': '联系人列表'
'menu.Contact.Contact-contact-list': '联系人列表',
};

@ -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<API.DeviceCategory>[];
currentRow: API.DeviceCategory | undefined;
};
const ColumnDrawer: React.FC<ColumnDrawProps> = (props) => {
return (
<Drawer
width={500}
open={props.isShowDetail}
onClose={() => {
props.handleDrawer();
}}
closable={true}
>
{props.currentRow?.id && (
<ProDescriptions<API.DeviceCategory>
column={2}
title={props.currentRow?.id}
request={async () => ({
data: props.currentRow || {},
})}
params={{
id: props.currentRow?.id,
}}
columns={props.columns as ProDescriptionsItemProps<API.DeviceCategory>[]}
/>
)}
</Drawer>
)
}
export {ColumnDrawer}

@ -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<CreateFormProps> = (props) => {
const intl = useIntl();
const [isAuto, setIsAuto] = useState(true);
// const [isAuto, setIsAuto] = useState(true);
const [form] = Form.useForm<API.DeviceCategory>();
return (
@ -92,7 +92,6 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
id: 'alarm.setting.table.list.code',
defaultMessage: '$$$',
})}`}
required={!isAuto}
initialValue=""
rules={[
{
@ -128,7 +127,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
})}`}
required={false}
debounceTime={1000}
request={async (keyWord) => {
request={async () => {
// TODO 此处需要使用告警级别接口联调
const resp = await postDeviceGroupGetDeviceGroupFkSelect({});
return resp.data.list.map((v: any) => {

@ -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<UpdateFormProps> = (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<UpdateFormProps> = (props) => {
initialValue={props.values.remark}
disabled={false}
/>
</ProForm.Group>
</ModalForm>
);

@ -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<API.DeviceCategory>;
export type CreateFormProps = {
alarmStatusModalOpen: boolean;
handleModal: () => void;
values: Partial<API.DeviceCategory>;
reload: any;
};
/**style */
const tipStyle: React.CSSProperties = {
display: 'flex',
width: '100%',
cursor: 'pointer',
paddingBottom: 20,
};
const AlarmStatusForm: React.FC<CreateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.DeviceCategory>();
const [alarmDict, setAlarmDict] = useState<Record<string, any>[]>([
alarmLevelStatusEnum[0],
alarmLevelStatusEnum[1],
alarmLevelStatusEnum[2],
]);
// 新增一项
function doAddItem() {
if (alarmDict.length >= 6) {
return;
}
setAlarmDict((data) => [...data, alarmLevelStatusEnum[alarmDict.length]]);
}
// 删除一项
function doDeleteItem(delItem: Record<string, any>) {
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 (
<ModalForm<API.DeviceCategory>
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 待讨论是否需要动态添加状态字段 */}
<ul>
{alarmDict.map((item, index) => {
const currVal = index % 6;
const currLevel = alarmLevelStatusEnum[currVal];
return (
<li key={item.id} style={{ display: 'flex', width: '100%' }}>
<div style={{ paddingTop: 5, paddingRight: 12 }}>
<AlarmLevelBox size={20} {...currLevel}></AlarmLevelBox>
</div>
<div style={{ width: '100%', flex: 1 }}>
<ProFormText name={item.id} initialValue={item.defaultLabel}></ProFormText>
</div>
{index === alarmDict.length - 1 && index > 2 ? (
<div
style={{ paddingTop: 5, paddingLeft: 12 }}
onClick={() => {
doDeleteItem(item);
}}
>
<DeleteOutlined
style={{
color: 'rgba(232, 13, 13, 1)',
}}
/>
</div>
) : (
<></>
)}
</li>
);
})}
{alarmDict.length < 6 ? (
<li
style={{ color: '#154DDD', ...tipStyle }}
onClick={() => {
doAddItem();
}}
>
<div style={{ paddingRight: 12, fontSize: 16 }}>
<PlusCircleOutlined />
</div>
<span>
{intl.formatMessage({
id: 'alarm.setting.table.model.alarmStatusSetting',
defaultMessage: '$$$',
})}
</span>
</li>
) : (
<li style={{ ...tipStyle }}>
<div style={{ paddingRight: 12, color: '#FAAD14' }}>
<ExclamationCircleOutlined />
</div>
<span>
{intl.formatMessage({
id: 'alarm.setting.table.model.alarmStatusSetting',
defaultMessage: '$$$',
})}
</span>
</li>
)}
</ul>
</ModalForm>
);
};
export default AlarmStatusForm;

@ -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<boolean>(false);
// 告警状态设置
const [alarmStatusModalOpen, setAlarmStatusModalOpen] = useState<boolean>(true);
/**
* @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
@ -40,12 +44,12 @@ const DeviceCategoryList: React.FC = () => {
const [currentRow, setCurrentRow] = useState<API.DeviceCategory>();
const [selectedRowsState, setSelectedRows] = useState<API.DeviceCategory[]>([]);
/**
// 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: (
<FormattedMessage id="alarm.setting.table.list.category" defaultMessage="$$$" />
),
title: <FormattedMessage id="alarm.setting.table.list.category" defaultMessage="$$$" />,
dataIndex: 'category',
hideInSearch: true,
},
{
title: (
<FormattedMessage id="alarm.setting.table.list.level" defaultMessage="$$$" />
),
dataIndex: 'level',
hideInSearch: true,
title: <FormattedMessage id="alarm.setting.table.list.level" defaultMessage="$$$" />,
dataIndex: 'level',
hideInSearch: true,
render: (text, record, index) => {
console.log(text, record, index, 'level_record');
const currVal = index % 6;
const currLevel = alarmLevelStatusEnum[currVal];
return (
<Space>
<AlarmLevelBox {...currLevel}></AlarmLevelBox>
<span style={{ color: currLevel.color }}>{currLevel.defaultLabel}</span>
</Space>
);
},
},
{
title: (
<FormattedMessage id="alarm.setting.table.list.createTime" defaultMessage="$$$" />
),
title: <FormattedMessage id="alarm.setting.table.list.createTime" defaultMessage="$$$" />,
dataIndex: 'createTime',
sorter: true,
hideInSearch: true,
@ -130,23 +138,34 @@ const DeviceCategoryList: React.FC = () => {
{
key: 'update',
renderDom: (
<Button
// <Button
// key="update"
// type="link"
// size="small"
// onClick={() => {
// setUpdateModalOpen(true);
// setCurrentRow(record);
// }}
// >
// <FormattedMessage id="common.edit" defaultMessage="Update" />
// </Button>
<EditOutlined
key="update"
type="link"
size="small"
style={{
color: 'rgba(21, 77, 221, 1)',
}}
onClick={() => {
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="common.edit" defaultMessage="Update" />
</Button>
/>
),
},
{
key: 'destroy',
renderDom: (
<IsDelete
buttonType="deleteIcon"
deleteApi={() => {
handleDestroy(record).then(() => {});
}}
@ -206,14 +225,15 @@ const DeviceCategoryList: React.FC = () => {
accessible={access.canUpdate(history.location.pathname)}
key={`${history.location.pathname}-add`}
>
<Button
<Button
type="primary"
key="primary"
key="setting"
onClick={() => {
setCreateModalOpen(true);
setAlarmStatusModalOpen(true);
}}
>
<SettingOutlined /> <FormattedMessage id="alarm.setting.table.list.setting" defaultMessage="New" />
<SettingOutlined />{' '}
<FormattedMessage id="alarm.setting.table.list.setting" defaultMessage="New" />
</Button>
<Button
type="primary"
@ -222,7 +242,8 @@ const DeviceCategoryList: React.FC = () => {
setCreateModalOpen(true);
}}
>
<PlusOutlined /> <FormattedMessage id="alarm.setting.table.list.add" defaultMessage="New" />
<PlusOutlined />{' '}
<FormattedMessage id="alarm.setting.table.list.add" defaultMessage="New" />
</Button>
</Access>,
]}
@ -257,7 +278,12 @@ const DeviceCategoryList: React.FC = () => {
},
}}
/>
<AlarmStatusForm
alarmStatusModalOpen={alarmStatusModalOpen}
values={currentRow || {}}
handleModal={handleAlarmStatusModal}
reload={actionRef.current?.reload}
/>
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
@ -270,13 +296,6 @@ const DeviceCategoryList: React.FC = () => {
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<ColumnDrawer
handleDrawer={handleColumnDrawer}
isShowDetail={showDetail}
columns={columns}
currentRow={currentRow}
/>
</PageContainer>
);
};

@ -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 (
<div className="occupyProportion_box">
<div className="occupy_up" style={{ marginTop: 24, marginBottom: 20, padding: 0, position: 'relative', width: '100%' }}>
<div
className="occupy_up"
style={{ marginTop: 24, marginBottom: 20, padding: 0, position: 'relative', width: '100%' }}
>
{/* <canvas ref={canvasRef} {...clipPathData} style={{ border: '1px dashed red' }}></canvas> */}
<ul
className="occupy_progress"
style={{
@ -100,7 +196,11 @@ const OccupyProportion: React.FC<{
width: 20,
}}
>
<Image width={20} src={'/images/computePowerAllocation/slideBtn1.png'} preview={false}></Image>
<Image
width={20}
src={'/images/computePowerAllocation/slideBtn1.png'}
preview={false}
></Image>
</li>
<li
style={{
@ -110,7 +210,11 @@ const OccupyProportion: React.FC<{
width: 20,
}}
>
<Image width={20} src={'/images/computePowerAllocation/slideBtn2.png'} preview={false}></Image>
<Image
width={20}
src={'/images/computePowerAllocation/slideBtn2.png'}
preview={false}
></Image>
</li>
</ul>
</div>
@ -121,12 +225,12 @@ const OccupyProportion: React.FC<{
display: 'flex',
paddingLeft: 0,
paddingBottom: 24,
margin: 0
margin: 0,
}}
>
{pools.map((item, index) => {
return (
<li key={index} style={{marginRight: 35}}>
<li key={index} style={{ marginRight: 35 }}>
<span
style={{
width: 12,
@ -140,7 +244,8 @@ const OccupyProportion: React.FC<{
</span>
{item.type != 2 ? (
<span style={{ paddingLeft: 8 }}>
<span style={{ fontWeight: 700 }} >{item.PretreatmentEfficiency} /</span>
<span style={{ fontWeight: 700 }}>{item.PretreatmentEfficiency} /</span>
</span>
) : (
<></>
@ -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 = () => {
<Image
width={62}
src={'/images/computePowerAllocation/icon1.png'}
placeholder={<Image preview={false} src={'/images/computePowerAllocation/icon1.png'} width={62} />}
placeholder={
<Image preview={false} src={'/images/computePowerAllocation/icon1.png'} width={62} />
}
/>
<div
style={{

@ -7,11 +7,16 @@ import TreeAndTableList, { ProCardTypeProps } from '@/layouts/treeAndTableList';
import { postProjectGetProjectByGroupId } from '@/services/project/Project';
import { postModelVersionGetModelVersionListByIds } from '@/services/resource/ModelVersion';
import { FormattedMessage } from '@@/exports';
import { CaretRightOutlined, PauseOutlined } from '@ant-design/icons';
import {
CaretRightOutlined,
DatabaseOutlined,
PauseOutlined,
WarningOutlined,
} from '@ant-design/icons';
import type { ActionType } from '@ant-design/pro-components';
import { PageContainer, ProCard, ProDescriptions, ProList } from '@ant-design/pro-components';
import { useAccess, useIntl } from '@umijs/max';
import { Button, Tag, message } from 'antd';
import { Button, Tabs, Tag, message } from 'antd';
import Tree, { DataNode } from 'antd/es/tree';
import React, { useEffect, useRef, useState } from 'react';
import ProjectCard from './components/ProjectCard';
@ -42,7 +47,7 @@ const AlgorithmSetting: React.FC = () => {
const [tabs, setTabs] = useState([]);
const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra');
const [modelVersionData, setModelVersionData] = useState<any[]>([]);
const [projectData, setProjectData] = useState<Record<string,any>>({});
const [projectData, setProjectData] = useState<Record<string, any>>({});
const [targetKeys, setTargetKeys] = useState<string[]>([]);
const [projectConfigId, setProjectConfigId] = useState<number>(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: <Button type="default">{v.name}</Button>,
key: v.id,
children: (
<ProList<any>
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 ? (
<Button type="primary" danger>
<PauseOutlined style={{ fontSize: 14, lineHeight: 1.5 }} />
@ -252,6 +260,7 @@ const AlgorithmSetting: React.FC = () => {
</Button>
);
return [currNode];
}}
dataSource={model_data}
/>
@ -354,9 +363,9 @@ const AlgorithmSetting: React.FC = () => {
<div className="gn">
<ProCard
title="网点详细信息"
headStyle={{borderBottom: '1px solid #E0E0E0', paddingTop: 0, paddingBottom:12 }}
style={{ background: 'transparent' , paddingTop: 24 }}
bodyStyle={{ paddingBottom: 0 }}
headStyle={{ borderBottom: '1px solid #E0E0E0', padding: '0px 16px 16px'}}
style={{ background: 'transparent', paddingTop: 16 }}
bodyStyle={{ padding: '16px 16px 0px' }}
colSpan="80%"
>
<ProDescriptions
@ -365,16 +374,47 @@ const AlgorithmSetting: React.FC = () => {
columns={columns}
></ProDescriptions>
</ProCard>
<ProCard
wrap
tabs={{
{/* tabs={{
activeKey: tab,
items: tabs,
onChange: (key) => {
changeProjectTab(key);
},
}}
></ProCard>
}} */}
<Tabs
items={[
{
key: '1',
label: (
<>
<DatabaseOutlined></DatabaseOutlined> <span></span>
</>
),
children: (
<Tabs
className='gn algorithmSetting_project_box'
type={'line'}
activeKey={tab}
items={tabs}
onChange={(key) => {
changeProjectTab(key);
}}
></Tabs>
),
},
{
key: '2',
label: (
<>
<WarningOutlined></WarningOutlined>
<span></span>
</>
),
children: (<ProCard style={{padding: 0, margin: 0}} bodyStyle={{padding: 16}}></ProCard>),
},
]}
/>
</div>
}
></TreeAndTableList>

@ -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()
}

@ -23,5 +23,5 @@
}
},
"include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx"]
"include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx", "src/utils/storage.js"]
}

Loading…
Cancel
Save