增加审批组件
This commit is contained in:
parent
f05e6a55fd
commit
a4ab7a6016
@ -206,7 +206,6 @@ const FormRenderer = forwardRef<FormRendererRef, FormRendererProps>((props, ref)
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
setFormData({});
|
||||
message.info('表单已重置');
|
||||
};
|
||||
|
||||
// 监听表单值变化
|
||||
|
||||
@ -14,7 +14,7 @@ const ToastViewport = React.forwardRef<
|
||||
<ToastPrimitives.Viewport
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed top-0 right-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:flex-col md:max-w-[420px]",
|
||||
"fixed top-0 right-0 z-[9999] flex max-h-screen w-full flex-col-reverse p-4 sm:flex-col md:max-w-[420px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { FormRenderer } from '@/components/FormDesigner';
|
||||
import Editor from '@/components/Editor';
|
||||
import { ArrowLeft, Loader2 } from 'lucide-react';
|
||||
import { getFormDataById } from './service';
|
||||
import type { FormDataResponse, FormDataStatus, FormDataBusinessType } from './types';
|
||||
@ -100,48 +100,59 @@ const FormDataDetail: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<Card className="mb-4">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-2xl font-bold">表单数据详情</h2>
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
返回列表
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>表单数据详情</CardTitle>
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
返回列表
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-0">
|
||||
<DescriptionItem label="表单标识" value={data.formKey} />
|
||||
<DescriptionItem label="表单版本" value={`v${data.formVersion}`} />
|
||||
<DescriptionItem label="业务类型" value={getBusinessTypeBadge(data.businessType)} />
|
||||
<DescriptionItem label="业务标识" value={data.businessKey || '-'} />
|
||||
<DescriptionItem label="提交人" value={data.submitter || '-'} />
|
||||
<DescriptionItem label="提交时间" value={data.submitTime || '-'} />
|
||||
<DescriptionItem label="状态" value={getStatusBadge(data.status)} />
|
||||
<DescriptionItem label="创建时间" value={data.createTime || '-'} />
|
||||
<DescriptionItem label="更新时间" value={data.updateTime || '-'} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-0">
|
||||
<DescriptionItem label="表单标识" value={data.formKey} />
|
||||
<DescriptionItem label="表单版本" value={`v${data.formVersion}`} />
|
||||
<DescriptionItem label="业务类型" value={getBusinessTypeBadge(data.businessType)} />
|
||||
<DescriptionItem label="业务标识" value={data.businessKey || '-'} />
|
||||
<DescriptionItem label="提交人" value={data.submitter || '-'} />
|
||||
<DescriptionItem label="提交时间" value={data.submitTime || '-'} />
|
||||
<DescriptionItem label="状态" value={getStatusBadge(data.status)} />
|
||||
<DescriptionItem label="创建时间" value={data.createTime || '-'} />
|
||||
<DescriptionItem label="更新时间" value={data.updateTime || '-'} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>表单数据</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{/* 使用 FormRenderer 以只读模式展示数据 */}
|
||||
<FormRenderer
|
||||
schema={data.schemaSnapshot}
|
||||
value={data.data}
|
||||
readonly={true}
|
||||
showSubmit={false}
|
||||
showCancel={true}
|
||||
cancelText="返回"
|
||||
onCancel={handleBack}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>表单数据</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="border rounded-md overflow-hidden">
|
||||
<Editor
|
||||
height="600px"
|
||||
language="json"
|
||||
value={JSON.stringify(data.data, null, 2)}
|
||||
options={{
|
||||
readOnly: true,
|
||||
minimap: { enabled: false },
|
||||
fontSize: 14,
|
||||
lineNumbers: 'on',
|
||||
scrollBeyondLastLine: false,
|
||||
automaticLayout: true,
|
||||
wordWrap: 'on',
|
||||
theme: 'vs-light'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -294,13 +294,13 @@ const FormDataList: React.FC = () => {
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[180px]">表单标识</TableHead>
|
||||
<TableHead className="w-[240px]">表单标识</TableHead>
|
||||
<TableHead className="w-[120px]">分类</TableHead>
|
||||
<TableHead className="w-[100px]">业务类型</TableHead>
|
||||
<TableHead className="w-[150px]">业务标识</TableHead>
|
||||
<TableHead className="w-[100px]">提交人</TableHead>
|
||||
<TableHead className="w-[180px]">提交时间</TableHead>
|
||||
<TableHead className="w-[100px]">状态</TableHead>
|
||||
<TableHead className="w-[140px]">状态</TableHead>
|
||||
<TableHead className="text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Modal, Button as AntButton } from 'antd';
|
||||
import { Card, CardHeader, CardTitle, CardContent, CardDescription } from '@/components/ui/card';
|
||||
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@/components/ui/table';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@ -8,7 +9,7 @@ import { Input } from '@/components/ui/input';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from '@/components/ui/dialog';
|
||||
import { DataTablePagination } from '@/components/ui/pagination';
|
||||
import { FormRenderer } from '@/components/FormDesigner';
|
||||
import { FormRenderer, type FormRendererRef } from '@/components/FormDesigner';
|
||||
import {
|
||||
Loader2, Plus, Search, Eye, Edit, FileText, Ban, Trash2,
|
||||
Database, MoreHorizontal, CheckCircle2, XCircle, Clock, AlertCircle,
|
||||
@ -61,6 +62,7 @@ const FormDefinitionList: React.FC = () => {
|
||||
// 预览弹窗
|
||||
const [previewVisible, setPreviewVisible] = useState(false);
|
||||
const [previewForm, setPreviewForm] = useState<FormDefinitionResponse | null>(null);
|
||||
const previewFormRef = useRef<FormRendererRef>(null);
|
||||
|
||||
// 删除确认弹窗
|
||||
const [deleteVisible, setDeleteVisible] = useState(false);
|
||||
@ -522,26 +524,30 @@ const FormDefinitionList: React.FC = () => {
|
||||
|
||||
{/* 预览弹窗 */}
|
||||
{previewForm && (
|
||||
<Dialog open={previewVisible} onOpenChange={setPreviewVisible}>
|
||||
<DialogContent className="max-w-4xl max-h-[85vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>预览表单</DialogTitle>
|
||||
<DialogDescription>
|
||||
{previewForm.name} - {previewForm.key} (v{previewForm.formVersion})
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<Separator className="my-4" />
|
||||
<div className="py-4">
|
||||
<FormRenderer
|
||||
schema={previewForm.schema}
|
||||
value={{}}
|
||||
readonly={true}
|
||||
showSubmit={false}
|
||||
onCancel={() => setPreviewVisible(false)}
|
||||
/>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<Modal
|
||||
title={`预览表单 - ${previewForm.name}`}
|
||||
open={previewVisible}
|
||||
onCancel={() => setPreviewVisible(false)}
|
||||
width={800}
|
||||
footer={[
|
||||
<AntButton
|
||||
key="close"
|
||||
onClick={() => setPreviewVisible(false)}
|
||||
>
|
||||
关闭
|
||||
</AntButton>,
|
||||
]}
|
||||
>
|
||||
<div className="text-sm text-muted-foreground mb-4">
|
||||
{previewForm.key} (v{previewForm.formVersion})
|
||||
</div>
|
||||
<FormRenderer
|
||||
ref={previewFormRef}
|
||||
schema={previewForm.schema}
|
||||
value={{}}
|
||||
readonly={true}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
{/* 删除确认弹窗 */}
|
||||
|
||||
@ -859,7 +859,6 @@ const handleSubmit = async () => {
|
||||
保存
|
||||
</Button>,
|
||||
]}
|
||||
destroyOnClose
|
||||
>
|
||||
<FormRenderer
|
||||
ref={modalFormRef}
|
||||
|
||||
@ -4,21 +4,9 @@
|
||||
*/
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Modal } from 'antd';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogPortal,
|
||||
AlertDialogOverlay,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { Modal, Button } from 'antd';
|
||||
import { FormRenderer, type FormRendererRef } from '@/components/FormDesigner';
|
||||
import { useToast } from '@/components/ui/use-toast';
|
||||
import type { FormDefinitionResponse } from '@/pages/Form/Definition/types';
|
||||
import type { WorkflowDefinition } from '../types';
|
||||
|
||||
@ -44,7 +32,7 @@ const StartWorkflowModal: React.FC<StartWorkflowModalProps> = ({
|
||||
}) => {
|
||||
const formRef = useRef<FormRendererRef>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showCancelConfirm, setShowCancelConfirm] = useState(false);
|
||||
const { toast } = useToast();
|
||||
|
||||
// 处理提交
|
||||
const handleSubmit = async (formData: Record<string, any>) => {
|
||||
@ -69,16 +57,18 @@ const StartWorkflowModal: React.FC<StartWorkflowModalProps> = ({
|
||||
};
|
||||
};
|
||||
|
||||
// 处理取消
|
||||
// 处理取消 - 直接关闭弹窗
|
||||
const handleCancel = () => {
|
||||
setShowCancelConfirm(true);
|
||||
onClose();
|
||||
};
|
||||
|
||||
// 确认取消
|
||||
const confirmCancel = () => {
|
||||
// 处理重置
|
||||
const handleReset = () => {
|
||||
formRef.current?.reset();
|
||||
setShowCancelConfirm(false);
|
||||
onClose();
|
||||
toast({
|
||||
title: "表单已重置",
|
||||
description: "所有字段已恢复为初始状态",
|
||||
});
|
||||
};
|
||||
|
||||
// 处理表单提交触发
|
||||
@ -100,72 +90,74 @@ const StartWorkflowModal: React.FC<StartWorkflowModalProps> = ({
|
||||
const { schema } = formDefinition;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
title={formDefinition.name || `启动工作流:${workflowDefinition.name}`}
|
||||
open={open}
|
||||
onCancel={handleCancel}
|
||||
width={schema.formConfig.formWidth || 600}
|
||||
footer={
|
||||
<div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
|
||||
<Button variant="outline" onClick={() => formRef.current?.reset()}>
|
||||
重置
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleTriggerSubmit}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? '启动中...' : '启动工作流'}
|
||||
</Button>
|
||||
<Modal
|
||||
title={
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingRight: '40px' }}>
|
||||
<span>{formDefinition.name || `启动工作流:${workflowDefinition.name}`}</span>
|
||||
<div style={{ display: 'flex', gap: '8px', fontSize: '12px' }}>
|
||||
<span style={{
|
||||
background: '#f5f5f5',
|
||||
padding: '2px 10px',
|
||||
borderRadius: '12px',
|
||||
color: '#666',
|
||||
fontWeight: 'normal'
|
||||
}}>
|
||||
工作流 v{workflowDefinition.flowVersion}
|
||||
</span>
|
||||
<span style={{
|
||||
background: '#f5f5f5',
|
||||
padding: '2px 10px',
|
||||
borderRadius: '12px',
|
||||
color: '#666',
|
||||
fontWeight: 'normal'
|
||||
}}>
|
||||
表单 v{formDefinition.formVersion}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
destroyOnClose
|
||||
>
|
||||
<FormRenderer
|
||||
ref={formRef}
|
||||
fields={schema.fields}
|
||||
formConfig={schema.formConfig}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
|
||||
{/* 表单元信息 */}
|
||||
<div style={{
|
||||
marginTop: 16,
|
||||
padding: 12,
|
||||
background: '#f5f5f5',
|
||||
borderRadius: 4,
|
||||
fontSize: 12,
|
||||
color: '#666'
|
||||
}}>
|
||||
<div><strong>工作流标识:</strong>{workflowDefinition.key}</div>
|
||||
<div><strong>工作流版本:</strong>v{workflowDefinition.flowVersion}</div>
|
||||
<div><strong>表单标识:</strong>{formDefinition.key}</div>
|
||||
<div><strong>表单版本:</strong>v{formDefinition.formVersion}</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
{/* 取消确认对话框 - 设置更高的 z-index 确保在 Modal 之上 */}
|
||||
<AlertDialog open={showCancelConfirm} onOpenChange={setShowCancelConfirm}>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay style={{ zIndex: 1050 }} />
|
||||
<AlertDialogContent style={{ zIndex: 1051 }}>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>确认取消</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
工作流将不会启动,确定要取消吗?
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={() => setShowCancelConfirm(false)}>返回</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={confirmCancel}>确定取消</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</AlertDialog>
|
||||
</>
|
||||
}
|
||||
open={open}
|
||||
onCancel={handleCancel}
|
||||
width={schema.formConfig.formWidth || 600}
|
||||
centered
|
||||
footer={
|
||||
<div style={{ display: 'flex', justifyContent: 'center', gap: '12px' }}>
|
||||
<Button
|
||||
key="reset"
|
||||
onClick={handleReset}
|
||||
style={{ minWidth: '88px' }}
|
||||
>
|
||||
重置
|
||||
</Button>
|
||||
<Button
|
||||
key="cancel"
|
||||
onClick={handleCancel}
|
||||
style={{ minWidth: '88px' }}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
loading={loading}
|
||||
onClick={handleTriggerSubmit}
|
||||
style={{
|
||||
minWidth: '120px',
|
||||
backgroundColor: '#000',
|
||||
borderColor: '#000'
|
||||
}}
|
||||
>
|
||||
启动工作流
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<FormRenderer
|
||||
ref={formRef}
|
||||
schema={schema}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user