mapServe.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. import React, { useState, useEffect, useMemo } from 'react';
  2. import { FlowchartFormWrapper } from '@antv/xflow';
  3. import {
  4. Position,
  5. Size,
  6. ColorPicker,
  7. InputNumberField,
  8. InputField,
  9. SelectField,
  10. } from '../fields';
  11. import { PREFIX } from '../constants';
  12. import { connect } from 'umi';
  13. import { UnityAction } from '@/utils/utils';
  14. import {
  15. Button,
  16. Radio,
  17. RadioChangeEvent,
  18. Select,
  19. TreeSelect,
  20. InputNumber,
  21. } from 'antd';
  22. const { Option } = Select;
  23. export const enum TYPE {
  24. INITIATOR = 1,
  25. AUDIT,
  26. JUDGE,
  27. COPYMAN,
  28. }
  29. export const typeOption = [
  30. { label: '审批人', value: TYPE.AUDIT },
  31. { label: '发起人', value: TYPE.INITIATOR },
  32. { label: '抄送人', value: TYPE.COPYMAN },
  33. ];
  34. export interface IConfig {
  35. label?: string;
  36. x?: number;
  37. y?: number;
  38. width?: number;
  39. height?: number;
  40. count?: number;
  41. fontSize?: number;
  42. fontFill?: string;
  43. fill?: string;
  44. stroke?: string;
  45. flow_id?: string;
  46. flow_node_id?: string;
  47. process_code?: string;
  48. type: TYPE;
  49. initiator: {
  50. label: string; //描述
  51. type: string;
  52. value: number;
  53. origin?: string | number;
  54. name?: string;
  55. }[];
  56. //审批人目前只支持单选角色或者单选人
  57. audits: {
  58. label: string; //描述
  59. type: string;
  60. value: number;
  61. origin?: string | number;
  62. name?: string;
  63. is_cc: number;
  64. }[];
  65. }
  66. export const enum IDTYPE {
  67. DEP = 'dep',
  68. USER = 'user',
  69. ROLE = 'role',
  70. LEADER = 'leader',
  71. }
  72. const Component = (props: any) => {
  73. const defaultConfig = {
  74. type: TYPE.AUDIT,
  75. };
  76. const { config, plugin = {}, depUserTree, roleList, userList } = props;
  77. const { updateNode } = plugin;
  78. const [isRole, setIsRole] = useState(1); ///按角色还是个人
  79. const [nodeConfig, setNodeConfig] = useState<IConfig>({
  80. ...defaultConfig,
  81. ...config,
  82. });
  83. const onNodeConfigChange = (key: string, value: number | string | object) => {
  84. if (key) {
  85. setNodeConfig({
  86. ...nodeConfig,
  87. [key]: value,
  88. });
  89. updateNode({
  90. type: nodeConfig.type ? nodeConfig.type : TYPE.AUDIT,
  91. [key]: value,
  92. });
  93. } else if (value instanceof Object) {
  94. setNodeConfig({
  95. ...nodeConfig,
  96. ...value,
  97. });
  98. updateNode({
  99. type: nodeConfig.type ? nodeConfig.type : TYPE.AUDIT,
  100. ...value,
  101. });
  102. }
  103. };
  104. useEffect(() => {
  105. let bool = 1;
  106. if (nodeConfig.audits?.length > 0)
  107. switch (nodeConfig.audits[0].type) {
  108. case IDTYPE.USER:
  109. bool = 0;
  110. break;
  111. case IDTYPE.ROLE:
  112. bool = 1;
  113. break;
  114. case IDTYPE.LEADER:
  115. bool = 2;
  116. break;
  117. }
  118. console.log(bool);
  119. setIsRole(bool);
  120. }, []);
  121. const handleTreeChange = (values: (string | number)[]) => {
  122. const newValues = values.map((cur) => {
  123. if (typeof cur == 'string' && cur.includes('||')) {
  124. return {
  125. type: IDTYPE.USER,
  126. value: Number(cur.split('||')[0]),
  127. origin: cur,
  128. };
  129. } else {
  130. return { type: IDTYPE.DEP, value: cur, origin: cur, is_cc: 1 };
  131. }
  132. });
  133. onNodeConfigChange('initiator', newValues);
  134. };
  135. // const onSave = () => {
  136. // UnityAction.emit('NODE_SAVE', nodeConfig);
  137. // };
  138. useEffect(() => {
  139. setNodeConfig({
  140. ...defaultConfig,
  141. ...config,
  142. });
  143. }, [config]);
  144. const renderAuditSelect = (key: Number) => {
  145. switch (key) {
  146. case 0:
  147. return (
  148. <>
  149. <label>审批人</label>
  150. <Select
  151. showSearch
  152. mode="multiple"
  153. style={{ width: '100%' }}
  154. value={nodeConfig.audits?.map((item) => item.value)}
  155. onChange={(value) => {
  156. const list = value.map((id) => {
  157. return {
  158. type: IDTYPE.USER,
  159. label:
  160. nodeConfig.label == '动作节点'
  161. ? '抄送人'
  162. : nodeConfig.label,
  163. value: Number(id),
  164. };
  165. });
  166. onNodeConfigChange('audits', list);
  167. }}
  168. filterOption={(input, option) =>
  169. option.props.children.indexOf(input) >= 0
  170. }
  171. >
  172. {(userList || []).map((item) => (
  173. <Option key={item.ID} value={item.ID}>
  174. {item.CName}
  175. </Option>
  176. ))}
  177. </Select>
  178. </>
  179. );
  180. case 1:
  181. return (
  182. <>
  183. <label>审批角色</label>
  184. <Select
  185. showSearch
  186. style={{ width: '100%' }}
  187. value={nodeConfig.audits?.map((item) => item.value)}
  188. filterOption={(input, option) =>
  189. option.props.children.indexOf(input) >= 0
  190. }
  191. onChange={(value) => {
  192. onNodeConfigChange('audits', [
  193. {
  194. type: IDTYPE.ROLE,
  195. label:
  196. nodeConfig.label == '动作节点'
  197. ? '审批人'
  198. : nodeConfig.label,
  199. value: Number(value),
  200. },
  201. ]);
  202. }}
  203. >
  204. {roleList &&
  205. roleList.map((item) => (
  206. <Option key={item.ID} value={item.ID}>
  207. {item.Name}
  208. </Option>
  209. ))}
  210. </Select>
  211. </>
  212. );
  213. case 2:
  214. return (
  215. <>
  216. <label>多级审批</label>
  217. <InputNumber
  218. style={{ width: '100%' }}
  219. value={
  220. nodeConfig.audits?.length > 0 ? nodeConfig.audits[0].value : 0
  221. }
  222. onChange={(value) => {
  223. onNodeConfigChange('audits', [
  224. {
  225. type: IDTYPE.LEADER,
  226. label:
  227. nodeConfig.label == '动作节点'
  228. ? '审批人'
  229. : nodeConfig.label,
  230. value: Number(value),
  231. },
  232. ]);
  233. }}
  234. />
  235. </>
  236. );
  237. }
  238. };
  239. return (
  240. <div className={`${PREFIX}-panel-body`}>
  241. <div className={`${PREFIX}-panel-group`}>
  242. <h5>内容</h5>
  243. <InputField
  244. label="标题"
  245. value={nodeConfig.label}
  246. onChange={(value) => {
  247. onNodeConfigChange('', {
  248. label: value,
  249. audits:
  250. nodeConfig?.audits?.length > 0
  251. ? [{ ...(nodeConfig?.audits[0] || []), label: value }]
  252. : [],
  253. });
  254. }}
  255. />
  256. <SelectField
  257. label="节点类型"
  258. value={nodeConfig.type}
  259. onChange={(value) => {
  260. onNodeConfigChange('type', value);
  261. }}
  262. options={typeOption}
  263. />
  264. </div>
  265. <div className={`${PREFIX}-panel-group`}>
  266. <h5>样式</h5>
  267. <Position
  268. x={nodeConfig.x}
  269. y={nodeConfig.y}
  270. onChange={(key, value) => {
  271. onNodeConfigChange(key, value);
  272. }}
  273. />
  274. <Size
  275. width={nodeConfig.width}
  276. height={nodeConfig.height}
  277. onChange={(key, value) => {
  278. onNodeConfigChange(key, value);
  279. }}
  280. />
  281. <ColorPicker
  282. label="填充"
  283. value={nodeConfig.fill}
  284. onChange={(value: string) => {
  285. onNodeConfigChange('fill', value);
  286. }}
  287. />
  288. <ColorPicker
  289. label="边框"
  290. value={nodeConfig.stroke}
  291. onChange={(value: string) => {
  292. onNodeConfigChange('stroke', value);
  293. }}
  294. />
  295. <InputNumberField
  296. label="消息数量"
  297. value={nodeConfig.count}
  298. onChange={(value) => {
  299. onNodeConfigChange('count', value);
  300. }}
  301. />
  302. <div className={`${PREFIX}-node-text-style`}>
  303. <InputNumberField
  304. label="字号"
  305. value={nodeConfig.fontSize}
  306. width={68}
  307. onChange={(value) => {
  308. onNodeConfigChange('fontSize', value);
  309. }}
  310. />
  311. <ColorPicker
  312. value={nodeConfig.fontFill}
  313. onChange={(value: string) => {
  314. onNodeConfigChange('fontFill', value);
  315. }}
  316. />
  317. </div>
  318. {nodeConfig.type == TYPE.INITIATOR && (
  319. <div className="group">
  320. <label>发起人</label>
  321. <TreeSelect
  322. showSearch
  323. multiple
  324. allowClear
  325. value={nodeConfig.initiator?.map((item) => item.origin)}
  326. style={{ width: '80%' }}
  327. placeholder="请选择"
  328. treeData={depUserTree}
  329. onChange={(values) => {
  330. handleTreeChange(values);
  331. }}
  332. />
  333. </div>
  334. )}
  335. {nodeConfig.type == TYPE.AUDIT && (
  336. <div className={`${PREFIX}-panel-group`}>
  337. <h5>审批人</h5>
  338. <Radio.Group
  339. onChange={(e: RadioChangeEvent) => {
  340. console.log(e.target.value);
  341. setIsRole(e.target.value);
  342. onNodeConfigChange('audits', []);
  343. }}
  344. value={isRole}
  345. >
  346. <Radio value={1}>发起人自选</Radio>
  347. <Radio value={0}>指定人</Radio>
  348. <Radio value={2}>部门主管</Radio>
  349. </Radio.Group>
  350. <div className="group">{renderAuditSelect(isRole)}</div>
  351. </div>
  352. )}
  353. </div>
  354. {nodeConfig.type == TYPE.COPYMAN && (
  355. <div className="group">
  356. <label>抄送人:</label>
  357. <Select
  358. showSearch
  359. mode="multiple"
  360. style={{ width: '80%' }}
  361. value={nodeConfig.audits?.map((item) => item.value)}
  362. onChange={(value) => {
  363. const list = value.map((id) => {
  364. return {
  365. type: IDTYPE.USER,
  366. label:
  367. nodeConfig.label == '动作节点'
  368. ? '抄送人'
  369. : nodeConfig.label,
  370. value: Number(id),
  371. is_cc: 1,
  372. };
  373. });
  374. onNodeConfigChange('audits', list);
  375. }}
  376. filterOption={(input, option) =>
  377. option?.props?.children.indexOf(input) >= 0
  378. }
  379. >
  380. {(userList || []).map((item) => (
  381. <Option key={item.ID} value={item.ID}>
  382. {item.CName}
  383. </Option>
  384. ))}
  385. </Select>
  386. </div>
  387. )}
  388. {/* <Button style={{ marginTop: 20 }} type="primary" onClick={onSave}>
  389. 保存
  390. </Button> */}
  391. </div>
  392. );
  393. };
  394. function RecthServe(props: any) {
  395. return (
  396. <FlowchartFormWrapper {...props}>
  397. {(config, plugin) => (
  398. <Component {...props} plugin={plugin} config={config} />
  399. )}
  400. </FlowchartFormWrapper>
  401. );
  402. }
  403. export default connect(({ xflow, flow, user }) => ({
  404. auditList: xflow.auditList,
  405. depUserTree: user.depUserTree,
  406. roleList: user.roleList,
  407. userList: user.list,
  408. }))(RecthServe);