Procházet zdrojové kódy

feat(notice): notice template

Lind před 3 roky
rodič
revize
34a26c222a

+ 8 - 0
src/pages/notice/Config/Detail/index.less

@@ -0,0 +1,8 @@
+.form {
+  :global {
+    .ant-radio-button-wrapper {
+      height: 100%;
+      margin-right: 15px;
+    }
+  }
+}

+ 223 - 0
src/pages/notice/Config/Detail/index.tsx

@@ -0,0 +1,223 @@
+import { PageContainer } from '@ant-design/pro-layout';
+import { createForm, onFieldValueChange } from '@formily/core';
+import { Card, Col, Input, Row } from 'antd';
+import { ISchema } from '@formily/json-schema';
+import { useMemo } from 'react';
+import { createSchemaField } from '@formily/react';
+import { FormButtonGroup, FormItem, Select, Submit, Switch, Form } from '@formily/antd';
+import styles from './index.less';
+import { service } from '@/pages/notice/Config';
+import { useAsyncDataSource } from '@/utils/util';
+import { useParams } from 'umi';
+import { typeList } from '@/pages/notice';
+
+const Detail = () => {
+  const { id } = useParams<{ id: string }>();
+
+  const form = useMemo(
+    () =>
+      createForm({
+        validateFirst: true,
+        effects() {
+          onFieldValueChange('type', async (field, f) => {
+            const type = field.value;
+            if (!type) return;
+            f.setFieldState('provider', (state) => {
+              state.value = undefined;
+              // state.dataSource = providerRef.current
+              //   .find((item) => type === item.id)
+              //   ?.providerInfos.map((i) => ({ label: i.name, value: i.id }));
+            });
+          });
+          onFieldValueChange('provider', async () => {
+            // eslint-disable-next-line @typescript-eslint/no-use-before-define
+            // currentType = field.value;
+            // await createSchema();
+          });
+        },
+      }),
+    [id],
+  );
+
+  const SchemaField = createSchemaField({
+    components: {
+      FormItem,
+      Input,
+      Select,
+      Switch,
+    },
+  });
+
+  const getTypes = async () =>
+    service.getTypes().then((resp) => {
+      return resp.result.map((item: NetworkType) => ({
+        label: item.name,
+        value: item.id,
+      }));
+    });
+
+  const schema: ISchema = {
+    type: 'object',
+    properties: {
+      name: {
+        title: '名称',
+        'x-component': 'Input',
+        'x-decorator': 'FormItem',
+      },
+      type: {
+        title: '分类',
+        'x-component': 'Input',
+        'x-value': id,
+      },
+      provider: {
+        title: '类型',
+        type: 'string',
+        'x-decorator': 'FormItem',
+        'x-component': 'Radio.Group',
+        'x-component-props': {
+          optionType: 'button',
+        },
+        required: true,
+        'x-visible': typeList[id]?.length > 0,
+        enum: typeList[id] || [],
+      },
+      configuration: {
+        type: 'object',
+        properties: {
+          weixin: {
+            type: 'void',
+            properties: {
+              corpId: {
+                title: 'corpID',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 企业消息
+              },
+              corpSecret: {
+                title: 'corpSecret',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 企业消息
+              },
+              AppId: {
+                title: 'appId',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 服务号
+              },
+              AppSecret: {
+                title: 'appSecret',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 服务号
+              },
+            },
+          },
+          dingTalk: {
+            type: 'void',
+            properties: {
+              AppKey: {
+                title: 'AppKey',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 钉钉消息通知
+              },
+              AppSecret: {
+                title: 'AppSecret',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 钉钉消息通知
+              },
+              Webhook: {
+                title: 'webHook',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+                // 群机器人
+              },
+            },
+          },
+          // 阿里云语音/短信
+          voiceOrSms: {
+            type: 'void',
+            properties: {
+              RegionId: {
+                title: 'regionId',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              AccessKeyId: {
+                title: 'accessKeyId',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              Secret: {
+                title: 'secret',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+            },
+          },
+          email: {
+            type: 'void',
+            properties: {
+              host: {
+                title: '服务器地址',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              port: {
+                title: '端口',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              enableSSL: {
+                title: '开启SSL',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              sender: {
+                title: '发件人',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              username: {
+                title: '用户名',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+              password: {
+                title: '密码',
+                'x-component': 'Input',
+                'x-decorator': 'FormItem',
+              },
+            },
+          },
+        },
+      },
+    },
+  };
+
+  return (
+    <PageContainer>
+      <Card>
+        <Row>
+          <Col span={10}>
+            <Form className={styles.form} form={form} layout={'vertical'}>
+              <SchemaField scope={{ useAsyncDataSource, getTypes }} schema={schema} />
+              <FormButtonGroup.Sticky>
+                <FormButtonGroup.FormItem>
+                  <Submit>保存</Submit>
+                </FormButtonGroup.FormItem>
+              </FormButtonGroup.Sticky>
+            </Form>
+          </Col>
+          <Col span={12} push={2}>
+            结果
+          </Col>
+        </Row>
+      </Card>
+    </PageContainer>
+  );
+};
+
+export default Detail;

+ 162 - 128
src/pages/notice/Config/index.tsx

@@ -6,17 +6,20 @@ import {
   BugOutlined,
   BugOutlined,
   EditOutlined,
   EditOutlined,
   MinusOutlined,
   MinusOutlined,
+  PlusOutlined,
 } from '@ant-design/icons';
 } from '@ant-design/icons';
-import { message, Popconfirm, Tooltip } from 'antd';
+import { Button, message, Popconfirm, Tooltip } from 'antd';
 import { useMemo, useRef, useState } from 'react';
 import { useMemo, useRef, useState } from 'react';
-import BaseCrud from '@/components/BaseCrud';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useIntl } from '@@/plugin-locale/localeExports';
-import type { ISchema } from '@formily/json-schema';
-import { downloadObject, useAsyncDataSource } from '@/utils/util';
+import { downloadObject } from '@/utils/util';
 import { CurdModel } from '@/components/BaseCrud/model';
 import { CurdModel } from '@/components/BaseCrud/model';
 import Service from '@/pages/notice/Config/service';
 import Service from '@/pages/notice/Config/service';
 import { createForm, onFieldValueChange } from '@formily/core';
 import { createForm, onFieldValueChange } from '@formily/core';
 import { observer } from '@formily/react';
 import { observer } from '@formily/react';
+import SearchComponent from '@/components/SearchComponent';
+import ProTable from '@jetlinks/pro-table';
+import { history } from '@@/core/history';
+import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 
 
 export const service = new Service('notifier/config');
 export const service = new Service('notifier/config');
 
 
@@ -26,112 +29,112 @@ const Config = observer(() => {
   const providerRef = useRef<NetworkType[]>([]);
   const providerRef = useRef<NetworkType[]>([]);
   const oldTypeRef = useRef();
   const oldTypeRef = useRef();
 
 
-  const [configSchema, setConfigSchema] = useState<ISchema>({});
-  const [loading, setLoading] = useState<boolean>(false);
+  // const [configSchema, setConfigSchema] = useState<ISchema>({});
+  // const [loading, setLoading] = useState<boolean>(false);
   const createSchema = async () => {
   const createSchema = async () => {
     // eslint-disable-next-line @typescript-eslint/no-use-before-define
     // eslint-disable-next-line @typescript-eslint/no-use-before-define
     const DForm = form;
     const DForm = form;
     if (!DForm?.values) return;
     if (!DForm?.values) return;
     DForm.setValuesIn('provider', DForm.values.provider);
     DForm.setValuesIn('provider', DForm.values.provider);
-    const resp = await service.getMetadata(
-      DForm?.values?.type,
-      // eslint-disable-next-line @typescript-eslint/no-use-before-define
-      currentType || DForm.values?.provider,
-    );
-    const properties = resp.result?.properties as ConfigMetadata[];
-    setConfigSchema({
-      type: 'object',
-      properties: properties?.reduce((previousValue, currentValue) => {
-        if (currentValue.type?.type === 'array') {
-          // 单独处理邮件的其他配置功能
-          previousValue[currentValue.property] = {
-            type: 'array',
-            title: '其他配置',
-            'x-component': 'ArrayItems',
-            'x-decorator': 'FormItem',
-            items: {
-              type: 'object',
-              properties: {
-                space: {
-                  type: 'void',
-                  'x-component': 'Space',
-                  properties: {
-                    sort: {
-                      type: 'void',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'ArrayItems.SortHandle',
-                    },
-                    name: {
-                      type: 'string',
-                      title: 'key',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'Input',
-                    },
-                    value: {
-                      type: 'string',
-                      title: 'value',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'Input',
-                    },
-                    description: {
-                      type: 'string',
-                      title: '备注',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'Input',
-                    },
-                    remove: {
-                      type: 'void',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'ArrayItems.Remove',
-                    },
-                  },
-                },
-              },
-            },
-            properties: {
-              add: {
-                type: 'void',
-                title: '添加条目',
-                'x-component': 'ArrayItems.Addition',
-              },
-            },
-          };
-        } else {
-          previousValue[currentValue.property] = {
-            title: currentValue.name,
-            type: 'string',
-            'x-component': 'Input',
-            'x-decorator': 'FormItem',
-          };
-        }
-        return previousValue;
-      }, {}),
-    });
-    DForm.setValues(CurdModel.current);
-    setLoading(false);
-  };
-  const schema: ISchema = {
-    type: 'object',
-    properties: {
-      name: {
-        title: '名称',
-        'x-component': 'Input',
-        'x-decorator': 'FormItem',
-      },
-      type: {
-        title: '类型',
-        'x-component': 'Select',
-        'x-decorator': 'FormItem',
-        'x-reactions': ['{{useAsyncDataSource(getTypes)}}'],
-      },
-      provider: {
-        title: '服务商',
-        'x-component': 'Select',
-        'x-decorator': 'FormItem',
-      },
-      configuration: configSchema,
-    },
+    // const resp = await service.getMetadata(
+    //   DForm?.values?.type,
+    //   // eslint-disable-next-line @typescript-eslint/no-use-before-define
+    //   currentType || DForm.values?.provider,
+    // );
+    // const properties = resp.result?.properties as ConfigMetadata[];
+    // setConfigSchema({
+    //   type: 'object',
+    //   properties: properties?.reduce((previousValue, currentValue) => {
+    //     if (currentValue.type?.type === 'array') {
+    //       // 单独处理邮件的其他配置功能
+    //       previousValue[currentValue.property] = {
+    //         type: 'array',
+    //         title: '其他配置',
+    //         'x-component': 'ArrayItems',
+    //         'x-decorator': 'FormItem',
+    //         items: {
+    //           type: 'object',
+    //           properties: {
+    //             space: {
+    //               type: 'void',
+    //               'x-component': 'Space',
+    //               properties: {
+    //                 sort: {
+    //                   type: 'void',
+    //                   'x-decorator': 'FormItem',
+    //                   'x-component': 'ArrayItems.SortHandle',
+    //                 },
+    //                 name: {
+    //                   type: 'string',
+    //                   title: 'key',
+    //                   'x-decorator': 'FormItem',
+    //                   'x-component': 'Input',
+    //                 },
+    //                 value: {
+    //                   type: 'string',
+    //                   title: 'value',
+    //                   'x-decorator': 'FormItem',
+    //                   'x-component': 'Input',
+    //                 },
+    //                 description: {
+    //                   type: 'string',
+    //                   title: '备注',
+    //                   'x-decorator': 'FormItem',
+    //                   'x-component': 'Input',
+    //                 },
+    //                 remove: {
+    //                   type: 'void',
+    //                   'x-decorator': 'FormItem',
+    //                   'x-component': 'ArrayItems.Remove',
+    //                 },
+    //               },
+    //             },
+    //           },
+    //         },
+    //         properties: {
+    //           add: {
+    //             type: 'void',
+    //             title: '添加条目',
+    //             'x-component': 'ArrayItems.Addition',
+    //           },
+    //         },
+    //       };
+    //     } else {
+    //       previousValue[currentValue.property] = {
+    //         title: currentValue.name,
+    //         type: 'string',
+    //         'x-component': 'Input',
+    //         'x-decorator': 'FormItem',
+    //       };
+    //     }
+    //     return previousValue;
+    //   }, {}),
+    // });
+    // DForm.setValues(CurdModel.current);
+    // setLoading(false);
   };
   };
+  // const schema: ISchema = {
+  //   type: 'object',
+  //   properties: {
+  //     name: {
+  //       title: '名称',
+  //       'x-component': 'Input',
+  //       'x-decorator': 'FormItem',
+  //     },
+  //     type: {
+  //       title: '类型',
+  //       'x-component': 'Select',
+  //       'x-decorator': 'FormItem',
+  //       'x-reactions': ['{{useAsyncDataSource(getTypes)}}'],
+  //     },
+  //     provider: {
+  //       title: '服务商',
+  //       'x-component': 'Select',
+  //       'x-decorator': 'FormItem',
+  //     },
+  //     configuration: configSchema,
+  //   },
+  // };
 
 
   const formEvent = () => {
   const formEvent = () => {
     onFieldValueChange('type', async (field, f) => {
     onFieldValueChange('type', async (field, f) => {
@@ -206,7 +209,7 @@ const Config = observer(() => {
         <a
         <a
           key="edit"
           key="edit"
           onClick={async () => {
           onClick={async () => {
-            setLoading(true);
+            // setLoading(true);
             CurdModel.update(record);
             CurdModel.update(record);
             form.setValues(record);
             form.setValues(record);
             await createSchema();
             await createSchema();
@@ -280,33 +283,64 @@ const Config = observer(() => {
     },
     },
   ];
   ];
 
 
-  const getTypes = async () =>
-    service.getTypes().then((resp) => {
-      providerRef.current = resp.result;
-      return resp.result.map((item: NetworkType) => ({
-        label: item.name,
-        value: item.id,
-      }));
-    });
-
+  // const getTypes = async () =>
+  //   service.getTypes().then((resp) => {
+  //     providerRef.current = resp.result;
+  //     return resp.result.map((item: NetworkType) => ({
+  //       label: item.name,
+  //       value: item.id,
+  //     }));
+  //   });
+  const [param, setParam] = useState({});
   return (
   return (
     <PageContainer className={'page-title-show'}>
     <PageContainer className={'page-title-show'}>
-      <BaseCrud
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.notice.config',
-          defaultMessage: '通知配置',
-        })}
-        modelConfig={{
-          width: '50vw',
-          loading: loading,
+      <SearchComponent
+        field={columns}
+        onSearch={(data) => {
+          actionRef.current?.reset?.();
+          setParam(data);
         }}
         }}
-        schema={schema}
-        form={form}
-        schemaConfig={{ scope: { useAsyncDataSource, getTypes } }}
-        actionRef={actionRef}
       />
       />
+      <ProTable<ConfigItem>
+        search={false}
+        params={param}
+        columns={columns}
+        headerTitle={'通知模版'}
+        toolBarRender={() => [
+          <Button
+            onClick={() => {
+              const id = (location as any).query?.id;
+              history.push(getMenuPathByParams(MENUS_CODE['notice/Config/Detail'], id));
+            }}
+            key="button"
+            icon={<PlusOutlined />}
+            type="primary"
+          >
+            {intl.formatMessage({
+              id: 'pages.data.option.add',
+              defaultMessage: '新增',
+            })}
+          </Button>,
+        ]}
+        request={async (params) => service.query(params)}
+      />
+
+      {/*<BaseCrud*/}
+      {/*  columns={columns}*/}
+      {/*  service={service}*/}
+      {/*  title={intl.formatMessage({*/}
+      {/*    id: 'pages.notice.config',*/}
+      {/*    defaultMessage: '通知配置',*/}
+      {/*  })}*/}
+      {/*  modelConfig={{*/}
+      {/*    width: '50vw',*/}
+      {/*    loading: loading,*/}
+      {/*  }}*/}
+      {/*  schema={schema}*/}
+      {/*  form={form}*/}
+      {/*  schemaConfig={{ scope: { useAsyncDataSource, getTypes } }}*/}
+      {/*  actionRef={actionRef}*/}
+      {/*/>*/}
     </PageContainer>
     </PageContainer>
   );
   );
 });
 });

+ 157 - 96
src/pages/notice/Template/Detail/index.tsx

@@ -5,6 +5,7 @@ import {
   FormButtonGroup,
   FormButtonGroup,
   FormItem,
   FormItem,
   Input,
   Input,
+  NumberPicker,
   PreviewText,
   PreviewText,
   Radio,
   Radio,
   Select,
   Select,
@@ -14,24 +15,18 @@ import {
 } from '@formily/antd';
 } from '@formily/antd';
 import type { Field } from '@formily/core';
 import type { Field } from '@formily/core';
 import { createForm, onFieldValueChange } from '@formily/core';
 import { createForm, onFieldValueChange } from '@formily/core';
-import { createSchemaField } from '@formily/react';
+import { createSchemaField, observer } from '@formily/react';
 import type { ISchema } from '@formily/json-schema';
 import type { ISchema } from '@formily/json-schema';
 import styles from './index.less';
 import styles from './index.less';
-import { useMemo, useState } from 'react';
+import { useEffect, useMemo } from 'react';
 import FUpload from '@/components/Upload';
 import FUpload from '@/components/Upload';
 import { useParams } from 'umi';
 import { useParams } from 'umi';
 import { PageContainer } from '@ant-design/pro-layout';
 import { PageContainer } from '@ant-design/pro-layout';
-import { Card, Col, Row } from 'antd';
+import { Card, Col, message, Row } from 'antd';
+import { typeList } from '@/pages/notice';
+import { service, state } from '@/pages/notice/Template';
 
 
-const createImageLabel = (image: string, text: string) => {
-  return (
-    <>
-      <img alt="" height="100px" src={image} />
-      <div style={{ textAlign: 'center' }}>{text}</div>
-    </>
-  );
-};
-const Detail = () => {
+const Detail = observer(() => {
   const { id } = useParams<{ id: string }>();
   const { id } = useParams<{ id: string }>();
 
 
   // 正则提取${}里面的值
   // 正则提取${}里面的值
@@ -47,13 +42,49 @@ const Detail = () => {
               .match(pattern)
               .match(pattern)
               ?.filter((i: string) => i)
               ?.filter((i: string) => i)
               .map((item: string) => ({ id: item }));
               .map((item: string) => ({ id: item }));
-            form1.setValuesIn('variableDefinitions', idList);
+            if (form1.modified) {
+              form1.setValuesIn('variableDefinitions', idList);
+            }
+          });
+          onFieldValueChange('variableDefinitions.*.type', () => {
+            // const value = (field as Field).value;
+            // console.log(value, 'value');
+            // const format = field.query('.format').take() as DataField;
+            // console.log(field.query('.format'), field.query('.format').take(), 'values')
+            // switch (format.value) {
+            //   case 'date':
+            //     break;
+            //   case 'string':
+            //     format.setComponent(Input);
+            //     format.setDataSource([])
+            //     break;
+            //   case 'number':
+            //     format.setComponent(Input);
+            //     // format.setValue('%.xf');
+            //     break;
+            //   case 'file':
+            //     format.setComponent(Select);
+            //     format.setDataSource([
+            //       {label: '视频', value: 'video'},
+            //       {label: '图片', value: 'img'},
+            //       {label: '全部', value: 'any'},
+            //       {label: '', value: ''},
+            //     ])
+            //
+            //     break;
+            // }
           });
           });
         },
         },
       }),
       }),
     [id],
     [id],
   );
   );
 
 
+  useEffect(() => {
+    if (state.current) {
+      form.setValues(state.current);
+    }
+  }, []);
+
   const SchemaField = createSchemaField({
   const SchemaField = createSchemaField({
     components: {
     components: {
       FormItem,
       FormItem,
@@ -66,74 +97,46 @@ const Detail = () => {
       PreviewText,
       PreviewText,
       Space,
       Space,
       FUpload,
       FUpload,
+      NumberPicker,
     },
     },
   });
   });
 
 
-  const [result, setResult] = useState<any>({});
   const handleSave = async () => {
   const handleSave = async () => {
-    const data = await form.submit();
-    setResult(data);
-  };
+    const data: TemplateItem = await form.submit();
 
 
-  const typeList = {
-    weixin: [
-      {
-        label: createImageLabel(
-          'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
-          '企业消息',
-        ),
-        value: 'corpMessage',
-      },
-      {
-        label: createImageLabel(
-          'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/Hire.png',
-          '服务号消息',
-        ),
-        value: 'officialMessage',
-      },
-    ],
-    dingTalk: [
-      {
-        label: createImageLabel(
-          'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
-          '钉钉消息',
-        ),
-        value: 'dingTalkMessage',
-      },
-      {
-        label: createImageLabel(
-          'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/Hire.png',
-          '群机器人消息',
-        ),
-        value: 'dingTalkRobotWebHook',
-      },
-    ],
-    voice: [
-      {
-        label: createImageLabel(
-          'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
-          '阿里云语音',
-        ),
-        value: 'aliyun',
-      },
-    ],
-    sms: [
-      {
-        label: createImageLabel(
-          'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
-          '阿里云短信',
-        ),
-        value: 'aliyunSms',
-      },
-    ],
-    email: [],
+    // dingTalkRobotWebHook
+
+    // 提交的时候处理内容
+    // 钉钉机器人-->dingTalkRobotWebHook
+    // r如果是text 的话。template.message=>template.text.content
+    // 如果是markdown 的话。 template.message=>template.markdown.text
+    // 如果是link的话。 template.message =>template.markdown.text
+    if (data.provider === 'dingTalkRobotWebHook') {
+      const type = data.template.messageType;
+      // emplate.messageType
+      switch (type) {
+        case 'text':
+          data.template.text = {
+            content: data.template.message,
+          };
+          // data.template.text.content = data.template.message;
+          break;
+        case 'markdown':
+          data.template.markdown.text = data.template.message;
+          break;
+        case 'link':
+          data.template.link.text = data.template.message;
+      }
+    }
+
+    const response: any = await service.save(data);
+
+    if (response?.status === 200) {
+      message.success('保存成功');
+      history.back();
+    }
   };
   };
 
 
-  // 提交的时候处理内容
-  // 钉钉机器人-->dingTalkRobotWebHook
-  // r如果是text 的话。template.message=>template.text.content
-  // 如果是markdown 的话。 template.message=>template.markdown.text
-  // 如果是link的话。 template.message =>template.markdown.text
   const schema: ISchema = {
   const schema: ISchema = {
     type: 'object',
     type: 'object',
     properties: {
     properties: {
@@ -154,6 +157,11 @@ const Detail = () => {
           },
           },
         ],
         ],
       },
       },
+      type: {
+        title: '类型',
+        'x-value': id,
+        'x-hidden': true,
+      },
       provider: {
       provider: {
         title: '类型',
         title: '类型',
         type: 'string',
         type: 'string',
@@ -184,7 +192,7 @@ const Detail = () => {
             type: 'void',
             type: 'void',
             'x-visible': id === 'weixin',
             'x-visible': id === 'weixin',
             properties: {
             properties: {
-              agentID: {
+              agentId: {
                 title: 'AgentId',
                 title: 'AgentId',
                 'x-component': 'Input',
                 'x-component': 'Input',
                 'x-decorator': 'FormItem',
                 'x-decorator': 'FormItem',
@@ -237,7 +245,7 @@ const Detail = () => {
               dingTalkMessage: {
               dingTalkMessage: {
                 type: 'void',
                 type: 'void',
                 properties: {
                 properties: {
-                  agentID: {
+                  agentId: {
                     title: 'AgentID',
                     title: 'AgentID',
                     'x-component': 'Input',
                     'x-component': 'Input',
                     'x-decorator': 'FormItem',
                     'x-decorator': 'FormItem',
@@ -329,7 +337,7 @@ const Detail = () => {
                         'x-component': 'Input',
                         'x-component': 'Input',
                         'x-decorator': 'FormItem',
                         'x-decorator': 'FormItem',
                       },
                       },
-                      picUrl: {
+                      '{url:picUrl}': {
                         title: '图片链接',
                         title: '图片链接',
                         'x-component': 'FUpload',
                         'x-component': 'FUpload',
                         'x-decorator': 'FormItem',
                         'x-decorator': 'FormItem',
@@ -373,7 +381,7 @@ const Detail = () => {
             properties: {
             properties: {
               voice: {
               voice: {
                 'x-visible': id === 'voice',
                 'x-visible': id === 'voice',
-                type: 'object',
+                type: 'void',
                 properties: {
                 properties: {
                   // ttsCode	String	语音-模版ID
                   // ttsCode	String	语音-模版ID
                   // calledShowNumbers	String	语音-被叫显号
                   // calledShowNumbers	String	语音-被叫显号
@@ -381,30 +389,86 @@ const Detail = () => {
                   // PlayTimes	String	语音-播放次数
                   // PlayTimes	String	语音-播放次数
                   ttsCode: {
                   ttsCode: {
                     title: '模版ID',
                     title: '模版ID',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入模版ID',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入模版ID',
+                    },
                   },
                   },
                   calledShowNumbers: {
                   calledShowNumbers: {
                     title: '被叫号码',
                     title: '被叫号码',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入calledShowNumbers',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入calledShowNumbers',
+                    },
                   },
                   },
-                  CalledNumber: {
+                  calledNumber: {
                     title: '被叫显号',
                     title: '被叫显号',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入CalledNumber',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入CalledNumber',
+                    },
                   },
                   },
                   PlayTimes: {
                   PlayTimes: {
                     title: '播放次数',
                     title: '播放次数',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入PlayTimes',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入PlayTimes',
+                    },
                   },
                   },
                 },
                 },
               },
               },
               sms: {
               sms: {
                 'x-visible': id === 'sms',
                 'x-visible': id === 'sms',
-                type: 'object',
+                type: 'void',
                 properties: {
                 properties: {
                   code: {
                   code: {
                     title: '模版ID',
                     title: '模版ID',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入模版ID',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入模版ID',
+                    },
                   },
                   },
                   phoneNumber: {
                   phoneNumber: {
                     title: '收信人',
                     title: '收信人',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入收信人',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入收信人',
+                    },
                   },
                   },
                   signName: {
                   signName: {
                     title: '签名',
                     title: '签名',
+                    'x-component': 'Input',
+                    'x-decorator': 'FormItem',
+                    'x-decorator-props': {
+                      tooltip: '请输入签名',
+                    },
+                    'x-component-props': {
+                      placeholder: '请输入签名',
+                    },
                   },
                   },
                   // code	String	短信-模板ID
                   // code	String	短信-模板ID
                   // signName	String	短信-签名
                   // signName	String	短信-签名
@@ -487,27 +551,17 @@ const Detail = () => {
             column3: {
             column3: {
               type: 'void',
               type: 'void',
               'x-component': 'ArrayTable.Column',
               'x-component': 'ArrayTable.Column',
-              'x-component-props': { title: '类型', width: '100px' },
+              'x-component-props': { title: '类型', width: '120px' },
               properties: {
               properties: {
                 type: {
                 type: {
                   type: 'string',
                   type: 'string',
                   'x-decorator': 'FormItem',
                   'x-decorator': 'FormItem',
                   'x-component': 'Select',
                   'x-component': 'Select',
                   enum: [
                   enum: [
+                    { label: '时间', value: 'date' },
+                    { label: '数字', value: 'number' },
                     { label: '字符串', value: 'string' },
                     { label: '字符串', value: 'string' },
-                    { label: '日期', value: 'date' },
-                    { label: 'int', value: 'int' },
-                    { label: '数组', value: 'array' },
-                    { label: '布尔', value: 'date' },
-                    { label: 'double', value: 'double' },
-                    { label: '枚举', value: 'enum' },
-                    { label: '浮点', value: 'float' },
-                    { label: 'long', value: 'long' },
-                    { label: '对象', value: 'object' },
                     { label: '文件', value: 'file' },
                     { label: '文件', value: 'file' },
-                    { label: '密码', value: 'password' },
-                    { label: 'geoShape', value: 'geoShape' },
-                    { label: 'geoPoint', value: 'geoPoint' },
                   ],
                   ],
                 },
                 },
               },
               },
@@ -520,7 +574,14 @@ const Detail = () => {
                 format: {
                 format: {
                   type: 'string',
                   type: 'string',
                   'x-decorator': 'FormItem',
                   'x-decorator': 'FormItem',
-                  'x-component': 'Input',
+                  'x-component': 'Select',
+                  enum: [
+                    { label: 'String类型的UTC时间戳 (毫秒)', value: 'string' },
+                    { label: 'yyyy-MM-dd', value: 'yyyy-MM-dd' },
+                    { label: 'yyyy-MM-dd HH:mm:ss', value: 'yyyy-MM-dd HH:mm:ss' },
+                    { label: 'yyyy-MM-dd HH:mm:ss EE', value: 'yyyy-MM-dd HH:mm:ss EE' },
+                    { label: 'yyyy-MM-dd HH:mm:ss zzz', value: 'yyyy-MM-dd HH:mm:ss zzz' },
+                  ],
                 },
                 },
               },
               },
             },
             },
@@ -552,11 +613,11 @@ const Detail = () => {
             </Form>
             </Form>
           </Col>
           </Col>
           <Col span={12} push={2}>
           <Col span={12} push={2}>
-            {JSON.stringify(result, null, 2)}
+            这里是放描述信息的
           </Col>
           </Col>
         </Row>
         </Row>
       </Card>
       </Card>
     </PageContainer>
     </PageContainer>
   );
   );
-};
+});
 export default Detail;
 export default Detail;

+ 16 - 11
src/pages/notice/Template/index.tsx

@@ -7,8 +7,8 @@ import ProTable from '@jetlinks/pro-table';
 import {
 import {
   ArrowDownOutlined,
   ArrowDownOutlined,
   BugOutlined,
   BugOutlined,
+  DeleteOutlined,
   EditOutlined,
   EditOutlined,
-  MinusOutlined,
   PlusOutlined,
   PlusOutlined,
 } from '@ant-design/icons';
 } from '@ant-design/icons';
 import { Button, Tooltip } from 'antd';
 import { Button, Tooltip } from 'antd';
@@ -19,19 +19,20 @@ import SearchComponent from '@/components/SearchComponent';
 // import Detail from '@/pages/notice/Template/Detail';
 // import Detail from '@/pages/notice/Template/Detail';
 import { history, useLocation } from 'umi';
 import { history, useLocation } from 'umi';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { model } from '@formily/reactive';
 
 
 export const service = new Service('notifier/template');
 export const service = new Service('notifier/template');
+export const state = model<{
+  current?: TemplateItem;
+}>({});
 const Template = () => {
 const Template = () => {
   const intl = useIntl();
   const intl = useIntl();
+  const location = useLocation<{ id: string }>();
+  const id = (location as any).query?.id;
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
 
 
   const columns: ProColumns<TemplateItem>[] = [
   const columns: ProColumns<TemplateItem>[] = [
     {
     {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
       dataIndex: 'name',
       dataIndex: 'name',
       title: intl.formatMessage({
       title: intl.formatMessage({
         id: 'pages.table.name',
         id: 'pages.table.name',
@@ -61,7 +62,13 @@ const Template = () => {
       align: 'center',
       align: 'center',
       width: 200,
       width: 200,
       render: (text, record) => [
       render: (text, record) => [
-        <a key="edit" onClick={() => console.log(record)}>
+        <a
+          key="edit"
+          onClick={() => {
+            state.current = record;
+            history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
+          }}
+        >
           <Tooltip
           <Tooltip
             title={intl.formatMessage({
             title={intl.formatMessage({
               id: 'pages.data.option.edit',
               id: 'pages.data.option.edit',
@@ -78,7 +85,7 @@ const Template = () => {
               defaultMessage: '删除',
               defaultMessage: '删除',
             })}
             })}
           >
           >
-            <MinusOutlined />
+            <DeleteOutlined />
           </Tooltip>
           </Tooltip>
         </a>,
         </a>,
         <a key="download">
         <a key="download">
@@ -600,8 +607,6 @@ const Template = () => {
   //   },
   //   },
   // };
   // };
 
 
-  const location = useLocation<{ id: string }>();
-
   const [param, setParam] = useState({});
   const [param, setParam] = useState({});
   return (
   return (
     <PageContainer className={'page-title-show'}>
     <PageContainer className={'page-title-show'}>
@@ -623,7 +628,7 @@ const Template = () => {
         toolBarRender={() => [
         toolBarRender={() => [
           <Button
           <Button
             onClick={() => {
             onClick={() => {
-              const id = (location as any).query?.id;
+              state.current = undefined;
               history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
               history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
             }}
             }}
             key="button"
             key="button"

+ 1 - 1
src/pages/notice/Template/typings.d.ts

@@ -2,7 +2,7 @@ type TemplateItem = {
   id: string;
   id: string;
   name: string;
   name: string;
   type: string;
   type: string;
-  template: string;
+  template: any;
   provider: string;
   provider: string;
   creatorId: string;
   creatorId: string;
   createTime: number;
   createTime: number;

+ 63 - 0
src/pages/notice/index.tsx

@@ -7,6 +7,69 @@ import { observer } from '@formily/react';
 import { history } from 'umi';
 import { history } from 'umi';
 import { getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
 import { getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
 
 
+const createImageLabel = (image: string, text: string) => {
+  return (
+    <>
+      <img alt="" height="100px" src={image} />
+      <div style={{ textAlign: 'center' }}>{text}</div>
+    </>
+  );
+};
+
+export const typeList = {
+  weixin: [
+    {
+      label: createImageLabel(
+        'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
+        '企业消息',
+      ),
+      value: 'corpMessage',
+    },
+    {
+      label: createImageLabel(
+        'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/Hire.png',
+        '服务号消息',
+      ),
+      value: 'officialMessage',
+    },
+  ],
+  dingTalk: [
+    {
+      label: createImageLabel(
+        'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
+        '钉钉消息',
+      ),
+      value: 'dingTalkMessage',
+    },
+    {
+      label: createImageLabel(
+        'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/Hire.png',
+        '群机器人消息',
+      ),
+      value: 'dingTalkRobotWebHook',
+    },
+  ],
+  voice: [
+    {
+      label: createImageLabel(
+        'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
+        '阿里云语音',
+      ),
+      value: 'aliyun',
+    },
+  ],
+  sms: [
+    {
+      label: createImageLabel(
+        'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/staticfiles/passport/OKR.png',
+        '阿里云短信',
+      ),
+      value: 'aliyunSms',
+    },
+  ],
+  email: [],
+};
+
 const Type = observer(() => {
 const Type = observer(() => {
   const list = [
   const list = [
     {
     {

+ 1 - 0
src/utils/menu/router.ts

@@ -47,6 +47,7 @@ export const MENUS_CODE = {
   'media/Stream': 'media/Stream',
   'media/Stream': 'media/Stream',
   'media/Stream/Detail': 'media/Stream/Detail',
   'media/Stream/Detail': 'media/Stream/Detail',
   'notice/Type': 'notice/Type',
   'notice/Type': 'notice/Type',
+  'notice/Config': 'notice/Config',
   'media/SplitScreen': 'media/SplitScreen',
   'media/SplitScreen': 'media/SplitScreen',
   'notice/Type/Config': 'notice/Config',
   'notice/Type/Config': 'notice/Config',
   'notice/Config/Detail': 'notice/Config/Detail',
   'notice/Config/Detail': 'notice/Config/Detail',