|
@@ -1,64 +1,54 @@
|
|
|
-import { useState, useEffect, useContext, useMemo, useCallback } from 'react'
|
|
|
-import { Button, Drawer, Radio, Tabs, Tooltip, Row, Col, Switch, Collapse } from 'antd'
|
|
|
+import { useState, useEffect, useContext, useMemo } from 'react'
|
|
|
+import { Button, Drawer, Radio, Tabs, Tooltip } from 'antd'
|
|
|
import { Actions, FlowContext } from '../../context'
|
|
|
import type { RadioChangeEvent } from 'antd'
|
|
|
import { ApprovalWay, ConfigureType, ParticipantMode } from '../../enum'
|
|
|
import { QuestionCircleFilled } from '@ant-design/icons'
|
|
|
-import { createForm, onFieldMount, onFieldReact, onFormValuesChange } from '@formily/core'
|
|
|
-import { createSchemaField, FormProvider } from '@formily/react'
|
|
|
-import { FormItem, Select } from '@formily/antd'
|
|
|
-import { participantSchema } from '../../utils'
|
|
|
-import { queryAccountList, queryInstitutionList } from '@/services/api/institution'
|
|
|
-import consts from '@/utils/consts'
|
|
|
-import { action } from '@formily/reactive'
|
|
|
+import { queryInstitutionList } from '@/services/api/institution'
|
|
|
import { buildUUID } from '@/utils/uuid'
|
|
|
import styles from './index.less'
|
|
|
-import { useDebounceFn } from 'ahooks'
|
|
|
-const configureItemTitle = {
|
|
|
- [ConfigureType.ADDSIGN]: {
|
|
|
- name: '允许加签',
|
|
|
- short: '签'
|
|
|
- },
|
|
|
- [ConfigureType.ASSISTAUDIT]: {
|
|
|
- name: '允许协审',
|
|
|
- short: '协'
|
|
|
- },
|
|
|
- [ConfigureType.RETURN]: {
|
|
|
- name: '允许退回',
|
|
|
- short: '退'
|
|
|
- },
|
|
|
- [ConfigureType.REVOKE]: {
|
|
|
- name: '允许撤回',
|
|
|
- short: '撤'
|
|
|
- },
|
|
|
- [ConfigureType.SKIP]: {
|
|
|
- name: '允许跳过',
|
|
|
- short: '跳'
|
|
|
- }
|
|
|
-}
|
|
|
+import ParticipantCard from './ParticipantCard'
|
|
|
+import { useRequest } from 'umi'
|
|
|
+import { saveApprovalParticipant } from '@/services/api/project'
|
|
|
+import consts from '@/utils/consts'
|
|
|
|
|
|
-const configureArr = [
|
|
|
- // ConfigureType.ADDSIGN,
|
|
|
- ConfigureType.ASSISTAUDIT,
|
|
|
- ConfigureType.RETURN
|
|
|
- // ConfigureType.REVOKE,
|
|
|
- // ConfigureType.SKIP
|
|
|
-]
|
|
|
const FlowDrawer = () => {
|
|
|
const { flowState, dispatch } = useContext(FlowContext)
|
|
|
- const { drawerConfig } = flowState
|
|
|
-
|
|
|
+ const { modalConfig: { nodeID = null, visible = false } = {}, dataID } = flowState
|
|
|
const [state, setState] = useState({
|
|
|
+ institutionList: [],
|
|
|
approvalWay: ApprovalWay.ACCOUNT,
|
|
|
- accounts: {}
|
|
|
+ accounts: []
|
|
|
})
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
- if (drawerConfig.nodeId && drawerConfig.visible) {
|
|
|
- const defaultStaffIds = flowState.flowData.get(drawerConfig.nodeId)?.approvalAccounts || []
|
|
|
- setState({ ...state, staffOptions: defaultStaffIds })
|
|
|
+ if (nodeID && visible) {
|
|
|
+ console.log(flowState.flowData.get(nodeID))
|
|
|
+
|
|
|
+ const defaultConfig = flowState.flowData.get(nodeID) || {
|
|
|
+ approvalWay: ApprovalWay.ACCOUNT,
|
|
|
+ accounts: []
|
|
|
+ }
|
|
|
+ setState({ ...state, ...defaultConfig })
|
|
|
+ }
|
|
|
+ }, [nodeID])
|
|
|
+
|
|
|
+ useRequest(() => queryInstitutionList({ current: 1, pageSize: 214000 }), {
|
|
|
+ onSuccess(result) {
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ institutionList: result.items.map(item => ({ label: item.name, value: item.ID }))
|
|
|
+ })
|
|
|
}
|
|
|
- }, [drawerConfig])
|
|
|
+ })
|
|
|
|
|
|
+ // 会签、或签按钮不禁用
|
|
|
+ const btnStatus = useMemo(() => {
|
|
|
+ if (state.accounts.length >= 1) {
|
|
|
+ return ![ApprovalWay.JOINTLYSIGN, ApprovalWay.ORSIGN].includes(state.approvalWay)
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ }, [state.approvalWay, state.accounts])
|
|
|
const handleCancel = () => dispatch({ type: Actions.CLOSE_MODAL })
|
|
|
|
|
|
const plainOptions = [{ label: '指定用户', value: ApprovalWay.ACCOUNT }]
|
|
@@ -69,120 +59,70 @@ const FlowDrawer = () => {
|
|
|
setState({ ...state, approvalWay: target.value })
|
|
|
}
|
|
|
}
|
|
|
- const handleOnOk = () => {
|
|
|
+ const handleOnOk = async () => {
|
|
|
+ const { approvalWay, accounts } = state
|
|
|
const payload = {
|
|
|
- id: drawerConfig.nodeId,
|
|
|
+ id: nodeID,
|
|
|
node: {
|
|
|
- approvalType: state.approvalType
|
|
|
+ approvalWay,
|
|
|
+ accounts
|
|
|
}
|
|
|
}
|
|
|
- dispatch({
|
|
|
- type: Actions.SET_FLOW_NODE,
|
|
|
- payload
|
|
|
+ const participantInfo: API.ParticipantInfo = {
|
|
|
+ approvalWay: state.approvalWay,
|
|
|
+ accounts: state.accounts
|
|
|
+ }
|
|
|
+ const { code = -1 } = await saveApprovalParticipant({
|
|
|
+ ID: dataID,
|
|
|
+ segmentID: nodeID,
|
|
|
+ participantInfo
|
|
|
})
|
|
|
- handleCancel()
|
|
|
+ if (code === consts.RET_CODE.SUCCESS) {
|
|
|
+ dispatch({
|
|
|
+ type: Actions.SET_FLOW_NODE,
|
|
|
+ payload
|
|
|
+ })
|
|
|
+ handleCancel()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 添加用户-参与者卡片
|
|
|
const addParticipantInfo = () => {
|
|
|
setState({
|
|
|
...state,
|
|
|
- accounts: {
|
|
|
+ accounts: [
|
|
|
...state.accounts,
|
|
|
- [buildUUID()]: {
|
|
|
+ {
|
|
|
+ uid: buildUUID(),
|
|
|
participantMode: ParticipantMode.ACCOUNT,
|
|
|
ID: null,
|
|
|
name: null,
|
|
|
institutionID: null,
|
|
|
configure: [ConfigureType.ASSISTAUDIT, ConfigureType.RETURN]
|
|
|
}
|
|
|
- }
|
|
|
+ ]
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- const { run: trySaveCardData } = useDebounceFn((targetID, formData) => {
|
|
|
- console.log(1)
|
|
|
-
|
|
|
+ const saveCardData = (targetID, formData) => {
|
|
|
setState({
|
|
|
...state,
|
|
|
- accounts: { ...state.accounts, [targetID]: { ...state.accounts[targetID], ...formData } }
|
|
|
- })
|
|
|
- })
|
|
|
- const renderCard = () => {
|
|
|
- const keys = Object.keys(state.accounts)
|
|
|
- return keys.map(key => {
|
|
|
- const participant = state.accounts?.[key]
|
|
|
- if (!participant) return null
|
|
|
- const formInstance = createForm({
|
|
|
- initialValues: {
|
|
|
- ID: participant.ID,
|
|
|
- participantMode: participant.participantMode,
|
|
|
- institutionID: participant.institutionID,
|
|
|
- name: participant.name
|
|
|
- },
|
|
|
- effects() {
|
|
|
- onFormValuesChange(form => {
|
|
|
- trySaveCardData(key, form.getValuesIn())
|
|
|
- })
|
|
|
- onFieldMount('ID', (field, form) => {
|
|
|
- field.setComponentProps({
|
|
|
- onSelect: (_, option: { label: string; value: string }) => {
|
|
|
- option && form.setValuesIn('name', option?.label)
|
|
|
- }
|
|
|
- })
|
|
|
- })
|
|
|
- onFieldReact('ID', async field => {
|
|
|
- const dataID = field.query('institutionID').get('value')
|
|
|
- if (dataID) {
|
|
|
- const { code = -1, data: { items = [] } = {} } = await queryAccountList({
|
|
|
- current: 1,
|
|
|
- pageSize: 214000,
|
|
|
- dataID
|
|
|
- })
|
|
|
- if (code === consts.RET_CODE.SUCCESS) {
|
|
|
- field.dataSource = items.map(item => ({ label: item.name, value: item.ID }))
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- const useAsyncDataSource = service => field => {
|
|
|
- field.loading = true
|
|
|
- service(field).then(
|
|
|
- action.bound(data => {
|
|
|
- field.dataSource = data
|
|
|
- field.loading = false
|
|
|
- })
|
|
|
- )
|
|
|
- }
|
|
|
- const loadInstitutionList = async () => {
|
|
|
- const { code = -1, data: { items = [] } = {} } = await queryInstitutionList({
|
|
|
- current: 1,
|
|
|
- pageSize: 214000
|
|
|
- })
|
|
|
- if (code === consts.RET_CODE.SUCCESS) {
|
|
|
- return items.map(item => ({ label: item.name, value: item.ID }))
|
|
|
- }
|
|
|
- return []
|
|
|
- }
|
|
|
- const SchemaField = createSchemaField({
|
|
|
- components: {
|
|
|
- FormItem,
|
|
|
- Select
|
|
|
+ accounts: state.accounts.map(item => {
|
|
|
+ if (item.uid === targetID) {
|
|
|
+ const newItem = { ...item, ...formData }
|
|
|
+ return newItem
|
|
|
}
|
|
|
+ return item
|
|
|
})
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
- const toggleCheck = (checked, target) => {
|
|
|
- participant.configure = checked
|
|
|
- ? [...participant.configure, target]
|
|
|
- : participant.configure.filter(item => item !== target)
|
|
|
- setState({ ...state, accounts: { ...state.accounts, [key]: participant } })
|
|
|
- }
|
|
|
+ const renderCard = () => {
|
|
|
+ return state.accounts.map(participant => {
|
|
|
+ if (!participant) return null
|
|
|
|
|
|
const delCardItem = id => {
|
|
|
- const newAccount = { ...state.accounts }
|
|
|
- delete newAccount[id]
|
|
|
- setState({ ...state, accounts: newAccount })
|
|
|
+ setState({ ...state, accounts: state.accounts.filter(item => item.uid !== id) })
|
|
|
}
|
|
|
return (
|
|
|
<div
|
|
@@ -190,66 +130,25 @@ const FlowDrawer = () => {
|
|
|
'shadow-base border rounded-md flex flex-col justify-between px-4 py-2 mt-6',
|
|
|
styles.participantCard
|
|
|
].join(' ')}
|
|
|
- key={key}>
|
|
|
+ key={participant.uid}>
|
|
|
<div className="flex flex-row justify-between">
|
|
|
<div className="text-base font-medium ">参与者</div>
|
|
|
- <div className="text-primary cursor-pointer" onClick={() => delCardItem(key)}>
|
|
|
+ <div
|
|
|
+ className="text-primary cursor-pointer"
|
|
|
+ onClick={() => delCardItem(participant.uid)}>
|
|
|
删除
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className="mt-3">
|
|
|
- <FormProvider form={formInstance}>
|
|
|
- <SchemaField
|
|
|
- schema={participantSchema}
|
|
|
- scope={{
|
|
|
- useAsyncDataSource,
|
|
|
- loadInstitutionList
|
|
|
- }}
|
|
|
- />
|
|
|
- </FormProvider>
|
|
|
+ <ParticipantCard
|
|
|
+ institutionList={state.institutionList}
|
|
|
+ defaultData={participant}
|
|
|
+ updateAction={formData => saveCardData(participant.uid, formData)}
|
|
|
+ />
|
|
|
</div>
|
|
|
{/* <Button onClick={() => console.log(formOptions.instance.getState().values)}>
|
|
|
11111
|
|
|
</Button> */}
|
|
|
-
|
|
|
- <Collapse
|
|
|
- defaultActiveKey={['1']}
|
|
|
- ghost
|
|
|
- expandIcon={({ isActive }) => (
|
|
|
- <span className="text-primary font-medium">{isActive ? '收叠' : '展开'}</span>
|
|
|
- )}
|
|
|
- expandIconPosition="right">
|
|
|
- <Collapse.Panel
|
|
|
- header={
|
|
|
- <div className="flex flex-row justify-between items-center">
|
|
|
- <div className="text-md font-midium h-24px leading-24px">配置信息</div>
|
|
|
- <div className="children:mx-1 flex flex-row ml-1">
|
|
|
- {participant.configure.map(item => (
|
|
|
- <div
|
|
|
- key={item}
|
|
|
- className="w-30px text-center rounded-lg text-primary border border-hex-0089ff bg-hex-e9f5ff">
|
|
|
- {configureItemTitle[item]?.short}
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- }
|
|
|
- key="1">
|
|
|
- <Row>
|
|
|
- {configureArr.map(item => (
|
|
|
- <Col span={8} key={item}>
|
|
|
- <div className="py-2 flex flex-row items-center ">
|
|
|
- <div className="mr-2">{configureItemTitle[item]?.name}</div>
|
|
|
- <Switch
|
|
|
- checked={participant.configure.includes(item)}
|
|
|
- onChange={checked => toggleCheck(checked, item)}
|
|
|
- />
|
|
|
- </div>
|
|
|
- </Col>
|
|
|
- ))}
|
|
|
- </Row>
|
|
|
- </Collapse.Panel>
|
|
|
- </Collapse>
|
|
|
</div>
|
|
|
)
|
|
|
})
|
|
@@ -257,7 +156,7 @@ const FlowDrawer = () => {
|
|
|
|
|
|
return (
|
|
|
<Drawer
|
|
|
- visible={drawerConfig.visible}
|
|
|
+ visible={visible}
|
|
|
onClose={handleCancel}
|
|
|
destroyOnClose
|
|
|
footer={
|
|
@@ -302,7 +201,11 @@ const FlowDrawer = () => {
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="mt-20px">
|
|
|
- <Button type="primary" size="middle" onClick={() => addParticipantInfo()}>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ size="middle"
|
|
|
+ disabled={btnStatus}
|
|
|
+ onClick={() => addParticipantInfo()}>
|
|
|
添加用户
|
|
|
</Button>
|
|
|
</div>
|