index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. import { PageContainer } from '@ant-design/pro-layout'
  2. import { Button, Input, InputNumber, message, Select, Tabs, Tag } from 'antd'
  3. import React, { useEffect, useState } from 'react'
  4. import { TweenOneGroup } from 'rc-tween-one'
  5. import { createUid, dayjsFormat } from '@/utils/util'
  6. import { queryRuleCodeList, updateRuleCode } from '@/services/api/business'
  7. import { useRequest } from '@umijs/max'
  8. import LeftMenu from './components/LeftMenu'
  9. import { querySubject } from '@/services/api/subject'
  10. const { TabPane } = Tabs
  11. const connectorOption = [
  12. { label: '无', value: '' },
  13. { label: '-', value: '-' },
  14. { label: '_', value: '_' }
  15. ]
  16. enum RuleOptionEunm {
  17. APPROVALTYPE = 'approvalType',
  18. CURRENTYEAR = 'currentYear',
  19. CURRENTMONTH = 'currentMonth',
  20. AUTOCODE = 'autoCode',
  21. FIXEDTEXT = 'fixedText'
  22. }
  23. const ruleOptionLabel = {
  24. [RuleOptionEunm.APPROVALTYPE]: '审核类型',
  25. [RuleOptionEunm.CURRENTYEAR]: '当前年份',
  26. [RuleOptionEunm.CURRENTMONTH]: '当前月份',
  27. [RuleOptionEunm.AUTOCODE]: '自动编号',
  28. [RuleOptionEunm.FIXEDTEXT]: '固定文本'
  29. }
  30. const ruleOption = [
  31. { label: ruleOptionLabel[RuleOptionEunm.APPROVALTYPE], value: RuleOptionEunm.APPROVALTYPE },
  32. { label: ruleOptionLabel[RuleOptionEunm.CURRENTYEAR], value: RuleOptionEunm.CURRENTYEAR },
  33. { label: ruleOptionLabel[RuleOptionEunm.CURRENTMONTH], value: RuleOptionEunm.CURRENTMONTH },
  34. { label: ruleOptionLabel[RuleOptionEunm.AUTOCODE], value: RuleOptionEunm.AUTOCODE },
  35. { label: ruleOptionLabel[RuleOptionEunm.FIXEDTEXT], value: RuleOptionEunm.FIXEDTEXT }
  36. ]
  37. const approvalTypeOption = [{ label: '预算', value: '01' }]
  38. interface iTags {
  39. ruleArr: ruleOption[]
  40. setRuleArr: (arr: ruleOption[]) => void
  41. }
  42. const RenderTags: React.FC<iTags> = ({ ruleArr, setRuleArr }) => {
  43. const handleClose = (removedTag: ruleOption) => {
  44. const tags = ruleArr.filter(tag => tag.id !== removedTag.id)
  45. setRuleArr(tags)
  46. }
  47. return (
  48. <div>
  49. <TweenOneGroup
  50. enter={{
  51. scale: 0.8,
  52. opacity: 0,
  53. type: 'from',
  54. duration: 100
  55. }}
  56. leave={{ opacity: 0, width: 0, scale: 0, duration: 200 }}
  57. appear={false}>
  58. {ruleArr?.map((tag, idx) => {
  59. return (
  60. <span key={idx} style={{ display: 'inline-block', marginBottom: '4px' }}>
  61. {tag?.label ? (
  62. <Tag
  63. closable
  64. onClose={(e: MouseEvent) => {
  65. e.preventDefault()
  66. handleClose(tag)
  67. }}>
  68. {tag.label}
  69. </Tag>
  70. ) : null}
  71. </span>
  72. )
  73. })}
  74. </TweenOneGroup>
  75. </div>
  76. )
  77. }
  78. const RulesCode = () => {
  79. const [state, setState] = useState({
  80. ruleTypeValue: RuleOptionEunm.APPROVALTYPE,
  81. tabId: 'yuS',
  82. subjectList: '',
  83. activeKey: '',
  84. subjectID: '',
  85. connector: '-',
  86. approvalTypeValue: '01',
  87. digits: '5',
  88. autoCode: '00001',
  89. fixedText: ''
  90. })
  91. console.log(state.subjectID)
  92. const [ruleArr, setRuleArr] = useState<ruleOption[]>([])
  93. // 处理自动位数编号 -> 联动起始编号
  94. const digitHandler = (value: any) => {
  95. if (value) {
  96. const length = value
  97. const code = parseInt(state.autoCode)
  98. const newCode = (Array(length).join('0') + code).slice(-length)
  99. setState({
  100. ...state,
  101. digits: value,
  102. autoCode: newCode
  103. })
  104. }
  105. }
  106. const autoCodeHandler = e => {
  107. const autoCodeValue = e.target.value
  108. if (autoCodeValue) {
  109. const digitsLength = parseInt(state.digits)
  110. const newCode = (Array(digitsLength).join('0') + autoCodeValue).slice(-digitsLength)
  111. setState({
  112. ...state,
  113. autoCode: newCode
  114. })
  115. }
  116. }
  117. const { run: tryRuleCode } = useRequest(
  118. () => queryRuleCodeList({ tab: state.tabId, subjectID: state.activeKey.split('_')[0] }),
  119. {
  120. manual: true,
  121. onSuccess: result => {
  122. setRuleArr(result.rules)
  123. setState({ ...state, connector: result.connector })
  124. }
  125. }
  126. )
  127. const { run: tryUpdateRuleCode } = useRequest(updateRuleCode, {
  128. manual: true,
  129. onSuccess: () => {
  130. message.success('规则更改成功')
  131. tryRuleCode()
  132. }
  133. })
  134. const { run: trySubjectList } = useRequest(() => querySubject(), {
  135. manual: true,
  136. onSuccess: result => {
  137. setState({ ...state, subjectList: result.items })
  138. }
  139. })
  140. // 只需首次加载执行一次
  141. useEffect(() => {
  142. trySubjectList()
  143. }, [])
  144. // 添加规则
  145. const addRule = () => {
  146. let ruleValue = null
  147. switch (state.ruleTypeValue) {
  148. case RuleOptionEunm.APPROVALTYPE:
  149. ruleValue = state.approvalTypeValue
  150. break
  151. case RuleOptionEunm.CURRENTYEAR:
  152. ruleValue = dayjsFormat(new Date(), 'YYYY')
  153. break
  154. case RuleOptionEunm.CURRENTMONTH:
  155. ruleValue = dayjsFormat(new Date(), 'M')
  156. break
  157. case RuleOptionEunm.AUTOCODE:
  158. ruleValue = state.autoCode
  159. break
  160. default:
  161. ruleValue = state.fixedText
  162. break
  163. }
  164. const rule = {
  165. id: createUid(),
  166. type: state.ruleTypeValue,
  167. label: ruleOptionLabel[state.ruleTypeValue],
  168. value: ruleValue
  169. }
  170. setRuleArr([...ruleArr, rule])
  171. }
  172. const renderExtraTabContent = () =>
  173. state.activeKey ? (
  174. <Button
  175. type="primary"
  176. onClick={() => {
  177. tryUpdateRuleCode({
  178. tab: state.tabId,
  179. subjectID: state.subjectID,
  180. rules: ruleArr.map(item => ({
  181. type: item.type,
  182. value: item.value,
  183. label: item.label,
  184. id: item.id
  185. })),
  186. connector: state.connector
  187. })
  188. }}>
  189. 保存
  190. </Button>
  191. ) : null
  192. return (
  193. <PageContainer title={false}>
  194. <div className="h-full w-full flex flex-row">
  195. {state.subjectList.length ? (
  196. <LeftMenu
  197. title="业务主体列表"
  198. options={state.subjectList}
  199. value={state.activeKey}
  200. initFn={() => tryRuleCode()}
  201. onChange={key =>
  202. setState({
  203. ...state,
  204. activeKey: key,
  205. tabId: key.split('_')[1],
  206. subjectID: key.split('_')[0]
  207. })
  208. }
  209. />
  210. ) : null}
  211. <div className="w-6/7 ml-8 p-4 bg-white">
  212. <Tabs
  213. defaultActiveKey="yuS"
  214. tabBarExtraContent={renderExtraTabContent()}
  215. onChange={key => {
  216. setState({
  217. ...state,
  218. tabId: key
  219. })
  220. }}>
  221. <TabPane key="yuS" tab="预算编号规则">
  222. {state.activeKey ? (
  223. <>
  224. <div className="flex items-center mb-3">
  225. <div className="w-100px text-right mr-1">编号预览:</div>
  226. <div className="min-h-32px leading-32px">
  227. {ruleArr?.map(item => item?.value).join(state.connector)}
  228. </div>
  229. </div>
  230. <div className="flex items-center mb-3">
  231. <div className="w-100px text-right mr-1">编号规则:</div>
  232. <div className="w-2/5 min-h-32px border-1 border-[#d9d9d9] border-solid rounded-2px pt-1 px-1">
  233. <RenderTags ruleArr={ruleArr} setRuleArr={setRuleArr} />
  234. </div>
  235. </div>
  236. <div className="flex items-center mb-3">
  237. <div className="w-100px text-right mr-1">连接符:</div>
  238. <div>
  239. <Select
  240. style={{ width: 160 }}
  241. options={connectorOption}
  242. defaultValue={state.connector}
  243. onSelect={value =>
  244. setState({
  245. ...state,
  246. connector: value
  247. })
  248. }
  249. />
  250. </div>
  251. </div>
  252. <div className="flex items-center mb-3">
  253. <div className="w-100px text-right mr-1">规则:</div>
  254. <div>
  255. <Select
  256. style={{ width: 160 }}
  257. options={ruleOption}
  258. defaultValue={state.ruleTypeValue}
  259. onSelect={value =>
  260. setState({
  261. ...state,
  262. ruleTypeValue: value
  263. })
  264. }
  265. />
  266. </div>
  267. {state.ruleTypeValue === RuleOptionEunm.APPROVALTYPE ? (
  268. <div className="flex items-center">
  269. <div className="w-100px text-right mr-1">类型:</div>
  270. <div>
  271. <Select
  272. style={{ width: 160 }}
  273. options={approvalTypeOption}
  274. defaultValue={state.approvalTypeValue}
  275. onSelect={value =>
  276. setState({
  277. ...state,
  278. approvalTypeValue: value
  279. })
  280. }
  281. />
  282. </div>
  283. </div>
  284. ) : null}
  285. {state.ruleTypeValue === RuleOptionEunm.AUTOCODE ? (
  286. <div className="flex items-center">
  287. <div className="w-100px text-right mr-1">数位:</div>
  288. <div>
  289. <InputNumber
  290. style={{ width: 160 }}
  291. defaultValue={state.digits}
  292. min={1}
  293. onChange={value => digitHandler(value)}
  294. />
  295. </div>
  296. </div>
  297. ) : null}
  298. {state.ruleTypeValue === RuleOptionEunm.FIXEDTEXT ? (
  299. <div className="flex items-center">
  300. <div className="w-100px text-right mr-1">规则:</div>
  301. <div>
  302. <Input
  303. style={{ width: 160 }}
  304. onChange={e =>
  305. setState({
  306. ...state,
  307. fixedText: e.target.value
  308. })
  309. }
  310. />
  311. </div>
  312. </div>
  313. ) : null}
  314. {state.ruleTypeValue === RuleOptionEunm.AUTOCODE ? (
  315. <div className="flex items-center">
  316. <div className="w-100px text-right mr-1">起始编号:</div>
  317. <div>
  318. <Input
  319. type="number"
  320. value={state.autoCode}
  321. onChange={e => autoCodeHandler(e)}
  322. defaultValue={state.autoCode}
  323. style={{ width: 160 }}
  324. />
  325. </div>
  326. </div>
  327. ) : null}
  328. <div className="ml-4">
  329. <Button type="primary" ghost onClick={() => addRule()}>
  330. 添加
  331. </Button>
  332. </div>
  333. </div>
  334. </>
  335. ) : null}
  336. </TabPane>
  337. </Tabs>
  338. </div>
  339. </div>
  340. </PageContainer>
  341. )
  342. }
  343. export default RulesCode