parent
a34a7cceb1
commit
18d8e7108e
|
|
@ -9,17 +9,18 @@ module.exports = {
|
|||
// 应用后端分支名称,部署上线需要
|
||||
javaGitBranch: "<branch-name>",
|
||||
// 接口服务地址
|
||||
API_HOST: "开发环境后端地址",
|
||||
API_HOST: "http://192.168.20.100:30140",
|
||||
// API_HOST: "http://127.0.0.1",
|
||||
},
|
||||
production: {
|
||||
// 应用后端分支名称,部署上线需要
|
||||
javaGitBranch: "<branch-name>",
|
||||
// 接口服务地址
|
||||
API_HOST: "",
|
||||
API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||
},
|
||||
},
|
||||
// 应用唯一标识符
|
||||
appIdentifier: "唯一应用标识,与后端gateway相同",
|
||||
appIdentifier: "fireResource",
|
||||
// 应用上下文注入全局变量
|
||||
contextInject: {
|
||||
// 应用Key
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"serve": "node node_modules/@cqsjjb/scripts/webpack.dev.server.js",
|
||||
"build": "node node_modules/@cqsjjb/scripts/webpack.build.js",
|
||||
"serve": "node node_modules/@cqsjjb/scripts/rspack.dev.server.js",
|
||||
"build": "node node_modules/@cqsjjb/scripts/rspack.build.js",
|
||||
"push": "jjb-cmd push java production",
|
||||
"clean-cache": "rimraf node_modules/.cache/webpack",
|
||||
"serve:development": "cross-env NODE_ENV=development npm run serve",
|
||||
|
|
@ -30,12 +30,12 @@
|
|||
"lodash-es": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"zy-react-library": "latest"
|
||||
"zy-react-library": "^1.1.41"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^5.4.1",
|
||||
"@babel/plugin-proposal-decorators": "^7.19.3",
|
||||
"@cqsjjb/scripts": "latest",
|
||||
"@cqsjjb/scripts": "2.0.0-rspack.1",
|
||||
"@eslint-react/eslint-plugin": "^2.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^9.37.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const controlRoomList = declareRequest(
|
||||
"controlRoomLoading",
|
||||
`Post >@/fireResource/controlRoom/list`,
|
||||
);
|
||||
|
||||
export const controlRoomDetail = declareRequest(
|
||||
"controlRoomLoading",
|
||||
`Get >/fireResource/controlRoom/{id}`,
|
||||
);
|
||||
|
||||
export const controlRoomAdd = declareRequest(
|
||||
"controlRoomLoading",
|
||||
`Post >@/fireResource/controlRoom/save`,
|
||||
);
|
||||
|
||||
export const controlRoomUpdate = declareRequest(
|
||||
"controlRoomLoading",
|
||||
`Put >@/fireResource/controlRoom/edit`,
|
||||
);
|
||||
|
||||
export const controlRoomDelete = declareRequest(
|
||||
"controlRoomLoading",
|
||||
`Delete >@/fireResource/controlRoom/{id}`,
|
||||
);
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const fireResourceStatsList = declareRequest(
|
||||
"fireResourceStatsLoading",
|
||||
`Post >@/fireResource/resource/list`,
|
||||
);
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const pumpRoomList = declareRequest(
|
||||
"pumpRoomLoading",
|
||||
`Post >@/fireResource/pumpRoom/list`,
|
||||
);
|
||||
|
||||
export const pumpRoomDetail = declareRequest(
|
||||
"pumpRoomLoading",
|
||||
`Get >/fireResource/pumpRoom/{id}`,
|
||||
);
|
||||
|
||||
export const pumpRoomAdd = declareRequest(
|
||||
"pumpRoomLoading",
|
||||
`Post >@/fireResource/pumpRoom/save`,
|
||||
);
|
||||
|
||||
export const pumpRoomUpdate = declareRequest(
|
||||
"pumpRoomLoading",
|
||||
`Put >@/fireResource/pumpRoom/edit`,
|
||||
);
|
||||
|
||||
export const pumpRoomDelete = declareRequest(
|
||||
"pumpRoomLoading",
|
||||
`Delete >@/fireResource/pumpRoom/{id}`,
|
||||
);
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const rescueTeamList = declareRequest(
|
||||
"rescueTeamLoading",
|
||||
`Post > @/fireResource/rescueTeam/list`,
|
||||
);
|
||||
|
||||
export const rescueTeamDetail = declareRequest(
|
||||
"rescueTeamLoading",
|
||||
`Get > /fireResource/rescueTeam/{id}`,
|
||||
);
|
||||
|
||||
export const rescueTeamAdd = declareRequest(
|
||||
"rescueTeamLoading",
|
||||
`Post >@/fireResource/rescueTeam/save`,
|
||||
);
|
||||
|
||||
export const rescueTeamUpdate = declareRequest(
|
||||
"rescueTeamLoading",
|
||||
`Put >@/fireResource/rescueTeam/edit`,
|
||||
);
|
||||
|
||||
export const rescueTeamDelete = declareRequest(
|
||||
"rescueTeamLoading",
|
||||
`Delete >@/fireResource/rescueTeam/{id}`,
|
||||
);
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const waterSourceList = declareRequest(
|
||||
"waterSourceLoading",
|
||||
`Post >@/fireResource/waterSource/list`,
|
||||
);
|
||||
|
||||
export const waterSourceDetail = declareRequest(
|
||||
"waterSourceLoading",
|
||||
`Get >/fireResource/waterSource/{id}`,
|
||||
);
|
||||
|
||||
export const waterSourceAdd = declareRequest(
|
||||
"waterSourceLoading",
|
||||
`Post >@/fireResource/waterSource/save`,
|
||||
);
|
||||
|
||||
export const waterSourceUpdate = declareRequest(
|
||||
"waterSourceLoading",
|
||||
`Put >@/fireResource/waterSource/edit`,
|
||||
);
|
||||
|
||||
export const waterSourceDelete = declareRequest(
|
||||
"waterSourceLoading",
|
||||
`Delete >@/fireResource/waterSource/{id}`,
|
||||
);
|
||||
|
|
@ -5,3 +5,8 @@
|
|||
import { defineNamespace } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
||||
export const NS_GLOBAL = defineNamespace("global");
|
||||
export const NS_CONTROL_ROOM = defineNamespace("controlRoom");
|
||||
export const NS_RESCUE_TEAM = defineNamespace("rescueTeam");
|
||||
export const NS_PUMP_ROOM = defineNamespace("pumpRoom");
|
||||
export const NS_WATER_SOURCE = defineNamespace("waterSource");
|
||||
export const NS_FIRE_RESOURCE_STATS = defineNamespace("fireResourceStats");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,534 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Col, Form, Input, InputNumber, message, Row, Space, Table } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import Upload from "zy-react-library/components/Upload";
|
||||
import { UPLOAD_FILE_TYPE_ENUM } from "zy-react-library/enum/uploadFile/gwj";
|
||||
import useDeleteFile from "zy-react-library/hooks/useDeleteFile";
|
||||
import useGetFile from "zy-react-library/hooks/useGetFile";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import useUploadFile from "zy-react-library/hooks/useUploadFile";
|
||||
import { NS_CONTROL_ROOM } from "~/enumerate/namespace";
|
||||
|
||||
function Add(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
// 设备信息列表
|
||||
const [deviceList, setDeviceList] = useState([]);
|
||||
// 人员信息列表
|
||||
const [personnelList, setPersonnelList] = useState([]);
|
||||
|
||||
// 文件上传相关hooks
|
||||
const { loading: uploadFileLoading, uploadFile } = useUploadFile();
|
||||
const { loading: deleteFileLoading, deleteFile } = useDeleteFile();
|
||||
const { loading: getFileLoading, getFile } = useGetFile();
|
||||
|
||||
// 保存要删除的文件列表
|
||||
const [deleteFiles, setDeleteFiles] = useState([]);
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["controlRoomDetail"]({ id: query.id });
|
||||
|
||||
// ⭐ 如果有业务ID,查询图片文件
|
||||
if (data.roomId) {
|
||||
const files = await getFile({
|
||||
eqType: UPLOAD_FILE_TYPE_ENUM[302], // 消防点检检查合格图片
|
||||
eqForeignKey: data.roomId,
|
||||
});
|
||||
data.roomImages = files;
|
||||
}
|
||||
|
||||
form.setFieldsValue(data);
|
||||
|
||||
// 设置设备列表
|
||||
if (data.devices && data.devices.length > 0) {
|
||||
setDeviceList(data.devices.map((item, index) => ({ ...item, key: item.id || index })));
|
||||
}
|
||||
|
||||
// 设置人员列表
|
||||
if (data.persons && data.persons.length > 0) {
|
||||
setPersonnelList(data.persons.map((item, index) => ({ ...item, key: item.id || index })));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error("加载详情失败:", error);
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
const onFinish = async (values) => {
|
||||
// 验证设备列表
|
||||
if (deviceList.length === 0) {
|
||||
message.warning("请至少添加一条设备信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证人员列表
|
||||
if (personnelList.length === 0) {
|
||||
message.warning("请至少添加一条人员信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证设备列表是否填写完整
|
||||
const invalidDevice = deviceList.find(
|
||||
item => !item.deviceName || !item.deviceModel || !item.deviceQty || !item.deviceLocation,
|
||||
);
|
||||
if (invalidDevice) {
|
||||
message.warning("请完善设备信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证人员列表是否填写完整
|
||||
const invalidPersonnel = personnelList.find(
|
||||
item => !item.personName || !item.personPhone,
|
||||
);
|
||||
if (invalidPersonnel) {
|
||||
message.warning("请完善人员信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证图片是否上传
|
||||
if (!values.roomImages || values.roomImages.length === 0) {
|
||||
message.warning("请上传消防控制室图片");
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true);
|
||||
try {
|
||||
// ⭐ 先删除标记删除的文件
|
||||
if (deleteFiles.length > 0) {
|
||||
await deleteFile({ single: false, files: deleteFiles });
|
||||
}
|
||||
|
||||
// ⭐ 上传图片文件,获取业务ID(room_id)
|
||||
const { id: roomId } = await uploadFile({
|
||||
single: false,
|
||||
files: values.roomImages,
|
||||
params: {
|
||||
type: UPLOAD_FILE_TYPE_ENUM[302], // ⭐ 消防点检检查合格图片
|
||||
foreignKey: values.roomId, // 编辑时传入已有的 roomId
|
||||
},
|
||||
});
|
||||
|
||||
const apiMethod = query.id ? props["controlRoomUpdate"] : props["controlRoomAdd"];
|
||||
|
||||
// 构建提交参数
|
||||
const params = {
|
||||
...values,
|
||||
roomId, // ⭐ 使用上传返回的业务ID
|
||||
// 设备列表:去掉前端添加的 key
|
||||
devices: deviceList.map(({ key, ...device }) => ({
|
||||
deviceName: device.deviceName,
|
||||
deviceModel: device.deviceModel,
|
||||
deviceQty: device.deviceQty,
|
||||
deviceLocation: device.deviceLocation,
|
||||
...(device.id && { id: device.id }),
|
||||
})),
|
||||
// 人员列表:去掉前端添加的 key
|
||||
persons: personnelList.map(({ key, ...personnel }) => ({
|
||||
personName: personnel.personName,
|
||||
personPhone: personnel.personPhone,
|
||||
dutyDesc: personnel.dutyDesc || "",
|
||||
...(personnel.id && { id: personnel.id }),
|
||||
})),
|
||||
};
|
||||
|
||||
if (query.id) {
|
||||
params.id = query.id;
|
||||
}
|
||||
|
||||
await apiMethod(params);
|
||||
message.success(query.id ? "修改成功" : "新增成功");
|
||||
props.history.goBack();
|
||||
}
|
||||
catch (error) {
|
||||
console.error("提交失败:", error);
|
||||
message.error(query.id ? "修改失败" : "新增失败");
|
||||
}
|
||||
finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 设备列表相关操作
|
||||
const addDevice = () => {
|
||||
const newDevice = {
|
||||
key: Date.now(),
|
||||
deviceName: "",
|
||||
deviceModel: "",
|
||||
deviceQty: null,
|
||||
deviceLocation: "",
|
||||
};
|
||||
setDeviceList([...deviceList, newDevice]);
|
||||
};
|
||||
|
||||
const removeDevice = (key) => {
|
||||
setDeviceList(deviceList.filter(item => item.key !== key));
|
||||
};
|
||||
|
||||
const updateDevice = (key, field, value) => {
|
||||
setDeviceList(
|
||||
deviceList.map(item => (item.key === key ? { ...item, [field]: value } : item)),
|
||||
);
|
||||
};
|
||||
|
||||
// 人员列表相关操作
|
||||
const addPersonnel = () => {
|
||||
const newPersonnel = {
|
||||
key: Date.now(),
|
||||
personName: "",
|
||||
personPhone: "",
|
||||
dutyDesc: "",
|
||||
};
|
||||
setPersonnelList([...personnelList, newPersonnel]);
|
||||
};
|
||||
|
||||
const removePersonnel = (key) => {
|
||||
setPersonnelList(personnelList.filter(item => item.key !== key));
|
||||
};
|
||||
|
||||
const updatePersonnel = (key, field, value) => {
|
||||
setPersonnelList(
|
||||
personnelList.map(item => (item.key === key ? { ...item, [field]: value } : item)),
|
||||
);
|
||||
};
|
||||
|
||||
// 设备表格列定义
|
||||
const deviceColumns = [
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备名称
|
||||
</>),
|
||||
dataIndex: "deviceName",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备名称"
|
||||
onChange={e => updateDevice(record.key, "deviceName", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备型号
|
||||
</>),
|
||||
dataIndex: "deviceModel",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备型号"
|
||||
onChange={e => updateDevice(record.key, "deviceModel", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备数量
|
||||
</>),
|
||||
dataIndex: "deviceQty",
|
||||
render: (text, record) => (
|
||||
<InputNumber
|
||||
value={text}
|
||||
placeholder="请输入设备数量"
|
||||
min={1}
|
||||
style={{ width: "100%" }}
|
||||
onChange={value => updateDevice(record.key, "deviceQty", value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备位置
|
||||
</>),
|
||||
dataIndex: "deviceLocation",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备位置"
|
||||
onChange={e => updateDevice(record.key, "deviceLocation", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => removeDevice(record.key)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 人员表格列定义
|
||||
const personnelColumns = [
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
人员姓名
|
||||
</>),
|
||||
dataIndex: "personName",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入人员姓名"
|
||||
onChange={e => updatePersonnel(record.key, "personName", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
人员手机号
|
||||
</>),
|
||||
dataIndex: "personPhone",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入人员手机号"
|
||||
maxLength={11}
|
||||
onChange={e => updatePersonnel(record.key, "personPhone", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "人员值班情况",
|
||||
dataIndex: "dutyDesc",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入人员值班情况"
|
||||
onChange={e => updatePersonnel(record.key, "dutyDesc", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => removePersonnel(record.key)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle={query.id ? "编辑消防控制室" : "新增消防控制室"}
|
||||
loading={loading || uploadFileLoading || deleteFileLoading || getFileLoading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
onFinish={onFinish}
|
||||
style={{ maxWidth: 1200, marginTop: 24 }}
|
||||
>
|
||||
<Card title="基本信息" style={{ marginBottom: 24 }}>
|
||||
{/* 添加隐藏字段保存 roomId */}
|
||||
<Form.Item name="roomId" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="消防控制室名称"
|
||||
name="roomName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入消防控制室名称" },
|
||||
{ max: 100, message: "消防控制室名称不能超过100个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入消防控制室名称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="消防控制室状态"
|
||||
name="roomStatus"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请选择消防控制室状态" }]}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="fire_resource_contro_root_type"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="负责人"
|
||||
name="principalName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入负责人" },
|
||||
{ max: 50, message: "负责人不能超过50个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入负责人" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="负责人手机号"
|
||||
name="principalPhone"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入负责人手机号" },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入负责人手机号" maxLength={11} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="经度"
|
||||
name="lng"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入经度" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入经度"
|
||||
style={{ width: "100%" }}
|
||||
min={-180}
|
||||
max={180}
|
||||
step={0.000001}
|
||||
precision={6}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="纬度"
|
||||
name="lat"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入纬度" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入纬度"
|
||||
style={{ width: "100%" }}
|
||||
min={-90}
|
||||
max={90}
|
||||
step={0.000001}
|
||||
precision={6}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="消防控制室图片"
|
||||
name="roomImages"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
rules={[{ required: true, message: "请上传消防控制室图片" }]}
|
||||
extra="默认上传4个,目前支持jpg、jpeg、png格式,单张图片不超过5mb"
|
||||
>
|
||||
<Upload
|
||||
fileType="image"
|
||||
maxCount={4}
|
||||
maxSize={5}
|
||||
accept=".jpg,.jpeg,.png"
|
||||
onGetRemoveFile={(file) => {
|
||||
setDeleteFiles([...deleteFiles, file]);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="设备信息"
|
||||
extra={(
|
||||
<Button type="primary" onClick={addDevice}>
|
||||
新增
|
||||
</Button>
|
||||
)}
|
||||
style={{ marginBottom: 24 }}
|
||||
>
|
||||
<Table
|
||||
columns={deviceColumns}
|
||||
dataSource={deviceList}
|
||||
pagination={false}
|
||||
rowKey="key"
|
||||
locale={{ emptyText: "暂无设备信息,请点击新增按钮添加" }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="人员信息"
|
||||
extra={(
|
||||
<Button type="primary" onClick={addPersonnel}>
|
||||
新增
|
||||
</Button>
|
||||
)}
|
||||
style={{ marginBottom: 24 }}
|
||||
>
|
||||
<Table
|
||||
columns={personnelColumns}
|
||||
dataSource={personnelList}
|
||||
pagination={false}
|
||||
rowKey="key"
|
||||
locale={{ emptyText: "暂无人员信息,请点击新增按钮添加" }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Form.Item wrapperCol={{ span: 24 }} style={{ textAlign: "center" }}>
|
||||
<Space size={16}>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" htmlType="submit" loading={submitting}>
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_CONTROL_ROOM], true)(Permission(Add));
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Form, message, 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 DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useDictionary from "zy-react-library/hooks/useDictionary";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { NS_CONTROL_ROOM } from "~/enumerate/namespace";
|
||||
|
||||
function List(props) {
|
||||
const [form] = Form.useForm();
|
||||
const query = useGetUrlQuery();
|
||||
|
||||
const { tableProps, getData } = useTable(props["controlRoomList"], { form });
|
||||
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [statusDict, setStatusDict] = useState([]);
|
||||
|
||||
const { getDictionary } = useDictionary();
|
||||
|
||||
useEffect(() => {
|
||||
if (props.location?.state?.refresh) {
|
||||
getData();
|
||||
props.history.replace({ ...props.location, state: {} });
|
||||
}
|
||||
}, [props.location?.state?.refresh]);
|
||||
|
||||
useEffect(() => {
|
||||
if (query.eqCorpId) {
|
||||
form.setFieldsValue({ eqCorpId: query.eqCorpId });
|
||||
getData();
|
||||
}
|
||||
}, [query.eqCorpId]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDict = async () => {
|
||||
try {
|
||||
const dict = await getDictionary({ dictValue: "fire_resource_contro_root_type" });
|
||||
setStatusDict(Array.isArray(dict) ? dict : []);
|
||||
}
|
||||
catch (error) {
|
||||
setStatusDict([]);
|
||||
}
|
||||
};
|
||||
fetchDict();
|
||||
}, []);
|
||||
|
||||
const getStatusLabel = (record) => {
|
||||
if (record.roomStatusName)
|
||||
return record.roomStatusName;
|
||||
const match = statusDict.find(item => item.dictValue === record.roomStatus);
|
||||
return match?.dictLabel || record.roomStatus || "-";
|
||||
};
|
||||
|
||||
const onDelete = (id) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "删除后不可恢复,确认继续?",
|
||||
okText: "确认",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true, loading: deleting },
|
||||
onOk: async () => {
|
||||
if (!props["controlRoomDelete"]) {
|
||||
message.warning("未接入 controlRoomDelete effect");
|
||||
return;
|
||||
}
|
||||
setDeleting(true);
|
||||
try {
|
||||
await props["controlRoomDelete"]({ id: String(id) });
|
||||
message.success("已删除");
|
||||
getData();
|
||||
}
|
||||
finally {
|
||||
setDeleting(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{
|
||||
name: "likeRoomName",
|
||||
label: "消防控制室名称:",
|
||||
span: 4,
|
||||
formItemProps: { style: { marginRight: 16 } },
|
||||
},
|
||||
{
|
||||
name: "eqRoomStatus",
|
||||
label: "消防控制室状态:",
|
||||
render: (<DictionarySelect dictValue="fire_resource_contro_root_type" />),
|
||||
span: 4,
|
||||
formItemProps: { style: { marginLeft: 16 } },
|
||||
},
|
||||
{ name: "eqCorpId", onlyForLabel: true },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
{/* {props.permission("xfkzs-btn-add") && ( */}
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
props.history.push("./add");
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
// { title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{ title: "消防控制室名称", dataIndex: "roomName", ellipsis: true, width: 140 },
|
||||
{
|
||||
title: "消防控制室状态",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (_, record) => getStatusLabel(record),
|
||||
},
|
||||
{ title: "负责人", dataIndex: "principalName", width: 120, align: "center" },
|
||||
{ title: "负责人手机号", dataIndex: "principalPhone", width: 140, align: "center" },
|
||||
{ title: "设备数", dataIndex: "deviceCount", width: 100, align: "center" },
|
||||
{ title: "人员数", dataIndex: "personCount", width: 100, align: "center" },
|
||||
{
|
||||
title: "操作",
|
||||
fixed: "right",
|
||||
width: 180,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
{/* {props.permission("xfkzs-btn-view") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./view?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
{/* )} */}
|
||||
|
||||
{/* {props.permission("xfkzs-btn-edit") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./add?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
{/* )} */}
|
||||
|
||||
{/* {props.permission("xfkzs-btn-delete") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => {
|
||||
onDelete(record.id);
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_CONTROL_ROOM], true)(Permission(List));
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Descriptions, Image, message, Space, Table } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import { UPLOAD_FILE_TYPE_ENUM } from "zy-react-library/enum/uploadFile/gwj";
|
||||
import useDictionary from "zy-react-library/hooks/useDictionary";
|
||||
import useGetFile from "zy-react-library/hooks/useGetFile";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import { NS_CONTROL_ROOM } from "~/enumerate/namespace";
|
||||
|
||||
function View(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [detail, setDetail] = useState(null);
|
||||
const [statusDict, setStatusDict] = useState([]);
|
||||
const [statusLabel, setStatusLabel] = useState("-");
|
||||
|
||||
const { loading: dictLoading, getDictionary } = useDictionary();
|
||||
const { loading: getFileLoading, getFile } = useGetFile();
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["controlRoomDetail"]({ id: query.id });
|
||||
|
||||
let nextDetail = data;
|
||||
if (data.roomId) {
|
||||
const files = await getFile({
|
||||
eqType: UPLOAD_FILE_TYPE_ENUM[302],
|
||||
eqForeignKey: data.roomId,
|
||||
});
|
||||
nextDetail = { ...data, roomImages: files };
|
||||
}
|
||||
|
||||
setDetail(nextDetail);
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, [query.id]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDict = async () => {
|
||||
try {
|
||||
const dict = await getDictionary({ dictValue: "fire_resource_contro_root_type" });
|
||||
setStatusDict(Array.isArray(dict) ? dict : []);
|
||||
}
|
||||
catch (error) {
|
||||
setStatusDict([]);
|
||||
}
|
||||
};
|
||||
fetchDict();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!detail)
|
||||
return;
|
||||
const match = statusDict.find(item => item.dictValue === detail.roomStatus);
|
||||
setStatusLabel(match?.dictLabel || detail.roomStatusName || detail.roomStatus || "-");
|
||||
}, [detail, statusDict]);
|
||||
|
||||
const longitude = detail?.lng ?? detail?.longitude;
|
||||
const latitude = detail?.lat ?? detail?.latitude;
|
||||
const lngLatText = longitude != null && latitude != null
|
||||
? `${longitude}, ${latitude}`
|
||||
: (longitude ?? latitude ?? "-");
|
||||
|
||||
const deviceColumns = [
|
||||
{
|
||||
title: "序号",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, __, index) => index + 1,
|
||||
},
|
||||
{
|
||||
title: "设备名称",
|
||||
dataIndex: "deviceName",
|
||||
width: 180,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "设备型号",
|
||||
dataIndex: "deviceModel",
|
||||
width: 180,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "设备数量",
|
||||
dataIndex: "deviceQty",
|
||||
align: "center",
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: "设备位置",
|
||||
dataIndex: "deviceLocation",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
width: 240,
|
||||
},
|
||||
];
|
||||
|
||||
const personnelColumns = [
|
||||
{
|
||||
title: "序号",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, __, index) => index + 1,
|
||||
},
|
||||
{
|
||||
title: "人员姓名",
|
||||
dataIndex: "personName",
|
||||
width: 160,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "人员手机号",
|
||||
dataIndex: "personPhone",
|
||||
width: 180,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "人员值班情况",
|
||||
render: (_, record) => record.dutyDesc || "-",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
width: 240,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle="查看消防控制室"
|
||||
loading={loading || dictLoading || getFileLoading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
{detail && (
|
||||
<>
|
||||
<Card title="基本信息" style={{ marginBottom: 24, marginTop: 24 }}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={2}
|
||||
labelStyle={{ width: 180, backgroundColor: "#fafafa" }}
|
||||
contentStyle={{ backgroundColor: "#fff" }}
|
||||
items={[
|
||||
{
|
||||
label: "消防控制室名称",
|
||||
children: detail.roomName || "-",
|
||||
},
|
||||
{
|
||||
label: "消防控制室状态",
|
||||
children: statusLabel,
|
||||
},
|
||||
{
|
||||
label: "负责人",
|
||||
children: detail.principalName || "-",
|
||||
},
|
||||
{
|
||||
label: "负责人手机号",
|
||||
children: detail.principalPhone || "-",
|
||||
},
|
||||
{
|
||||
label: "经纬度",
|
||||
children: lngLatText,
|
||||
span: 2,
|
||||
},
|
||||
{
|
||||
label: "消防控制室图片",
|
||||
children: detail.roomImages && detail.roomImages.length > 0
|
||||
? (
|
||||
<Image.PreviewGroup>
|
||||
<Space>
|
||||
{detail.roomImages.map((img, index) => (
|
||||
<Image
|
||||
key={index}
|
||||
width={100}
|
||||
height={100}
|
||||
src={img}
|
||||
style={{ objectFit: "cover" }}
|
||||
/>
|
||||
))}
|
||||
</Space>
|
||||
</Image.PreviewGroup>
|
||||
)
|
||||
: (
|
||||
"无"
|
||||
),
|
||||
span: 2,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="设备信息" style={{ marginBottom: 24 }}>
|
||||
<Table
|
||||
columns={deviceColumns}
|
||||
dataSource={detail.devices || []}
|
||||
pagination={false}
|
||||
rowKey={(record, index) => index}
|
||||
locale={{ emptyText: "暂无设备信息" }}
|
||||
bordered
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="人员信息" style={{ marginBottom: 24 }}>
|
||||
<Table
|
||||
columns={personnelColumns}
|
||||
dataSource={detail.persons || []}
|
||||
pagination={false}
|
||||
rowKey={(record, index) => index}
|
||||
locale={{ emptyText: "暂无人员信息" }}
|
||||
bordered
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<div style={{ marginTop: 24, textAlign: "center" }}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
props.history.replace({
|
||||
pathname: "/Container/BranchCompany/ControlRoom/list",
|
||||
state: { refresh: true },
|
||||
});
|
||||
}}
|
||||
>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_CONTROL_ROOM], true)(Permission(View));
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Route, Switch } from "react-router-dom";
|
||||
import Add from "./Add";
|
||||
import List from "./List";
|
||||
import View from "./View";
|
||||
|
||||
function ControlRoom() {
|
||||
return (
|
||||
<div>
|
||||
<Switch>
|
||||
<Route path="/Container/BranchCompany/ControlRoom/list" component={List} />
|
||||
<Route path="/Container/BranchCompany/ControlRoom/add" component={Add} />
|
||||
<Route path="/Container/BranchCompany/ControlRoom/view" component={View} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ControlRoom;
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Form } from "antd";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import Search from "zy-react-library/components/Search";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { NS_FIRE_RESOURCE_STATS } from "~/enumerate/namespace";
|
||||
|
||||
function FireResourceStats(props) {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const { tableProps, getData } = useTable(props["fireResourceStatsList"], { form });
|
||||
|
||||
const handleViewDetail = (record, type) => {
|
||||
const routeMap = {
|
||||
rescueTeam: "/container/branchCompany/rescueTeam/list",
|
||||
controlRoom: "/container/branchCompany/controlRoom/list",
|
||||
pumpRoom: "/container/branchCompany/pumpRoom/list",
|
||||
waterSource: "/container/branchCompany/waterSource/list",
|
||||
};
|
||||
|
||||
if (routeMap[type]) {
|
||||
const corpId = record.corpId || record.companyId || "";
|
||||
props.history.push(`${routeMap[type]}?eqCorpId=${corpId}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{ name: "likeCompanyName", label: "企业名称" },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
columns={[
|
||||
{ title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{
|
||||
title: "企业名称",
|
||||
dataIndex: "companyName",
|
||||
ellipsis: true,
|
||||
render: text => text || "一公司",
|
||||
},
|
||||
{
|
||||
title: "消防救援队数",
|
||||
dataIndex: "rescueTeamCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "rescueTeam")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防控制室数",
|
||||
dataIndex: "controlRoomCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "controlRoom")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防泵房数",
|
||||
dataIndex: "pumpRoomCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "pumpRoom")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防水源数",
|
||||
dataIndex: "waterSourceCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "waterSource")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_FIRE_RESOURCE_STATS], true)(Permission(FireResourceStats));
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Col, Form, Input, InputNumber, message, Row, Space, Table } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import Upload from "zy-react-library/components/Upload";
|
||||
import { UPLOAD_FILE_TYPE_ENUM } from "zy-react-library/enum/uploadFile/gwj";
|
||||
import useDeleteFile from "zy-react-library/hooks/useDeleteFile";
|
||||
import useGetFile from "zy-react-library/hooks/useGetFile";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import useUploadFile from "zy-react-library/hooks/useUploadFile";
|
||||
import { NS_PUMP_ROOM } from "~/enumerate/namespace";
|
||||
|
||||
function Add(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
// 设备信息列表
|
||||
const [devices, setDeviceList] = useState([]);
|
||||
|
||||
const { loading: uploadFileLoading, uploadFile } = useUploadFile();
|
||||
const { loading: deleteFileLoading, deleteFile } = useDeleteFile();
|
||||
const { loading: getFileLoading, getFile } = useGetFile();
|
||||
|
||||
const [deleteFiles, setDeleteFiles] = useState([]);
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["pumpRoomDetail"]({ id: query.id });
|
||||
const roomKey = data.roomId || data.pumpRoomId || data.id;
|
||||
if (roomKey) {
|
||||
const files = await getFile({
|
||||
eqType: UPLOAD_FILE_TYPE_ENUM[302],
|
||||
eqForeignKey: roomKey,
|
||||
});
|
||||
data.roomImages = files;
|
||||
}
|
||||
form.setFieldsValue(data);
|
||||
|
||||
// 设置设备列表
|
||||
if (data.devices && data.devices.length > 0) {
|
||||
setDeviceList(data.devices.map((item, index) => ({ ...item, key: index })));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
const onFinish = async (values) => {
|
||||
// 验证设备列表
|
||||
if (devices.length === 0) {
|
||||
message.warning("请至少添加一条设备信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证设备列表是否填写完整
|
||||
const invalidDevice = devices.find(
|
||||
item => !item.deviceName || !item.deviceModel || !item.deviceQty || !item.deviceLocation,
|
||||
);
|
||||
if (invalidDevice) {
|
||||
message.warning("请完善设备信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 楠岃瘉鍥剧墖鏄惁涓婁紶
|
||||
if (!values.roomImages || values.roomImages.length === 0) {
|
||||
message.warning("璇蜂笂浼犳秷闃叉车鎴垮浘鐗?");
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true);
|
||||
try {
|
||||
if (deleteFiles.length > 0) {
|
||||
await deleteFile({ single: false, files: deleteFiles });
|
||||
}
|
||||
|
||||
const { id: pumpRoomId } = await uploadFile({
|
||||
single: false,
|
||||
files: values.roomImages,
|
||||
params: {
|
||||
type: UPLOAD_FILE_TYPE_ENUM[302],
|
||||
foreignKey: values.roomId || values.pumpRoomId || query.id,
|
||||
},
|
||||
});
|
||||
|
||||
const apiMethod = query.id ? props["pumpRoomUpdate"] : props["pumpRoomAdd"];
|
||||
const params = {
|
||||
...values,
|
||||
pumpRoomId,
|
||||
devices: devices.map(({ key, ...device }) => ({
|
||||
deviceCode: device.deviceCode,
|
||||
deviceName: device.deviceName,
|
||||
deviceModel: device.deviceModel,
|
||||
deviceQty: device.deviceQty,
|
||||
deviceLocation: device.deviceLocation,
|
||||
...(device.id && { id: device.id }),
|
||||
})),
|
||||
};
|
||||
if (query.id) {
|
||||
params.id = query.id;
|
||||
}
|
||||
|
||||
await apiMethod(params);
|
||||
message.success(query.id ? "修改成功" : "新增成功");
|
||||
props.history.goBack();
|
||||
}
|
||||
catch (error) {
|
||||
message.error(query.id ? "修改失败" : "新增失败");
|
||||
}
|
||||
finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 设备列表相关操作
|
||||
const addDevice = () => {
|
||||
const newDevice = {
|
||||
key: Date.now(),
|
||||
deviceName: "",
|
||||
deviceModel: "",
|
||||
deviceQty: null,
|
||||
deviceLocation: "",
|
||||
};
|
||||
setDeviceList([...devices, newDevice]);
|
||||
};
|
||||
|
||||
const removeDevice = (key) => {
|
||||
setDeviceList(devices.filter(item => item.key !== key));
|
||||
};
|
||||
|
||||
const updateDevice = (key, field, value) => {
|
||||
setDeviceList(
|
||||
devices.map(item => (item.key === key ? { ...item, [field]: value } : item)),
|
||||
);
|
||||
};
|
||||
|
||||
// 设备表格列定义
|
||||
const deviceColumns = [
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备编号
|
||||
</>),
|
||||
dataIndex: "deviceCode",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备编号"
|
||||
onChange={e => updateDevice(record.key, "deviceCode", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备名称
|
||||
</>),
|
||||
dataIndex: "deviceName",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备名称"
|
||||
onChange={e => updateDevice(record.key, "deviceName", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备型号
|
||||
</>),
|
||||
dataIndex: "deviceModel",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备型号"
|
||||
onChange={e => updateDevice(record.key, "deviceModel", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备数量
|
||||
</>),
|
||||
dataIndex: "deviceQty",
|
||||
render: (text, record) => (
|
||||
<InputNumber
|
||||
value={text}
|
||||
placeholder="请输入设备数量"
|
||||
min={1}
|
||||
style={{ width: "100%" }}
|
||||
onChange={value => updateDevice(record.key, "deviceQty", value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
设备位置
|
||||
</>),
|
||||
dataIndex: "deviceLocation",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入设备位置"
|
||||
onChange={e => updateDevice(record.key, "deviceLocation", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => removeDevice(record.key)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle={query.id ? "编辑消防泵房" : "新增消防泵房"}
|
||||
loading={loading || uploadFileLoading || deleteFileLoading || getFileLoading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
onFinish={onFinish}
|
||||
style={{ maxWidth: 1200, marginTop: 24 }}
|
||||
>
|
||||
<Card title="基本信息" style={{ marginBottom: 24 }}>
|
||||
<Form.Item name="pumpRoomId" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="消防泵房名称"
|
||||
name="pumpRoomName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入消防泵房名称" },
|
||||
{ max: 100, message: "消防泵房名称不能超过100个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入消防泵房名称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="消防泵房状态"
|
||||
name="pumpRoomStatus"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请选择消防泵房状态" }]}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="fire_resource_contro_root_type"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="负责人"
|
||||
name="principalName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入负责人" },
|
||||
{ max: 50, message: "负责人不能超过50个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入负责人" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="负责人手机号"
|
||||
name="principalPhone"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入负责人手机号" },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入负责人手机号" maxLength={11} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="经度"
|
||||
name="lng"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入经度" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入经度"
|
||||
style={{ width: "100%" }}
|
||||
min={-180}
|
||||
max={180}
|
||||
step={0.000001}
|
||||
precision={6}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="纬度"
|
||||
name="lat"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入纬度" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入纬度"
|
||||
style={{ width: "100%" }}
|
||||
min={-90}
|
||||
max={90}
|
||||
step={0.000001}
|
||||
precision={6}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={24}>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="消防泵房图片"
|
||||
name="roomImages"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
rules={[{ required: true, message: "请上传消防泵房图片" }]}
|
||||
extra="默认上传4个,目前支持jpg、jpeg、png格式,单张图片不超过5mb"
|
||||
>
|
||||
<Upload
|
||||
fileType="image"
|
||||
maxCount={4}
|
||||
maxSize={5}
|
||||
accept=".jpg,.jpeg,.png"
|
||||
onGetRemoveFile={(file) => {
|
||||
setDeleteFiles([...deleteFiles, file]);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="设备信息"
|
||||
extra={(
|
||||
<Button type="primary" onClick={addDevice}>
|
||||
新增
|
||||
</Button>
|
||||
)}
|
||||
style={{ marginBottom: 24 }}
|
||||
>
|
||||
<Table
|
||||
columns={deviceColumns}
|
||||
dataSource={devices}
|
||||
pagination={false}
|
||||
rowKey="key"
|
||||
locale={{ emptyText: "暂无设备信息,请点击新增按钮添加" }}
|
||||
/>
|
||||
|
||||
</Card>
|
||||
|
||||
<Form.Item wrapperCol={{ span: 24 }} style={{ textAlign: "center" }}>
|
||||
<Space size={16}>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" htmlType="submit" loading={submitting}>
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_PUMP_ROOM], true)(Permission(Add));
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Form, message, 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 DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useDictionary from "zy-react-library/hooks/useDictionary";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { NS_PUMP_ROOM } from "~/enumerate/namespace";
|
||||
|
||||
function List(props) {
|
||||
const [form] = Form.useForm();
|
||||
const query = useGetUrlQuery();
|
||||
|
||||
const { tableProps, getData } = useTable(props["pumpRoomList"], { form });
|
||||
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [statusDict, setStatusDict] = useState([]);
|
||||
|
||||
const { getDictionary } = useDictionary();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDict = async () => {
|
||||
try {
|
||||
const dict = await getDictionary({ dictValue: "fire_resource_contro_root_type" });
|
||||
setStatusDict(Array.isArray(dict) ? dict : []);
|
||||
}
|
||||
catch (error) {
|
||||
setStatusDict([]);
|
||||
}
|
||||
};
|
||||
fetchDict();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (query.eqCorpId) {
|
||||
form.setFieldsValue({ eqCorpId: query.eqCorpId });
|
||||
getData();
|
||||
}
|
||||
}, [query.eqCorpId]);
|
||||
|
||||
const getStatusLabel = (record) => {
|
||||
if (record.roomStatusName)
|
||||
return record.roomStatusName;
|
||||
const match = statusDict.find(item => item.dictValue === record.pumpRoomStatus);
|
||||
return match?.dictLabel || record.pumpRoomStatus || "-";
|
||||
};
|
||||
const onDelete = (id) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "删除后不可恢复,确认继续?",
|
||||
okText: "确认",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true, loading: deleting },
|
||||
onOk: async () => {
|
||||
if (!props["pumpRoomDelete"]) {
|
||||
message.warning("未接入 pumpRoomDelete effect");
|
||||
return;
|
||||
}
|
||||
setDeleting(true);
|
||||
try {
|
||||
await props["pumpRoomDelete"]({ id });
|
||||
message.success("已删除");
|
||||
getData();
|
||||
}
|
||||
finally {
|
||||
setDeleting(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{ name: "likePumpRoomName", label: "消防泵房名称" },
|
||||
{
|
||||
name: "eqPumpRoomStatus",
|
||||
label: "消防泵房状态",
|
||||
render: (<DictionarySelect dictValue="fire_resource_contro_root_type" />),
|
||||
},
|
||||
{ name: "eqCorpId", onlyForLabel: true },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
props.history.push("./add");
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
// { title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{ title: "消防泵房名称", dataIndex: "pumpRoomName", ellipsis: true, width: 120 },
|
||||
{
|
||||
title: "消防泵房状态",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (_, record) => getStatusLabel(record),
|
||||
},
|
||||
{ title: "负责人", dataIndex: "principalName", width: 120 },
|
||||
{ title: "负责人手机号", dataIndex: "principalPhone", width: 140 },
|
||||
{ title: "设备数", dataIndex: "deviceCount", width: 100, align: "center" },
|
||||
{
|
||||
title: "操作",
|
||||
fixed: "right",
|
||||
width: 180,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./view?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./add?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => onDelete(record.id)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_PUMP_ROOM], true)(Permission(List));
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Descriptions, Image, message, Space, Table } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import { UPLOAD_FILE_TYPE_ENUM } from "zy-react-library/enum/uploadFile/gwj";
|
||||
import useDictionary from "zy-react-library/hooks/useDictionary";
|
||||
import useGetFile from "zy-react-library/hooks/useGetFile";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import { NS_PUMP_ROOM } from "~/enumerate/namespace";
|
||||
|
||||
function View(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [detail, setDetail] = useState(null);
|
||||
const [statusDict, setStatusDict] = useState([]);
|
||||
|
||||
const { getDictionary } = useDictionary();
|
||||
const { loading: getFileLoading, getFile } = useGetFile();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDict = async () => {
|
||||
try {
|
||||
const dict = await getDictionary({ dictValue: "fire_resource_contro_root_type" });
|
||||
setStatusDict(Array.isArray(dict) ? dict : []);
|
||||
}
|
||||
catch (error) {
|
||||
setStatusDict([]);
|
||||
}
|
||||
};
|
||||
fetchDict();
|
||||
}, []);
|
||||
|
||||
const getStatusLabel = (record) => {
|
||||
if (!record)
|
||||
return "-";
|
||||
if (record.roomStatusName)
|
||||
return record.roomStatusName;
|
||||
const match = statusDict.find(item => item.dictValue === record.pumpRoomStatus);
|
||||
return match?.dictLabel || record.pumpRoomStatus || "-";
|
||||
};
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["pumpRoomDetail"]({ id: query.id });
|
||||
let nextDetail = data;
|
||||
const roomKey = data.roomId || data.pumpRoomId || data.id;
|
||||
if (roomKey) {
|
||||
const files = await getFile({
|
||||
eqType: UPLOAD_FILE_TYPE_ENUM[302],
|
||||
eqForeignKey: roomKey,
|
||||
});
|
||||
nextDetail = { ...data, roomImages: files };
|
||||
}
|
||||
setDetail(nextDetail);
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
// 设备表格列定义
|
||||
const deviceColumns = [
|
||||
{ title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{ title: "设备编号", dataIndex: "deviceCode", align: "center" },
|
||||
{ title: "设备名称", dataIndex: "deviceName", align: "center" },
|
||||
{ title: "设备型号", dataIndex: "deviceModel", align: "center" },
|
||||
{ title: "设备数量", dataIndex: "deviceQty", align: "center" },
|
||||
{ title: "设备位置", dataIndex: "deviceLocation", align: "center" },
|
||||
];
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle="查看消防泵房"
|
||||
loading={loading || getFileLoading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
{detail && (
|
||||
<>
|
||||
<Card title="基本信息" style={{ marginBottom: 24, marginTop: 24 }}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={2}
|
||||
labelStyle={{ width: 180, backgroundColor: "#fafafa" }}
|
||||
contentStyle={{ backgroundColor: "#fff" }}
|
||||
items={[
|
||||
{
|
||||
label: "消防泵房名称",
|
||||
children: detail.pumpRoomName,
|
||||
},
|
||||
{
|
||||
label: "消防泵房状态",
|
||||
children: getStatusLabel(detail),
|
||||
},
|
||||
{
|
||||
label: "负责人",
|
||||
children: detail.principalName,
|
||||
},
|
||||
{
|
||||
label: "负责人手机号",
|
||||
children: detail.principalPhone,
|
||||
},
|
||||
{
|
||||
label: "经度",
|
||||
children: detail.lng,
|
||||
},
|
||||
{
|
||||
label: "纬度",
|
||||
children: detail.lat,
|
||||
},
|
||||
{
|
||||
label: "消防泵房图片",
|
||||
children: detail.roomImages && detail.roomImages.length > 0
|
||||
? (
|
||||
<Image.PreviewGroup>
|
||||
<Space>
|
||||
{detail.roomImages.map((img, index) => (
|
||||
<Image
|
||||
key={index}
|
||||
width={100}
|
||||
height={100}
|
||||
src={img}
|
||||
style={{ objectFit: "cover" }}
|
||||
/>
|
||||
))}
|
||||
</Space>
|
||||
</Image.PreviewGroup>
|
||||
)
|
||||
: (
|
||||
"无"
|
||||
),
|
||||
span: 2,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="设备信息" style={{ marginBottom: 24 }}>
|
||||
<Table
|
||||
columns={deviceColumns}
|
||||
dataSource={detail.devices || []}
|
||||
pagination={false}
|
||||
rowKey={(record, index) => index}
|
||||
locale={{ emptyText: "暂无设备信息" }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<div style={{ marginTop: 24, textAlign: "center" }}>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_PUMP_ROOM], true)(Permission(View));
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
function Index(props) {
|
||||
return (<div>{props.children}</div>);
|
||||
}
|
||||
|
||||
export default Index;
|
||||
|
|
@ -0,0 +1,407 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Col, DatePicker, Form, Input, message, Row, Space, Table } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import { NS_RESCUE_TEAM } from "~/enumerate/namespace";
|
||||
|
||||
function Add(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
// 消防队员列表
|
||||
const [rescueMembers, setRescueMembers] = useState([]);
|
||||
|
||||
// ⭐ 添加状态保存字典显示名称
|
||||
const [teamTypeName, setTeamTypeName] = useState("");
|
||||
const [regionScopeName, setRegionScopeName] = useState("");
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["rescueTeamDetail"]({ id: query.id });
|
||||
|
||||
// 处理日期字段
|
||||
if (data.establishDate) {
|
||||
data.establishDate = dayjs(data.establishDate);
|
||||
}
|
||||
|
||||
form.setFieldsValue(data);
|
||||
|
||||
// ⭐ 设置字典显示名称
|
||||
if (data.teamTypeName) {
|
||||
setTeamTypeName(data.teamTypeName);
|
||||
}
|
||||
if (data.regionScopeName) {
|
||||
setRegionScopeName(data.regionScopeName);
|
||||
}
|
||||
|
||||
// 设置消防队员列表
|
||||
if (data.rescueMembers && data.rescueMembers.length > 0) {
|
||||
setRescueMembers(data.rescueMembers.map((item, index) => ({ ...item, key: index })));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
const onFinish = async (values) => {
|
||||
// 验证消防队员列表
|
||||
if (rescueMembers.length === 0) {
|
||||
message.warning("请至少添加一名消防队员");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证消防队员必填项
|
||||
const invalidMember = rescueMembers.find(
|
||||
item => !item.personName || !item.personPhone,
|
||||
);
|
||||
if (invalidMember) {
|
||||
message.warning("请完善消防队员信息");
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true);
|
||||
try {
|
||||
const apiMethod = query.id ? props["rescueTeamUpdate"] : props["rescueTeamAdd"];
|
||||
|
||||
// 处理日期格式和提交参数
|
||||
const params = {
|
||||
...values,
|
||||
establishDate: values.establishDate ? values.establishDate.format("YYYY-MM-DD") : null,
|
||||
|
||||
// ⭐ 从状态中获取字典显示名称
|
||||
teamTypeName,
|
||||
regionScopeName,
|
||||
|
||||
// 队员数量
|
||||
memberCount: rescueMembers.length,
|
||||
|
||||
// 队员列表:去掉前端添加的 key
|
||||
rescueMembers: rescueMembers.map(({ key, ...member }) => ({
|
||||
personName: member.personName,
|
||||
personPhone: member.personPhone,
|
||||
dutyDesc: member.dutyDesc || "",
|
||||
roleCode: member.roleCode || 1,
|
||||
...(member.id && { id: member.id }),
|
||||
})),
|
||||
};
|
||||
|
||||
if (query.id) {
|
||||
params.id = query.id;
|
||||
params.teamId = values.teamId;
|
||||
}
|
||||
|
||||
await apiMethod(params);
|
||||
message.success(query.id ? "修改成功" : "新增成功");
|
||||
props.history.goBack();
|
||||
}
|
||||
catch (error) {
|
||||
message.error(query.id ? "修改失败" : "新增失败");
|
||||
}
|
||||
finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 消防队员相关操作
|
||||
const addMember = () => {
|
||||
const newMember = {
|
||||
key: Date.now(),
|
||||
personName: "",
|
||||
personPhone: "",
|
||||
dutyDesc: "",
|
||||
roleCode: 1,
|
||||
};
|
||||
setRescueMembers([...rescueMembers, newMember]);
|
||||
};
|
||||
|
||||
const removeMember = (key) => {
|
||||
setRescueMembers(rescueMembers.filter(item => item.key !== key));
|
||||
};
|
||||
|
||||
const updateMember = (key, field, value) => {
|
||||
setRescueMembers(
|
||||
rescueMembers.map(item => (item.key === key ? { ...item, [field]: value } : item)),
|
||||
);
|
||||
};
|
||||
|
||||
// 消防队员表格列定义
|
||||
const memberColumns = [
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
队员姓名
|
||||
</>),
|
||||
dataIndex: "personName",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入队员姓名"
|
||||
onChange={e => updateMember(record.key, "personName", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: (<>
|
||||
<span style={{ color: "red" }}>*</span>
|
||||
队员电话
|
||||
</>),
|
||||
dataIndex: "personPhone",
|
||||
render: (text, record) => (
|
||||
<Input
|
||||
value={text}
|
||||
placeholder="请输入队员电话"
|
||||
maxLength={11}
|
||||
onChange={e => updateMember(record.key, "personPhone", e.target.value)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => removeMember(record.key)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle={query.id ? "编辑救援队" : "新增救援队"}
|
||||
loading={loading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
onFinish={onFinish}
|
||||
style={{ maxWidth: 1200, marginTop: 24 }}
|
||||
>
|
||||
<Card title="基本信息" style={{ marginBottom: 24 }}>
|
||||
<Form.Item name="teamId" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
{/* 第一行:救援队名称、类型 */}
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="救援队名称"
|
||||
name="teamName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入救援队名称" },
|
||||
{ max: 100, message: "救援队名称不能超过100个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入救援队名称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="类型"
|
||||
name="teamType"
|
||||
labelCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请选择救援队类型" },
|
||||
{ max: 50, message: "救援队类型不能超过50个字符" },
|
||||
]}
|
||||
wrapperCol={{ span: 12 }}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="fire_resource_team_type"
|
||||
placeholder="请选择"
|
||||
onChange={(value, option) => {
|
||||
// ⭐ 监听选择事件,保存显示名称
|
||||
setTeamTypeName(option?.children || option?.label || "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* 第二行:队长、队长电话 */}
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="队长"
|
||||
name="captainName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入队长姓名" },
|
||||
{ max: 50, message: "队长姓名不能超过50个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入队长姓名" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="队长电话"
|
||||
name="captainPhone"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入队长电话" },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入队长电话" maxLength={11} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* 第三行:指挥人员、建立日期 */}
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="指挥人员"
|
||||
name="commandCrew"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入指挥人员姓名" },
|
||||
{ max: 50, message: "指挥人员姓名不能超过50个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入指挥人员" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="建立日期"
|
||||
name="establishDate"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请选择建立日期" }]}
|
||||
>
|
||||
<DatePicker
|
||||
placeholder="请选择日期"
|
||||
style={{ width: "100%" }}
|
||||
format="YYYY-MM-DD"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* 第四行:所属区域或范围、职责和任务范围 */}
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="所属区域或范围"
|
||||
name="regionScope"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请选择救援队所属区域或范围" },
|
||||
{ max: 50, message: "救援队所属区域或范围不能超过50个字符" },
|
||||
]}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="fire_resource_area_scope"
|
||||
placeholder="请选择"
|
||||
onChange={(value, option) => {
|
||||
// ⭐ 监听选择事件,保存显示名称
|
||||
setRegionScopeName(option?.children || option?.label || "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="职责和任务范围"
|
||||
name="dutyScope"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入职责和任务范围" },
|
||||
{ max: 500, message: "职责和任务范围不能超过500个字符" },
|
||||
]}
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder="请输入职责和任务范围"
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
showCount
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* 第五行:负责人单位或部门(单独一行) */}
|
||||
<Row gutter={24}>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
label="负责人单位或部门"
|
||||
name="chargeOrgDept"
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入负责人单位或部门" },
|
||||
{ max: 200, message: "负责人单位或部门不能超过200个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入负责人单位或部门" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="队员信息"
|
||||
extra={(
|
||||
<Button type="primary" onClick={addMember}>
|
||||
新增
|
||||
</Button>
|
||||
)}
|
||||
style={{ marginBottom: 24 }}
|
||||
>
|
||||
<Table
|
||||
columns={memberColumns}
|
||||
dataSource={rescueMembers}
|
||||
pagination={false}
|
||||
rowKey="key"
|
||||
locale={{ emptyText: "暂无队员信息,请点击新增按钮添加" }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Form.Item wrapperCol={{ span: 24 }} style={{ textAlign: "center" }}>
|
||||
<Space size={16}>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" htmlType="submit" loading={submitting}>
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_RESCUE_TEAM], true)(Permission(Add));
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Form, message, 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 DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { getLabelName } from "zy-react-library/utils";
|
||||
import { NS_RESCUE_TEAM } from "~/enumerate/namespace";
|
||||
|
||||
function List(props) {
|
||||
const [form] = Form.useForm();
|
||||
const query = useGetUrlQuery();
|
||||
|
||||
const { tableProps, getData } = useTable(props["rescueTeamList"], { form });
|
||||
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (query.eqCorpId) {
|
||||
form.setFieldsValue({ eqCorpId: query.eqCorpId });
|
||||
getData();
|
||||
}
|
||||
}, [query.eqCorpId]);
|
||||
|
||||
const onDelete = (id) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "删除后不可恢复,确认继续?",
|
||||
okText: "确认",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true, loading: deleting },
|
||||
onOk: async () => {
|
||||
if (!props["rescueTeamDelete"]) {
|
||||
message.warning("未接入 rescueTeamDelete effect");
|
||||
return;
|
||||
}
|
||||
setDeleting(true);
|
||||
try {
|
||||
await props["rescueTeamDelete"]({ id });
|
||||
message.success("已删除");
|
||||
getData();
|
||||
}
|
||||
finally {
|
||||
setDeleting(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{ name: "likeTeamName", label: "救援队名称" },
|
||||
{
|
||||
name: "eqTeamType",
|
||||
label: "类型",
|
||||
render: (<DictionarySelect dictValue="fire_resource_team_type" />),
|
||||
},
|
||||
{ name: "likeChargeOrgDept", label: "负责人单位或部门" },
|
||||
{ name: "likeCaptainName", label: "队长" },
|
||||
{ name: "eqCorpId", onlyForLabel: true },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
{/* {props.permission("jydgl-btn-add") && ( */}
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
props.history.push("./add");
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
// { title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{ title: "救援队名称", dataIndex: "teamName", ellipsis: true },
|
||||
{
|
||||
title: "类型",
|
||||
dataIndex: "teamTypeName",
|
||||
width: 140,
|
||||
align: "center",
|
||||
},
|
||||
{ title: "负责人单位或部门", dataIndex: "chargeOrgDept", ellipsis: true },
|
||||
{ title: "队长", dataIndex: "captainName", width: 120, align: "center" },
|
||||
{ title: "指挥人员", dataIndex: "commandCrew", width: 120, align: "center" },
|
||||
{ title: "队员人数", dataIndex: "memberCount", width: 110, align: "center" },
|
||||
{
|
||||
title: "操作",
|
||||
fixed: "right",
|
||||
width: 180,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
{/* {props.permission("jydgl-btn-view") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./view?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
{/* )} */}
|
||||
|
||||
{/* {props.permission("jydgl-btn-edit") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./add?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
{/* )} */}
|
||||
|
||||
{/* {props.permission("jydgl-btn-delete") && ( */}
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => onDelete(record.id)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_RESCUE_TEAM], true)(Permission(List));
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Descriptions, message, Table } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import { NS_RESCUE_TEAM } from "~/enumerate/namespace";
|
||||
|
||||
function View(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [detail, setDetail] = useState(null);
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["rescueTeamDetail"]({ id: query.id });
|
||||
setDetail(data);
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
// 队员表格列定义
|
||||
const memberColumns = [
|
||||
{ title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{ title: "队员", dataIndex: "personName" },
|
||||
{ title: "队员电话", dataIndex: "personPhone" },
|
||||
];
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle="查看救援队"
|
||||
loading={loading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
{detail && (
|
||||
<>
|
||||
<Card title="基本信息" style={{ marginBottom: 24, marginTop: 24 }}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={2}
|
||||
contentStyle={{ backgroundColor: "#fff" }}
|
||||
labelStyle={{
|
||||
width: "180px",
|
||||
backgroundColor: "#fafafa",
|
||||
fontWeight: "normal",
|
||||
}}
|
||||
items={[
|
||||
{
|
||||
label: "救援队名称",
|
||||
children: detail.teamName || "-",
|
||||
},
|
||||
{
|
||||
label: "负责人单位或部门",
|
||||
children: detail.chargeOrgDept || "-",
|
||||
},
|
||||
{
|
||||
label: "类型",
|
||||
children: detail.teamTypeName || detail.teamType || "-",
|
||||
},
|
||||
{
|
||||
label: "职责和任务范围",
|
||||
children: detail.dutyScope || "-",
|
||||
},
|
||||
{
|
||||
label: "队长",
|
||||
children: detail.captainName || "-",
|
||||
},
|
||||
{
|
||||
label: "队长电话",
|
||||
children: detail.captainPhone || "-",
|
||||
},
|
||||
{
|
||||
label: "指挥人员",
|
||||
children: detail.commandCrew || "-",
|
||||
},
|
||||
{
|
||||
label: "建立日期",
|
||||
children: detail.establishDate || "-",
|
||||
},
|
||||
{
|
||||
label: "所属区域或范围",
|
||||
children: detail.regionScopeName || detail.regionScope || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="队员信息" style={{ marginBottom: 24 }}>
|
||||
<Table
|
||||
columns={memberColumns}
|
||||
dataSource={detail.rescueMembers || []}
|
||||
pagination={false}
|
||||
rowKey={(record, index) => index}
|
||||
locale={{ emptyText: "暂无队员信息" }}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<div style={{ marginTop: 24, textAlign: "center" }}>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_RESCUE_TEAM], true)(Permission(View));
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
function RescueTeam(props) {
|
||||
return (<div>{props.children}</div>);
|
||||
}
|
||||
export default RescueTeam;
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Col, Form, Input, InputNumber, message, Row, Space } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import { NS_WATER_SOURCE } from "~/enumerate/namespace";
|
||||
|
||||
function Add(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["waterSourceDetail"]({ id: query.id });
|
||||
form.setFieldsValue(data);
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
const onFinish = async (values) => {
|
||||
setSubmitting(true);
|
||||
try {
|
||||
const apiMethod = query.id ? props["waterSourceUpdate"] : props["waterSourceAdd"];
|
||||
const params = query.id ? { ...values, id: query.id } : values;
|
||||
|
||||
await apiMethod(params);
|
||||
message.success(query.id ? "修改成功" : "新增成功");
|
||||
props.history.goBack();
|
||||
}
|
||||
catch (error) {
|
||||
message.error(query.id ? "修改失败" : "新增失败");
|
||||
}
|
||||
finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle={query.id ? "编辑消防水源" : "新增消防水源"}
|
||||
loading={loading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
onFinish={onFinish}
|
||||
style={{ maxWidth: 1200, marginTop: 24 }}
|
||||
>
|
||||
<Card title="基本信息" style={{ marginBottom: 24 }}>
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="消防水源名称"
|
||||
name="waterSourceName"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入消防水源名称" },
|
||||
{ max: 100, message: "消防水源名称不能超过100个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入消防水源名称" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="消防水源状态"
|
||||
name="waterSourceStatus"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请选择消防水源状态" }]}
|
||||
>
|
||||
<DictionarySelect
|
||||
dictValue="fire_resource_water_type"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="经度"
|
||||
name="lng"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入经度" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入经度"
|
||||
style={{ width: "100%" }}
|
||||
min={-180}
|
||||
max={180}
|
||||
step={0.000001}
|
||||
precision={6}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="纬度"
|
||||
name="lat"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入纬度" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入纬度"
|
||||
style={{ width: "100%" }}
|
||||
min={-90}
|
||||
max={90}
|
||||
step={0.000001}
|
||||
precision={6}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="所属单位或部门"
|
||||
name="belongOrgDept"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入所属单位或部门" },
|
||||
{ max: 200, message: "所属单位或部门不能超过200个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入所属单位或部门" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="水源位置"
|
||||
name="waterLocation"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[
|
||||
{ required: true, message: "请输入水源位置" },
|
||||
{ max: 200, message: "水源位置不能超过200个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入水源位置" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="接口形式"
|
||||
name="interfaceForm"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入接口形式" }]}
|
||||
>
|
||||
<Input placeholder="请输入接口形式" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="水源类型"
|
||||
name="waterType"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入水源类型" }]}
|
||||
>
|
||||
<Input placeholder="请输入水源类型" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="水源编号"
|
||||
name="waterCode"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入水源编号" }]}
|
||||
>
|
||||
<Input placeholder="请输入水源编号" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="吸水口规格"
|
||||
name="suctionSpec"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入吸水口规格" }]}
|
||||
>
|
||||
<InputNumber
|
||||
placeholder="请输入吸水口规格"
|
||||
style={{ width: "100%" }}
|
||||
min={0}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="水源容量"
|
||||
name="capacity"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入水源容量" }]}
|
||||
>
|
||||
<Input placeholder="请输入水源容量" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="供水能力"
|
||||
name="supplyAbility"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入供水能力" }]}
|
||||
>
|
||||
<Input placeholder="请输入供水能力" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label="设备清单"
|
||||
name="equipmentList"
|
||||
labelCol={{ span: 12 }}
|
||||
wrapperCol={{ span: 12 }}
|
||||
rules={[{ required: true, message: "请输入设备清单" }]}
|
||||
>
|
||||
<Input placeholder="请输入设备清单" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Form.Item wrapperCol={{ span: 24 }} style={{ textAlign: "center" }}>
|
||||
<Space>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" htmlType="submit" loading={submitting}>
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_WATER_SOURCE], true)(Permission(Add));
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Form, message, 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 DictionarySelect from "zy-react-library/components/Select/Dictionary";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useDictionary from "zy-react-library/hooks/useDictionary";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { NS_WATER_SOURCE } from "~/enumerate/namespace";
|
||||
|
||||
function List(props) {
|
||||
const [form] = Form.useForm();
|
||||
const query = useGetUrlQuery();
|
||||
|
||||
const { tableProps, getData } = useTable(props["waterSourceList"], { form });
|
||||
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [statusDict, setStatusDict] = useState([]);
|
||||
|
||||
const { getDictionary } = useDictionary();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDict = async () => {
|
||||
try {
|
||||
const dict = await getDictionary({ dictValue: "fire_resource_water_type" });
|
||||
setStatusDict(Array.isArray(dict) ? dict : []);
|
||||
}
|
||||
catch (error) {
|
||||
setStatusDict([]);
|
||||
}
|
||||
};
|
||||
fetchDict();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (query.eqCorpId) {
|
||||
form.setFieldsValue({ eqCorpId: query.eqCorpId });
|
||||
getData();
|
||||
}
|
||||
}, [query.eqCorpId]);
|
||||
|
||||
const getStatusLabel = (record) => {
|
||||
if (record.sourceStatusName)
|
||||
return record.sourceStatusName;
|
||||
const match = statusDict.find(item => item.dictValue === record.waterSourceStatus);
|
||||
return match?.dictLabel || record.sourceStatus || "-";
|
||||
};
|
||||
|
||||
const onDelete = (id) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "删除后不可恢复,确认继续?",
|
||||
okText: "确认",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true, loading: deleting },
|
||||
onOk: async () => {
|
||||
if (!props["waterSourceDelete"]) {
|
||||
message.warning("未接入 waterSourceDelete effect");
|
||||
return;
|
||||
}
|
||||
setDeleting(true);
|
||||
try {
|
||||
await props["waterSourceDelete"]({ id });
|
||||
message.success("已删除");
|
||||
getData();
|
||||
}
|
||||
finally {
|
||||
setDeleting(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{ name: "likeWaterSourceName", label: "消防水源名称" },
|
||||
{
|
||||
name: "eqWaterSourceStatus",
|
||||
label: "消防水源状态",
|
||||
render: (<DictionarySelect dictValue="fire_resource_water_type" />),
|
||||
},
|
||||
{ name: "likeBelongOrgDept", label: "所属单位或部门" },
|
||||
{ name: "eqCorpId", onlyForLabel: true },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
toolBarRender={() => (
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
props.history.push("./add");
|
||||
}}
|
||||
>
|
||||
新增
|
||||
</Button>
|
||||
</Space>
|
||||
)}
|
||||
columns={[
|
||||
// { title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{ title: "消防水源名称", dataIndex: "waterSourceName", ellipsis: true },
|
||||
{
|
||||
title: "消防水源状态",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (_, record) => getStatusLabel(record),
|
||||
},
|
||||
{ title: "所属单位或部门", dataIndex: "belongOrgDept", ellipsis: true },
|
||||
{ title: "水源位置", dataIndex: "waterLocation", ellipsis: true },
|
||||
{
|
||||
title: "操作",
|
||||
fixed: "right",
|
||||
width: 180,
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./view?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
props.history.push(`./add?id=${record.id}`);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => onDelete(record.id)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_WATER_SOURCE], true)(Permission(List));
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Button, Card, Col, Descriptions, message, Row } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import useDictionary from "zy-react-library/hooks/useDictionary";
|
||||
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||
import { NS_WATER_SOURCE } from "~/enumerate/namespace";
|
||||
|
||||
function View(props) {
|
||||
const query = useGetUrlQuery();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [detail, setDetail] = useState(null);
|
||||
const [statusDict, setStatusDict] = useState([]);
|
||||
|
||||
const { getDictionary } = useDictionary();
|
||||
|
||||
const getData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await props["waterSourceDetail"]({ id: query.id });
|
||||
setDetail(data);
|
||||
}
|
||||
catch (error) {
|
||||
message.error("加载详情失败");
|
||||
}
|
||||
finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
query.id && getData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDict = async () => {
|
||||
try {
|
||||
const dict = await getDictionary({ dictValue: "fire_resource_water_type" });
|
||||
setStatusDict(Array.isArray(dict) ? dict : []);
|
||||
}
|
||||
catch (error) {
|
||||
setStatusDict([]);
|
||||
}
|
||||
};
|
||||
fetchDict();
|
||||
}, []);
|
||||
|
||||
const getStatusLabel = (status) => {
|
||||
if (!status)
|
||||
return "-";
|
||||
const match = statusDict.find(item => item.dictValue === status);
|
||||
return match?.dictLabel || status;
|
||||
};
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerTitle="查看消防水源"
|
||||
loading={loading}
|
||||
isShowFooter={false}
|
||||
>
|
||||
{detail && (
|
||||
<>
|
||||
<Card title="基本信息" style={{ marginBottom: 24, marginTop: 24 }}>
|
||||
<Row gutter={24}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "消防水源名称",
|
||||
children: detail.waterSourceName || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "消防水源状态",
|
||||
children: getStatusLabel(detail.waterSourceStatus),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "经度",
|
||||
children: detail.lng || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "纬度",
|
||||
children: detail.lat || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "所属单位或部门",
|
||||
children: detail.belongOrgDept || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "水源位置",
|
||||
children: detail.waterLocation || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "接口形式",
|
||||
children: detail.interfaceForm || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "水源类型",
|
||||
children: detail.waterType || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "水源编号",
|
||||
children: detail.waterCode || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "吸水口规格",
|
||||
children: detail.suctionSpec || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "水源容量",
|
||||
children: detail.capacity || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "供水能力",
|
||||
children: detail.supplyAbility || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Descriptions
|
||||
bordered
|
||||
column={1}
|
||||
labelStyle={{ width: "50%" }}
|
||||
items={[
|
||||
{
|
||||
label: "设备清单",
|
||||
children: detail.equipmentList || "-",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<div style={{ marginTop: 24, textAlign: "center" }}>
|
||||
<Button onClick={() => props.history.goBack()}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_WATER_SOURCE], true)(Permission(View));
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
function Index(props) {
|
||||
return (<div>{props.children}</div>);
|
||||
}
|
||||
|
||||
export default Index;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// 简单的路由容器
|
||||
function BranchCompany(props) {
|
||||
return (<div>{props.children}</div>);
|
||||
}
|
||||
export default BranchCompany;
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Form } from "antd";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import Search from "zy-react-library/components/Search";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { NS_FIRE_RESOURCE_STATS } from "~/enumerate/namespace";
|
||||
|
||||
function FireResourceStats(props) {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const { tableProps, getData } = useTable(props["fireResourceStatsList"], { form });
|
||||
|
||||
const handleViewDetail = (record, type) => {
|
||||
// 跳转到对应的详情列表页面
|
||||
const routeMap = {
|
||||
rescueTeam: "/container/branchCompany/rescueTeam/list",
|
||||
controlRoom: "/container/branchCompany/controlRoom/list",
|
||||
pumpRoom: "/container/branchCompany/pumpRoom/list",
|
||||
waterSource: "/container/branchCompany/waterSource/list",
|
||||
};
|
||||
|
||||
if (routeMap[type]) {
|
||||
const corpId = record.corpId || record.companyId || "";
|
||||
props.history.push(`${routeMap[type]}?corpId=${corpId}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{ name: "likeCompanyName", label: "企业名称" },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
columns={[
|
||||
{ title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{
|
||||
title: "企业名称",
|
||||
dataIndex: "companyName",
|
||||
ellipsis: true,
|
||||
render: (text) => text || "一公司",
|
||||
},
|
||||
{
|
||||
title: "消防救援队数",
|
||||
dataIndex: "rescueTeamCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "rescueTeam")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防控制室数",
|
||||
dataIndex: "controlRoomCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "controlRoom")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防泵房数",
|
||||
dataIndex: "pumpRoomCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "pumpRoom")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防水源数",
|
||||
dataIndex: "waterSourceCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "waterSource")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_FIRE_RESOURCE_STATS], true)(Permission(FireResourceStats));
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
import {
|
||||
ColumnHeightOutlined,
|
||||
FullscreenOutlined,
|
||||
PlusOutlined,
|
||||
ReloadOutlined,
|
||||
SearchOutlined,
|
||||
SettingOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
message,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "antd";
|
||||
// RescueTeamPage.jsx
|
||||
// 依赖:antd@5
|
||||
import React, { useMemo, useState } from "react";
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
export default function RescueTeamPage() {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
// mock 数据(你接后端时直接替换为接口)
|
||||
const [data, setData] = useState([
|
||||
{
|
||||
id: 1,
|
||||
name: "救援队名称示例",
|
||||
type: "专职消防队",
|
||||
org: "负责单位示例",
|
||||
leader: "张三",
|
||||
commander: "李四",
|
||||
memberCount: 5,
|
||||
},
|
||||
]);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: "序号",
|
||||
dataIndex: "idx",
|
||||
width: 80,
|
||||
align: "center",
|
||||
render: (_, __, index) => index + 1,
|
||||
},
|
||||
{ title: "救援队名称", dataIndex: "name", ellipsis: true },
|
||||
{ title: "类型", dataIndex: "type", width: 140, align: "center" },
|
||||
{ title: "负责人单位或部门", dataIndex: "org", ellipsis: true },
|
||||
{ title: "队长", dataIndex: "leader", width: 120, align: "center" },
|
||||
{ title: "指挥人员", dataIndex: "commander", width: 120, align: "center" },
|
||||
{
|
||||
title: "队员人数",
|
||||
dataIndex: "memberCount",
|
||||
width: 110,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "actions",
|
||||
width: 220,
|
||||
align: "center",
|
||||
render: (_, record) => (
|
||||
<Space size={16}>
|
||||
<a
|
||||
onClick={() => {
|
||||
message.info(`查看:${record.name}`);
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</a>
|
||||
<a
|
||||
onClick={() => {
|
||||
message.info(`编辑:${record.name}`);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</a>
|
||||
<a
|
||||
style={{ color: "#ff4d4f" }}
|
||||
onClick={() => {
|
||||
setData(prev => prev.filter(x => x.id !== record.id));
|
||||
message.success("已删除");
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</a>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
],
|
||||
[setData],
|
||||
);
|
||||
|
||||
const onSearch = async () => {
|
||||
const values = await form.validateFields().catch(() => null);
|
||||
if (!values)
|
||||
return;
|
||||
|
||||
// 这里接你的查询接口:values 里包含所有筛选条件
|
||||
// 示例:仅做前端过滤演示
|
||||
const { name, type, org, region, leader } = values;
|
||||
const source = [
|
||||
{
|
||||
id: 1,
|
||||
name: "救援队名称示例",
|
||||
type: "专职消防队",
|
||||
org: "负责单位示例",
|
||||
leader: "张三",
|
||||
commander: "李四",
|
||||
memberCount: 5,
|
||||
},
|
||||
];
|
||||
const filtered = source.filter((r) => {
|
||||
const okName = !name || r.name.includes(name);
|
||||
const okType = !type || r.type === type;
|
||||
const okOrg = !org || r.org.includes(org);
|
||||
const okLeader = !leader || r.leader.includes(leader);
|
||||
// region 只是占位,后端一般按行政区划过滤
|
||||
const okRegion = !region || region === "内容待提供";
|
||||
return okName && okType && okOrg && okLeader && okRegion;
|
||||
});
|
||||
setData(filtered);
|
||||
};
|
||||
|
||||
const onReset = () => {
|
||||
form.resetFields();
|
||||
// 你可以选择是否立刻拉取列表
|
||||
onSearch();
|
||||
};
|
||||
|
||||
const onCreate = () => {
|
||||
message.info("新增:打开新增弹窗/跳转新增页");
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: 16, background: "#f5f7fb", minHeight: "100vh" }}>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
|
||||
{/* 顶部筛选 */}
|
||||
<Card
|
||||
bodyStyle={{ padding: 16 }}
|
||||
style={{ borderRadius: 10 }}
|
||||
bordered={false}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
initialValues={{ region: "内容待提供" }}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr 1fr 1fr 1fr",
|
||||
gap: 12,
|
||||
alignItems: "end",
|
||||
}}
|
||||
>
|
||||
<Form.Item label="救援队名称" name="name" style={{ marginBottom: 0 }}>
|
||||
<Input placeholder="" allowClear />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="类型" name="type" style={{ marginBottom: 0 }}>
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
options={[
|
||||
{ value: "专职消防队", label: "专职消防队" },
|
||||
{ value: "社会救援队", label: "社会救援队" },
|
||||
{ value: "企业救援队", label: "企业救援队" },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="负责人单位或部门"
|
||||
name="org"
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Input placeholder="" allowClear />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={(
|
||||
<span>
|
||||
<span style={{ color: "#ff4d4f" }}>*</span>
|
||||
所属区域范围
|
||||
</span>
|
||||
)}
|
||||
name="region"
|
||||
style={{ marginBottom: 0 }}
|
||||
rules={[{ required: true, message: "请选择所属区域范围" }]}
|
||||
>
|
||||
<Select
|
||||
options={[{ value: "内容待提供", label: "内容待提供" }]}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<SearchOutlined />}
|
||||
onClick={onSearch}
|
||||
>
|
||||
搜索
|
||||
</Button>
|
||||
<Button icon={<ReloadOutlined />} onClick={onReset}>
|
||||
重置
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
{/* 第二行:队长 + 留白 */}
|
||||
<Form.Item label="队长" name="leader" style={{ marginBottom: 0 }}>
|
||||
<Input placeholder="" allowClear />
|
||||
</Form.Item>
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
{/* 列表区 */}
|
||||
<Card
|
||||
bodyStyle={{ padding: 0 }}
|
||||
style={{ borderRadius: 10 }}
|
||||
bordered={false}
|
||||
>
|
||||
{/* 工具条 */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
alignItems: "center",
|
||||
gap: 10,
|
||||
padding: "12px 16px",
|
||||
borderBottom: "1px solid #f0f0f0",
|
||||
}}
|
||||
>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={onCreate}>
|
||||
新增
|
||||
</Button>
|
||||
|
||||
<Tooltip title="列设置/表格配置(占位)">
|
||||
<Button icon={<SettingOutlined />} />
|
||||
</Tooltip>
|
||||
<Tooltip title="行高/密度(占位)">
|
||||
<Button icon={<ColumnHeightOutlined />} />
|
||||
</Tooltip>
|
||||
<Tooltip title="全屏(占位)">
|
||||
<Button icon={<FullscreenOutlined />} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<Table
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
size="middle"
|
||||
scroll={{ x: 1100 }}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
import { Form } from "antd";
|
||||
import Page from "zy-react-library/components/Page";
|
||||
import Search from "zy-react-library/components/Search";
|
||||
import Table from "zy-react-library/components/Table";
|
||||
import useTable from "zy-react-library/hooks/useTable";
|
||||
import { NS_FIRE_RESOURCE_STATS } from "~/enumerate/namespace";
|
||||
|
||||
function FireResourceStats(props) {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const { tableProps, getData } = useTable(props["fireResourceStatsList"], { form });
|
||||
|
||||
const handleViewDetail = (record, type) => {
|
||||
const routeMap = {
|
||||
rescueTeam: "/container/branchCompany/rescueTeam/list",
|
||||
controlRoom: "/container/branchCompany/controlRoom/list",
|
||||
pumpRoom: "/container/branchCompany/pumpRoom/list",
|
||||
waterSource: "/container/branchCompany/waterSource/list",
|
||||
};
|
||||
|
||||
if (routeMap[type]) {
|
||||
const corpId = record.corpId || record.companyId || "";
|
||||
props.history.push(`${routeMap[type]}?eqCorpId=${corpId}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page isShowAllAction={false}>
|
||||
<Search
|
||||
labelCol={{ span: 8 }}
|
||||
options={[
|
||||
{ name: "corpName", label: "企业名称" },
|
||||
]}
|
||||
form={form}
|
||||
onFinish={getData}
|
||||
/>
|
||||
<Table
|
||||
columns={[
|
||||
// { title: "序号", width: 80, align: "center", render: (_, __, index) => index + 1 },
|
||||
{
|
||||
title: "企业名称",
|
||||
dataIndex: "corpName",
|
||||
ellipsis: true,
|
||||
render: text => text || "一公司",
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: "消防救援队数",
|
||||
dataIndex: "rescueTeamCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "rescueTeam")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防控制室数",
|
||||
dataIndex: "controlRoomCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "controlRoom")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防泵房数",
|
||||
dataIndex: "pumpRoomCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "pumpRoom")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "消防水源数",
|
||||
dataIndex: "waterSourceCount",
|
||||
width: 140,
|
||||
align: "center",
|
||||
render: (text, record) => (
|
||||
<a
|
||||
style={{ color: "#1677ff", fontWeight: 600, textDecoration: "underline" }}
|
||||
onClick={() => handleViewDetail(record, "waterSource")}
|
||||
>
|
||||
{text || 0}
|
||||
</a>
|
||||
),
|
||||
},
|
||||
]}
|
||||
{...tableProps}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default Connect([NS_FIRE_RESOURCE_STATS], true)(Permission(FireResourceStats));
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
function Index(props) {
|
||||
return (<div>{props.children}</div>);
|
||||
}
|
||||
|
||||
export default Index;
|
||||
Loading…
Reference in New Issue