index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. import { PageContainer } from '@ant-design/pro-layout';
  2. import { useRef, useState } from 'react';
  3. import type { ActionType, ProColumns } from '@jetlinks/pro-table';
  4. import {
  5. ArrowDownOutlined,
  6. BugOutlined,
  7. DeleteOutlined,
  8. EditOutlined,
  9. EyeOutlined,
  10. PlusOutlined,
  11. UnorderedListOutlined,
  12. } from '@ant-design/icons';
  13. import { Space, Upload } from 'antd';
  14. import { useIntl } from '@@/plugin-locale/localeExports';
  15. import Service from '@/pages/notice/Template/service';
  16. import ConfigService from '@/pages/notice/Config/service';
  17. import SearchComponent from '@/components/SearchComponent';
  18. import { history, useLocation } from 'umi';
  19. import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
  20. import { model } from '@formily/reactive';
  21. import Debug from './Debug';
  22. import Log from '@/pages/notice/Template/Log';
  23. import { downloadObject, onlyMessage } from '@/utils/util';
  24. import moment from 'moment';
  25. import { PermissionButton, ProTableCard } from '@/components';
  26. import NoticeCard, { typeList } from '@/components/ProTableCard/CardItems/noticeTemplate';
  27. import { observer } from '@formily/react';
  28. import usePermissions from '@/hooks/permission';
  29. export const service = new Service('notifier/template');
  30. export const configService = new ConfigService('notifier/config');
  31. export const state = model<{
  32. current?: TemplateItem;
  33. debug?: boolean;
  34. log?: boolean;
  35. }>({
  36. debug: false,
  37. log: false,
  38. });
  39. const list = {
  40. weixin: {
  41. corpMessage: {
  42. text: '企业消息',
  43. status: 'corpMessage',
  44. },
  45. // officialMessage: {
  46. // text: '服务号消息',
  47. // status: 'officialMessage',
  48. // },
  49. },
  50. dingTalk: {
  51. dingTalkMessage: {
  52. text: '钉钉消息',
  53. status: 'dingTalkMessage',
  54. },
  55. dingTalkRobotWebHook: {
  56. text: '群机器人消息',
  57. status: 'dingTalkRobotWebHook',
  58. },
  59. },
  60. voice: {
  61. aliyun: {
  62. text: '阿里云语音',
  63. status: 'aliyun',
  64. },
  65. },
  66. sms: {
  67. aliyunSms: {
  68. text: '阿里云短信',
  69. status: 'aliyunSms',
  70. },
  71. },
  72. email: {
  73. embedded: {
  74. text: '邮件',
  75. status: 'embedded',
  76. },
  77. },
  78. webhook: {
  79. http: {
  80. text: 'Webhook',
  81. status: 'http',
  82. },
  83. },
  84. };
  85. const Template = observer(() => {
  86. const intl = useIntl();
  87. const location = useLocation<{ id: string }>();
  88. const id = (location as any).query?.id;
  89. const actionRef = useRef<ActionType>();
  90. const { permission: templatePermission } = usePermissions('notice');
  91. const columns: ProColumns<TemplateItem>[] = [
  92. {
  93. dataIndex: 'name',
  94. title: '模版名称',
  95. ellipsis: true,
  96. },
  97. {
  98. dataIndex: 'provider',
  99. title: '通知方式',
  100. renderText: (text, record) => {
  101. return typeList[record?.type][record?.provider];
  102. },
  103. valueType: 'select',
  104. valueEnum: list[id],
  105. },
  106. {
  107. dataIndex: 'description',
  108. title: '说明',
  109. ellipsis: true,
  110. },
  111. {
  112. title: intl.formatMessage({
  113. id: 'pages.data.option',
  114. defaultMessage: '操作',
  115. }),
  116. valueType: 'option',
  117. align: 'left',
  118. width: 200,
  119. render: (text, record) => [
  120. <PermissionButton
  121. key="edit"
  122. style={{ padding: 0 }}
  123. type="link"
  124. isPermission={templatePermission.update}
  125. onClick={() => {
  126. state.current = record;
  127. history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
  128. }}
  129. tooltip={{
  130. title: intl.formatMessage({
  131. id: 'pages.data.option.edit',
  132. defaultMessage: '编辑',
  133. }),
  134. }}
  135. >
  136. <EditOutlined />
  137. </PermissionButton>,
  138. <PermissionButton
  139. key="download"
  140. style={{ padding: 0 }}
  141. type="link"
  142. tooltip={{ title: '导出' }}
  143. isPermission={templatePermission.export}
  144. onClick={() => {
  145. downloadObject(
  146. record,
  147. `${record.name}-${moment(new Date()).format('YYYY/MM/DD HH:mm:ss')}`,
  148. );
  149. }}
  150. >
  151. <ArrowDownOutlined />
  152. </PermissionButton>,
  153. <PermissionButton
  154. isPermission={templatePermission.debug}
  155. key="debug"
  156. style={{ padding: 0 }}
  157. type="link"
  158. onClick={() => {
  159. state.debug = true;
  160. state.current = record;
  161. }}
  162. tooltip={{
  163. title: intl.formatMessage({
  164. id: 'pages.notice.option.debug',
  165. defaultMessage: '调试',
  166. }),
  167. }}
  168. >
  169. <BugOutlined />
  170. </PermissionButton>,
  171. <PermissionButton
  172. isPermission={templatePermission.log}
  173. key="log"
  174. style={{ padding: 0 }}
  175. type="link"
  176. onClick={() => {
  177. state.log = true;
  178. }}
  179. tooltip={{ title: '通知记录' }}
  180. >
  181. <UnorderedListOutlined />
  182. </PermissionButton>,
  183. <PermissionButton
  184. style={{ padding: 0 }}
  185. type="link"
  186. popConfirm={{
  187. title: '确认删除?',
  188. onConfirm: async () => {
  189. await service.remove(record.id);
  190. actionRef.current?.reload();
  191. },
  192. }}
  193. tooltip={{
  194. title: intl.formatMessage({
  195. id: 'pages.data.option.remove',
  196. defaultMessage: '删除',
  197. }),
  198. }}
  199. isPermission={templatePermission.delete}
  200. key="delete"
  201. >
  202. <DeleteOutlined />
  203. </PermissionButton>,
  204. ],
  205. },
  206. ];
  207. const [param, setParam] = useState({});
  208. return (
  209. <PageContainer>
  210. <SearchComponent
  211. defaultParam={[{ column: 'type$IN', value: id }]}
  212. field={columns}
  213. onSearch={(data) => {
  214. actionRef.current?.reset?.();
  215. setParam(data);
  216. }}
  217. />
  218. <ProTableCard<TemplateItem>
  219. actionRef={actionRef}
  220. rowKey="id"
  221. search={false}
  222. params={param}
  223. columns={columns}
  224. columnEmptyText={''}
  225. gridColumns={[2, 2, 3]}
  226. headerTitle={
  227. <Space>
  228. <PermissionButton
  229. isPermission={templatePermission.add}
  230. onClick={() => {
  231. state.current = undefined;
  232. history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
  233. }}
  234. key="button"
  235. icon={<PlusOutlined />}
  236. type="primary"
  237. >
  238. {intl.formatMessage({
  239. id: 'pages.data.option.add',
  240. defaultMessage: '新增',
  241. })}
  242. </PermissionButton>
  243. <Upload
  244. disabled={!templatePermission.import}
  245. key={'import'}
  246. accept=".json"
  247. showUploadList={false}
  248. beforeUpload={(file) => {
  249. const reader = new FileReader();
  250. reader.readAsText(file);
  251. reader.onload = async (result) => {
  252. const text = result.target?.result as string;
  253. if (!file.type.includes('json')) {
  254. onlyMessage('文件内容格式错误', 'warning');
  255. return;
  256. }
  257. try {
  258. const data = JSON.parse(text || '{}');
  259. const res: any = await service.savePatch(data);
  260. if (res.status === 200) {
  261. onlyMessage('操作成功');
  262. actionRef.current?.reload();
  263. }
  264. } catch {
  265. onlyMessage('文件内容格式错误', 'warning');
  266. }
  267. };
  268. return false;
  269. }}
  270. >
  271. <PermissionButton isPermission={templatePermission.import} style={{ marginLeft: 12 }}>
  272. 导入
  273. </PermissionButton>
  274. </Upload>
  275. <PermissionButton
  276. popConfirm={{
  277. title: '确定导出?',
  278. onConfirm: async () => {
  279. const resp: any = await service.queryNoPagingPost({ ...param, paging: false });
  280. if (resp.status === 200) {
  281. downloadObject(resp.result, '通知模版数据');
  282. onlyMessage('导出成功');
  283. } else {
  284. onlyMessage('导出错误', 'error');
  285. }
  286. },
  287. }}
  288. isPermission={templatePermission.export}
  289. >
  290. 导出
  291. </PermissionButton>
  292. </Space>
  293. }
  294. gridColumn={3}
  295. cardRender={(record) => (
  296. <NoticeCard
  297. {...record}
  298. type={id}
  299. detail={
  300. <div
  301. style={{ fontSize: 18, padding: 8 }}
  302. onClick={() => {
  303. state.current = record;
  304. history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
  305. }}
  306. >
  307. <EyeOutlined />
  308. </div>
  309. }
  310. actions={[
  311. <PermissionButton
  312. isPermission={templatePermission.update}
  313. key="edit"
  314. onClick={() => {
  315. state.current = record;
  316. history.push(getMenuPathByParams(MENUS_CODE['notice/Template/Detail'], id));
  317. }}
  318. >
  319. <EditOutlined />
  320. 编辑
  321. </PermissionButton>,
  322. <PermissionButton
  323. isPermission={templatePermission.debug}
  324. key="debug"
  325. onClick={() => {
  326. state.debug = true;
  327. state.current = record;
  328. }}
  329. >
  330. <BugOutlined />
  331. 调试
  332. </PermissionButton>,
  333. <PermissionButton
  334. key="export"
  335. isPermission={templatePermission.export}
  336. onClick={() => {
  337. downloadObject(
  338. record,
  339. `${record.name}-${moment(new Date()).format('YYYY/MM/DD HH:mm:ss')}`,
  340. );
  341. }}
  342. >
  343. <ArrowDownOutlined />
  344. 导出
  345. </PermissionButton>,
  346. <PermissionButton
  347. isPermission={templatePermission.log}
  348. key="log"
  349. onClick={() => {
  350. state.log = true;
  351. state.current = record;
  352. }}
  353. >
  354. <UnorderedListOutlined />
  355. 通知记录
  356. </PermissionButton>,
  357. <PermissionButton
  358. popConfirm={{
  359. title: '确认删除?',
  360. onConfirm: async () => {
  361. await service.remove(record.id);
  362. actionRef.current?.reset?.();
  363. },
  364. }}
  365. isPermission={templatePermission.delete}
  366. key="delete"
  367. >
  368. <DeleteOutlined />
  369. </PermissionButton>,
  370. ]}
  371. />
  372. )}
  373. request={async (params) =>
  374. service.query({ ...params, sorts: [{ name: 'createTime', order: 'desc' }] })
  375. }
  376. />
  377. <Debug />
  378. {state.log && <Log />}
  379. </PageContainer>
  380. );
  381. });
  382. export default Template;