index.tsx 9.9 KB

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