index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. import { Modal, Spin } from 'antd';
  2. import { useEffect, useMemo, useRef, useState } from 'react';
  3. import { createForm, Field, FormPath, onFieldReact, onFieldValueChange } from '@formily/core';
  4. import { createSchemaField, observer } from '@formily/react';
  5. import {
  6. ArrayTable,
  7. Form,
  8. FormItem,
  9. Input,
  10. NumberPicker,
  11. PreviewText,
  12. Select,
  13. } from '@formily/antd';
  14. import { ISchema } from '@formily/json-schema';
  15. import { configService, service, state } from '@/pages/notice/Template';
  16. // import { useLocation } from 'umi';
  17. import { onlyMessage, useAsyncDataSource } from '@/utils/util';
  18. import { Store } from 'jetlinks-store';
  19. import { FDatePicker } from '@/components';
  20. import FUpload from '@/components/Upload';
  21. const Debug = observer(() => {
  22. // const location = useLocation<{ id: string }>();
  23. // const id = (location as any).query?.id;
  24. const variableRef = useRef<any>([]);
  25. const form = useMemo(
  26. () =>
  27. createForm({
  28. validateFirst: true,
  29. effects() {
  30. onFieldValueChange('configId', async (field, form1) => {
  31. const value = (field as Field).value;
  32. const configs = Store.get('notice-config');
  33. const target = configs.find((item: { id: any }) => item.id === value);
  34. // 从缓存中获取通知配置信息
  35. if (target && target.variableDefinitions) {
  36. form1.setValuesIn('variableDefinitions', target.variableDefinitions);
  37. }
  38. });
  39. onFieldReact('variableDefinitions.*.type', async (field) => {
  40. const value = (field as Field).value;
  41. const format = field.query('.value').take() as Field;
  42. const _id = field.query('.id').take() as Field;
  43. const configId = field.query('configId');
  44. if (format && value) {
  45. switch (value) {
  46. case 'date':
  47. let dateFormat = 'yyyy-MM-dd HH:mm:ss';
  48. if (variableRef.current) {
  49. const a = variableRef.current?.find((i: any) => i.id === _id.value);
  50. dateFormat = a?.format;
  51. }
  52. format.setComponent(FDatePicker, {
  53. showTime: true,
  54. format: dateFormat === 'timestamp' ? 'X' : dateFormat.replace('dd', 'DD'),
  55. });
  56. break;
  57. case 'string':
  58. format.setComponent(Input);
  59. break;
  60. case 'number':
  61. format.setComponent(NumberPicker, {});
  62. break;
  63. case 'file':
  64. format.setComponent(FUpload, {
  65. type: 'file',
  66. });
  67. break;
  68. case 'other':
  69. format.setComponent(Input);
  70. break;
  71. }
  72. }
  73. if (variableRef.current) {
  74. const a = variableRef.current?.find((i: any) => i.id === _id.value);
  75. const _configId = configId.value();
  76. const businessType = a?.expands?.businessType;
  77. if (state.current?.type === 'dingTalk' || state.current?.type === 'weixin') {
  78. if (_configId) {
  79. switch (businessType) {
  80. case 'org':
  81. // 获取org
  82. const orgList = await service[state.current?.type].getDepartments(_configId);
  83. format.setComponent(Select);
  84. format.setDataSource(orgList);
  85. break;
  86. case 'user':
  87. // 获取user
  88. const userList = await service[state.current?.type].getUser(_configId);
  89. format.setComponent(Select);
  90. format.setDataSource(userList);
  91. break;
  92. case 'tag':
  93. // 获取user
  94. const tagList = await service[state.current?.type].getTags(_configId);
  95. format.setComponent(Select);
  96. format.setDataSource(tagList);
  97. break;
  98. case 'file':
  99. format.setComponent(FUpload, {
  100. type: 'file',
  101. });
  102. break;
  103. }
  104. } else if (['tag', 'org', 'user'].includes(businessType)) {
  105. format.setComponent(Select);
  106. format.setDataSource([]);
  107. }
  108. }
  109. }
  110. });
  111. onFieldReact('variableDefinitions.*.value', (field: any) => {
  112. const path = FormPath.transform(
  113. field.path,
  114. /\d+/,
  115. (index) => `variableDefinitions.${parseInt(index)}.required`,
  116. );
  117. const item = field.query(path).get('value');
  118. field.required = item;
  119. // console.log(item)
  120. });
  121. },
  122. }),
  123. [state.debug, state.current],
  124. );
  125. useEffect(() => {
  126. // const data = state.current;
  127. // 从后端接口来获取变量参数
  128. if (state.current?.id) {
  129. service.getVariableDefinitions(state.current?.id || '').then((resp) => {
  130. const _template = resp.result;
  131. if (_template?.variableDefinitions?.length > 0) {
  132. variableRef.current = _template?.variableDefinitions;
  133. form.setFieldState('variableDefinitions', (state1) => {
  134. state1.visible = true;
  135. state1.value = _template?.variableDefinitions;
  136. });
  137. }
  138. });
  139. }
  140. }, [state.current, state.debug]);
  141. const SchemaField = createSchemaField({
  142. components: {
  143. FormItem,
  144. Input,
  145. Select,
  146. ArrayTable,
  147. PreviewText,
  148. NumberPicker,
  149. FDatePicker,
  150. FUpload,
  151. },
  152. });
  153. const getConfig = () =>
  154. configService
  155. .queryNoPagingPost({
  156. terms: [
  157. { column: 'type$IN', value: state.current?.type },
  158. { column: 'provider', value: state.current?.provider },
  159. ],
  160. })
  161. .then((resp: any) => {
  162. // 缓存通知配置
  163. Store.set('notice-config', resp.result);
  164. return resp.result?.map((item: { name: any; id: any }) => ({
  165. label: item.name,
  166. value: item.id,
  167. }));
  168. });
  169. const schema: ISchema = {
  170. type: 'object',
  171. properties: {
  172. configId: {
  173. title: '通知配置',
  174. type: 'string',
  175. required: true,
  176. default: state?.current?.configId,
  177. 'x-decorator': 'FormItem',
  178. 'x-component': 'Select',
  179. 'x-reactions': '{{useAsyncDataSource(getConfig)}}',
  180. },
  181. variableDefinitions: {
  182. required: true,
  183. title: '变量',
  184. type: 'string',
  185. 'x-decorator': 'FormItem',
  186. 'x-component': 'ArrayTable',
  187. 'x-component-props': {
  188. pagination: { pageSize: 9999 },
  189. scroll: { x: '100%' },
  190. },
  191. 'x-visible': false,
  192. items: {
  193. type: 'object',
  194. properties: {
  195. column0: {
  196. type: 'void',
  197. 'x-component': 'ArrayTable.Column',
  198. 'x-component-props': { title: '类型', width: '120px' },
  199. 'x-hidden': true,
  200. properties: {
  201. type: {
  202. type: 'string',
  203. 'x-decorator': 'FormItem',
  204. 'x-component': 'PreviewText.Input',
  205. 'x-disabled': true,
  206. },
  207. },
  208. },
  209. column1: {
  210. type: 'void',
  211. 'x-component': 'ArrayTable.Column',
  212. 'x-component-props': { title: '变量', width: '120px' },
  213. properties: {
  214. id: {
  215. type: 'string',
  216. 'x-decorator': 'FormItem',
  217. 'x-component': 'PreviewText.Input',
  218. 'x-disabled': true,
  219. },
  220. },
  221. },
  222. column2: {
  223. type: 'void',
  224. 'x-component': 'ArrayTable.Column',
  225. 'x-component-props': { title: '名称', width: '120px' },
  226. properties: {
  227. name: {
  228. type: 'string',
  229. 'x-decorator': 'FormItem',
  230. 'x-component': 'PreviewText.Input',
  231. 'x-disabled': true,
  232. },
  233. },
  234. },
  235. column3: {
  236. type: 'void',
  237. 'x-component': 'ArrayTable.Column',
  238. 'x-component-props': { title: '值', width: '120px' },
  239. properties: {
  240. value: {
  241. required: true,
  242. type: 'string',
  243. 'x-decorator': 'FormItem',
  244. 'x-component': 'Input',
  245. },
  246. type: {
  247. 'x-hidden': true,
  248. type: 'string',
  249. 'x-decorator': 'FormItem',
  250. 'x-component': 'Input',
  251. },
  252. required: {
  253. 'x-hidden': true,
  254. type: 'string',
  255. 'x-decorator': 'FormItem',
  256. 'x-component': 'Input',
  257. },
  258. },
  259. },
  260. },
  261. },
  262. },
  263. },
  264. };
  265. const [spinning, setSpinning] = useState<boolean>(false);
  266. const start = async () => {
  267. setSpinning(true);
  268. // const data: { configId: string; variableDefinitions: any } = await form.submit();
  269. form
  270. .submit()
  271. .then(async (data: any) => {
  272. // 应该取选择的配置信息
  273. if (!state.current) return;
  274. const resp = await service.debug(
  275. data.configId,
  276. state?.current.id,
  277. data.variableDefinitions?.reduce(
  278. (previousValue: any, currentValue: { id: any; value: any }) => {
  279. return {
  280. ...previousValue,
  281. [currentValue.id]: currentValue.value,
  282. };
  283. },
  284. {},
  285. ),
  286. );
  287. if (resp.status === 200) {
  288. onlyMessage('操作成功!');
  289. setSpinning(false);
  290. state.debug = false;
  291. } else {
  292. setSpinning(false);
  293. }
  294. })
  295. .catch(() => {
  296. setSpinning(false);
  297. });
  298. };
  299. return (
  300. <Modal
  301. title="调试"
  302. width="40vw"
  303. destroyOnClose
  304. forceRender={true}
  305. visible={state.debug}
  306. onCancel={() => (state.debug = false)}
  307. onOk={start}
  308. >
  309. <Spin spinning={spinning}>
  310. <Form form={form} layout={'vertical'}>
  311. <SchemaField schema={schema} scope={{ getConfig, useAsyncDataSource }} />
  312. </Form>
  313. </Spin>
  314. </Modal>
  315. );
  316. });
  317. export default Debug;