|
|
@@ -1,5 +1,4 @@
|
|
|
import { PageContainer } from '@ant-design/pro-layout';
|
|
|
-import BaseService from '@/utils/BaseService';
|
|
|
import type { ActionType, ProColumns } from '@jetlinks/pro-table';
|
|
|
import {
|
|
|
ArrowDownOutlined,
|
|
|
@@ -8,16 +7,165 @@ import {
|
|
|
EditOutlined,
|
|
|
MinusOutlined,
|
|
|
} from '@ant-design/icons';
|
|
|
-import { Tooltip } from 'antd';
|
|
|
-import { useRef } from 'react';
|
|
|
+import { message, Popconfirm, Tooltip } from 'antd';
|
|
|
+import { useMemo, useRef, useState } from 'react';
|
|
|
import BaseCrud from '@/components/BaseCrud';
|
|
|
import { useIntl } from '@@/plugin-locale/localeExports';
|
|
|
+import type { ISchema } from '@formily/json-schema';
|
|
|
+import { downObject, useAsyncDataSource } from '@/utils/util';
|
|
|
+import { CurdModel } from '@/components/BaseCrud/model';
|
|
|
+import Service from '@/pages/notice/Config/service';
|
|
|
+import { createForm, onFieldValueChange } from '@formily/core';
|
|
|
+import { observer } from '@formily/react';
|
|
|
|
|
|
-export const service = new BaseService<ConfigItem>('notifier/config');
|
|
|
+export const service = new Service('notifier/config');
|
|
|
|
|
|
-const Config = () => {
|
|
|
+const Config = observer(() => {
|
|
|
const intl = useIntl();
|
|
|
const actionRef = useRef<ActionType>();
|
|
|
+ const providerRef = useRef<NetworkType[]>([]);
|
|
|
+ const oldTypeRef = useRef();
|
|
|
+
|
|
|
+ const [configSchema, setConfigSchema] = useState<ISchema>({});
|
|
|
+ const [loading, setLoading] = useState<boolean>(false);
|
|
|
+ const createSchema = async () => {
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
|
+ const DForm = form;
|
|
|
+ if (!DForm?.values) return;
|
|
|
+ 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 formEvent = () => {
|
|
|
+ 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 (field) => {
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
|
+ currentType = field.value;
|
|
|
+ await createSchema();
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const form = useMemo(
|
|
|
+ () =>
|
|
|
+ createForm({
|
|
|
+ effects: formEvent,
|
|
|
+ initialValues: CurdModel.current,
|
|
|
+ }),
|
|
|
+ [],
|
|
|
+ );
|
|
|
+
|
|
|
+ let currentType = form.values.provider;
|
|
|
+
|
|
|
+ if (oldTypeRef.current !== currentType) {
|
|
|
+ form.clearFormGraph('configuration.*'); // 回收字段模型
|
|
|
+ form.deleteValuesIn('configuration.*');
|
|
|
+ }
|
|
|
|
|
|
const columns: ProColumns<ConfigItem>[] = [
|
|
|
{
|
|
|
@@ -55,7 +203,16 @@ const Config = () => {
|
|
|
align: 'center',
|
|
|
width: 200,
|
|
|
render: (text, record) => [
|
|
|
- <a onClick={() => console.log(record)}>
|
|
|
+ <a
|
|
|
+ key="edit"
|
|
|
+ onClick={async () => {
|
|
|
+ setLoading(true);
|
|
|
+ CurdModel.update(record);
|
|
|
+ form.setValues(record);
|
|
|
+ await createSchema();
|
|
|
+ CurdModel.model = 'edit';
|
|
|
+ }}
|
|
|
+ >
|
|
|
<Tooltip
|
|
|
title={intl.formatMessage({
|
|
|
id: 'pages.data.option.edit',
|
|
|
@@ -65,17 +222,7 @@ const Config = () => {
|
|
|
<EditOutlined />
|
|
|
</Tooltip>
|
|
|
</a>,
|
|
|
- <a>
|
|
|
- <Tooltip
|
|
|
- title={intl.formatMessage({
|
|
|
- id: 'pages.data.option.remove',
|
|
|
- defaultMessage: '删除',
|
|
|
- })}
|
|
|
- >
|
|
|
- <MinusOutlined />
|
|
|
- </Tooltip>
|
|
|
- </a>,
|
|
|
- <a>
|
|
|
+ <a onClick={() => downObject(record, '通知配置')} key="download">
|
|
|
<Tooltip
|
|
|
title={intl.formatMessage({
|
|
|
id: 'pages.data.option.download',
|
|
|
@@ -85,7 +232,7 @@ const Config = () => {
|
|
|
<ArrowDownOutlined />
|
|
|
</Tooltip>
|
|
|
</a>,
|
|
|
- <a>
|
|
|
+ <a key="debug">
|
|
|
<Tooltip
|
|
|
title={intl.formatMessage({
|
|
|
id: 'pages.notice.option.debug',
|
|
|
@@ -95,7 +242,7 @@ const Config = () => {
|
|
|
<BugOutlined />
|
|
|
</Tooltip>
|
|
|
</a>,
|
|
|
- <a>
|
|
|
+ <a key="record">
|
|
|
<Tooltip
|
|
|
title={intl.formatMessage({
|
|
|
id: 'pages.data.option.record',
|
|
|
@@ -105,11 +252,42 @@ const Config = () => {
|
|
|
<BarsOutlined />
|
|
|
</Tooltip>
|
|
|
</a>,
|
|
|
+ <a key="remove">
|
|
|
+ <Popconfirm
|
|
|
+ onConfirm={async () => {
|
|
|
+ await service.remove(record.id);
|
|
|
+ message.success(
|
|
|
+ intl.formatMessage({
|
|
|
+ id: 'pages.data.option.success',
|
|
|
+ defaultMessage: '操作成功!',
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ actionRef.current?.reload();
|
|
|
+ }}
|
|
|
+ title="确认删除?"
|
|
|
+ >
|
|
|
+ <Tooltip
|
|
|
+ title={intl.formatMessage({
|
|
|
+ id: 'pages.data.option.remove',
|
|
|
+ defaultMessage: '删除',
|
|
|
+ })}
|
|
|
+ >
|
|
|
+ <MinusOutlined />
|
|
|
+ </Tooltip>
|
|
|
+ </Popconfirm>
|
|
|
+ </a>,
|
|
|
],
|
|
|
},
|
|
|
];
|
|
|
|
|
|
- const schema = {};
|
|
|
+ const getTypes = async () =>
|
|
|
+ service.getTypes().then((resp) => {
|
|
|
+ providerRef.current = resp.result;
|
|
|
+ return resp.result.map((item: NetworkType) => ({
|
|
|
+ label: item.name,
|
|
|
+ value: item.id,
|
|
|
+ }));
|
|
|
+ });
|
|
|
|
|
|
return (
|
|
|
<PageContainer>
|
|
|
@@ -120,10 +298,16 @@ const Config = () => {
|
|
|
id: 'pages.notice.config',
|
|
|
defaultMessage: '通知配置',
|
|
|
})}
|
|
|
+ modelConfig={{
|
|
|
+ width: '50vw',
|
|
|
+ loading: loading,
|
|
|
+ }}
|
|
|
schema={schema}
|
|
|
+ form={form}
|
|
|
+ schemaConfig={{ scope: { useAsyncDataSource, getTypes } }}
|
|
|
actionRef={actionRef}
|
|
|
/>
|
|
|
</PageContainer>
|
|
|
);
|
|
|
-};
|
|
|
+});
|
|
|
export default Config;
|