From f07c5f38c7262129adb1dfe916956dcc4ab2c140 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期六, 07 三月 2026 14:25:40 +0800
Subject: [PATCH] #任务步骤

---
 rsf-admin/src/page/task/FlowStepInstanceModal.jsx |  243 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 243 insertions(+), 0 deletions(-)

diff --git a/rsf-admin/src/page/task/FlowStepInstanceModal.jsx b/rsf-admin/src/page/task/FlowStepInstanceModal.jsx
new file mode 100644
index 0000000..fa71460
--- /dev/null
+++ b/rsf-admin/src/page/task/FlowStepInstanceModal.jsx
@@ -0,0 +1,243 @@
+import React, { useState, useEffect } from "react";
+import {
+    useTranslate,
+    useNotify,
+    useRefresh,
+    Button,
+    DatagridConfigurable,
+    TextField,
+    NumberField,
+    DateField,
+    EditButton,
+    Toolbar,
+    useRecordContext,
+    SimpleForm,
+    TextInput,
+    NumberInput,
+    SelectInput,
+    WrapperField
+} from 'react-admin';
+
+import { Box, DialogContent, DialogTitle, DialogActions, Dialog, IconButton, Tooltip } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import DialogCloseButton from "../components/DialogCloseButton";
+import request from '@/utils/request';
+import AddIcon from '@mui/icons-material/Add';
+import DeleteIcon from '@mui/icons-material/Delete';
+import EditIcon from '@mui/icons-material/Edit';
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+    '& .css-1vooibu-MuiSvgIcon-root': {
+        height: '.9em'
+    },
+    '& .RaDatagrid-row': {
+        cursor: 'auto'
+    },
+    '& .opt': {
+        width: 150
+    },
+}));
+
+const FlowStepInstanceModal = (props) => {
+    const { open, setOpen, record } = props;
+    const translate = useTranslate();
+    const notify = useNotify();
+    const [data, setData] = useState([]);
+    const [loading, setLoading] = useState(false);
+
+    // Form states
+    const [formOpen, setFormOpen] = useState(false);
+    const [isEdit, setIsEdit] = useState(false);
+    const [formData, setFormData] = useState({});
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+        }
+    };
+
+    const fetchData = async () => {
+        if (!record?.taskCode) return;
+        setLoading(true);
+        try {
+            const res = await request.post(`/flowStepInstance/page`, {
+                taskNo: record.taskCode,
+                current: 1,
+                pageSize: 999
+            });
+            if (res.data.code === 200) {
+                setData(res.data.data.records || []);
+            } else {
+                notify(res.data.msg, { type: 'error' });
+            }
+        } catch (error) {
+            notify('Failed to fetch data', { type: 'error' });
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    useEffect(() => {
+        if (open && record) {
+            fetchData();
+        }
+    }, [open, record]);
+
+    const handleCreate = () => {
+        setFormData({ taskNo: record?.taskCode, status: 0 }); // Default values
+        setIsEdit(false);
+        setFormOpen(true);
+    };
+
+    const handleEdit = (item) => {
+        setFormData(item);
+        setIsEdit(true);
+        setFormOpen(true);
+    };
+
+    const handleDelete = async (item) => {
+        try {
+            const res = await request.post(`/flowStepInstance/remove/${item.id}`);
+            if (res.data.code === 200) {
+                notify('Deleted successfully', { type: 'success' });
+                fetchData();
+            } else {
+                notify(res.data.msg, { type: 'error' });
+            }
+        } catch (error) {
+            notify('Delete failed', { type: 'error' });
+        }
+    };
+
+    const handleFormClose = () => {
+        setFormOpen(false);
+        setFormData({});
+    };
+
+    const handleSave = async (dataToSave) => {
+        try {
+            let res;
+            if (isEdit) {
+                res = await request.post(`/flowStepInstance/update`, dataToSave);
+            } else {
+                res = await request.post(`/flowStepInstance/save`, dataToSave);
+            }
+
+            if (res.data.code === 200) {
+                notify(isEdit ? 'Updated successfully' : 'Created successfully', { type: 'success' });
+                setFormOpen(false);
+                fetchData();
+            } else {
+                notify(res.data.msg, { type: 'error' });
+            }
+        } catch (error) {
+            notify('Save failed', { type: 'error' });
+        }
+    };
+
+    return (
+        <React.Fragment>
+            <Dialog
+                open={open}
+                onClose={handleClose}
+                aria-labelledby="form-dialog-title"
+                fullWidth
+                maxWidth="lg"
+            >
+                <DialogTitle id="form-dialog-title" sx={{
+                    position: 'sticky',
+                    top: 0,
+                    backgroundColor: 'background.paper',
+                    zIndex: 1000
+                }}>
+                    {translate('menu.missionFlowStepInstance')}
+                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                        <DialogCloseButton onClose={handleClose} />
+                    </Box>
+                </DialogTitle>
+                <DialogContent sx={{ minHeight: 400 }}>
+                    <Box sx={{ mb: 2, display: 'flex', justifyContent: 'flex-end' }}>
+                        <Button variant="contained" label="ra.action.create" onClick={handleCreate}>
+                            <AddIcon />
+                        </Button>
+                    </Box>
+                    <StyledDatagrid
+                        data={data}
+                        isLoading={loading}
+                        bulkActionButtons={false}
+                        rowClick={false}
+                    >
+                        <NumberField source="id" label={translate("table.field.flowStepInstance.id")} />
+                        <NumberField source="stepOrder" label={translate("table.field.flowStepInstance.stepOrder")} />
+                        <TextField source="stepCode" label={translate("table.field.flowStepInstance.stepCode")} />
+                        <TextField source="stepName" label={translate("table.field.flowStepInstance.stepName")} />
+                        <TextField source="stepType" label={translate("table.field.flowStepInstance.stepType")} />
+                        <NumberField source="status" label={translate("table.field.flowStepInstance.status")} />
+                        <TextField source="executeResult" label={translate("table.field.flowStepInstance.executeResult")} />
+                        <TextField source="taskNo" label={translate("table.field.flowStepInstance.taskNo")} />
+                        <DateField source="createTime" label={translate("table.field.flowStepInstance.createTime")} showTime />
+                        <WrapperField cellClassName="opt" label="common.field.opt" onClick={(e) => e.stopPropagation()} >
+                            <RowActions onEdit={handleEdit} onDelete={handleDelete} />
+                        </WrapperField>
+                    </StyledDatagrid>
+                </DialogContent>
+                <DialogActions>
+                    <Button label="ra.action.close" onClick={handleClose} />
+                </DialogActions>
+            </Dialog>
+
+            {/* Nested Form Dialog */}
+            <Dialog open={formOpen} onClose={handleFormClose} fullWidth maxWidth="sm">
+                <DialogTitle>
+                    {isEdit ? translate("ra.action.edit") : translate("ra.action.create")}
+                </DialogTitle>
+                <DialogContent>
+                    <SimpleForm record={formData} onSubmit={handleSave} toolbar={<CustomToolbar />}>
+                        <TextInput source="taskNo" disabled fullWidth label={translate("table.field.flowStepInstance.taskNo")} />
+                        <NumberInput source="stepOrder" required fullWidth label={translate("table.field.flowStepInstance.stepOrder")} />
+                        <TextInput source="stepCode" required fullWidth label={translate("table.field.flowStepInstance.stepCode")} />
+                        <TextInput source="stepName" required fullWidth label={translate("table.field.flowStepInstance.stepName")} />
+                        <TextInput source="stepType" required fullWidth label={translate("table.field.flowStepInstance.stepType")} />
+                        <SelectInput source="status" label={translate("table.field.flowStepInstance.status")} choices={[
+                            { id: 0, name: '鎺掗槦涓�' },
+                            { id: 1, name: '寰呮墽琛�' },
+                            { id: 2, name: '鎵ц涓�' },
+                            { id: 3, name: '鎵ц鎴愬姛' },
+                            { id: 4, name: '鎵ц澶辫触' },
+                            { id: 5, name: '宸茶烦杩�' },
+                            { id: 6, name: '宸插彇娑�' }
+                        ]} required fullWidth />
+                        <TextInput source="executeResult" fullWidth label={translate("table.field.flowStepInstance.executeResult")} />
+                    </SimpleForm>
+                </DialogContent>
+            </Dialog>
+        </React.Fragment>
+    );
+};
+
+const RowActions = ({ onEdit, onDelete }) => {
+    const record = useRecordContext();
+    return (
+        <Box display="flex">
+            <Tooltip title="Edit">
+                <IconButton onClick={() => onEdit(record)} size="small" color="primary">
+                    <EditIcon fontSize="small" />
+                </IconButton>
+            </Tooltip>
+            {/* If there's an issue with event propagation you might need to handle it in onClick */}
+            <Tooltip title="Delete">
+                <IconButton onClick={() => onDelete(record)} size="small" color="error">
+                    <DeleteIcon fontSize="small" />
+                </IconButton>
+            </Tooltip>
+        </Box>
+    );
+};
+
+const CustomToolbar = props => (
+    <Toolbar {...props}>
+        <Button label="ra.action.save" type="submit" variant="contained" />
+    </Toolbar>
+);
+
+export default FlowStepInstanceModal;

--
Gitblit v1.9.1