import React, { useState, useEffect } from "react";
|
import { useTranslate, useNotify, useRefresh } from 'react-admin';
|
import {
|
Dialog,
|
DialogActions,
|
DialogContent,
|
DialogTitle,
|
Box,
|
Button,
|
IconButton,
|
Table,
|
TableBody,
|
TableCell,
|
TableContainer,
|
TableHead,
|
TableRow,
|
Paper,
|
Grid,
|
TextField,
|
MenuItem,
|
Select,
|
FormControl,
|
InputLabel,
|
} from '@mui/material';
|
import DialogCloseButton from "../../components/DialogCloseButton";
|
import AddIcon from '@mui/icons-material/Add';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
import SaveIcon from '@mui/icons-material/Save';
|
import request from '@/utils/request';
|
|
const defaultPair = () => ({ stationName: '', stationId: '' });
|
|
const BasStationInitModal = ({ open, setOpen, initialData = null, onClose }) => {
|
const translate = useTranslate();
|
const notify = useNotify();
|
const refresh = useRefresh();
|
|
const [pairs, setPairs] = useState([defaultPair()]);
|
const [common, setCommon] = useState({
|
type: 0,
|
useStatus: '',
|
areaIds: [],
|
containerTypes: [],
|
inAble: 0,
|
outAble: 0,
|
});
|
const [loading, setLoading] = useState(false);
|
|
const [useStatusOptions, setUseStatusOptions] = useState([]);
|
const [areaOptions, setAreaOptions] = useState([]);
|
const [containerTypeOptions, setContainerTypeOptions] = useState([]);
|
|
useEffect(() => {
|
if (!open) return;
|
request.post('/dictData/page', { dictTypeCode: 'sys_sta_use_stas', current: 1, pageSize: 100 })
|
.then((res) => {
|
if (res?.data?.code === 200 && res?.data?.data?.records) {
|
setUseStatusOptions(res.data.data.records.map((item) => ({
|
value: item.value,
|
label: item.label ?? item.value,
|
})));
|
}
|
})
|
.catch(() => {});
|
}, [open]);
|
|
useEffect(() => {
|
if (!open) return;
|
request.post('/warehouseAreas/list', {})
|
.then((res) => {
|
if (res?.data?.code === 200 && res?.data?.data) {
|
const list = Array.isArray(res.data.data) ? res.data.data : (res.data.data?.records || []);
|
setAreaOptions(list.map((item) => ({ id: item.id, name: item.name ?? item.id })));
|
}
|
})
|
.catch(() => {});
|
}, [open]);
|
|
useEffect(() => {
|
if (!open) return;
|
request.post('/dictData/page', { dictTypeCode: 'sys_container_type', current: 1, pageSize: 100 })
|
.then((res) => {
|
if (res?.data?.code === 200 && res?.data?.data?.records) {
|
const options = res.data.data.records.map((item) => ({
|
id: item.id,
|
value: item.value,
|
label: item.label ?? item.value ?? item.id,
|
}));
|
setContainerTypeOptions(options);
|
if (initialData?.common?.containerTypes?.length) {
|
const list = initialData.common.containerTypes;
|
const mapped = list.map((item) => {
|
const byId = options.find((o) => Number(o.id) === Number(item) || String(o.id) === String(item));
|
if (byId) return String(byId.value);
|
const byVal = options.find((o) => String(o.value) === String(item) || o.value == item);
|
if (byVal) return String(byVal.value);
|
return item;
|
});
|
setCommon((prev) => ({ ...prev, containerTypes: mapped }));
|
}
|
}
|
})
|
.catch(() => {});
|
}, [open]);
|
useEffect(() => {
|
if (!open) return;
|
if (initialData?.pairs?.length) {
|
setPairs(initialData.pairs);
|
}
|
if (initialData?.common) {
|
setCommon({
|
type: initialData.common.type ?? 0,
|
useStatus: initialData.common.useStatus ?? '',
|
areaIds: Array.isArray(initialData.common.areaIds) ? [...initialData.common.areaIds] : [],
|
containerTypes: Array.isArray(initialData.common.containerTypes) ? [...initialData.common.containerTypes] : [],
|
inAble: initialData.common.inAble ?? 0,
|
outAble: initialData.common.outAble ?? 0,
|
});
|
}
|
}, [open, initialData]);
|
const handleClose = (event, reason) => {
|
if (reason !== "backdropClick") {
|
setOpen(false);
|
setPairs([defaultPair()]);
|
if (typeof onClose === 'function') onClose();
|
}
|
};
|
|
const addRow = () => setPairs((prev) => [...prev, defaultPair()]);
|
const removeRow = (index) => {
|
if (pairs.length <= 1) return;
|
setPairs((prev) => prev.filter((_, i) => i !== index));
|
};
|
const changePair = (index, field, value) => {
|
setPairs((prev) => prev.map((p, i) => (i === index ? { ...p, [field]: value } : p)));
|
};
|
|
const handleSubmit = async () => {
|
const toSave = pairs.filter(
|
(p) => (p.stationName || '').trim() && (p.stationId || '').trim()
|
);
|
if (toSave.length === 0) {
|
notify('请至少填写一组站点名称和站点编码', { type: 'error' });
|
return;
|
}
|
if (!(common.areaIds?.length)) {
|
notify('请选择可跨库区', { type: 'error' });
|
return;
|
}
|
if (!(common.containerTypes?.length)) {
|
notify('请选择容器类型', { type: 'error' });
|
return;
|
}
|
|
setLoading(true);
|
let success = 0;
|
let fail = 0;
|
for (const p of toSave) {
|
const body = {
|
stationName: (p.stationName || '').trim(),
|
stationId: (p.stationId || '').trim(),
|
type: common.type,
|
useStatus: common.useStatus || undefined,
|
areaIds: common.areaIds,
|
containerTypes: (common.containerTypes || []).map((v) => Number(v)),
|
inAble: Number(common.inAble),
|
outAble: Number(common.outAble),
|
};
|
try {
|
const res = await request.post('/basStation/save', body);
|
if (res?.data?.code === 200) success++;
|
else {
|
fail++;
|
notify(res?.data?.msg || '保存失败', { type: 'error' });
|
}
|
} catch (e) {
|
fail++;
|
notify(e?.message || '保存失败', { type: 'error' });
|
}
|
}
|
setLoading(false);
|
if (success > 0) {
|
notify(`成功保存 ${success} 条${fail > 0 ? `,失败 ${fail} 条` : ''}`);
|
setOpen(false);
|
refresh();
|
}
|
};
|
|
return (
|
<Dialog
|
open={open}
|
onClose={handleClose}
|
aria-labelledby="form-dialog-title"
|
fullWidth
|
disableRestoreFocus
|
maxWidth="md"
|
>
|
<DialogTitle
|
id="form-dialog-title"
|
sx={{
|
position: 'sticky',
|
top: 0,
|
backgroundColor: 'background.paper',
|
zIndex: 1000,
|
}}
|
>
|
{translate('toolbar.siteInit')}
|
<Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
|
<DialogCloseButton onClose={handleClose} />
|
</Box>
|
</DialogTitle>
|
<DialogContent sx={{ mt: 2 }}>
|
<Grid container rowSpacing={2} columnSpacing={2}>
|
<Grid item xs={12}>
|
<TableContainer component={Paper} variant="outlined">
|
<Table size="small">
|
<TableHead>
|
<TableRow>
|
<TableCell>{translate('table.field.basStation.stationName')}</TableCell>
|
<TableCell>{translate('table.field.basStation.stationId')}</TableCell>
|
<TableCell width={80}>操作</TableCell>
|
</TableRow>
|
</TableHead>
|
<TableBody>
|
{pairs.map((p, index) => (
|
<TableRow key={index}>
|
<TableCell>
|
<TextField
|
size="small"
|
fullWidth
|
placeholder={translate('table.field.basStation.stationName')}
|
value={p.stationName || ''}
|
onChange={(e) => changePair(index, 'stationName', e.target.value)}
|
/>
|
</TableCell>
|
<TableCell>
|
<TextField
|
size="small"
|
fullWidth
|
placeholder={translate('table.field.basStation.stationId')}
|
value={p.stationId || ''}
|
onChange={(e) => changePair(index, 'stationId', e.target.value)}
|
/>
|
</TableCell>
|
<TableCell>
|
<IconButton
|
size="small"
|
onClick={() => removeRow(index)}
|
disabled={pairs.length <= 1}
|
>
|
<DeleteIcon fontSize="small" />
|
</IconButton>
|
</TableCell>
|
</TableRow>
|
))}
|
</TableBody>
|
</Table>
|
</TableContainer>
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
|
<span>{translate('table.field.basStation.stationName')} / {translate('table.field.basStation.stationId')}(必填)</span>
|
<Button size="small" startIcon={<AddIcon />} onClick={addRow}>
|
新增一行
|
</Button>
|
</Box>
|
|
</Grid>
|
|
{/* 以下与新增页顺序、含义完全一致 */}
|
<Grid item xs={6} display="flex" gap={1}>
|
<FormControl fullWidth size="small">
|
<InputLabel>{translate('table.field.basStation.type')}</InputLabel>
|
<Select
|
label={translate('table.field.basStation.type')}
|
value={common.type}
|
onChange={(e) => setCommon((c) => ({ ...c, type: e.target.value }))}
|
>
|
<MenuItem value={0}>智能站点</MenuItem>
|
<MenuItem value={1}>普通站点</MenuItem>
|
</Select>
|
</FormControl>
|
</Grid>
|
<Grid item xs={6} display="flex" gap={1}>
|
<FormControl fullWidth size="small">
|
<InputLabel>{translate('table.field.basStation.useStatus')}</InputLabel>
|
<Select
|
label={translate('table.field.basStation.useStatus')}
|
value={common.useStatus ?? ''}
|
onChange={(e) => setCommon((c) => ({ ...c, useStatus: e.target.value }))}
|
>
|
<MenuItem value="">请选择</MenuItem>
|
{useStatusOptions.map((opt) => (
|
<MenuItem key={opt.value} value={opt.value}>
|
{opt.label}
|
</MenuItem>
|
))}
|
</Select>
|
</FormControl>
|
</Grid>
|
<Grid item xs={6} display="flex" gap={1}>
|
<FormControl fullWidth size="small">
|
<InputLabel>{translate('table.field.basStation.crossZoneArea')}</InputLabel>
|
<Select
|
multiple
|
label={translate('table.field.basStation.crossZoneArea')}
|
value={common.areaIds ?? []}
|
onChange={(e) => setCommon((c) => ({ ...c, areaIds: e.target.value }))}
|
renderValue={(selected) =>
|
(selected || [])
|
.map((id) => areaOptions.find((a) => a.id === id)?.name ?? id)
|
.join(', ')
|
}
|
>
|
{areaOptions.map((opt) => (
|
<MenuItem key={opt.id} value={opt.id}>
|
{opt.name}
|
</MenuItem>
|
))}
|
</Select>
|
</FormControl>
|
</Grid>
|
<Grid item xs={6} display="flex" gap={1}>
|
<FormControl fullWidth size="small">
|
<InputLabel>{translate('table.field.basStation.containerType')}</InputLabel>
|
<Select
|
multiple
|
label={translate('table.field.basStation.containerType')}
|
value={common.containerTypes ?? []}
|
onChange={(e) => setCommon((c) => ({ ...c, containerTypes: e.target.value }))}
|
renderValue={(selected) =>
|
(selected || [])
|
.map((val) => containerTypeOptions.find((c) => String(c.value) === String(val))?.label ?? val)
|
.join(', ')
|
}
|
>
|
{containerTypeOptions.map((opt) => (
|
<MenuItem key={opt.value} value={opt.value}>
|
{opt.label}
|
</MenuItem>
|
))}
|
</Select>
|
</FormControl>
|
</Grid>
|
<Grid item xs={6} display="flex" gap={1}>
|
<FormControl fullWidth size="small">
|
<InputLabel>{translate('table.field.basStation.inAble')}</InputLabel>
|
<Select
|
label={translate('table.field.basStation.inAble')}
|
value={common.inAble}
|
onChange={(e) => setCommon((c) => ({ ...c, inAble: e.target.value }))}
|
>
|
<MenuItem value={0}>否</MenuItem>
|
<MenuItem value={1}>是</MenuItem>
|
</Select>
|
</FormControl>
|
</Grid>
|
<Grid item xs={6} display="flex" gap={1}>
|
<FormControl fullWidth size="small">
|
<InputLabel>{translate('table.field.basStation.outAble')}</InputLabel>
|
<Select
|
label={translate('table.field.basStation.outAble')}
|
value={common.outAble}
|
onChange={(e) => setCommon((c) => ({ ...c, outAble: e.target.value }))}
|
>
|
<MenuItem value={0}>否</MenuItem>
|
<MenuItem value={1}>是</MenuItem>
|
</Select>
|
</FormControl>
|
</Grid>
|
</Grid>
|
</DialogContent>
|
<DialogActions
|
sx={{
|
position: 'sticky',
|
bottom: 0,
|
backgroundColor: 'background.paper',
|
zIndex: 1000,
|
}}
|
>
|
<Button
|
disabled={loading}
|
variant="contained"
|
startIcon={<SaveIcon />}
|
onClick={handleSubmit}
|
>
|
{loading ? '保存中...' : translate('ra.action.save')}
|
</Button>
|
</DialogActions>
|
</Dialog>
|
);
|
};
|
|
export default BasStationInitModal;
|