Ver código fonte

feat: add CredentialModal and ProductForm

BaiLuoYan 3 dias atrás
pai
commit
21ba8e9478

+ 49 - 0
src/pages/Admin/Product/Detail/components/CredentialModal.tsx

@@ -0,0 +1,49 @@
+import { useIntl } from '@umijs/max';
+import { Alert, Modal, Typography } from 'antd';
+
+const { Paragraph } = Typography;
+
+interface CredentialModalProps {
+  open: boolean;
+  data: API.FetchInitialCredentialsResp | null;
+  onClose: () => void;
+}
+
+const CopyField = ({ label, value }: { label: string; value: string }) => (
+  <div className="mb-3">
+    <div className="text-xs text-gray-500 mb-1">{label}</div>
+    <Paragraph copyable className="font-mono bg-gray-50 px-3 py-2 rounded mb-0">
+      {value}
+    </Paragraph>
+  </div>
+);
+
+export const CredentialModal = ({ open, data, onClose }: CredentialModalProps) => {
+  const intl = useIntl();
+  return (
+    <Modal
+      title={intl.formatMessage({ id: 'admin.product.credential.title' })}
+      open={open}
+      onOk={onClose}
+      onCancel={onClose}
+      okText={intl.formatMessage({ id: 'admin.product.credential.confirm' })}
+      cancelButtonProps={{ style: { display: 'none' } }}
+      maskClosable={false}
+    >
+      <Alert
+        type="warning"
+        message={intl.formatMessage({ id: 'admin.product.credential.warning' })}
+        className="mb-4"
+        showIcon
+      />
+      {data && (
+        <>
+          <CopyField label="App Key" value={data.appKey} />
+          <CopyField label="App Secret" value={data.appSecret} />
+          <CopyField label="管理员账号" value={data.adminUser} />
+          <CopyField label="管理员初始密码" value={data.adminPassword} />
+        </>
+      )}
+    </Modal>
+  );
+};

+ 67 - 0
src/pages/Admin/Product/components/Form.tsx

@@ -0,0 +1,67 @@
+import { fetchDeptTree } from '@/services/dept';
+import { fetchCreateProduct, fetchUpdateProduct } from '@/services/product';
+import { DrawerForm, ProFormItem, ProFormText } from '@ant-design/pro-components';
+import { TreeSelect } from 'antd';
+import { useEffect, useState } from 'react';
+
+interface ProductFormProps {
+  mode: EditorFormMode;
+  initialValues?: Partial<API.ProductItem>;
+  trigger: React.ReactElement;
+  onSuccess: (credentialsTicket?: string) => void;
+}
+
+const buildDeptTreeData = (items: API.DeptItem[]): any[] =>
+  items.map((d) => ({
+    value: d.id,
+    title: d.name,
+    children: d.children ? buildDeptTreeData(d.children) : undefined,
+  }));
+
+export const ProductForm = ({ mode, initialValues, trigger, onSuccess }: ProductFormProps) => {
+  const [deptTree, setDeptTree] = useState<any[]>([]);
+  const title = mode === 'edit' ? '编辑产品' : '新建产品';
+
+  useEffect(() => {
+    fetchDeptTree().then((res) => setDeptTree(buildDeptTreeData(res.data ?? [])));
+  }, []);
+
+  const handleFinish = async (values: any) => {
+    if (mode === 'edit' && initialValues?.id) {
+      await fetchUpdateProduct({ id: initialValues.id, name: values.name, remark: values.remark });
+      onSuccess();
+    } else {
+      const res = await fetchCreateProduct(values);
+      onSuccess(res.data?.credentialsTicket);
+    }
+    return true;
+  };
+
+  return (
+    <DrawerForm
+      title={title}
+      trigger={trigger}
+      initialValues={mode === 'edit' ? initialValues : undefined}
+      onFinish={handleFinish}
+      drawerProps={{ destroyOnClose: true }}
+    >
+      <ProFormText name="name" label="产品名称" rules={[{ required: true }]} />
+      {mode !== 'edit' && (
+        <ProFormText
+          name="code"
+          label="产品 Code"
+          rules={[
+            { required: true },
+            { pattern: /^[a-z0-9-]+$/, message: '只允许小写字母、数字和连字符' },
+          ]}
+        />
+      )}
+      {mode !== 'edit' && (
+        <ProFormItem name="adminDeptId" label="管理员所属部门" rules={[{ required: true }]}>
+          <TreeSelect treeData={deptTree} placeholder="请选择部门" />
+        </ProFormItem>
+      )}
+      <ProFormText name="remark" label="备注" />
+    </DrawerForm>
+  );
+};