|
@@ -0,0 +1,327 @@
|
|
|
|
+import { PageContainer } from '@ant-design/pro-layout'
|
|
|
|
+import { Button, Input, InputNumber, message, Select, Tabs, Tag } from 'antd'
|
|
|
|
+import React, { useEffect, useState } from 'react'
|
|
|
|
+import { TweenOneGroup } from 'rc-tween-one'
|
|
|
|
+import { createUid, dayjsFormat } from '@/utils/util'
|
|
|
|
+import { queryRuleCodeList, updateRuleCode } from '@/services/api/business'
|
|
|
|
+import { useRequest } from '@umijs/max'
|
|
|
|
+
|
|
|
|
+const { TabPane } = Tabs
|
|
|
|
+const contentHeight = document.body.clientHeight - 122
|
|
|
|
+
|
|
|
|
+const connectorOption = [
|
|
|
|
+ { label: '无', value: '' },
|
|
|
|
+ { label: '-', value: '-' },
|
|
|
|
+ { label: '_', value: '_' }
|
|
|
|
+]
|
|
|
|
+
|
|
|
|
+enum RuleOptionEunm {
|
|
|
|
+ APPROVALTYPE = 'approvalType',
|
|
|
|
+ CURRENTYEAR = 'currentYear',
|
|
|
|
+ CURRENTMONTH = 'currentMonth',
|
|
|
|
+ AUTOCODE = 'autoCode',
|
|
|
|
+ FIXEDTEXT = 'fixedText'
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const ruleOptionLabel = {
|
|
|
|
+ [RuleOptionEunm.APPROVALTYPE]: '审核类型',
|
|
|
|
+ [RuleOptionEunm.CURRENTYEAR]: '当前年份',
|
|
|
|
+ [RuleOptionEunm.CURRENTMONTH]: '当前月份',
|
|
|
|
+ [RuleOptionEunm.AUTOCODE]: '自动编号',
|
|
|
|
+ [RuleOptionEunm.FIXEDTEXT]: '固定文本'
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const ruleOption = [
|
|
|
|
+ { label: ruleOptionLabel[RuleOptionEunm.APPROVALTYPE], value: RuleOptionEunm.APPROVALTYPE },
|
|
|
|
+ { label: ruleOptionLabel[RuleOptionEunm.CURRENTYEAR], value: RuleOptionEunm.CURRENTYEAR },
|
|
|
|
+ { label: ruleOptionLabel[RuleOptionEunm.CURRENTMONTH], value: RuleOptionEunm.CURRENTMONTH },
|
|
|
|
+ { label: ruleOptionLabel[RuleOptionEunm.AUTOCODE], value: RuleOptionEunm.AUTOCODE },
|
|
|
|
+ { label: ruleOptionLabel[RuleOptionEunm.FIXEDTEXT], value: RuleOptionEunm.FIXEDTEXT }
|
|
|
|
+]
|
|
|
|
+
|
|
|
|
+const approvalTypeOption = [{ label: '预算', value: '01' }]
|
|
|
|
+interface iTags {
|
|
|
|
+ ruleArr: ruleOption[]
|
|
|
|
+ setRuleArr: (arr: ruleOption[]) => void
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const RenderTags: React.FC<iTags> = ({ ruleArr, setRuleArr }) => {
|
|
|
|
+ const handleClose = (removedTag: ruleOption) => {
|
|
|
|
+ const tags = ruleArr.filter(tag => tag.id !== removedTag.id)
|
|
|
|
+ setRuleArr(tags)
|
|
|
|
+ }
|
|
|
|
+ return (
|
|
|
|
+ <div>
|
|
|
|
+ <TweenOneGroup
|
|
|
|
+ enter={{
|
|
|
|
+ scale: 0.8,
|
|
|
|
+ opacity: 0,
|
|
|
|
+ type: 'from',
|
|
|
|
+ duration: 100
|
|
|
|
+ }}
|
|
|
|
+ leave={{ opacity: 0, width: 0, scale: 0, duration: 200 }}
|
|
|
|
+ appear={false}>
|
|
|
|
+ {ruleArr.map((tag, idx) => {
|
|
|
|
+ return (
|
|
|
|
+ <span key={idx} style={{ display: 'inline-block', marginBottom: '4px' }}>
|
|
|
|
+ {tag?.label ? (
|
|
|
|
+ <Tag
|
|
|
|
+ closable
|
|
|
|
+ onClose={(e: MouseEvent) => {
|
|
|
|
+ e.preventDefault()
|
|
|
|
+ handleClose(tag)
|
|
|
|
+ }}>
|
|
|
|
+ {tag.label}
|
|
|
|
+ </Tag>
|
|
|
|
+ ) : null}
|
|
|
|
+ </span>
|
|
|
|
+ )
|
|
|
|
+ })}
|
|
|
|
+ </TweenOneGroup>
|
|
|
|
+ </div>
|
|
|
|
+ )
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const RulesCode = () => {
|
|
|
|
+ const [state, setState] = useState({
|
|
|
|
+ ruleTypeValue: RuleOptionEunm.APPROVALTYPE,
|
|
|
|
+ tabId: 'yuS',
|
|
|
|
+ connector: '-',
|
|
|
|
+ approvalTypeValue: '01',
|
|
|
|
+ digits: '5',
|
|
|
|
+ autoCode: '00001',
|
|
|
|
+ fixedText: ''
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const [ruleArr, setRuleArr] = useState<ruleOption[]>([])
|
|
|
|
+
|
|
|
|
+ // 处理自动位数编号 -> 联动起始编号
|
|
|
|
+ const digitHandler = (value: any) => {
|
|
|
|
+ if (value) {
|
|
|
|
+ const length = value
|
|
|
|
+ const code = parseInt(state.autoCode)
|
|
|
|
+ const newCode = (Array(length).join('0') + code).slice(-length)
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ digits: value,
|
|
|
|
+ autoCode: newCode
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const autoCodeHandler = e => {
|
|
|
|
+ const autoCodeValue = e.target.value
|
|
|
|
+ if (autoCodeValue) {
|
|
|
|
+ const digitsLength = parseInt(state.digits)
|
|
|
|
+ const newCode = (Array(digitsLength).join('0') + autoCodeValue).slice(-digitsLength)
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ autoCode: newCode
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const { run: tryRuleCode } = useRequest(() => queryRuleCodeList({ tab: state.tabId }), {
|
|
|
|
+ manual: true,
|
|
|
|
+ onSuccess: result => {
|
|
|
|
+ setRuleArr(result.rules)
|
|
|
|
+ setState({ ...state, connector: result.connector })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const { run: tryUpdateRuleCode } = useRequest(updateRuleCode, {
|
|
|
|
+ manual: true,
|
|
|
|
+ onSuccess: () => {
|
|
|
|
+ message.success('规则更改成功')
|
|
|
|
+ tryRuleCode()
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // 只需首次加载执行一次
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ function fectTryRuleCode() {
|
|
|
|
+ if (state.tabId === 'yuS') {
|
|
|
|
+ tryRuleCode()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ fectTryRuleCode()
|
|
|
|
+ }, [])
|
|
|
|
+
|
|
|
|
+ // 添加规则
|
|
|
|
+ const addRule = () => {
|
|
|
|
+ let ruleValue = null
|
|
|
|
+ switch (state.ruleTypeValue) {
|
|
|
|
+ case RuleOptionEunm.APPROVALTYPE:
|
|
|
|
+ ruleValue = state.approvalTypeValue
|
|
|
|
+ break
|
|
|
|
+ case RuleOptionEunm.CURRENTYEAR:
|
|
|
|
+ ruleValue = dayjsFormat(new Date(), 'YYYY')
|
|
|
|
+ break
|
|
|
|
+ case RuleOptionEunm.CURRENTMONTH:
|
|
|
|
+ ruleValue = dayjsFormat(new Date(), 'M')
|
|
|
|
+ break
|
|
|
|
+ case RuleOptionEunm.AUTOCODE:
|
|
|
|
+ ruleValue = state.autoCode
|
|
|
|
+ break
|
|
|
|
+ default:
|
|
|
|
+ ruleValue = state.fixedText
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ const rule = {
|
|
|
|
+ id: createUid(),
|
|
|
|
+ type: state.ruleTypeValue,
|
|
|
|
+ label: ruleOptionLabel[state.ruleTypeValue],
|
|
|
|
+ value: ruleValue
|
|
|
|
+ }
|
|
|
|
+ setRuleArr([...ruleArr, rule])
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const renderExtraTabContent = () => (
|
|
|
|
+ <Button
|
|
|
|
+ type="primary"
|
|
|
|
+ onClick={() => {
|
|
|
|
+ tryUpdateRuleCode({
|
|
|
|
+ tab: state.tabId,
|
|
|
|
+ rules: ruleArr.map(item => ({
|
|
|
|
+ type: item.type,
|
|
|
|
+ value: item.value,
|
|
|
|
+ label: item.label,
|
|
|
|
+ id: item.id
|
|
|
|
+ })),
|
|
|
|
+ connector: state.connector
|
|
|
|
+ })
|
|
|
|
+ }}>
|
|
|
|
+ 保存
|
|
|
|
+ </Button>
|
|
|
|
+ )
|
|
|
|
+ return (
|
|
|
|
+ <PageContainer title={false}>
|
|
|
|
+ <div className="p-4 bg-white" style={{ height: `${contentHeight}px` }}>
|
|
|
|
+ <Tabs
|
|
|
|
+ defaultActiveKey="yuS"
|
|
|
|
+ tabBarExtraContent={renderExtraTabContent()}
|
|
|
|
+ onChange={key => {
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ tabId: key
|
|
|
|
+ })
|
|
|
|
+ }}>
|
|
|
|
+ <TabPane key="yuS" tab="预算编号规则">
|
|
|
|
+ <div className="flex items-center mb-3">
|
|
|
|
+ <div className="w-100px text-right mr-1">编号预览:</div>
|
|
|
|
+ <div className="min-h-32px leading-32px">
|
|
|
|
+ {ruleArr.map(item => item?.value).join(state.connector)}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="flex items-center mb-3">
|
|
|
|
+ <div className="w-100px text-right mr-1">编号规则:</div>
|
|
|
|
+ <div className="w-2/5 min-h-32px border-1 border-[#d9d9d9] border-solid rounded-2px pt-1 px-1">
|
|
|
|
+ <RenderTags ruleArr={ruleArr} setRuleArr={setRuleArr} />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="flex items-center mb-3">
|
|
|
|
+ <div className="w-100px text-right mr-1">连接符:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <Select
|
|
|
|
+ style={{ width: 160 }}
|
|
|
|
+ options={connectorOption}
|
|
|
|
+ defaultValue={state.connector}
|
|
|
|
+ onSelect={value =>
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ connector: value
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="flex items-center mb-3">
|
|
|
|
+ <div className="w-100px text-right mr-1">规则:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <Select
|
|
|
|
+ style={{ width: 160 }}
|
|
|
|
+ options={ruleOption}
|
|
|
|
+ defaultValue={state.ruleTypeValue}
|
|
|
|
+ onSelect={value =>
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ ruleTypeValue: value
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ {state.ruleTypeValue === RuleOptionEunm.APPROVALTYPE ? (
|
|
|
|
+ <div className="flex items-center">
|
|
|
|
+ <div className="w-100px text-right mr-1">类型:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <Select
|
|
|
|
+ style={{ width: 160 }}
|
|
|
|
+ options={approvalTypeOption}
|
|
|
|
+ defaultValue={state.approvalTypeValue}
|
|
|
|
+ onSelect={value =>
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ approvalTypeValue: value
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ) : null}
|
|
|
|
+ {state.ruleTypeValue === RuleOptionEunm.AUTOCODE ? (
|
|
|
|
+ <div className="flex items-center">
|
|
|
|
+ <div className="w-100px text-right mr-1">数位:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <InputNumber
|
|
|
|
+ style={{ width: 160 }}
|
|
|
|
+ defaultValue={state.digits}
|
|
|
|
+ min={1}
|
|
|
|
+ onChange={value => digitHandler(value)}
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ) : null}
|
|
|
|
+ {state.ruleTypeValue === RuleOptionEunm.FIXEDTEXT ? (
|
|
|
|
+ <div className="flex items-center">
|
|
|
|
+ <div className="w-100px text-right mr-1">规则:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <Input
|
|
|
|
+ style={{ width: 160 }}
|
|
|
|
+ onChange={e =>
|
|
|
|
+ setState({
|
|
|
|
+ ...state,
|
|
|
|
+ fixedText: e.target.value
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ) : null}
|
|
|
|
+ {state.ruleTypeValue === RuleOptionEunm.AUTOCODE ? (
|
|
|
|
+ <div className="flex items-center">
|
|
|
|
+ <div className="w-100px text-right mr-1">起始编号:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <Input
|
|
|
|
+ type="number"
|
|
|
|
+ value={state.autoCode}
|
|
|
|
+ onChange={e => autoCodeHandler(e)}
|
|
|
|
+ defaultValue={state.autoCode}
|
|
|
|
+ style={{ width: 160 }}
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ) : null}
|
|
|
|
+ <div className="ml-4">
|
|
|
|
+ <Button type="primary" ghost onClick={() => addRule()}>
|
|
|
|
+ 添加
|
|
|
|
+ </Button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </TabPane>
|
|
|
|
+ </Tabs>
|
|
|
|
+ </div>
|
|
|
|
+ </PageContainer>
|
|
|
|
+ )
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export default RulesCode
|