mapServe.tsx 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. import React, { useState, useEffect } from 'react';
  2. import { FlowchartFormWrapper, MODELS, useXFlowApp } from '@antv/xflow';
  3. import { Button, message, Select } from 'antd';
  4. import LuckyExcel from 'luckyexcel';
  5. import {
  6. Position,
  7. Size,
  8. ColorPicker,
  9. InputNumberFiled,
  10. InputFiled,
  11. UploadFiled,
  12. RadioField,
  13. SelectField,
  14. } from '../fields';
  15. import { PREFIX } from '../constants';
  16. import { UnityAction } from '@/utils/utils';
  17. import { connect } from 'dva';
  18. import { IProps } from '@/components/Flow/index';
  19. interface ExcelInfo {
  20. file_name?: string;
  21. excel_cols?: any;
  22. }
  23. export interface IConfig {
  24. id?: string;
  25. label?: string;
  26. x?: number;
  27. y?: number;
  28. width?: number;
  29. height?: number;
  30. fontSize?: number;
  31. count?: number;
  32. fontFill?: string;
  33. fill?: string;
  34. stroke?: string;
  35. muti_version?: string | number;
  36. is_start_node?: string | number;
  37. bom_template?: string;
  38. version_name?: string;
  39. data?: any;
  40. excel_info?: ExcelInfo;
  41. role_list?: string;
  42. is_seal?: string | number;
  43. node_type_psr?: number | string;
  44. }
  45. const defaultConfig: IConfig = {
  46. muti_version: 1,
  47. is_start_node: 0,
  48. is_seal: 0,
  49. node_type_psr: 0,
  50. excel_info: { file_name: '' },
  51. };
  52. const Component = (props: any) => {
  53. const { config, plugin = {}, roleList } = props;
  54. const { updateNode } = plugin;
  55. const [options, setOptions] = useState([]);
  56. const [fileName, setFileName] = useState('');
  57. const [nodeConfig, setNodeConfig] = useState<IConfig>({
  58. ...defaultConfig,
  59. ...config,
  60. });
  61. const app = useXFlowApp();
  62. const [meta, setMeta] = useState<IProps['meta']>(null);
  63. const onNodeConfigChange = (key: string, value: number | string | object) => {
  64. if (key) {
  65. setNodeConfig({
  66. ...nodeConfig,
  67. [key]: value,
  68. });
  69. updateNode({
  70. [key]: value,
  71. });
  72. } else if (value instanceof Object) {
  73. setNodeConfig({
  74. ...nodeConfig,
  75. ...value,
  76. });
  77. updateNode({
  78. ...value,
  79. });
  80. }
  81. };
  82. const onSave = () => {
  83. UnityAction.emit('NODE_SAVE', nodeConfig);
  84. };
  85. const beforeUpload = (file: any) => {
  86. try {
  87. LuckyExcel.transformExcelToLucky(file, (exportJson, luckysheetfile) => {
  88. if (exportJson.sheets == null || exportJson.sheets.length == 0) {
  89. message.error('读取xlsx文件失败!');
  90. return;
  91. }
  92. console.log(exportJson);
  93. // const sheet = exportJson.sheets[0];
  94. let cell = [];
  95. exportJson.sheets.forEach((sheet, index) => {
  96. let titleCell = [];
  97. sheet.celldata.forEach(item => {
  98. if (item.r == 0) {
  99. // 标题头
  100. titleCell.push(item);
  101. }
  102. // 生成cid
  103. item.v.cid = `${item.r}-${item.c}`;
  104. });
  105. sheet.order = index;
  106. let tempCell = titleCell.map(item => {
  107. let value = '';
  108. if (item.v?.v) {
  109. value = item.v?.v;
  110. } else if (item.v.ct?.s && item.v.ct?.s instanceof Array) {
  111. value = item.v.ct.s.map(item => item?.v).join?.('');
  112. }
  113. return { sheet_name: sheet.name, col_idx: item.r, col_axis: item.c, col_value: value };
  114. });
  115. cell = [...cell, ...tempCell];
  116. });
  117. console.log(cell);
  118. onNodeConfigChange(null, {
  119. data: exportJson.sheets,
  120. excel_info: {
  121. file_name: file.name,
  122. excel_cols: cell,
  123. },
  124. });
  125. });
  126. } catch (error) {
  127. message.error('excel文件导入失败!请联系管理员。');
  128. return false;
  129. }
  130. };
  131. useEffect(() => {
  132. if (config.id != nodeConfig.id) {
  133. setNodeConfig({
  134. ...defaultConfig,
  135. ...config,
  136. });
  137. }
  138. }, [config]);
  139. useEffect(() => {
  140. MODELS.GRAPH_META.useValue(app.modelService).then((meta: IProps['meta']) => {
  141. setMeta(meta);
  142. });
  143. }, []);
  144. const updataFileName = (name: string) => {
  145. var idx = name?.lastIndexOf('/');
  146. let str = name.substring(idx + 1, name.length);
  147. setFileName(str);
  148. onNodeConfigChange('version_name', str);
  149. };
  150. useEffect(() => {
  151. if (config.bom_template) updataFileName(config.bom_template);
  152. if (nodeConfig.excel_info?.file_name) updataFileName(nodeConfig.excel_info.file_name);
  153. }, [nodeConfig.bom_template, nodeConfig.excel_info.file_name]);
  154. // console.log(nodeConfig, config)
  155. useEffect(() => {
  156. if (!roleList || roleList.length <= 0) return;
  157. let op = [];
  158. console.log(roleList);
  159. roleList
  160. .filter(cur => cur.RoleType == 4)
  161. .forEach(item => {
  162. op.push({ label: `${item.Name}(${item.ID})`, value: item.ID });
  163. });
  164. setOptions(op);
  165. console.log(op);
  166. }, [roleList]);
  167. // const handleFileNameClick = () => {
  168. // if (nodeConfig.bom_template) window.open(nodeConfig.bom_template);
  169. // };
  170. return (
  171. <div className={`${PREFIX}-panel-body`}>
  172. <div className={`${PREFIX}-panel-group`}>
  173. <h5>内容</h5>
  174. <InputFiled
  175. label="标题"
  176. value={nodeConfig.label}
  177. disabled={meta?.editMode == 2}
  178. onChange={value => {
  179. onNodeConfigChange('label', value);
  180. }}
  181. />
  182. </div>
  183. <div className={`${PREFIX}-panel-group`}>
  184. <h5>数据</h5>
  185. <RadioField
  186. label="多个版本"
  187. value={nodeConfig.muti_version}
  188. onChange={value => {
  189. onNodeConfigChange('muti_version', value);
  190. }}
  191. options={[
  192. { label: '是', value: 1 },
  193. { label: '否', value: 0 },
  194. ]}
  195. />
  196. <RadioField
  197. label="起始起点"
  198. value={nodeConfig.is_start_node}
  199. onChange={value => {
  200. onNodeConfigChange('is_start_node', value);
  201. }}
  202. options={[
  203. { label: '是', value: 1 },
  204. { label: '否', value: 0 },
  205. ]}
  206. />
  207. <RadioField
  208. label="是否用印"
  209. value={nodeConfig.is_seal}
  210. onChange={value => {
  211. onNodeConfigChange('is_seal', value);
  212. }}
  213. options={[
  214. { label: '是', value: 1 },
  215. { label: '否', value: 0 },
  216. ]}
  217. />
  218. <SelectField
  219. label="节点类型"
  220. value={nodeConfig.node_type_psr}
  221. onChange={value => {
  222. onNodeConfigChange('node_type_psr', value);
  223. }}
  224. options={[
  225. { label: '默认', value: 0 },
  226. { label: '投标版', value: 1 },
  227. { label: '签字版', value: 2 },
  228. { label: '投标测算', value: 3 },
  229. { label: '合同测算', value: 4 },
  230. { label: '采购合同', value: 5 },
  231. { label: '方案总审', value: 6 },
  232. { label: '清单权限', value: 7 }, //发起人和审批人可见
  233. ]}
  234. />
  235. {nodeConfig.is_start_node == 1 && (
  236. <>
  237. <InputFiled
  238. label="模板名称"
  239. value={nodeConfig.version_name}
  240. onChange={value => {
  241. onNodeConfigChange('version_name', value);
  242. }}
  243. />
  244. <UploadFiled
  245. label="模板"
  246. onChange={url => onNodeConfigChange('bom_template', url)}
  247. beforeUpload={beforeUpload}
  248. />
  249. {/* <div onClick={handleFileNameClick}>{fileName}</div> */}
  250. <a href={nodeConfig.bom_template}>{fileName}</a>
  251. </>
  252. )}
  253. <div className="group">
  254. <label>权限</label>
  255. <Select
  256. value={
  257. nodeConfig.role_list ? nodeConfig.role_list.split(',').map(item => Number(item)) : []
  258. }
  259. mode="multiple"
  260. allowClear
  261. style={{ width: '100%' }}
  262. placeholder="选择权限"
  263. onChange={(v: number[]) => {
  264. onNodeConfigChange('role_list', v.join(','));
  265. }}
  266. disabled={meta?.editMode == 2}
  267. options={options}
  268. />
  269. </div>
  270. </div>
  271. {meta?.editMode != 2 && (
  272. <div className={`${PREFIX}-panel-group`}>
  273. <h5>样式</h5>
  274. <Position
  275. x={nodeConfig.x}
  276. y={nodeConfig.y}
  277. onChange={(key, value) => {
  278. onNodeConfigChange(key, value);
  279. }}
  280. />
  281. <Size
  282. width={nodeConfig.width}
  283. height={nodeConfig.height}
  284. onChange={(key, value) => {
  285. onNodeConfigChange(key, value);
  286. }}
  287. />
  288. <ColorPicker
  289. label="填充"
  290. value={nodeConfig.fill}
  291. onChange={(value: string) => {
  292. onNodeConfigChange('fill', value);
  293. }}
  294. />
  295. <ColorPicker
  296. label="边框"
  297. value={nodeConfig.stroke}
  298. onChange={(value: string) => {
  299. onNodeConfigChange('stroke', value);
  300. }}
  301. />
  302. <InputNumberFiled
  303. label="消息数量"
  304. value={nodeConfig.count}
  305. onChange={value => {
  306. onNodeConfigChange('count', value);
  307. }}
  308. />
  309. <div style={{ display: 'flex' }}>
  310. <InputNumberFiled
  311. label="字号"
  312. value={nodeConfig.fontSize}
  313. width={68}
  314. onChange={value => {
  315. onNodeConfigChange('fontSize', value);
  316. }}
  317. style={{ marginRight: 10 }}
  318. />
  319. <ColorPicker
  320. value={nodeConfig.fontFill}
  321. onChange={(value: string) => {
  322. onNodeConfigChange('fontFill', value);
  323. }}
  324. />
  325. </div>
  326. </div>
  327. )}
  328. <Button type="primary" onClick={onSave}>
  329. 保存
  330. </Button>
  331. </div>
  332. );
  333. };
  334. function RecthServe(props: any) {
  335. return (
  336. <FlowchartFormWrapper {...props}>
  337. {(config, plugin) => <Component {...props} plugin={plugin} config={config} />}
  338. </FlowchartFormWrapper>
  339. );
  340. }
  341. export default connect(({ user }) => ({ roleList: user.roleList }))(RecthServe);