修改页面 调试接口
parent
54b2201fd2
commit
40c99ec0fa
|
|
@ -9,8 +9,8 @@ module.exports = {
|
|||
// 应用后端分支名称,部署上线需要
|
||||
javaGitBranch: "<branch-name>",
|
||||
// 接口服务地址
|
||||
// API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||
API_HOST: "http://192.168.10.45:80",
|
||||
API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||
// API_HOST: "http://192.168.10.45:80",
|
||||
// API_HOST: "http://192.168.20.100:30140",
|
||||
},
|
||||
production: {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,11 @@
|
|||
"ahooks": "^3.9.5",
|
||||
"antd": "^5.27.6",
|
||||
"dayjs": "^1.11.7",
|
||||
"echarts": "^6.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"zy-react-library": "^1.2.20"
|
||||
"zy-react-library": "^1.2.39"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^5.4.1",
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
|||
|
||||
export const dcsAlarmInfoList = declareRequest("dcsAlarmInfoLoading", "Post > @/iotalarm/alarmRecord/list");
|
||||
export const thresholdAlarmInfoList = declareRequest("thresholdAlarmInfoLoading", "Post > @/iotalarm/alarmRecord/list");
|
||||
export const thresholdAlarmInfoInfo = declareRequest("thresholdAlarmInfoLoading", "Get > /iotalarm/alarmRecord/{id}");
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ export const alarmRecordList = declareRequest(
|
|||
);
|
||||
export const alarmRecordInfo = declareRequest(
|
||||
"alarmRecordLoading",
|
||||
`Get > @/iotalarm/alarmRecord/{id}`,
|
||||
`Get > /iotalarm/alarmRecord/{id}`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const deviceRegionList = declareRequest("deviceRegionLoading", "Post > @/iotalarm/deviceRegion/list");
|
||||
export const deviceRegionFireRegionList = declareRequest("deviceRegionLoading", "Get > @/fireCheck/fireRegion/listAll");
|
||||
export const deviceRegionFireRegionList = declareRequest("deviceRegionLoading", "Get > /fireCheck/fireRegion/listAll");
|
||||
export const deviceRegionSaveOrUpdate = declareRequest("deviceRegionLoading", "Post > @/iotalarm/deviceRegion/saveOrUpdate");
|
||||
export const deviceRegionBindSensor = declareRequest("deviceRegionLoading", "Post > @/iotalarm/deviceRegion/bindSensor");
|
||||
export const deviceRegionUnbindSensor = declareRequest("deviceRegionLoading", "Post > @/iotalarm/deviceRegion/unbindSensor");
|
||||
export const deviceRegionManager = declareRequest("deviceRegionLoading", "Put > @/iotalarm/deviceRegion/manager");
|
||||
export const deviceRegionInfo = declareRequest("deviceRegionLoading", "Get > @/iotalarm/deviceRegion/{id}");
|
||||
export const deviceRegionInfo = declareRequest("deviceRegionLoading", "Get > /iotalarm/deviceRegion/{id}");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const sensorDeviceList = declareRequest("sensorDeviceLoading", "Post > @/iotalarm/sensorDevice/list");
|
||||
export const sensorDeviceInfo = declareRequest("sensorDeviceLoading", "Get > @/iotalarm/sensorDevice/{id}");
|
||||
export const sensorDeviceInfo = declareRequest("sensorDeviceLoading", "Get > /iotalarm/sensorDevice/{id}");
|
||||
export const sensorDeviceSave = declareRequest("sensorDeviceLoading", "Post > @/iotalarm/sensorDevice/save");
|
||||
export const sensorDeviceEdit = declareRequest("sensorDeviceLoading", "Put > @/iotalarm/sensorDevice/edit");
|
||||
export const sensorDeviceEdit = declareRequest("sensorDeviceLoading", "Post > @/iotalarm/sensorDevice/edit");
|
||||
export const sensorDeviceStatus = declareRequest("sensorDeviceLoading", "Put > @/iotalarm/sensorDevice/status");
|
||||
export const sensorDeviceThreshold = declareRequest("sensorDeviceLoading", "Put > @/iotalarm/sensorDevice/threshold");
|
||||
export const sensorDeviceRemove = declareRequest("sensorDeviceLoading", "Delete > @/iotalarm/sensorDevice/{id}");
|
||||
export const sensorDeviceRemove = declareRequest("sensorDeviceLoading", "Post > @/iotalarm/sensorDevice/{id}");
|
||||
export const sensorDevicelistBySensorDevice = declareRequest("sensorDeviceLoading", "Post > @/iotalarm/alarmRecord/listBySensorDevice");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const sensorTypeList = declareRequest("sensorTypeLoading", "Post > @/iotalarm/sensorType/list");
|
||||
export const sensorTypeInfo = declareRequest("sensorTypeLoading", "Get > @/iotalarm/sensorType/{id}");
|
||||
export const sensorTypeInfo = declareRequest("sensorTypeLoading", "Get > /iotalarm/sensorType/{id}");
|
||||
export const sensorTypeSave = declareRequest("sensorTypeLoading", "Post > @/iotalarm/sensorType/save");
|
||||
export const sensorTypeEdit = declareRequest("sensorTypeLoading", "Put > @/iotalarm/sensorType/edit");
|
||||
export const sensorTypeRemove = declareRequest("sensorTypeLoading", "Delete > @/iotalarm/sensorType/{id}");
|
||||
export const sensorTypeEdit = declareRequest("sensorTypeLoading", "Post > @/iotalarm/sensorType/edit");
|
||||
export const sensorTypeRemove = declareRequest("sensorTypeLoading", "Post > @/iotalarm/sensorType/{id}");
|
||||
|
|
|
|||
|
|
@ -1,37 +1,102 @@
|
|||
import { Form, Modal } from "antd";
|
||||
import { useEffect } from "react";
|
||||
import { Col, Descriptions, Divider, Form, message, Modal, Row, Select } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import PersonnelSelect from "zy-react-library/components/Select/Personnel/Gwj";
|
||||
import useGetUserInfo from "zy-react-library/hooks/useGetUserInfo";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import BaiduMap from "~/components/BaiduMap";
|
||||
import { DISPOSAL_STATIS, SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
|
||||
function AssignModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [detail, setDetail] = useState({});
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [corpinfoId, setCorpinfoId] = useState(null);
|
||||
const { getUserInfo } = useGetUserInfo();
|
||||
const alarmLevelName = useRef(null);
|
||||
const alarmTypeName = useRef(null);
|
||||
const disposeStatus = Form.useWatch("disposeStatus", form);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
return;
|
||||
}
|
||||
|
||||
form.resetFields();
|
||||
}, [form, props.open]);
|
||||
setDetail({});
|
||||
|
||||
if (!props.isBatch && props.alarmId && props.alarmRecordInfo) {
|
||||
props.alarmRecordInfo({ id: props.alarmId }).then((res) => {
|
||||
if (res?.success) {
|
||||
setDetail(res.data || {});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [form, props.open, props.isBatch, props.alarmId]);
|
||||
|
||||
useEffect(() => {
|
||||
getUserInfo().then((data) => {
|
||||
setCorpinfoId(data.corpinfoId);
|
||||
});
|
||||
}, [getUserInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (disposeStatus !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
form.setFieldsValue({
|
||||
alarmType: undefined,
|
||||
alarmLevel: undefined,
|
||||
disposeUserId: undefined,
|
||||
});
|
||||
}, [disposeStatus, form]);
|
||||
|
||||
const handleCancel = () => {
|
||||
form.resetFields();
|
||||
setDetail({});
|
||||
props.onCancel();
|
||||
};
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
if (props.isBatch) {
|
||||
await props.alarmBatchAssign({
|
||||
ids: props.alarmIds,
|
||||
disposeUserId: values.disposeUserId,
|
||||
});
|
||||
if (submitting) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
await props.alarmAssign({
|
||||
id: props.alarmId,
|
||||
disposeUserId: values.disposeUserId,
|
||||
});
|
||||
|
||||
setSubmitting(true);
|
||||
values.alarmLevelName = alarmLevelName.current;
|
||||
values.alarmTypeName = alarmTypeName.current;
|
||||
values.status = values.disposeStatus === 1 ? 40 : 20;
|
||||
|
||||
try {
|
||||
let res;
|
||||
if (props.isBatch) {
|
||||
values.ids = props.alarmIds;
|
||||
res = await props.alarmAssign(values);
|
||||
} else {
|
||||
values.ids = [props.alarmId];
|
||||
res = await props.alarmAssign(values);
|
||||
}
|
||||
|
||||
if (res?.success) {
|
||||
handleCancel();
|
||||
props.getData();
|
||||
message.success("处置成功");
|
||||
}
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
handleCancel();
|
||||
props.getData();
|
||||
};
|
||||
|
||||
const formatTime = (value) => {
|
||||
if (!value) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
const time = dayjs(value);
|
||||
return time.isValid() ? time.format("YYYY-MM-DD HH:mm:ss") : value;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -41,17 +106,125 @@ function AssignModal(props) {
|
|||
title={props.isBatch ? "批量分配" : "分配处置"}
|
||||
onCancel={handleCancel}
|
||||
onOk={form.submit}
|
||||
confirmLoading={props.loading}
|
||||
width={640}
|
||||
confirmLoading={props.loading || submitting}
|
||||
maskClosable={false}
|
||||
width={1200}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item
|
||||
label="处置人"
|
||||
name="disposeUserId"
|
||||
rules={[{ required: true, message: "请选择处置人" }]}
|
||||
>
|
||||
<PersonnelSelect placeholder="请选择处置人" />
|
||||
</Form.Item>
|
||||
{!props.isBatch && (
|
||||
<>
|
||||
<Divider orientation="left">报警信息</Divider>
|
||||
<Descriptions column={2} bordered labelStyle={{ width: 200 }}>
|
||||
<Descriptions.Item label="传感器编码">{detail.sensorCode || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器名称">{detail.sensorName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器类型">{detail.sensorTypeName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器属性">
|
||||
{getLabelName({ status: detail.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="告警值">{renderAlarmCurrentValue(detail)}</Descriptions.Item>
|
||||
<Descriptions.Item label="计量单位">{detail.unitName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="高高报警阈值">{detail.thresholdHighHigh || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="高报警阈值">{detail.thresholdHigh || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="低低报警阈值">{detail.thresholdLowLow || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="低报警阈值">{detail.thresholdLow || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警编号">{detail.alarmNo || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警时间">{formatTime(detail.alarmTime)}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警描述" span={2}>
|
||||
{detail.alarmDesc || detail.deviceSourceDesc || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="报警位置" span={2}>
|
||||
{detail.longitude && detail.latitude
|
||||
? (
|
||||
<BaiduMap
|
||||
longitude={detail.longitude}
|
||||
latitude={detail.latitude}
|
||||
style={{
|
||||
border: "1px solid #f0f0f0",
|
||||
borderRadius: 4,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
)
|
||||
: "暂无定位信息"}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Divider orientation="left">处置分配</Divider>
|
||||
<Form
|
||||
form={form}
|
||||
layout="horizontal"
|
||||
onFinish={handleSubmit}
|
||||
labelCol={{ span: 4 }}
|
||||
initialValues={{ disposeStatus: 0 }}
|
||||
>
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="报警处置"
|
||||
name="disposeStatus"
|
||||
rules={[{ required: true, message: "请选择报警处置" }]}
|
||||
>
|
||||
<Select
|
||||
options={DISPOSAL_STATIS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择报警处置"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
{disposeStatus !== 1 && (
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="报警类型"
|
||||
name="alarmType"
|
||||
rules={[{ required: true, message: "请选择报警类型" }]}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="alarmType"
|
||||
onGetLabel={label => {
|
||||
alarmTypeName.current = label;
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
|
||||
{disposeStatus !== 1 && (
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="报警级别"
|
||||
name="alarmLevel"
|
||||
rules={[{ required: true, message: "请选择报警级别" }]}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="alarmLevel"
|
||||
onGetLabel={label => {
|
||||
alarmLevelName.current = label;
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="处置人"
|
||||
name="disposeUserId"
|
||||
rules={[{ required: true, message: "请选择处置人" }]}
|
||||
>
|
||||
<PersonnelSelect
|
||||
placeholder="请选择处置人"
|
||||
isNeedDepartmentId={false}
|
||||
isNeedCorpInfoId={true}
|
||||
params={{ corpinfoId }}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import Table from "zy-react-library/components/Table";
|
|||
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import AlarmRecordView from "~/components/AlarmRecord/View";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
import AssignModal from "./components/AssignModal";
|
||||
|
||||
function AssignList(props) {
|
||||
|
|
@ -16,11 +17,15 @@ function AssignList(props) {
|
|||
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||
const [currentAlarmId, setCurrentAlarmId] = useState(null);
|
||||
const [isBatch, setIsBatch] = useState(false);
|
||||
|
||||
const { tableProps, getData } = useTable(props["alarmAssignList"], { form });
|
||||
|
||||
const pageType = props.type || "fgs";
|
||||
const assignPermission = `${pageType}-iotalarm-alarm-assign`;
|
||||
const { tableProps, getData } = useTable(props.alarmRecordList, {
|
||||
form,
|
||||
transform: formData => ({
|
||||
...formData,
|
||||
alarmTimeStart: formData.alarmTime?.[0],
|
||||
alarmTimeEnd: formData.alarmTime?.[1],
|
||||
status: 10,
|
||||
}),
|
||||
});
|
||||
|
||||
const handleBatchAssign = () => {
|
||||
if (selectedRowKeys.length === 0) {
|
||||
|
|
@ -43,28 +48,11 @@ function AssignList(props) {
|
|||
onChange: setSelectedRowKeys,
|
||||
};
|
||||
|
||||
const handleSearch = (values) => {
|
||||
getData({
|
||||
sensorName: values.sensorName,
|
||||
alarmTimeStart: values.alarmTime?.[0]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
alarmTimeEnd: values.alarmTime?.[1]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
});
|
||||
};
|
||||
|
||||
const renderCurrentValue = (_, record) => {
|
||||
if (record.currentValue == null || record.currentValue === "") {
|
||||
return "-";
|
||||
}
|
||||
const suffix = record.compareFlag === "UP" ? " 上升" : record.compareFlag === "DOWN" ? " 下降" : "";
|
||||
const unit = record.unitName ? ` ${record.unitName}` : "";
|
||||
return `${record.currentValue}${unit}${suffix}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
form={form}
|
||||
onFinish={handleSearch}
|
||||
onFinish={getData}
|
||||
options={[
|
||||
{ name: "sensorName", label: "传感器名称" },
|
||||
{ name: "alarmTime", label: "报警时间", render: FORM_ITEM_RENDER_ENUM.DATE_RANGE },
|
||||
|
|
@ -75,11 +63,13 @@ function AssignList(props) {
|
|||
rowSelection={rowSelection}
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
{props.permission(assignPermission) && (
|
||||
{
|
||||
// props.permission("bjczfp-plcz") &&
|
||||
|
||||
<Button type="primary" onClick={handleBatchAssign}>
|
||||
批量处置
|
||||
</Button>
|
||||
)}
|
||||
}
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
|
|
@ -87,26 +77,36 @@ function AssignList(props) {
|
|||
{ title: "传感器名称", dataIndex: "sensorName", ellipsis: true },
|
||||
{ title: "报警时间", dataIndex: "alarmTime", width: 180 },
|
||||
{ title: "报警描述", dataIndex: "alarmDesc", ellipsis: true },
|
||||
{ title: "告警值", render: renderCurrentValue },
|
||||
{ title: "告警值", render: (_, record) => renderAlarmCurrentValue(record) },
|
||||
{
|
||||
title: "操作",
|
||||
width: 180,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
{props.permission(assignPermission) && (
|
||||
<Button type="link" onClick={() => handleSingleAssign(record)}>
|
||||
处置分配
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setDetailId(record.id);
|
||||
setDetailOpen(true);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
{
|
||||
props.permission("bjczfp-czfp")
|
||||
|
||||
&& (
|
||||
<Button type="link" onClick={() => handleSingleAssign(record)}>
|
||||
处置分配
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
{
|
||||
props.permission("bjczfp-info")
|
||||
&& (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setDetailId(record.id);
|
||||
setDetailOpen(true);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
)
|
||||
|
||||
}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
|
|
@ -132,6 +132,7 @@ function AssignList(props) {
|
|||
alarmIds={selectedRowKeys}
|
||||
loading={props.alarmDisposeLoading}
|
||||
getData={getData}
|
||||
alarmRecordInfo={props.alarmRecordInfo}
|
||||
alarmAssign={props.alarmAssign}
|
||||
alarmBatchAssign={props.alarmBatchAssign}
|
||||
onCancel={() => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,124 @@
|
|||
import { Descriptions, Divider, Form, Modal, Select } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import PersonnelSelect from "zy-react-library/components/Select/Personnel/Gwj";
|
||||
import { DISPOSAL_STATIS } from "~/enumerate/constant";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
|
||||
function DetailModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [detail, setDetail] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
return;
|
||||
}
|
||||
props.alarmRecordInfo({ id: props.currentId }).then((res) => {
|
||||
if (res?.success) {
|
||||
setDetail(res.data || {});
|
||||
}
|
||||
});
|
||||
}, [props.open, props.currentId, props.alarmRecordInfo]);
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
if (props.isBatch) {
|
||||
await props.alarmBatchAssign({
|
||||
ids: props.alarmIds,
|
||||
disposeUserId: values.disposeUserId,
|
||||
});
|
||||
} else {
|
||||
await props.alarmAssign({
|
||||
id: props.alarmId,
|
||||
disposeUserId: values.disposeUserId,
|
||||
});
|
||||
}
|
||||
props.history.goBack();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
open={props.open}
|
||||
title="查看"
|
||||
onCancel={props.onCancel}
|
||||
footer={null}
|
||||
maskClosable={false}
|
||||
width={720}
|
||||
>
|
||||
<Divider orientation="left">报警信息</Divider>
|
||||
{detail && (
|
||||
<Descriptions column={2} bordered>
|
||||
<Descriptions.Item label="传感器编码">{detail.sensorCode || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器名称">{detail.sensorName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器类型">{detail.sensorTypeName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器属性">{detail.sensorAttrName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="告警值">{renderAlarmCurrentValue(detail)}</Descriptions.Item>
|
||||
<Descriptions.Item label="计量单位">{detail.unitName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="高高报警阈值">{detail.thresholdHighHigh || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="高报警阈值">{detail.thresholdHigh || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="低低报警阈值">{detail.thresholdLowLow || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="低报警阈值">{detail.thresholdLow || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警编号">{detail.alarmNo || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警时间">{detail.alarmTime || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警描述" span={2}>
|
||||
{detail.deviceSourceDesc || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="报警位置" span={2}>{detail.disposeRemark || "-"}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
)}
|
||||
<Divider orientation="left">处置分配</Divider>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item
|
||||
label="报警处置"
|
||||
name="disposeUserId"
|
||||
rules={[{ required: true, message: "请选择报警处置" }]}
|
||||
>
|
||||
<Select
|
||||
options={DISPOSAL_STATIS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择报警处置"
|
||||
disabled
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="报警类型"
|
||||
name="disposeUserId"
|
||||
rules={[{ required: true, message: "请选择报警类型" }]}
|
||||
>
|
||||
<Select
|
||||
options={DISPOSAL_STATIS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择报警类型"
|
||||
disabled
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="报警级别"
|
||||
name="disposeUserId"
|
||||
rules={[{ required: true, message: "请选择报警级别" }]}
|
||||
>
|
||||
<Select
|
||||
options={DISPOSAL_STATIS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择报警级别"
|
||||
disabled
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="处置人"
|
||||
name="disposeUserId"
|
||||
rules={[{ required: true, message: "请选择处置人" }]}
|
||||
>
|
||||
<PersonnelSelect placeholder="请选择处置人" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default DetailModal;
|
||||
|
|
@ -5,75 +5,55 @@ import Search from "zy-react-library/components/Search";
|
|||
import Table from "zy-react-library/components/Table";
|
||||
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { ALARM_STATUS_OPTIONS } from "~/enumerate/constant";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
import AlarmRecordView from "../View";
|
||||
|
||||
function AlarmRecordList(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [detailOpen, setDetailOpen] = useState(false);
|
||||
const [currentId, setCurrentId] = useState("");
|
||||
const { tableProps, getData } = useTable(props["alarmRecordList"], { form });
|
||||
const { tableProps, getData } = useTable(props.alarmRecordList, {
|
||||
form,
|
||||
transform: formData => ({
|
||||
...formData,
|
||||
alarmTimeStart: formData.alarmTime?.[0],
|
||||
alarmTimeEnd: formData.alarmTime?.[1],
|
||||
disposeTimeStart: formData.disposeTime?.[0],
|
||||
disposeTimeEnd: formData.disposeTime?.[1],
|
||||
}),
|
||||
});
|
||||
|
||||
const handleViewDetail = (record) => {
|
||||
setCurrentId(record.id);
|
||||
setDetailOpen(true);
|
||||
};
|
||||
|
||||
const handleSearch = (values) => {
|
||||
getData({
|
||||
sensorName: values.sensorName,
|
||||
disposeUserName: values.disposeUserName,
|
||||
status: values.status,
|
||||
alarmTimeStart: values.alarmTime?.[0]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
alarmTimeEnd: values.alarmTime?.[1]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
disposeTimeStart: values.disposeTime?.[0]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
disposeTimeEnd: values.disposeTime?.[1]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
});
|
||||
};
|
||||
|
||||
const renderCurrentValue = (_, record) => {
|
||||
if (record.currentValue == null || record.currentValue === "") {
|
||||
return "-";
|
||||
}
|
||||
const suffix = record.compareFlag === "UP" ? " 上升" : record.compareFlag === "DOWN" ? " 下降" : "";
|
||||
const unit = record.unitName ? ` ${record.unitName}` : "";
|
||||
return `${record.currentValue}${unit}${suffix}`;
|
||||
};
|
||||
|
||||
const renderAlarmStatus = (_, record) => {
|
||||
if (record.status === 30) {
|
||||
return "已消警";
|
||||
}
|
||||
if (record.status === 40) {
|
||||
return "误报";
|
||||
}
|
||||
return "报警中";
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
form={form}
|
||||
onFinish={handleSearch}
|
||||
onFinish={getData}
|
||||
options={[
|
||||
{ name: "sensorName", label: "传感器名称" },
|
||||
{ name: "disposeUserName", label: "处置人" },
|
||||
{
|
||||
name: "alarmTime",
|
||||
label: "报警时间",
|
||||
render: FORM_ITEM_RENDER_ENUM.DATE_RANGE,
|
||||
},
|
||||
{
|
||||
name: "status",
|
||||
label: "报警状态",
|
||||
render: FORM_ITEM_RENDER_ENUM.SELECT,
|
||||
items: ALARM_STATUS_OPTIONS,
|
||||
},
|
||||
{
|
||||
name: "alarmTime",
|
||||
label: "报警时间",
|
||||
render: FORM_ITEM_RENDER_ENUM.DATE_RANGE,
|
||||
},
|
||||
{
|
||||
name: "disposeTime",
|
||||
label: "处置时间",
|
||||
render: FORM_ITEM_RENDER_ENUM.DATE_RANGE,
|
||||
},
|
||||
{ name: "disposeUserName", label: "处置人" },
|
||||
]}
|
||||
/>
|
||||
<Table
|
||||
|
|
@ -83,9 +63,9 @@ function AlarmRecordList(props) {
|
|||
{ title: "传感器名称", dataIndex: "sensorName" },
|
||||
{ title: "报警时间", dataIndex: "alarmTime" },
|
||||
{ title: "报警描述", dataIndex: "alarmDesc", ellipsis: true },
|
||||
{ title: "告警值", render: renderCurrentValue },
|
||||
{ title: "报警级别", dataIndex: "alarmLevel" },
|
||||
{ title: "报警类型", dataIndex: "alarmType" },
|
||||
{ title: "告警值", render: (_, record) => renderAlarmCurrentValue(record) },
|
||||
{ title: "报警级别", dataIndex: "alarmLevelName" },
|
||||
{ title: "报警类型", dataIndex: "alarmTypeName" },
|
||||
{
|
||||
title: "处置人",
|
||||
dataIndex: "disposeUserName",
|
||||
|
|
@ -93,17 +73,16 @@ function AlarmRecordList(props) {
|
|||
{ title: "处置时间", dataIndex: "disposeTime" },
|
||||
{
|
||||
title: "报警状态",
|
||||
render: renderAlarmStatus,
|
||||
dataIndex: "status",
|
||||
render: (_, record) => getLabelName({ status: record.status, list: ALARM_STATUS_OPTIONS }),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 100,
|
||||
hidden: !props.permission("bjjlgl-info"),
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleViewDetail(record)}
|
||||
>
|
||||
<Button type="link" onClick={() => handleViewDetail(record)}>
|
||||
查看
|
||||
</Button>
|
||||
</Space>
|
||||
|
|
@ -116,6 +95,7 @@ function AlarmRecordList(props) {
|
|||
<AlarmRecordView
|
||||
open={detailOpen}
|
||||
currentId={currentId}
|
||||
type={1}
|
||||
alarmRecordInfo={props.alarmRecordInfo}
|
||||
onCancel={() => {
|
||||
setDetailOpen(false);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,22 @@
|
|||
import { Descriptions, Modal } from "antd";
|
||||
import { Descriptions, Divider, Modal } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import { useEffect, useState } from "react";
|
||||
import VideoIcon from "zy-react-library/components/Icon/VideoIcon";
|
||||
import Video from "zy-react-library/components/Video";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { ALARM_SOURCE_OPTIONS, ALARM_STATUS_OPTIONS } from "~/enumerate/constant";
|
||||
import { DISPOSAL_STATIS, SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
import BaiduMap from "../../BaiduMap";
|
||||
|
||||
function DetailModal(props) {
|
||||
const [detail, setDetail] = useState(null);
|
||||
const [detail, setDetail] = useState({});
|
||||
const [videoModalOpen, setVideoModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
return;
|
||||
}
|
||||
|
||||
props.alarmRecordInfo({ id: props.currentId }).then((res) => {
|
||||
if (res?.success) {
|
||||
setDetail(res.data || {});
|
||||
|
|
@ -17,13 +24,28 @@ function DetailModal(props) {
|
|||
});
|
||||
}, [props.open, props.currentId, props.alarmRecordInfo]);
|
||||
|
||||
const renderCurrentValue = () => {
|
||||
if (!detail || detail.currentValue == null || detail.currentValue === "") {
|
||||
const formatTime = (value) => {
|
||||
if (!value) {
|
||||
return "-";
|
||||
}
|
||||
const suffix = detail.compareFlag === "UP" ? " 上升" : detail.compareFlag === "DOWN" ? " 下降" : "";
|
||||
const unit = detail.unitName ? ` ${detail.unitName}` : "";
|
||||
return `${detail.currentValue}${unit}${suffix}`;
|
||||
|
||||
const time = dayjs(value);
|
||||
return time.isValid() ? time.format("YYYY-MM-DD HH:mm:ss") : value;
|
||||
};
|
||||
|
||||
const renderDisposalStatus = () => {
|
||||
const status = detail.confirmStatus ?? detail.disposeStatus ?? detail.disposalStatus;
|
||||
const statusName = detail.confirmStatusName ?? detail.disposeStatusName ?? detail.disposalStatusName;
|
||||
|
||||
if (statusName) {
|
||||
return statusName;
|
||||
}
|
||||
|
||||
if (status === 0 || status === 1) {
|
||||
return getLabelName({ status, list: DISPOSAL_STATIS }) || status;
|
||||
}
|
||||
|
||||
return "-";
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -33,31 +55,84 @@ function DetailModal(props) {
|
|||
title="查看"
|
||||
onCancel={props.onCancel}
|
||||
footer={null}
|
||||
width={720}
|
||||
maskClosable={false}
|
||||
width={1200}
|
||||
>
|
||||
{detail && (
|
||||
<Descriptions column={2} bordered>
|
||||
<Descriptions.Item label="报警编号">{detail.alarmNo || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警来源">
|
||||
{getLabelName({ status: detail.alarmSource, list: ALARM_SOURCE_OPTIONS }) || detail.alarmSource || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器编码">{detail.sensorCode || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器名称">{detail.sensorName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警时间">{detail.alarmTime || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警级别">{detail.alarmLevel || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警类型">{detail.alarmType || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警描述">{detail.alarmDesc || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="状态">
|
||||
{getLabelName({ status: detail.status, list: ALARM_STATUS_OPTIONS }) || detail.status || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="告警值">{renderCurrentValue()}</Descriptions.Item>
|
||||
<Descriptions.Item label="设备来源描述" span={2}>
|
||||
{detail.deviceSourceDesc || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处置人">{detail.disposeUserName || detail.disposeUserId || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置时间">{detail.disposeTime || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置备注" span={2}>{detail.disposeRemark || "-"}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<Divider orientation="left">报警信息</Divider>
|
||||
<Descriptions column={2} bordered labelStyle={{ width: 200 }}>
|
||||
<Descriptions.Item label="传感器编码">{detail.sensorCode || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器名称">{detail.sensorName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器类型">{detail.sensorTypeName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="传感器属性">
|
||||
{getLabelName({ status: detail.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="告警值">{renderAlarmCurrentValue(detail)}</Descriptions.Item>
|
||||
<Descriptions.Item label="计量单位">{detail.unitName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="高高报警阈值">{detail.thresholdHighHigh || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="高报警阈值">{detail.thresholdHigh || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="低低报警阈值">{detail.thresholdLowLow || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="低报警阈值">{detail.thresholdLow || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警编号">{detail.alarmNo || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警时间">{formatTime(detail.alarmTime)}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警描述" span={2}>
|
||||
{detail.alarmDesc || detail.deviceSourceDesc || "-"}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="报警位置" span={2}>
|
||||
{detail.longitude && detail.latitude
|
||||
? (
|
||||
<BaiduMap
|
||||
longitude={detail.longitude}
|
||||
latitude={detail.latitude}
|
||||
style={{
|
||||
border: "1px solid #f0f0f0",
|
||||
borderRadius: 4,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
)
|
||||
: "暂无定位信息"}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
{props.type === 1 && (
|
||||
<div>
|
||||
<Divider orientation="left">报警处置</Divider>
|
||||
<Descriptions column={2} bordered labelStyle={{ width: 200 }}>
|
||||
<Descriptions.Item label="报警确认">{renderDisposalStatus()}</Descriptions.Item>
|
||||
<Descriptions.Item label="确认时间">{detail.assignTime || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警类型">{detail.alarmTypeName || detail.alarmType || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="报警级别">{detail.alarmLevelName || detail.alarmLevel || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置人">{detail.disposeUserName || "-"}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<Divider orientation="left">处置结果</Divider>
|
||||
<Descriptions column={2} bordered labelStyle={{ width: 200 }}>
|
||||
<Descriptions.Item label="处置人">{detail.disposeUserName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置时间">{detail.disposeTime || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置结果" span={2}>{detail.disposeResult || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置图片" span={2}>{detail.disposeImage || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="处置视频" span={2}>
|
||||
{detail.videoUrl
|
||||
? (
|
||||
<VideoIcon
|
||||
onClick={() => {
|
||||
setVideoModalOpen(true);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
: "-"}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{videoModalOpen && (
|
||||
<Video
|
||||
visible={videoModalOpen}
|
||||
source={detail.videoUrl}
|
||||
onCancel={() => setVideoModalOpen(false)}
|
||||
title="处置视频"
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import { useState } from "react";
|
||||
import LocationIcon from "zy-react-library/components/Icon/LocationIcon";
|
||||
import MapSelector from "zy-react-library/components/Map/MapSelector";
|
||||
|
||||
function BaiduMap({
|
||||
longitude,
|
||||
latitude,
|
||||
disable = true,
|
||||
onChange,
|
||||
onConfirm,
|
||||
enablePointSelect,
|
||||
onPointSelect,
|
||||
}) {
|
||||
const [mapVisible, setMapVisible] = useState(false);
|
||||
const [selectedLocation, setSelectedLocation] = useState({
|
||||
longitude: "",
|
||||
latitude: "",
|
||||
});
|
||||
const currentLongitude = longitude || selectedLocation.longitude;
|
||||
const currentLatitude = latitude || selectedLocation.latitude;
|
||||
const mapDisabled = disable && !enablePointSelect;
|
||||
|
||||
const handleConfirm = (nextLongitude, nextLatitude, extra) => {
|
||||
setSelectedLocation({
|
||||
longitude: nextLongitude,
|
||||
latitude: nextLatitude,
|
||||
});
|
||||
onPointSelect?.(nextLongitude, nextLatitude, extra);
|
||||
onChange?.(nextLongitude, nextLatitude, extra);
|
||||
onConfirm?.(nextLongitude, nextLatitude, extra);
|
||||
setMapVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
|
||||
<span>
|
||||
经度:
|
||||
{currentLongitude || "-"}
|
||||
</span>
|
||||
<span>
|
||||
纬度:
|
||||
{currentLatitude || "-"}
|
||||
</span>
|
||||
<LocationIcon onClick={() => {
|
||||
setMapVisible(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{mapVisible && (
|
||||
<MapSelector
|
||||
visible={mapVisible}
|
||||
onClose={() => setMapVisible(false)}
|
||||
longitude={currentLongitude}
|
||||
latitude={currentLatitude}
|
||||
disable={mapDisabled}
|
||||
onConfirm={handleConfirm}
|
||||
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BaiduMap;
|
||||
|
|
@ -6,38 +6,27 @@ import Table from "zy-react-library/components/Table";
|
|||
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import AlarmRecordView from "~/components/AlarmRecord/View";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
|
||||
function DcsList(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [detailOpen, setDetailOpen] = useState(false);
|
||||
const [currentId, setCurrentId] = useState("");
|
||||
const { tableProps, getData } = useTable(props["dcsAlarmInfoList"], {
|
||||
const { tableProps, getData } = useTable(props.dcsAlarmInfoList, {
|
||||
form,
|
||||
defaultParams: { alarmSource: "DCS" },
|
||||
transform: formData => ({
|
||||
...formData,
|
||||
alarmTimeStart: formData.alarmTime?.[0],
|
||||
alarmTimeEnd: formData.alarmTime?.[1],
|
||||
alarmSource: "DCS",
|
||||
}),
|
||||
});
|
||||
|
||||
const handleSearch = (values) => {
|
||||
getData({
|
||||
sensorName: values.sensorName,
|
||||
alarmTimeStart: values.alarmTime?.[0]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
alarmTimeEnd: values.alarmTime?.[1]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
});
|
||||
};
|
||||
|
||||
const renderCurrentValue = (_, record) => {
|
||||
if (record.currentValue == null || record.currentValue === "") {
|
||||
return "-";
|
||||
}
|
||||
const suffix = record.compareFlag === "UP" ? " 上升" : record.compareFlag === "DOWN" ? " 下降" : "";
|
||||
const unit = record.unitName ? ` ${record.unitName}` : "";
|
||||
return `${record.currentValue}${unit}${suffix}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
form={form}
|
||||
onFinish={handleSearch}
|
||||
onFinish={getData}
|
||||
options={[
|
||||
{ name: "sensorName", label: "传感器名称" },
|
||||
{
|
||||
|
|
@ -54,10 +43,11 @@ function DcsList(props) {
|
|||
{ title: "传感器名称", dataIndex: "sensorName" },
|
||||
{ title: "报警时间", dataIndex: "alarmTime" },
|
||||
{ title: "报警描述", dataIndex: "alarmDesc", ellipsis: true },
|
||||
{ title: "告警值", render: renderCurrentValue },
|
||||
{ title: "告警值", render: (_, record) => renderAlarmCurrentValue(record) },
|
||||
{
|
||||
title: "操作",
|
||||
width: 100,
|
||||
hidden: !props.permission("sfbjxx-info"),
|
||||
render: (_, record) => (
|
||||
<a
|
||||
onClick={() => {
|
||||
|
|
@ -76,7 +66,7 @@ function DcsList(props) {
|
|||
<AlarmRecordView
|
||||
open={detailOpen}
|
||||
currentId={currentId}
|
||||
alarmRecordInfo={props.alarmRecordInfo}
|
||||
alarmRecordInfo={props.thresholdAlarmInfoInfo}
|
||||
onCancel={() => {
|
||||
setDetailOpen(false);
|
||||
setCurrentId("");
|
||||
|
|
|
|||
|
|
@ -1,71 +1,36 @@
|
|||
import { Checkbox, Empty, message, Modal, Typography } from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Form, message, Modal } from "antd";
|
||||
import { useState } from "react";
|
||||
import Search from "zy-react-library/components/Search";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { SENSOR_ATTR_OPTIONS, SENSOR_STATUS_OPTIONS } from "~/enumerate/constant";
|
||||
|
||||
function BindSensorModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [detail, setDetail] = useState({});
|
||||
const [options, setOptions] = useState([]);
|
||||
const [initialSensorIds, setInitialSensorIds] = useState([]);
|
||||
const [tableReady, setTableReady] = useState(false);
|
||||
|
||||
const [selectedSensorIds, setSelectedSensorIds] = useState([]);
|
||||
const { tableProps, getData } = useTable(props.sensorDeviceList, { form });
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open || !props.currentId) {
|
||||
return;
|
||||
}
|
||||
const loadData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const [detailRes, deviceRes] = await Promise.all([
|
||||
props.deviceRegionInfo({ id: props.currentId }),
|
||||
props.sensorDeviceList({ pageIndex: 1, pageSize: 500 }),
|
||||
]);
|
||||
const regionDetail = detailRes?.data || {};
|
||||
const deviceList = deviceRes?.data || [];
|
||||
const boundIds = (regionDetail.boundSensors || []).map(item => item.id);
|
||||
setDetail(regionDetail);
|
||||
setInitialSensorIds(boundIds);
|
||||
setSelectedSensorIds(boundIds);
|
||||
setOptions(
|
||||
deviceList.map(item => ({
|
||||
value: item.id,
|
||||
label: `${item.sensorCode} - ${item.sensorName}${item.sensorTypeName ? `(${item.sensorTypeName})` : ""}`,
|
||||
})),
|
||||
);
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
loadData();
|
||||
}, [props.currentId, props.deviceRegionInfo, props.open, props.sensorDeviceList]);
|
||||
|
||||
const changes = useMemo(() => {
|
||||
const initialSet = new Set(initialSensorIds);
|
||||
const selectedSet = new Set(selectedSensorIds);
|
||||
return {
|
||||
addIds: selectedSensorIds.filter(id => !initialSet.has(id)),
|
||||
removeIds: initialSensorIds.filter(id => !selectedSet.has(id)),
|
||||
};
|
||||
}, [initialSensorIds, selectedSensorIds]);
|
||||
|
||||
const fireRegionName = detail.fireRegionName || props.currentRecord?.fireRegionName || "-";
|
||||
const fireRegionCode = detail.fireRegionCode || props.currentRecord?.fireRegionCode || "-";
|
||||
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
getData();
|
||||
};
|
||||
const handleSubmit = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
for (const sensorId of changes.addIds) {
|
||||
await props.deviceRegionBindSensor({
|
||||
regionConfigId: props.currentId,
|
||||
sensorId,
|
||||
});
|
||||
const res = await props.deviceRegionBindSensor({
|
||||
fireRegionId: props.currentRecord.fireRegionId,
|
||||
deviceIdList: selectedSensorIds,
|
||||
});
|
||||
if (res.success) {
|
||||
message.success("关联传感器已更新");
|
||||
props.onCancel();
|
||||
props.getData();
|
||||
}
|
||||
for (const sensorId of changes.removeIds) {
|
||||
await props.deviceRegionUnbindSensor({ sensorId });
|
||||
}
|
||||
message.success("关联传感器已更新");
|
||||
props.onCancel();
|
||||
props.getData();
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
|
|
@ -79,44 +44,60 @@ function BindSensorModal(props) {
|
|||
title="关联传感器"
|
||||
onCancel={props.onCancel}
|
||||
onOk={handleSubmit}
|
||||
confirmLoading={loading || props.loading}
|
||||
width={760}
|
||||
afterOpenChange={open => setTableReady(open)}
|
||||
confirmLoading={loading}
|
||||
maskClosable={false}
|
||||
width={1200}
|
||||
>
|
||||
<Typography.Paragraph style={{ marginBottom: 16 }}>
|
||||
当前区域:
|
||||
{fireRegionName}
|
||||
{" "}
|
||||
/
|
||||
{" "}
|
||||
{fireRegionCode}
|
||||
</Typography.Paragraph>
|
||||
{options.length
|
||||
? (
|
||||
<Checkbox.Group
|
||||
value={selectedSensorIds}
|
||||
onChange={setSelectedSensorIds}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
maxHeight: 420,
|
||||
overflowY: "auto",
|
||||
border: "1px solid #f0f0f0",
|
||||
borderRadius: 6,
|
||||
padding: 12,
|
||||
}}
|
||||
>
|
||||
{options.map(item => (
|
||||
<div key={item.value} style={{ padding: "6px 0" }}>
|
||||
<Checkbox value={item.value}>{item.label}</Checkbox>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Checkbox.Group>
|
||||
)
|
||||
: (
|
||||
<Empty description="暂无可绑定的传感器设备" />
|
||||
)}
|
||||
<Search
|
||||
form={form}
|
||||
labelCol={{ span: 8 }}
|
||||
onFinish={getData}
|
||||
onReset={handleReset}
|
||||
options={[
|
||||
{
|
||||
name: "sensorName",
|
||||
label: "传感器名称",
|
||||
},
|
||||
{
|
||||
name: "sensorAttr",
|
||||
label: "传感器属性",
|
||||
render: FORM_ITEM_RENDER_ENUM.SELECT,
|
||||
items: SENSOR_ATTR_OPTIONS,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
{tableReady && (
|
||||
<Table
|
||||
{...tableProps}
|
||||
options={false}
|
||||
rowKey="sensorDeviceId"
|
||||
disabledResizer={true}
|
||||
scroll={{ y: 360 }}
|
||||
pagination={tableProps.pagination ? { ...tableProps.pagination, showSizeChanger: true } : false}
|
||||
rowSelection={{
|
||||
preserveSelectedRowKeys: true,
|
||||
selectedRowKeys: selectedSensorIds,
|
||||
onChange: keys => setSelectedSensorIds(keys),
|
||||
}}
|
||||
columns={[
|
||||
{ title: "传感器编码", dataIndex: "sensorCode" },
|
||||
{ title: "传感器名称", dataIndex: "sensorName" },
|
||||
{ title: "传感器类型", dataIndex: "sensorTypeName" },
|
||||
{
|
||||
title: "传感器属性",
|
||||
dataIndex: "sensorAttr",
|
||||
render: (_, record) => getLabelName({ status: record.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || "-",
|
||||
},
|
||||
{
|
||||
title: "传感器状态",
|
||||
dataIndex: "sensorStatus",
|
||||
render: (_, record) => getLabelName({ status: record.sensorStatus, list: SENSOR_STATUS_OPTIONS }) || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,17 @@
|
|||
import { Form, Modal } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import PersonnelSelect from "zy-react-library/components/Select/Personnel/Gwj";
|
||||
import DepartmentSelectTree from "zy-react-library/components/SelectTree/Department/Gwj";
|
||||
|
||||
function ManagerModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [departmentId, setDepartmentId] = useState();
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open || !props.currentId) {
|
||||
return;
|
||||
if (props.currentRecord && props.currentRecord.fireRegionId) {
|
||||
form.setFieldsValue({ managerId: props.currentRecord.managerId });
|
||||
}
|
||||
props.deviceRegionInfo({ id: props.currentId }).then((res) => {
|
||||
if (!res?.success) {
|
||||
return;
|
||||
}
|
||||
const data = res.data || {};
|
||||
setDepartmentId(data.departmentId);
|
||||
form.setFieldsValue({
|
||||
departmentId: data.departmentId,
|
||||
managerId: data.managerId,
|
||||
managerName: data.managerName,
|
||||
});
|
||||
});
|
||||
}, [form, props.currentId, props.deviceRegionInfo, props.open]);
|
||||
}, []);
|
||||
|
||||
const handleCancel = () => {
|
||||
form.resetFields();
|
||||
|
|
@ -32,9 +20,22 @@ function ManagerModal(props) {
|
|||
};
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
await props.deviceRegionManager({ ...values, id: props.currentId });
|
||||
handleCancel();
|
||||
props.getData();
|
||||
if (submitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true);
|
||||
values.fireRegionId = props.currentRecord.fireRegionId;
|
||||
values.regionConfigId = props.currentRecord.regionConfigId;
|
||||
|
||||
try {
|
||||
await props.deviceRegionManager({ ...values });
|
||||
handleCancel();
|
||||
props.getData();
|
||||
}
|
||||
finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -44,21 +45,16 @@ function ManagerModal(props) {
|
|||
title="设置负责人"
|
||||
onCancel={handleCancel}
|
||||
onOk={form.submit}
|
||||
confirmLoading={props.loading}
|
||||
confirmLoading={props.loading || submitting}
|
||||
maskClosable={false}
|
||||
|
||||
width={640}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item label="负责部门" name="departmentId">
|
||||
<DepartmentSelectTree
|
||||
onChange={(value) => {
|
||||
setDepartmentId(value);
|
||||
form.setFieldValue("managerId", undefined);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="负责人" name="managerId">
|
||||
<Form form={form} layout="horizontal" onFinish={handleSubmit} labelCol={{ span: 4 }}>
|
||||
|
||||
<Form.Item label="负责人" name="managerId" rules={[{ required: true, message: "请选择负责人" }]}>
|
||||
<PersonnelSelect
|
||||
params={{ departmentId }}
|
||||
params={{ departmentId: props.currentRecord.departmentId }}
|
||||
onGetLabel={label => form.setFieldValue("managerName", label)}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { Button, Descriptions, Form, Modal, Space } from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Button, Descriptions, Divider, Form, Modal, Space } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import Search from "zy-react-library/components/Search";
|
||||
import DepartmentSelectTree from "zy-react-library/components/SelectTree/Department/Gwj";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
||||
import BindSensorModal from "./components/BindSensorModal";
|
||||
import ManagerModal from "./components/ManagerModal";
|
||||
|
||||
|
|
@ -14,6 +16,7 @@ function DeviceRegionList(props) {
|
|||
const [managerOpen, setManagerOpen] = useState(false);
|
||||
const [bindOpen, setBindOpen] = useState(false);
|
||||
const [viewOpen, setViewOpen] = useState(false);
|
||||
const [viewLoading, setViewLoading] = useState(false);
|
||||
const [currentId, setCurrentId] = useState("");
|
||||
const [viewRecord, setViewRecord] = useState(null);
|
||||
const [currentRecord, setCurrentRecord] = useState(null);
|
||||
|
|
@ -34,52 +37,40 @@ function DeviceRegionList(props) {
|
|||
|
||||
useEffect(() => {
|
||||
loadFireRegionOptions();
|
||||
}, [props.deviceRegionFireRegionList]);
|
||||
}, []);
|
||||
|
||||
const dataSource = useMemo(() => (tableProps.dataSource || []).map(item => ({
|
||||
...item,
|
||||
departmentName: item.departmentName || "-",
|
||||
managerName: item.managerName || "-",
|
||||
bindSensorCount: item.bindSensorCount ?? 0,
|
||||
})), [tableProps.dataSource]);
|
||||
|
||||
const ensureConfigId = async (record) => {
|
||||
if (record.id) {
|
||||
return record.id;
|
||||
}
|
||||
await props.deviceRegionSaveOrUpdate({
|
||||
fireRegionId: record.fireRegionId,
|
||||
fireRegionName: record.fireRegionName,
|
||||
fireRegionCode: record.fireRegionCode,
|
||||
departmentId: record.departmentId,
|
||||
status: 1,
|
||||
});
|
||||
const res = await props.deviceRegionList({
|
||||
pageIndex: 1,
|
||||
pageSize: 1000,
|
||||
fireRegionId: record.fireRegionId,
|
||||
});
|
||||
const config = (res?.data || []).find(item => item.fireRegionId === record.fireRegionId);
|
||||
if (!config?.id) {
|
||||
throw new Error("区域配置创建失败");
|
||||
}
|
||||
return config.id;
|
||||
};
|
||||
// const dataSource = useMemo(() => (tableProps.dataSource || []).map(item => ({
|
||||
// ...item,
|
||||
// departmentName: item.departmentName || "-",
|
||||
// managerName: item.managerName || "-",
|
||||
// bindSensorCount: item.bindSensorCount ?? 0,
|
||||
// })), [tableProps.dataSource]);
|
||||
|
||||
const handleOpenManager = async (record) => {
|
||||
const configId = await ensureConfigId(record);
|
||||
setCurrentId(configId);
|
||||
setCurrentRecord(record);
|
||||
setManagerOpen(true);
|
||||
};
|
||||
|
||||
const handleOpenBind = async (record) => {
|
||||
const configId = await ensureConfigId(record);
|
||||
setCurrentId(configId);
|
||||
setCurrentRecord(record);
|
||||
setBindOpen(true);
|
||||
};
|
||||
|
||||
const handleOpenView = async (record) => {
|
||||
setViewLoading(true);
|
||||
try {
|
||||
const res = await props.deviceRegionInfo({ id: record.fireRegionId });
|
||||
setViewRecord({
|
||||
...record,
|
||||
boundSensors: res?.data?.boundSensors || [],
|
||||
});
|
||||
setViewOpen(true);
|
||||
}
|
||||
finally {
|
||||
setViewLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
|
|
@ -116,55 +107,89 @@ function DeviceRegionList(props) {
|
|||
width: 260,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
{props.permission(editPermission) && (
|
||||
<Button type="link" onClick={() => handleOpenBind(record)}>
|
||||
关联传感器
|
||||
</Button>
|
||||
)}
|
||||
{props.permission(editPermission) && (
|
||||
<Button type="link" onClick={() => handleOpenManager(record)}>
|
||||
设置负责人
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setViewRecord(record);
|
||||
setViewOpen(true);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
{/* {props.permission("sbqugl-glcgq") && ( */}
|
||||
<Button type="link" onClick={() => handleOpenBind(record)}>
|
||||
关联传感器
|
||||
</Button>
|
||||
{/* )} */}
|
||||
{/* {props.permission("sbqugl-szfer") && ( */}
|
||||
<Button type="link" onClick={() => handleOpenManager(record)}>
|
||||
设置负责人
|
||||
</Button>
|
||||
{/* )} */}
|
||||
{
|
||||
// props.permission("sbqugl-info") &&
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleOpenView(record)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
dataSource={dataSource}
|
||||
// dataSource={dataSource}
|
||||
/>
|
||||
<Modal
|
||||
destroyOnClose
|
||||
open={viewOpen}
|
||||
title="查看"
|
||||
footer={null}
|
||||
maskClosable={false}
|
||||
onCancel={() => {
|
||||
setViewOpen(false);
|
||||
setViewRecord(null);
|
||||
}}
|
||||
width={680}
|
||||
width={1200}
|
||||
>
|
||||
<Divider orientation="left">区域信息</Divider>
|
||||
<Descriptions bordered column={2}>
|
||||
<Descriptions.Item label="消防区域">{viewRecord?.fireRegionName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="消防区域编码">{viewRecord?.fireRegionCode || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="负责部门">{viewRecord?.departmentName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="负责人">{viewRecord?.managerName || "-"}</Descriptions.Item>
|
||||
<Descriptions.Item label="关联传感器数">{viewRecord?.bindSensorCount ?? 0}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<Divider orientation="left">设备信息</Divider>
|
||||
|
||||
<Table
|
||||
options={false}
|
||||
rowKey="id"
|
||||
loading={viewLoading}
|
||||
disabledResizer={true}
|
||||
pagination={false}
|
||||
dataSource={viewRecord?.boundSensors || []}
|
||||
columns={[
|
||||
|
||||
{ title: "传感器编码", dataIndex: "sensorCode" },
|
||||
{ title: "传感器名称", dataIndex: "sensorName" },
|
||||
{ title: "传感器类型", dataIndex: "sensorTypeName" },
|
||||
{
|
||||
title: "传感器属性",
|
||||
dataIndex: "sensorAttr",
|
||||
render: (_, record) => getLabelName({ status: record.sensorAttr, list: SENSOR_ATTR_OPTIONS }),
|
||||
},
|
||||
{
|
||||
title: "传感器状态",
|
||||
dataIndex: "sensorStatusName",
|
||||
},
|
||||
{
|
||||
title: "是否定位",
|
||||
dataIndex: "positioningFlag",
|
||||
render: (_, record) => record.latitude ? "是" : "否",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Modal>
|
||||
{managerOpen && (
|
||||
<ManagerModal
|
||||
open={managerOpen}
|
||||
currentId={currentId}
|
||||
currentRecord={currentRecord}
|
||||
loading={props.deviceRegionLoading}
|
||||
getData={getData}
|
||||
deviceRegionInfo={props.deviceRegionInfo}
|
||||
|
|
@ -172,7 +197,7 @@ function DeviceRegionList(props) {
|
|||
onCancel={() => {
|
||||
setManagerOpen(false);
|
||||
setCurrentId("");
|
||||
setCurrentRecord(null);
|
||||
setCurrentRecord({});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -181,7 +206,7 @@ function DeviceRegionList(props) {
|
|||
open={bindOpen}
|
||||
currentId={currentId}
|
||||
currentRecord={currentRecord}
|
||||
loading={props.deviceRegionLoading || props.sensorDeviceLoading}
|
||||
loading={props.deviceRegionLoading}
|
||||
getData={getData}
|
||||
deviceRegionInfo={props.deviceRegionInfo}
|
||||
deviceRegionBindSensor={props.deviceRegionBindSensor}
|
||||
|
|
@ -190,7 +215,7 @@ function DeviceRegionList(props) {
|
|||
onCancel={() => {
|
||||
setBindOpen(false);
|
||||
setCurrentId("");
|
||||
setCurrentRecord(null);
|
||||
setCurrentRecord({});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,31 @@
|
|||
import { DatePicker, Form, Input, InputNumber, Modal, Radio, Select } from "antd";
|
||||
import { DatePicker, Form, Input, Modal, Select } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import { useEffect } from "react";
|
||||
import Map from "zy-react-library/components/Map";
|
||||
import { ENABLE_STATUS_OPTIONS, SENSOR_STATUS_OPTIONS, YES_NO_OPTIONS } from "~/enumerate/constant";
|
||||
import { useEffect, useReducer, useRef, useState } from "react";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { SENSOR_ATTR_OPTIONS, SENSOR_STATUS_OPTIONS, YES_NO_OPTIONS } from "~/enumerate/constant";
|
||||
|
||||
function SensorDeviceModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const submitLockRef = useRef(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [detailLoading, dispatchDetailLoading] = useReducer((_, value) => value, false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
return;
|
||||
}
|
||||
let active = true;
|
||||
submitLockRef.current = false;
|
||||
form.resetFields();
|
||||
if (!props.currentId) {
|
||||
form.resetFields();
|
||||
form.setFieldsValue({
|
||||
sensorStatus: "NORMAL",
|
||||
positioningFlag: 0,
|
||||
alarmSwitch: 0,
|
||||
});
|
||||
return;
|
||||
dispatchDetailLoading(false);
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}
|
||||
dispatchDetailLoading(true);
|
||||
props.sensorDeviceInfo({ id: props.currentId }).then((res) => {
|
||||
if (!res?.success) {
|
||||
if (!active || !res?.success) {
|
||||
return;
|
||||
}
|
||||
const data = { ...(res.data || {}) };
|
||||
|
|
@ -29,27 +33,56 @@ function SensorDeviceModal(props) {
|
|||
data.factoryDate = dayjs(data.factoryDate);
|
||||
}
|
||||
form.setFieldsValue(data);
|
||||
}).finally(() => {
|
||||
if (active) {
|
||||
dispatchDetailLoading(false);
|
||||
}
|
||||
});
|
||||
}, [form, props.currentId, props.open, props.sensorDeviceInfo]);
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, [form, props.currentId, props.open]);
|
||||
|
||||
const handleCancel = () => {
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
dispatchDetailLoading(false);
|
||||
form.resetFields();
|
||||
props.onCancel();
|
||||
};
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
if (submitLockRef.current) {
|
||||
return;
|
||||
}
|
||||
submitLockRef.current = true;
|
||||
setSubmitting(true);
|
||||
values.sensorStatusName = getLabelName({ status: values.sensorStatus, list: SENSOR_STATUS_OPTIONS });
|
||||
const payload = {
|
||||
...values,
|
||||
factoryDate: values.factoryDate ? values.factoryDate.format("YYYY-MM-DD") : undefined,
|
||||
};
|
||||
if (props.currentId) {
|
||||
await props.sensorDeviceEdit({ ...payload, id: props.currentId });
|
||||
let res;
|
||||
try {
|
||||
if (props.currentId) {
|
||||
res = await props.sensorDeviceEdit({ ...payload, id: props.currentId });
|
||||
}
|
||||
else {
|
||||
res = await props.sensorDeviceSave(payload);
|
||||
}
|
||||
if (res?.success) {
|
||||
handleCancel();
|
||||
props.getData();
|
||||
return;
|
||||
}
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
}
|
||||
else {
|
||||
await props.sensorDeviceSave(payload);
|
||||
catch (error) {
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
throw error;
|
||||
}
|
||||
handleCancel();
|
||||
props.getData();
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -59,32 +92,32 @@ function SensorDeviceModal(props) {
|
|||
title={props.currentId ? "编辑传感器设备" : "新增传感器设备"}
|
||||
onCancel={handleCancel}
|
||||
onOk={form.submit}
|
||||
confirmLoading={props.loading}
|
||||
confirmLoading={props.loading || submitting || detailLoading}
|
||||
loading={!!props.currentId && (props.loading || detailLoading)}
|
||||
maskClosable={false}
|
||||
width={720}
|
||||
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
layout="horizontal"
|
||||
onFinish={handleSubmit}
|
||||
initialValues={{
|
||||
sensorStatus: "NORMAL",
|
||||
positioningFlag: 0,
|
||||
alarmSwitch: 0,
|
||||
}}
|
||||
labelCol={{ span: 6 }}
|
||||
|
||||
>
|
||||
<Form.Item
|
||||
label="传感器编码"
|
||||
name="sensorCode"
|
||||
rules={[{ required: true, message: "请输入传感器编码" }]}
|
||||
>
|
||||
<Input maxLength={100} placeholder="请输入传感器编码" />
|
||||
<Input maxLength={50} placeholder="请输入传感器编码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="传感器名称"
|
||||
name="sensorName"
|
||||
rules={[{ required: true, message: "请输入传感器名称" }]}
|
||||
>
|
||||
<Input maxLength={200} placeholder="请输入传感器名称" />
|
||||
<Input maxLength={50} placeholder="请输入传感器名称" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="传感器类型"
|
||||
|
|
@ -101,56 +134,69 @@ function SensorDeviceModal(props) {
|
|||
value: item.id,
|
||||
label: `${item.typeName}${item.typeCode ? `(${item.typeCode})` : ""}`,
|
||||
}))}
|
||||
onChange={(e) => {
|
||||
props.sensorTypeOptions.forEach((item) => {
|
||||
if (item.id === e) {
|
||||
form.setFieldsValue({ sensorAttr: item.sensorAttr });
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="安装位置" name="installPosition">
|
||||
<Input maxLength={255} placeholder="请输入安装位置" />
|
||||
<Form.Item
|
||||
label="传感器属性"
|
||||
name="sensorAttr"
|
||||
>
|
||||
<Select
|
||||
|
||||
options={SENSOR_ATTR_OPTIONS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择传感器属性"
|
||||
disabled
|
||||
/>
|
||||
|
||||
</Form.Item>
|
||||
<Map required={false} />
|
||||
<Form.Item label="传感器状态" name="sensorStatus">
|
||||
<Radio.Group>
|
||||
{SENSOR_STATUS_OPTIONS.map(item => (
|
||||
<Radio key={item.bianma} value={item.bianma}>
|
||||
{item.name}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
<Form.Item
|
||||
label="传感器状态"
|
||||
name="sensorStatus"
|
||||
>
|
||||
<Select
|
||||
options={SENSOR_STATUS_OPTIONS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择传感器状态"
|
||||
|
||||
/>
|
||||
|
||||
</Form.Item>
|
||||
<Form.Item label="是否定位" name="positioningFlag">
|
||||
<Radio.Group>
|
||||
{YES_NO_OPTIONS.map(item => (
|
||||
<Radio key={item.bianma} value={item.bianma}>
|
||||
{item.name}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
<Form.Item
|
||||
label="安装位置"
|
||||
name="installPosition"
|
||||
>
|
||||
<Input maxLength={50} placeholder="请输入安装位置" />
|
||||
</Form.Item>
|
||||
<Form.Item label="报警开关" name="alarmSwitch">
|
||||
<Radio.Group>
|
||||
{ENABLE_STATUS_OPTIONS.map(item => (
|
||||
<Radio key={item.bianma} value={item.bianma}>
|
||||
{item.name}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
<Form.Item
|
||||
label="出厂日期"
|
||||
name="factoryDate"
|
||||
>
|
||||
<DatePicker format="YYYY-MM-DD" style={{ width: "100%" }} placeholder="请选择出厂日期" />
|
||||
</Form.Item>
|
||||
<Form.Item label="单位" name="unitName">
|
||||
<Input maxLength={50} placeholder="请输入单位" />
|
||||
</Form.Item>
|
||||
<Form.Item label="量程下限" name="rangeMin">
|
||||
<InputNumber style={{ width: "100%" }} placeholder="请输入量程下限" />
|
||||
</Form.Item>
|
||||
<Form.Item label="量程上限" name="rangeMax">
|
||||
<InputNumber style={{ width: "100%" }} placeholder="请输入量程上限" />
|
||||
</Form.Item>
|
||||
<Form.Item label="出厂日期" name="factoryDate">
|
||||
<DatePicker style={{ width: "100%" }} placeholder="请选择出厂日期" />
|
||||
</Form.Item>
|
||||
<Form.Item label="企业侧源编码" name="enterpriseSourceCode">
|
||||
<Input maxLength={100} placeholder="请输入企业侧源编码" />
|
||||
</Form.Item>
|
||||
<Form.Item label="备注" name="remarks">
|
||||
<Input.TextArea rows={4} maxLength={255} placeholder="请输入备注" />
|
||||
<Form.Item
|
||||
label="是否通过系统设定报警"
|
||||
name="thresholdFlag"
|
||||
rules={[{ required: true, message: "请选择是否通过系统设定报警" }]}
|
||||
>
|
||||
<Select
|
||||
options={YES_NO_OPTIONS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择是否通过系统设定报警"
|
||||
disabled={!!props.currentId}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Button, Form, message, Modal, Space, Switch } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import AddIcon from "zy-react-library/components/Icon/AddIcon";
|
||||
import MapSelector from "zy-react-library/components/Map/MapSelector";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import Search from "zy-react-library/components/Search";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
|
|
@ -25,9 +26,10 @@ function SensorDeviceList(props) {
|
|||
const [currentRecord, setCurrentRecord] = useState({});
|
||||
const [sensorTypeOptions, setSensorTypeOptions] = useState([]);
|
||||
const { tableProps, getData } = useTable(props["sensorDeviceList"], { form });
|
||||
|
||||
const pageType = props.type || "fgs";
|
||||
const editPermission = `${pageType}-iotalarm-sensor-device-edit`;
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [selectedLng, setSelectedLng] = useState("");
|
||||
const [selectedLat, setSelectedLat] = useState("");
|
||||
const [rowData, setRowData] = useState({});
|
||||
|
||||
const loadSensorTypeOptions = async () => {
|
||||
const res = await props["sensorTypeList"]({
|
||||
|
|
@ -39,10 +41,25 @@ function SensorDeviceList(props) {
|
|||
setSensorTypeOptions(res.data || []);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpen = (row) => {
|
||||
setSelectedLng(row.longitude);
|
||||
setSelectedLat(row.latitude);
|
||||
setRowData(row);
|
||||
setVisible(true);
|
||||
};
|
||||
const handleConfirm = (lng, lat, extra) => {
|
||||
rowData.latitude = lat;
|
||||
rowData.longitude = lng;
|
||||
console.log(rowData);
|
||||
props["sensorDeviceEdit"](rowData).then((res) => {
|
||||
if (res?.success) {
|
||||
message.success("定位成功!");
|
||||
}
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
loadSensorTypeOptions();
|
||||
}, [props.sensorTypeList]);
|
||||
}, []);
|
||||
|
||||
const sensorTypeSelectOptions = sensorTypeOptions.map(item => ({
|
||||
bianma: item.id,
|
||||
|
|
@ -52,18 +69,23 @@ function SensorDeviceList(props) {
|
|||
const handleDelete = (record) => {
|
||||
Modal.confirm({
|
||||
title: "确定删除这条传感器设备吗?",
|
||||
maskClosable: false,
|
||||
onOk: async () => {
|
||||
await props["sensorDeviceRemove"]({ id: record.id });
|
||||
message.success("删除成功");
|
||||
getData();
|
||||
const res = await props["sensorDeviceRemove"]({ id: record.id });
|
||||
if (res?.success) {
|
||||
message.success("删除成功");
|
||||
getData();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleAlarmSwitch = async (record, checked) => {
|
||||
await props["sensorDeviceStatus"]({ id: record.id, alarmSwitch: checked ? 1 : 0 });
|
||||
message.success("报警开关更新成功");
|
||||
getData();
|
||||
const res = await props["sensorDeviceEdit"]({ id: record.id, alarmSwitch: checked ? 1 : 0 });
|
||||
if (res?.success) {
|
||||
message.success("报警开关更新成功");
|
||||
getData();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -74,10 +96,10 @@ function SensorDeviceList(props) {
|
|||
options={[
|
||||
{ name: "sensorName", label: "传感器名称" },
|
||||
{
|
||||
name: "sensorTypeId",
|
||||
label: "传感器类型",
|
||||
name: "thresholdFlag",
|
||||
label: "是否阈值设定",
|
||||
render: FORM_ITEM_RENDER_ENUM.SELECT,
|
||||
items: sensorTypeSelectOptions,
|
||||
items: YES_NO_OPTIONS,
|
||||
},
|
||||
{
|
||||
name: "sensorStatus",
|
||||
|
|
@ -86,10 +108,10 @@ function SensorDeviceList(props) {
|
|||
items: SENSOR_STATUS_OPTIONS,
|
||||
},
|
||||
{
|
||||
name: "thresholdFlag",
|
||||
label: "是否阈值设定",
|
||||
name: "sensorTypeId",
|
||||
label: "传感器类型",
|
||||
render: FORM_ITEM_RENDER_ENUM.SELECT,
|
||||
items: YES_NO_OPTIONS,
|
||||
items: sensorTypeSelectOptions,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
|
@ -97,18 +119,18 @@ function SensorDeviceList(props) {
|
|||
rowKey="id"
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
{props.permission(editPermission) && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<AddIcon />}
|
||||
onClick={() => {
|
||||
setCurrentId("");
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
)}
|
||||
{/* {props.permission("cgqsbgl-add") && ( */}
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<AddIcon />}
|
||||
onClick={() => {
|
||||
setCurrentId("");
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
|
|
@ -118,17 +140,17 @@ function SensorDeviceList(props) {
|
|||
{
|
||||
title: "传感器属性",
|
||||
dataIndex: "sensorAttr",
|
||||
render: value => getLabelName({ status: value, list: SENSOR_ATTR_OPTIONS }) || value || "-",
|
||||
render: (_, record) => getLabelName({ status: record.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || "-",
|
||||
},
|
||||
{
|
||||
title: "传感器状态",
|
||||
dataIndex: "sensorStatus",
|
||||
render: value => getLabelName({ status: value, list: SENSOR_STATUS_OPTIONS }) || value || "-",
|
||||
render: (_, record) => getLabelName({ status: record.sensorStatus, list: SENSOR_STATUS_OPTIONS }) || "-",
|
||||
},
|
||||
{
|
||||
title: "是否定位",
|
||||
dataIndex: "positioningFlag",
|
||||
render: value => getLabelName({ status: value, list: YES_NO_OPTIONS }) || value || "-",
|
||||
render: (_, record) => record.latitude ? "是" : "否",
|
||||
},
|
||||
{
|
||||
title: "报警开关",
|
||||
|
|
@ -138,75 +160,87 @@ function SensorDeviceList(props) {
|
|||
checked={record.alarmSwitch === 1}
|
||||
checkedChildren="开"
|
||||
unCheckedChildren="关"
|
||||
disabled={!props.permission(editPermission)}
|
||||
// disabled={!props.permission(editPermission)}
|
||||
onChange={checked => handleAlarmSwitch(record, checked)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "是否阈值设定",
|
||||
title: "是否通过系统设定报警",
|
||||
dataIndex: "thresholdFlag",
|
||||
render: value => getLabelName({ status: value, list: YES_NO_OPTIONS }) || value || "-",
|
||||
render: (_, record) => getLabelName({ status: record.thresholdFlag, list: YES_NO_OPTIONS }) || "-",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 320,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentRecord(record);
|
||||
setViewOpen(true);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentRecord(record);
|
||||
setPositionOpen(true);
|
||||
}}
|
||||
>
|
||||
定位
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentRecord(record);
|
||||
setRealtimeOpen(true);
|
||||
}}
|
||||
>
|
||||
实时数据
|
||||
</Button>
|
||||
{props.permission(editPermission) && record.sensorAttr === "NUMBER" && record.thresholdFlag === 1 && (
|
||||
{
|
||||
// props.permission("cgqsbgl-info") &&
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentId(record.id);
|
||||
setThresholdOpen(true);
|
||||
setCurrentRecord(record);
|
||||
setViewOpen(true);
|
||||
}}
|
||||
>
|
||||
阈值设定
|
||||
查看
|
||||
</Button>
|
||||
)}
|
||||
{props.permission(editPermission) && (
|
||||
}
|
||||
{/* {props.permission("cgqsbgl-edit") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentId(record.id);
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
{/* )} */}
|
||||
|
||||
{/* {props.permission("cgqsbgl-del") && ( */}
|
||||
<Button danger type="link" onClick={() => handleDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
{/* )} */}
|
||||
{
|
||||
// props.permission("cgqsbgl-locate") &&
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleOpen(record)}
|
||||
>
|
||||
定位
|
||||
</Button>
|
||||
}
|
||||
{
|
||||
// props.permission("cgqsbgl-sssj") &&
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentId(record.id);
|
||||
setModalOpen(true);
|
||||
setCurrentRecord(record);
|
||||
setRealtimeOpen(true);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
实时数据
|
||||
</Button>
|
||||
)}
|
||||
{props.permission(editPermission) && (
|
||||
<Button danger type="link" onClick={() => handleDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
)}
|
||||
}
|
||||
{/* {props.permission("cgqsbgl-yzsd") && record.sensorAttr === "NUMBER" && record.thresholdFlag === 1 && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentId(record.id);
|
||||
setCurrentRecord(record);
|
||||
setThresholdOpen(true);
|
||||
}}
|
||||
>
|
||||
阈值设定
|
||||
</Button>
|
||||
{/* )} */}
|
||||
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
|
|
@ -233,13 +267,15 @@ function SensorDeviceList(props) {
|
|||
<ThresholdModal
|
||||
open={thresholdOpen}
|
||||
currentId={currentId}
|
||||
record={currentRecord}
|
||||
loading={props.sensorDeviceLoading}
|
||||
getData={getData}
|
||||
sensorDeviceInfo={props.sensorDeviceInfo}
|
||||
sensorDeviceThreshold={props.sensorDeviceThreshold}
|
||||
sensorDeviceEdit={props.sensorDeviceEdit}
|
||||
onCancel={() => {
|
||||
setThresholdOpen(false);
|
||||
setCurrentId("");
|
||||
setCurrentRecord({});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -267,12 +303,27 @@ function SensorDeviceList(props) {
|
|||
<RealtimeModal
|
||||
open={realtimeOpen}
|
||||
record={currentRecord}
|
||||
sensorDeviceList={props["sensorDevicelistBySensorDevice"]}
|
||||
onCancel={() => {
|
||||
setRealtimeOpen(false);
|
||||
setCurrentRecord({});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{
|
||||
visible
|
||||
&& (
|
||||
<MapSelector
|
||||
|
||||
visible={visible}
|
||||
latitude={selectedLat}
|
||||
longitude={selectedLng}
|
||||
onClose={() => setVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Button, Descriptions, Modal } from "antd";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { ENABLE_STATUS_OPTIONS, SENSOR_ATTR_OPTIONS, SENSOR_STATUS_OPTIONS, YES_NO_OPTIONS } from "~/enumerate/constant";
|
||||
import { SENSOR_ATTR_OPTIONS, SENSOR_STATUS_OPTIONS, YES_NO_OPTIONS } from "~/enumerate/constant";
|
||||
|
||||
function ViewModal(props) {
|
||||
const record = props.record || {};
|
||||
|
|
@ -13,6 +13,7 @@ function ViewModal(props) {
|
|||
cancelText="关闭"
|
||||
width={800}
|
||||
onCancel={props.onCancel}
|
||||
maskClosable={false}
|
||||
footer={(
|
||||
<div>
|
||||
<Button onClick={props.onCancel}>关闭</Button>
|
||||
|
|
@ -37,29 +38,14 @@ function ViewModal(props) {
|
|||
children: getLabelName({ status: record.sensorStatus, list: SENSOR_STATUS_OPTIONS }) || record.sensorStatus || "-",
|
||||
span: 2,
|
||||
},
|
||||
{
|
||||
label: "是否定位",
|
||||
children: getLabelName({ status: record.positioningFlag, list: YES_NO_OPTIONS }) || record.positioningFlag || "-",
|
||||
span: 2,
|
||||
},
|
||||
{
|
||||
label: "报警开关",
|
||||
children: getLabelName({ status: record.alarmSwitch, list: ENABLE_STATUS_OPTIONS }) || record.alarmSwitch || "-",
|
||||
span: 2,
|
||||
},
|
||||
{ label: "安装位置", children: record.installPosition || "-", span: 2 },
|
||||
{ label: "出厂日期", children: record.factoryDate || "-", span: 2 },
|
||||
{
|
||||
label: "是否阈值设定",
|
||||
children: getLabelName({ status: record.thresholdFlag, list: YES_NO_OPTIONS }) || record.thresholdFlag || "-",
|
||||
span: 2,
|
||||
},
|
||||
{ label: "安装位置", children: record.installPosition || "-", span: 2 },
|
||||
{ label: "经度", children: record.longitude || "-", span: 2 },
|
||||
{ label: "纬度", children: record.latitude || "-", span: 2 },
|
||||
{ label: "单位", children: record.unitName || "-", span: 2 },
|
||||
{ label: "量程", children: `${record.rangeMin ?? "-"} ~ ${record.rangeMax ?? "-"}`, span: 2 },
|
||||
{ label: "出厂日期", children: record.factoryDate || "-", span: 2 },
|
||||
{ label: "企业侧源编码", children: record.enterpriseSourceCode || "-", span: 2 },
|
||||
{ label: "备注", children: record.remarks || "-", span: 2 },
|
||||
|
||||
]}
|
||||
/>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ function PositionModal(props) {
|
|||
cancelText="关闭"
|
||||
width={720}
|
||||
onCancel={props.onCancel}
|
||||
maskClosable={false}
|
||||
footer={(
|
||||
<div>
|
||||
<Button onClick={props.onCancel}>关闭</Button>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,117 @@
|
|||
import { Descriptions, Modal } from "antd";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { ENABLE_STATUS_OPTIONS, SENSOR_STATUS_OPTIONS, YES_NO_OPTIONS } from "~/enumerate/constant";
|
||||
import {
|
||||
ReloadOutlined,
|
||||
SearchOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Button, DatePicker, Form, Modal, Space } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
|
||||
const COLLECT_INTERVAL_SECONDS = 10;
|
||||
const COLLECT_DURATION_SECONDS = 60 * 60;
|
||||
|
||||
function getMockCollectData(record) {
|
||||
const now = dayjs();
|
||||
const rangeMin = Number(record.rangeMin);
|
||||
const rangeMax = Number(record.rangeMax);
|
||||
const hasRange = Number.isFinite(rangeMin) && Number.isFinite(rangeMax) && rangeMax > rangeMin;
|
||||
const base = hasRange ? (rangeMin + rangeMax) / 2 : 50;
|
||||
const amplitude = hasRange ? (rangeMax - rangeMin) * 0.18 : 8;
|
||||
const count = COLLECT_DURATION_SECONDS / COLLECT_INTERVAL_SECONDS;
|
||||
|
||||
return Array.from({ length: count + 1 }, (_, index) => {
|
||||
const time = now.subtract(COLLECT_DURATION_SECONDS - index * COLLECT_INTERVAL_SECONDS, "second");
|
||||
const value = record.sensorAttr === "SWITCH"
|
||||
? Math.round(Math.random())
|
||||
: base
|
||||
+ Math.sin(index / 10) * amplitude
|
||||
+ (Math.random() - 0.5) * amplitude * 0.5;
|
||||
|
||||
return {
|
||||
time: time.format("HH:mm:ss"),
|
||||
value: Number(value.toFixed(2)),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function RealtimeModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const { tableProps, getData } = useTable(props.sensorDeviceList, {
|
||||
form,
|
||||
usePermission: false,
|
||||
transform: formData => ({
|
||||
alarmTimeStart: formData.createTime?.[0]?.format("YYYY-MM-DD"),
|
||||
alarmTimeEnd: formData.createTime?.[1]?.format("YYYY-MM-DD"),
|
||||
sensorDeviceId: props.record.sensorDeviceId,
|
||||
}),
|
||||
});
|
||||
const record = props.record || {};
|
||||
const chartRef = useRef(null);
|
||||
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
getData();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open || !chartRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chart = echarts.init(chartRef.current);
|
||||
const data = getMockCollectData(record);
|
||||
console.log(data);
|
||||
chart.setOption({
|
||||
grid: {
|
||||
top: 48,
|
||||
right: 24,
|
||||
bottom: 48,
|
||||
left: 56,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
data: data.map(item => item.time),
|
||||
axisLabel: {
|
||||
hideOverlap: true,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
// name: `采集值${unit}`,
|
||||
scale: true,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "采集值",
|
||||
type: "line",
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
data: data.map(item => item.value),
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
},
|
||||
areaStyle: {
|
||||
opacity: 0.08,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const handleResize = () => chart.resize();
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
chart.dispose();
|
||||
};
|
||||
}, [props.open, record]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
|
@ -11,39 +119,45 @@ function RealtimeModal(props) {
|
|||
title="实时概览"
|
||||
onCancel={props.onCancel}
|
||||
footer={null}
|
||||
width={720}
|
||||
maskClosable={false}
|
||||
width={1200}
|
||||
>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={2}
|
||||
items={[
|
||||
{ label: "传感器编码", children: record.sensorCode || "-" },
|
||||
{ label: "传感器名称", children: record.sensorName || "-" },
|
||||
{ label: "传感器类型", children: record.sensorTypeName || "-" },
|
||||
{
|
||||
label: "传感器状态",
|
||||
children: getLabelName({ status: record.sensorStatus, list: SENSOR_STATUS_OPTIONS }) || record.sensorStatus || "-",
|
||||
},
|
||||
{
|
||||
label: "报警开关",
|
||||
children: getLabelName({ status: record.alarmSwitch, list: ENABLE_STATUS_OPTIONS }) || record.alarmSwitch || "-",
|
||||
},
|
||||
{
|
||||
label: "是否定位",
|
||||
children: getLabelName({ status: record.positioningFlag, list: YES_NO_OPTIONS }) || record.positioningFlag || "-",
|
||||
},
|
||||
{ label: "经度", children: record.longitude || "-" },
|
||||
{ label: "纬度", children: record.latitude || "-" },
|
||||
{ label: "当前量程", children: `${record.rangeMin ?? "-"} ~ ${record.rangeMax ?? "-"}` },
|
||||
{ label: "单位", children: record.unitName || "-" },
|
||||
{ label: "安装位置", children: record.installPosition || "-" },
|
||||
{ label: "低低报", children: record.thresholdLowLow ?? "-" },
|
||||
{ label: "低报", children: record.thresholdLow ?? "-" },
|
||||
{ label: "高报", children: record.thresholdHigh ?? "-" },
|
||||
{ label: "高高报", children: record.thresholdHighHigh ?? "-" },
|
||||
{ label: "企业侧源编码", children: record.enterpriseSourceCode || "-" },
|
||||
{ label: "备注", children: record.remarks || "-" },
|
||||
<div
|
||||
ref={chartRef}
|
||||
style={{ width: "100%", height: 320, marginBottom: 16 }}
|
||||
/>
|
||||
|
||||
<Form form={form} layout="inline" style={{ marginBottom: 16 }}>
|
||||
<Form.Item name="createTime" label="采集时间">
|
||||
<DatePicker.RangePicker format="YYYY-MM-DD" />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" icon={<SearchOutlined />} onClick={() => getData()}>
|
||||
搜索
|
||||
</Button>
|
||||
<Button icon={<ReloadOutlined />} onClick={handleReset}>
|
||||
重置
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<Table
|
||||
options={false}
|
||||
disabledResizer={true}
|
||||
columns={[
|
||||
{ title: "传感器名称", dataIndex: "sensorName" },
|
||||
{ title: "采集时间", dataIndex: "alarmTime" },
|
||||
{ title: "报警描述", dataIndex: "alarmDesc" },
|
||||
{ title: "告警值", dataIndex: "currentValue" },
|
||||
{ title: "计量单位", dataIndex: "unitName" },
|
||||
{ title: "高高报警阈值", dataIndex: "thresholdHighHigh" },
|
||||
{ title: "高报警阈值", dataIndex: "thresholdHigh" },
|
||||
{ title: "低低报警阈值", dataIndex: "thresholdLowLow" },
|
||||
{ title: "低报警阈值", dataIndex: "thresholdLow" },
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,32 +1,107 @@
|
|||
import { Alert, Form, InputNumber, Modal } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Form, Input, InputNumber, Modal, Select } from "antd";
|
||||
import { useEffect, useReducer, useRef, useState } from "react";
|
||||
import { SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
||||
|
||||
function ThresholdModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const submitLockRef = useRef(false);
|
||||
const [sensorAttr, setSensorAttr] = useState("");
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [detailLoading, dispatchDetailLoading] = useReducer((_, value) => value, false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open || !props.currentId) {
|
||||
if (!props.open) {
|
||||
return;
|
||||
}
|
||||
|
||||
let active = true;
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
form.resetFields();
|
||||
setSensorAttr("");
|
||||
|
||||
if (!props.currentId) {
|
||||
dispatchDetailLoading(false);
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}
|
||||
|
||||
dispatchDetailLoading(true);
|
||||
props.sensorDeviceInfo({ id: props.currentId }).then((res) => {
|
||||
if (res?.success) {
|
||||
form.setFieldsValue(res.data || {});
|
||||
setSensorAttr(res.data?.sensorAttr || "");
|
||||
if (!active || !res?.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = { ...(res.data || {}) };
|
||||
data.sensorTypeName = data.sensorTypeName || props.record.sensorTypeName;
|
||||
form.setFieldsValue(data);
|
||||
setSensorAttr(data.sensorAttr || "");
|
||||
}).finally(() => {
|
||||
if (active) {
|
||||
dispatchDetailLoading(false);
|
||||
}
|
||||
});
|
||||
}, [form, props.currentId, props.open, props.sensorDeviceInfo]);
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const validateHighAlarm = (_, value) => {
|
||||
const highHighAlarm = form.getFieldValue("thresholdHighHigh");
|
||||
if (value === undefined || value === null || highHighAlarm === undefined || highHighAlarm === null) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (Number(value) > Number(highHighAlarm)) {
|
||||
return Promise.reject(new Error("高报警阈值默认值不能大于高高报警阈值默认值"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const validateLowAlarm = (_, value) => {
|
||||
const lowLowAlarm = form.getFieldValue("thresholdLowLow");
|
||||
if (value === undefined || value === null || lowLowAlarm === undefined || lowLowAlarm === null) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (Number(value) < Number(lowLowAlarm)) {
|
||||
return Promise.reject(new Error("低报警阈值默认值不能小于低低报警阈值默认值"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
dispatchDetailLoading(false);
|
||||
form.resetFields();
|
||||
setSensorAttr("");
|
||||
props.onCancel();
|
||||
};
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
await props.sensorDeviceThreshold({ ...values, id: props.currentId });
|
||||
handleCancel();
|
||||
props.getData();
|
||||
if (submitLockRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
submitLockRef.current = true;
|
||||
setSubmitting(true);
|
||||
|
||||
try {
|
||||
const res = await props.sensorDeviceEdit({ ...values, id: props.currentId });
|
||||
if (res?.success) {
|
||||
handleCancel();
|
||||
props.getData();
|
||||
return;
|
||||
}
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
}
|
||||
catch (error) {
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const isNumberType = sensorAttr === "NUMBER";
|
||||
|
|
@ -35,38 +110,96 @@ function ThresholdModal(props) {
|
|||
<Modal
|
||||
destroyOnClose
|
||||
open={props.open}
|
||||
title="阈值配置"
|
||||
title="阈值设置"
|
||||
onCancel={handleCancel}
|
||||
onOk={isNumberType ? form.submit : undefined}
|
||||
confirmLoading={props.loading}
|
||||
width={560}
|
||||
confirmLoading={props.loading || submitting || detailLoading}
|
||||
loading={props.loading || detailLoading}
|
||||
maskClosable={false}
|
||||
width={800}
|
||||
footer={isNumberType ? undefined : null}
|
||||
>
|
||||
{!isNumberType && sensorAttr && (
|
||||
<Alert
|
||||
type="warning"
|
||||
message="仅数值型传感器支持阈值配置"
|
||||
description="当前传感器属性为开关量,无需配置四级阈值。"
|
||||
showIcon
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
)}
|
||||
{isNumberType && (
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item label="低低报阈值" name="thresholdLowLow">
|
||||
<InputNumber style={{ width: "100%" }} placeholder="请输入低低报阈值" />
|
||||
</Form.Item>
|
||||
<Form.Item label="低报阈值" name="thresholdLow">
|
||||
<InputNumber style={{ width: "100%" }} placeholder="请输入低报阈值" />
|
||||
</Form.Item>
|
||||
<Form.Item label="高报阈值" name="thresholdHigh">
|
||||
<InputNumber style={{ width: "100%" }} placeholder="请输入高报阈值" />
|
||||
</Form.Item>
|
||||
<Form.Item label="高高报阈值" name="thresholdHighHigh">
|
||||
<InputNumber style={{ width: "100%" }} placeholder="请输入高高报阈值" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
)}
|
||||
<Form form={form} layout="horizontal" onFinish={handleSubmit} labelCol={{ span: 6 }}>
|
||||
<Form.Item label="传感器编码" name="sensorCode">
|
||||
<Input maxLength={50} placeholder="请输入传感器编码" disabled />
|
||||
</Form.Item>
|
||||
<Form.Item label="传感器名称" name="sensorName">
|
||||
<Input maxLength={50} placeholder="请输入传感器名称" disabled />
|
||||
</Form.Item>
|
||||
<Form.Item label="传感器类型" name="sensorTypeName">
|
||||
<Input maxLength={50} placeholder="请输入传感器类型" disabled />
|
||||
</Form.Item>
|
||||
<Form.Item label="传感器属性" name="sensorAttr">
|
||||
<Select
|
||||
options={SENSOR_ATTR_OPTIONS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
disabled
|
||||
placeholder="请选择传感器属性"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item noStyle shouldUpdate={(prevValues, nextValues) => prevValues.sensorAttr !== nextValues.sensorAttr}>
|
||||
{({ getFieldValue }) => getFieldValue("sensorAttr") === "NUMBER" && (
|
||||
<>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
label="计量单位"
|
||||
name="unitName"
|
||||
rules={[{ required: true, message: "请输入计量单位" }]}
|
||||
>
|
||||
<Input maxLength={50} placeholder="请输入计量单位" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
label="量程上限默认值"
|
||||
name="rangeMax"
|
||||
rules={[{ required: true, message: "请输入量程上限默认值" }]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入量程上限默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
label="量程下限默认值"
|
||||
name="rangeMin"
|
||||
rules={[{ required: true, message: "请输入量程下限默认值" }]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入量程下限默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item preserve={false} label="高高报警阈值默认值" name="thresholdHighHigh">
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入高高报警阈值默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
dependencies={["thresholdHighHigh"]}
|
||||
label="高报警阈值默认值"
|
||||
name="thresholdHigh"
|
||||
rules={[
|
||||
{ required: true, message: "请输入高报警阈值默认值" },
|
||||
{ validator: validateHighAlarm },
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入高报警阈值默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item preserve={false} label="低低报警阈值默认值" name="thresholdLowLow">
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入低低报警阈值默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
dependencies={["thresholdLowLow"]}
|
||||
label="低报警阈值默认值"
|
||||
name="thresholdLow"
|
||||
rules={[
|
||||
{ required: true, message: "请输入低报警阈值默认值" },
|
||||
{ validator: validateLowAlarm },
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入低报警阈值默认值" />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,101 @@
|
|||
import { Form, Input, InputNumber, Modal, Radio } from "antd";
|
||||
import { useEffect } from "react";
|
||||
import { ENABLE_STATUS_OPTIONS, SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
||||
import { Form, Input, InputNumber, message, Modal, Select } from "antd";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
||||
|
||||
function SensorTypeModal(props) {
|
||||
const [form] = Form.useForm();
|
||||
const submitLockRef = useRef(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const validateHighAlarm = (_, value) => {
|
||||
const highHighAlarm = form.getFieldValue("thresholdHighHigh");
|
||||
if (value === undefined || value === null || highHighAlarm === undefined || highHighAlarm === null) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (Number(value) > Number(highHighAlarm)) {
|
||||
return Promise.reject(new Error("高报警阈值默认值不能大于高高报警阈值默认值"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const validateLowAlarm = (_, value) => {
|
||||
const lowLowAlarm = form.getFieldValue("thresholdLowLow");
|
||||
if (value === undefined || value === null || lowLowAlarm === undefined || lowLowAlarm === null) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (Number(value) < Number(lowLowAlarm)) {
|
||||
return Promise.reject(new Error("低报警阈值默认值不能小于低低报警阈值默认值"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
return;
|
||||
}
|
||||
let active = true;
|
||||
submitLockRef.current = false;
|
||||
form.resetFields();
|
||||
|
||||
if (!props.currentId) {
|
||||
form.resetFields();
|
||||
form.setFieldsValue({
|
||||
sensorAttr: "NUMBER",
|
||||
status: 1,
|
||||
sortNo: 0,
|
||||
});
|
||||
return;
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}
|
||||
props.sensorTypeInfo({ id: props.currentId }).then((res) => {
|
||||
if (res?.success) {
|
||||
form.setFieldsValue(res.data || {});
|
||||
console.log( props.currentId);
|
||||
props["sensorTypeInfo"]({ id: props.currentId }).then((res) => {
|
||||
|
||||
if (!active || !res?.success) {
|
||||
return;
|
||||
}
|
||||
form.setFieldsValue({
|
||||
sensorAttr: "NUMBER",
|
||||
...(res.data || {}),
|
||||
});
|
||||
});
|
||||
}, [form, props.currentId, props.open, props.sensorTypeInfo]);
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, [form, props.currentId, props.open]);
|
||||
|
||||
const handleCancel = () => {
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
form.resetFields();
|
||||
props.onCancel();
|
||||
};
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
if (props.currentId) {
|
||||
await props.sensorTypeEdit({ ...values, id: props.currentId });
|
||||
if (submitLockRef.current) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
await props.sensorTypeSave(values);
|
||||
submitLockRef.current = true;
|
||||
setSubmitting(true);
|
||||
let res;
|
||||
try {
|
||||
if (props.currentId) {
|
||||
res = await props.sensorTypeEdit({ ...values, id: props.currentId });
|
||||
}
|
||||
else {
|
||||
res = await props.sensorTypeSave(values);
|
||||
}
|
||||
if (res?.success) {
|
||||
message.success("操作成功!");
|
||||
handleCancel();
|
||||
props.getData();
|
||||
return;
|
||||
}
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
}
|
||||
catch (error) {
|
||||
submitLockRef.current = false;
|
||||
setSubmitting(false);
|
||||
throw error;
|
||||
}
|
||||
handleCancel();
|
||||
props.getData();
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -48,64 +105,103 @@ function SensorTypeModal(props) {
|
|||
title={props.currentId ? "编辑传感器类型" : "新增传感器类型"}
|
||||
onCancel={handleCancel}
|
||||
onOk={form.submit}
|
||||
confirmLoading={props.loading}
|
||||
confirmLoading={props.loading || submitting}
|
||||
maskClosable={false}
|
||||
width={640}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
labelCol={{ span: 6 }}
|
||||
layout="horizontal"
|
||||
onFinish={handleSubmit}
|
||||
loading={props.loading}
|
||||
initialValues={{
|
||||
sensorAttr: "NUMBER",
|
||||
status: 1,
|
||||
sortNo: 0,
|
||||
}}
|
||||
>
|
||||
{/* <Form.Item */}
|
||||
{/* label="类型编码" */}
|
||||
{/* name="typeCode" */}
|
||||
{/* rules={[{ required: true, message: "请输入类型编码" }]} */}
|
||||
{/* > */}
|
||||
{/* <Input maxLength={64} placeholder="请输入类型编码" /> */}
|
||||
{/* </Form.Item> */}
|
||||
<Form.Item
|
||||
label="类型编码"
|
||||
name="typeCode"
|
||||
rules={[{ required: true, message: "请输入类型编码" }]}
|
||||
>
|
||||
<Input maxLength={64} placeholder="请输入类型编码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="类型名称"
|
||||
label="传感器类型"
|
||||
name="typeName"
|
||||
rules={[{ required: true, message: "请输入类型名称" }]}
|
||||
rules={[{ required: true, message: "请输入传感器类型" }]}
|
||||
>
|
||||
<Input maxLength={100} placeholder="请输入类型名称" />
|
||||
<Input maxLength={50} placeholder="请输入传感器类型" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="传感器属性"
|
||||
name="sensorAttr"
|
||||
rules={[{ required: true, message: "请选择传感器属性" }]}
|
||||
>
|
||||
<Radio.Group disabled={!!props.currentId}>
|
||||
{SENSOR_ATTR_OPTIONS.map(item => (
|
||||
<Radio key={item.bianma} value={item.bianma}>
|
||||
{item.name}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
<Select
|
||||
options={SENSOR_ATTR_OPTIONS.map(item => ({
|
||||
value: item.bianma,
|
||||
label: item.name,
|
||||
}))}
|
||||
placeholder="请选择传感器属性"
|
||||
/>
|
||||
{/* <Radio.Group disabled={!!props.currentId}> */}
|
||||
{/* {SENSOR_ATTR_OPTIONS.map(item => ( */}
|
||||
{/* <Radio key={item.bianma} value={item.bianma}> */}
|
||||
{/* {item.name} */}
|
||||
{/* </Radio> */}
|
||||
{/* ))} */}
|
||||
{/* </Radio.Group> */}
|
||||
</Form.Item>
|
||||
<Form.Item label="排序" name="sortNo">
|
||||
<InputNumber min={0} precision={0} style={{ width: "100%" }} placeholder="请输入排序" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="状态"
|
||||
name="status"
|
||||
rules={[{ required: true, message: "请选择状态" }]}
|
||||
>
|
||||
<Radio.Group>
|
||||
{ENABLE_STATUS_OPTIONS.map(item => (
|
||||
<Radio key={item.bianma} value={item.bianma}>
|
||||
{item.name}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="备注" name="remarks">
|
||||
<Input.TextArea rows={4} maxLength={255} placeholder="请输入备注" />
|
||||
<Form.Item noStyle shouldUpdate={(prevValues, nextValues) => prevValues.sensorAttr !== nextValues.sensorAttr}>
|
||||
{({ getFieldValue }) => getFieldValue("sensorAttr") === "NUMBER" && (
|
||||
<>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
label="计量单位"
|
||||
name="unitName"
|
||||
rules={[{ required: true, message: "请输入计量单位" }]}
|
||||
>
|
||||
<Input maxLength={50} placeholder="请输入计量单位" />
|
||||
</Form.Item>
|
||||
<Form.Item preserve={false} label="量程上限默认值" name="rangeMax" rules={[{ required: true, message: "请输入量程上限默认值" }]}>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入量程上限默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item preserve={false} label="量程下限默认值" name="rangeMin" rules={[{ required: true, message: "请输入量程下限默认值" }]}>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入量程下限默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item preserve={false} label="高高报警阈值默认值" name="thresholdHighHigh">
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="高高报警阈值默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
dependencies={["thresholdHighHigh"]}
|
||||
label="高报警阈值默认值"
|
||||
name="thresholdHigh"
|
||||
rules={[
|
||||
{ required: true, message: "请输入高报警阈值默认值" },
|
||||
{ validator: validateHighAlarm },
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入高报警阈值默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item preserve={false} label="低低报警阈值默认值" name="thresholdLowLow">
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入低低报警阈值默认值" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
preserve={false}
|
||||
dependencies={["thresholdLowLow"]}
|
||||
label="低报警阈值默认值"
|
||||
name="thresholdLow"
|
||||
rules={[
|
||||
{ required: true, message: "请输入低报警阈值默认值" },
|
||||
{ validator: validateLowAlarm },
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: "100%" }} placeholder="请输入低报警阈值默认值" />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -18,16 +18,16 @@ function SensorTypeList(props) {
|
|||
const [currentId, setCurrentId] = useState("");
|
||||
const { tableProps, getData } = useTable(props["sensorTypeList"], { form });
|
||||
|
||||
const pageType = props.type || "fgs";
|
||||
const editPermission = `${pageType}-iotalarm-sensor-type-edit`;
|
||||
|
||||
const handleDelete = (record) => {
|
||||
Modal.confirm({
|
||||
title: "确定删除这条传感器类型吗?",
|
||||
maskClosable: false,
|
||||
onOk: async () => {
|
||||
await props["sensorTypeRemove"]({ id: record.id });
|
||||
message.success("删除成功");
|
||||
getData();
|
||||
const res = await props["sensorTypeRemove"]({ id: record.id });
|
||||
if (res?.success) {
|
||||
message.success("删除成功");
|
||||
getData();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -45,18 +45,18 @@ function SensorTypeList(props) {
|
|||
rowKey="id"
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
{props.permission(editPermission) && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<AddIcon />}
|
||||
onClick={() => {
|
||||
setCurrentId("");
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
)}
|
||||
{/* {props.permission("cgqbj-add") && ( */}
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<AddIcon />}
|
||||
onClick={() => {
|
||||
setCurrentId("");
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
|
|
@ -64,13 +64,16 @@ function SensorTypeList(props) {
|
|||
{
|
||||
title: "传感器属性",
|
||||
dataIndex: "sensorAttr",
|
||||
render: value => getLabelName({ status: value, list: SENSOR_ATTR_OPTIONS }) || value || "-",
|
||||
render: (_, record) => getLabelName({ status: record.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || "-",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 220,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
{/* { */}
|
||||
{/* props.permission("cgqbj-info") && ( */}
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
|
|
@ -80,22 +83,24 @@ function SensorTypeList(props) {
|
|||
>
|
||||
查看
|
||||
</Button>
|
||||
{props.permission(editPermission) && (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentId(record.id);
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
)}
|
||||
{props.permission(editPermission) && (
|
||||
<Button danger type="link" onClick={() => handleDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
)}
|
||||
)
|
||||
{/* } */}
|
||||
{/* {props.permission("cgqbj-edit") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
setCurrentId(record.id);
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
{/* )} */}
|
||||
{/* {props.permission("cgqbj-del") && ( */}
|
||||
<Button danger type="link" onClick={() => handleDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,6 +4,26 @@ import { SENSOR_ATTR_OPTIONS } from "~/enumerate/constant";
|
|||
|
||||
function ViewModal(props) {
|
||||
const record = props.record || {};
|
||||
const isNumberAttr = record.sensorAttr === "NUMBER";
|
||||
const items = [
|
||||
{ label: "传感器类型", children: record.typeName || "-" },
|
||||
{
|
||||
label: "传感器属性",
|
||||
children: getLabelName({ status: record.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || record.sensorAttr || "-",
|
||||
},
|
||||
];
|
||||
|
||||
if (isNumberAttr) {
|
||||
items.push(
|
||||
{ label: "计量单位", children: record.unitName || "-" },
|
||||
{ label: "量程上限默认值", children: record.rangeMax || "-" },
|
||||
{ label: "量程下限默认值", children: record.rangeMin || "-" },
|
||||
{ label: "高高报警阈值默认值", children: record.thresholdHighHigh || "-" },
|
||||
{ label: "高报警阈值默认值", children: record.thresholdHigh || "-" },
|
||||
{ label: "低低报警阈值默认值", children: record.thresholdLowLow || "-" },
|
||||
{ label: "低报警阈值默认值", children: record.thresholdLow || "-" },
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
|
@ -13,6 +33,7 @@ function ViewModal(props) {
|
|||
cancelText="关闭"
|
||||
width={640}
|
||||
onCancel={props.onCancel}
|
||||
maskClosable={false}
|
||||
footer={(
|
||||
<div>
|
||||
<Button onClick={props.onCancel}>关闭</Button>
|
||||
|
|
@ -22,14 +43,8 @@ function ViewModal(props) {
|
|||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: 160 }}
|
||||
items={[
|
||||
{ label: "传感器类型", children: record.typeName || "-" },
|
||||
{
|
||||
label: "传感器属性",
|
||||
children: getLabelName({ status: record.sensorAttr, list: SENSOR_ATTR_OPTIONS }) || record.sensorAttr || "-",
|
||||
},
|
||||
]}
|
||||
labelStyle={{ width: 200 }}
|
||||
items={items}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,38 +6,27 @@ import Table from "zy-react-library/components/Table";
|
|||
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import AlarmRecordView from "~/components/AlarmRecord/View";
|
||||
import { renderAlarmCurrentValue } from "~/utils/alarm";
|
||||
|
||||
function ThresholdList(props) {
|
||||
const [form] = Form.useForm();
|
||||
const [detailOpen, setDetailOpen] = useState(false);
|
||||
const [currentId, setCurrentId] = useState("");
|
||||
const { tableProps, getData } = useTable(props["thresholdAlarmInfoList"], {
|
||||
const { tableProps, getData } = useTable(props.thresholdAlarmInfoList, {
|
||||
form,
|
||||
defaultParams: { alarmSource: "THRESHOLD" },
|
||||
transform: formData => ({
|
||||
...formData,
|
||||
alarmTimeStart: formData.alarmTime?.[0],
|
||||
alarmTimeEnd: formData.alarmTime?.[1],
|
||||
alarmSource: "THRESHOLD",
|
||||
}),
|
||||
});
|
||||
|
||||
const handleSearch = (values) => {
|
||||
getData({
|
||||
sensorName: values.sensorName,
|
||||
alarmTimeStart: values.alarmTime?.[0]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
alarmTimeEnd: values.alarmTime?.[1]?.format?.("YYYY-MM-DD HH:mm:ss"),
|
||||
});
|
||||
};
|
||||
|
||||
const renderCurrentValue = (_, record) => {
|
||||
if (record.currentValue == null || record.currentValue === "") {
|
||||
return "-";
|
||||
}
|
||||
const suffix = record.compareFlag === "UP" ? " 上升" : record.compareFlag === "DOWN" ? " 下降" : "";
|
||||
const unit = record.unitName ? ` ${record.unitName}` : "";
|
||||
return `${record.currentValue}${unit}${suffix}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
form={form}
|
||||
onFinish={handleSearch}
|
||||
onFinish={getData}
|
||||
options={[
|
||||
{ name: "sensorName", label: "传感器名称" },
|
||||
{
|
||||
|
|
@ -54,10 +43,11 @@ function ThresholdList(props) {
|
|||
{ title: "传感器名称", dataIndex: "sensorName" },
|
||||
{ title: "报警时间", dataIndex: "alarmTime" },
|
||||
{ title: "报警描述", dataIndex: "alarmDesc", ellipsis: true },
|
||||
{ title: "告警值", render: renderCurrentValue },
|
||||
{ title: "告警值", render: (_, record) => renderAlarmCurrentValue(record) },
|
||||
{
|
||||
title: "操作",
|
||||
width: 100,
|
||||
hidden: !props.permission("yzbjxx-info"),
|
||||
render: (_, record) => (
|
||||
<a
|
||||
onClick={() => {
|
||||
|
|
@ -76,7 +66,7 @@ function ThresholdList(props) {
|
|||
<AlarmRecordView
|
||||
open={detailOpen}
|
||||
currentId={currentId}
|
||||
alarmRecordInfo={props.alarmRecordInfo}
|
||||
alarmRecordInfo={props.thresholdAlarmInfoInfo}
|
||||
onCancel={() => {
|
||||
setDetailOpen(false);
|
||||
setCurrentId("");
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ export const SENSOR_STATUS_OPTIONS = [
|
|||
{ bianma: "NORMAL", name: "正常" },
|
||||
{ bianma: "FAULT", name: "故障" },
|
||||
{ bianma: "OFFLINE", name: "离线" },
|
||||
{ bianma: "deactivate", name: "停用" },
|
||||
];
|
||||
|
||||
export const ALARM_STATUS_OPTIONS = [
|
||||
{ bianma: 10, name: "报警中-待研判" },
|
||||
{ bianma: 20, name: "报警中-待处置" },
|
||||
{ bianma: 30, name: "已消警" },
|
||||
{ bianma: 40, name: "误报" },
|
||||
{ bianma: 10, name: "已报警" },
|
||||
{ bianma: 20, name: "报警中" },
|
||||
{ bianma: 30, name: "已取消" },
|
||||
];
|
||||
|
||||
export const ALARM_SOURCE_OPTIONS = [
|
||||
|
|
@ -42,3 +42,7 @@ export const ALARM_TYPE_OPTIONS = [
|
|||
{ bianma: "DCS_ALARM", name: "DCS 报警" },
|
||||
{ bianma: "THRESHOLD_ALARM", name: "阈值报警" },
|
||||
];
|
||||
export const DISPOSAL_STATIS = [
|
||||
{ bianma: 1, name: "误报" },
|
||||
{ bianma: 0, name: "处置" },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { setJJBCommonAntdMessage } from "@cqsjjb/jjb-common-lib";
|
||||
import { setup } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { message } from "antd";
|
||||
import { ConfigProvider, message } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import { getFileUrlFromServer } from "zy-react-library/utils";
|
||||
import "dayjs/locale/zh-cn";
|
||||
|
|
@ -9,6 +9,12 @@ import "../blessed_by_buddha";
|
|||
require("antd/dist/reset.css");
|
||||
require("zy-react-library/css/common.less");
|
||||
|
||||
const ANT_PREFIX = process.env.app.antd?.["ant-prefix"] || "ant";
|
||||
|
||||
ConfigProvider.config({
|
||||
prefixCls: ANT_PREFIX,
|
||||
});
|
||||
|
||||
dayjs.locale("zh-cn");
|
||||
setJJBCommonAntdMessage(message);
|
||||
window.mapLongitude = "119.69457721306945";
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import React from "react";
|
|||
|
||||
import { InjectContext } from "~/enumerate/context";
|
||||
|
||||
const ANT_PREFIX = process.env.app.antd?.["ant-prefix"] || "ant";
|
||||
|
||||
export default class Container extends React.Component {
|
||||
state = window?.base?.themeConfig || {
|
||||
algorithm: "defaultAlgorithm",
|
||||
|
|
@ -38,6 +40,7 @@ export default class Container extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<ConfigProvider
|
||||
prefixCls={ANT_PREFIX}
|
||||
theme={{
|
||||
token: this.token,
|
||||
algorithm: this.algorithm,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
export function renderAlarmCurrentValue(record) {
|
||||
if (!record || record.currentValue == null || record.currentValue === "") {
|
||||
return "-";
|
||||
}
|
||||
|
||||
if (record.sensorAttr !== "NUMBER") {
|
||||
return Number(record.currentValue) === 1 ? "开" : "关";
|
||||
}
|
||||
|
||||
const currentValue = Number(record.currentValue);
|
||||
const thresholdHighHigh = Number(record.thresholdHighHigh);
|
||||
const thresholdHigh = Number(record.thresholdHigh);
|
||||
const thresholdLowLow = Number(record.thresholdLowLow);
|
||||
const thresholdLow = Number(record.thresholdLow);
|
||||
|
||||
let suffix = "";
|
||||
let color = "";
|
||||
|
||||
if (
|
||||
(Number.isFinite(thresholdHighHigh) && currentValue > thresholdHighHigh)
|
||||
|| (Number.isFinite(thresholdHigh) && currentValue > thresholdHigh)
|
||||
) {
|
||||
suffix = " ↑";
|
||||
color = "red";
|
||||
} else if (
|
||||
(Number.isFinite(thresholdLowLow) && currentValue < thresholdLowLow)
|
||||
|| (Number.isFinite(thresholdLow) && currentValue < thresholdLow)
|
||||
) {
|
||||
suffix = " ↓";
|
||||
color = "red";
|
||||
}
|
||||
|
||||
const unit = record.unitName ? ` ${record.unitName}` : "";
|
||||
const content = `${record.currentValue}${unit}${suffix}`;
|
||||
return color ? <span style={{ color }}>{content}</span> : content;
|
||||
}
|
||||
Loading…
Reference in New Issue