| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import React, { useState, useImperativeHandle, forwardRef } from 'react';
- import { postApi, PostVO, PostStatus } from '../api/Post';
- import { toast } from 'sonner';
- import { Modal, Form, Input, Button, Select, Spin } from 'antd';
- import { DICT_TYPE, getIntDictOptions } from '../utils/dict';
- import { useTranslation } from 'react-i18next';
- interface PostFormProps {
- onSuccess?: () => void;
- }
- export interface PostFormRef {
- open: (type: string, id?: number) => void;
- }
- const PostForm = forwardRef<PostFormRef, PostFormProps>(({ onSuccess }, ref) => {
- const { t } = useTranslation();
- const [dialogVisible, setDialogVisible] = useState(false);
- const [dialogTitle, setDialogTitle] = useState('');
- const [formType, setFormType] = useState<'create' | 'update'>('create');
- const [formLoading, setFormLoading] = useState(false);
- const [currentId, setCurrentId] = useState<number | undefined>();
- const [form] = Form.useForm();
-
- // 获取最新的字典选项(每次调用都从缓存中获取最新数据)
- const getStatusOptions = () => getIntDictOptions(DICT_TYPE.COMMON_STATUS);
- // 暴露方法给父组件
- useImperativeHandle(ref, () => ({
- open: (type: string, id?: number) => {
- setDialogTitle(type === 'create' ? t('common.addPost') : t('common.editPost'));
- setFormType(type as 'create' | 'update');
- setCurrentId(id);
- form.resetFields();
- if (id) {
- loadPostData(id);
- } else {
- // 从字典中获取默认启用状态值
- const defaultStatus = getStatusOptions().find(opt => opt.label === '启用' || opt.colorType === 'success')?.value ?? getStatusOptions()[0]?.value ?? 1;
- form.setFieldsValue({
- name: '',
- code: '',
- sort: 0,
- status: defaultStatus,
- remark: '',
- });
- setFormLoading(false);
- }
- setDialogVisible(true);
- },
- }));
- // 加载岗位数据
- const loadPostData = async (id: number) => {
- setFormLoading(true);
- try {
- const res = await postApi.getPost(id);
- const data = (res as any)?.data || res;
- form.setFieldsValue({
- name: data.name,
- code: data.code,
- sort: data.sort ?? 0,
- status: typeof data.status === 'string' ? Number(data.status) : (data.status ?? (getStatusOptions().find(opt => opt.label === '启用' || opt.colorType === 'success')?.value ?? getStatusOptions()[0]?.value ?? 1)),
- remark: data.remark || '',
- });
- } catch (error: any) {
- toast.error(error.message || t('common.error'));
- } finally {
- setFormLoading(false);
- }
- };
- // 提交表单
- const submitForm = async () => {
- try {
- const values = await form.validateFields();
- setFormLoading(true);
-
- const submitData: PostVO = {
- ...values,
- sort: Number(values.sort) || 0,
- status: Number(values.status),
- };
- if (formType === 'create') {
- await postApi.createPost(submitData);
- toast.success(t('common.addSuccess'));
- } else {
- if (currentId) {
- submitData.id = currentId;
- }
- await postApi.updatePost(submitData);
- toast.success(t('common.updateSuccess'));
- }
- setDialogVisible(false);
- onSuccess?.();
- } catch (error: any) {
- if (error.errorFields) {
- // 表单验证错误
- return;
- }
- toast.error(error.message || t('common.saveFailed'));
- } finally {
- setFormLoading(false);
- }
- };
- return (
- <Modal
- title={dialogTitle}
- open={dialogVisible}
- onCancel={() => setDialogVisible(false)}
- onOk={submitForm}
- confirmLoading={formLoading}
- okText={t('common.confirm')}
- cancelText={t('common.cancel')}
- width={600}
- destroyOnClose
- >
- <Spin spinning={formLoading && formType === 'update'}>
- <Form
- form={form}
- layout="horizontal"
- labelCol={{ span: 4 }}
- wrapperCol={{ span: 20 }}
- initialValues={{
- sort: 0,
- status: getStatusOptions().find(opt => opt.label === '启用' || opt.colorType === 'success')?.value ?? getStatusOptions()[0]?.value ?? 1,
- remark: '',
- }}
- >
- <Form.Item
- label={t('form.postName')}
- name="name"
- rules={[
- { required: true, message: t('form.postNamePlaceholder') },
- { max: 50, message: t('common.error') },
- ]}
- >
- <Input placeholder={t('form.postNamePlaceholder')} />
- </Form.Item>
- <Form.Item
- label={t('form.postCode')}
- name="code"
- rules={[
- { required: true, message: t('form.postCodePlaceholder') },
- { max: 50, message: t('common.error') },
- ]}
- >
- <Input placeholder={t('form.postCodePlaceholder')} />
- </Form.Item>
- <Form.Item
- label={t('table.postSort')}
- name="sort"
- rules={[{ required: true, message: t('form.sortPlaceholder') }]}
- >
- <Input type="number" placeholder={t('form.sortPlaceholder')} min={0} />
- </Form.Item>
- <Form.Item
- label={t('form.status')}
- name="status"
- rules={[{ required: true, message: t('common.pleaseSelect') }]}
- >
- <Select placeholder={t('common.pleaseSelect')}>
- {getStatusOptions().map((option) => (
- <Select.Option key={option.value} value={option.value}>
- {option.label}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
- <Form.Item
- label={t('form.remark')}
- name="remark"
- >
- <Input.TextArea placeholder={t('form.remarkPlaceholder')} rows={4} />
- </Form.Item>
- </Form>
- </Spin>
- </Modal>
- );
- });
- PostForm.displayName = 'PostForm';
- export default PostForm;
|