|
@@ -1,39 +1,34 @@
|
|
|
import React, { useEffect, useRef } from 'react'
|
|
|
import { message, Button } from 'antd'
|
|
|
-import { connect, useRequest } from 'umi'
|
|
|
-import consts from '@/utils/consts'
|
|
|
-import {
|
|
|
- addAccount,
|
|
|
- updateAccount,
|
|
|
- queryAccountDetail,
|
|
|
- queryInstitutionList,
|
|
|
- queryOrganizationalStructureList
|
|
|
-} from '@/services/api/institution'
|
|
|
-import DebounceSelect from './DebounceSelect'
|
|
|
-// import { delay } from '@/utils/util'
|
|
|
-import FormRender, { useForm } from 'form-render'
|
|
|
-import { BaseMenuEnum } from '@/pages/Schema/Base'
|
|
|
+import { connect, Link, useRequest } from 'umi'
|
|
|
+import { addAccount, updateAccount } from '@/services/api/institution'
|
|
|
+import { BaseMenuEnum, generateFieldIsCreated, SchemaEnum } from '@/pages/Schema/Base'
|
|
|
import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
|
|
|
import type { ConnectProps } from 'umi'
|
|
|
import type { InstitutionsModelState } from '../../model'
|
|
|
-
|
|
|
-import 'antd/lib/tree-select/style/index'
|
|
|
import { ModalType } from '@/utils/enum'
|
|
|
import type { ProFormInstance } from '@ant-design/pro-form'
|
|
|
import { ModalForm, ProFormText } from '@ant-design/pro-form'
|
|
|
import { changeAccountPsw } from '@/services/api/user'
|
|
|
-
|
|
|
+import { createForm, onFieldMount, onFieldReact } from '@formily/core'
|
|
|
+import { createSchemaField } from '@formily/react'
|
|
|
+import { loadOrganizationalStructureList } from '@/utils/schema'
|
|
|
+import {
|
|
|
+ FormItem,
|
|
|
+ Input,
|
|
|
+ Switch,
|
|
|
+ Select,
|
|
|
+ FormLayout,
|
|
|
+ Form,
|
|
|
+ TreeSelect,
|
|
|
+ FormButtonGroup,
|
|
|
+ Submit
|
|
|
+} from '@formily/antd'
|
|
|
type StaffModalProps = ConnectProps & {
|
|
|
- visible: boolean
|
|
|
readOnly: boolean
|
|
|
onVisibleChange: (visible: boolean) => void
|
|
|
- institutionDisable: boolean
|
|
|
type: ModalType
|
|
|
- defaultFormData?: {
|
|
|
- dataID?: string
|
|
|
- institutionID?: string
|
|
|
- institutionDisable?: boolean
|
|
|
- }
|
|
|
+ defaultFormData?: Nullable<API.AccountListItem>
|
|
|
accountTypeList: API.AccountType
|
|
|
organizationList: API.OrganizationalStructureListItem[]
|
|
|
reload: () => void
|
|
@@ -41,16 +36,15 @@ type StaffModalProps = ConnectProps & {
|
|
|
}
|
|
|
|
|
|
const StaffDrawer: React.FC<StaffModalProps> = ({
|
|
|
- visible,
|
|
|
onVisibleChange,
|
|
|
- schema,
|
|
|
+ staffSchema,
|
|
|
dispatch,
|
|
|
type,
|
|
|
defaultFormData,
|
|
|
accountTypeList,
|
|
|
reload
|
|
|
}) => {
|
|
|
- const form = useForm()
|
|
|
+ const { institution, ...otherValues } = defaultFormData
|
|
|
const formRef = useRef<ProFormInstance>(null)
|
|
|
const { run: tryUpdateAccount } = useRequest(updateAccount, {
|
|
|
manual: true,
|
|
@@ -63,6 +57,8 @@ const StaffDrawer: React.FC<StaffModalProps> = ({
|
|
|
manual: true,
|
|
|
onSuccess: () => {
|
|
|
message.success('修改成功')
|
|
|
+ // eslint-disable-next-line no-unused-expressions
|
|
|
+ formRef?.current?.setFieldsValue()
|
|
|
}
|
|
|
})
|
|
|
|
|
@@ -74,164 +70,24 @@ const StaffDrawer: React.FC<StaffModalProps> = ({
|
|
|
})
|
|
|
|
|
|
useEffect(() => {
|
|
|
- if (visible) {
|
|
|
- if (!schema) {
|
|
|
- dispatch({
|
|
|
- type: 'schemaBase/querySchema',
|
|
|
- payload: {
|
|
|
- columnType: BaseMenuEnum.STAFF
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- }, [visible])
|
|
|
-
|
|
|
- const queryInstitutionOptions = async params => {
|
|
|
- const { code = -1, data = {} } = await queryInstitutionList({
|
|
|
- ...params,
|
|
|
- current: 1,
|
|
|
- pageSize: 100
|
|
|
- })
|
|
|
- if (code === consts.RET_CODE.SUCCESS) {
|
|
|
- return data.items.map(item => ({ label: item.name, value: item.ID }))
|
|
|
- }
|
|
|
- return []
|
|
|
- }
|
|
|
-
|
|
|
- const SiteInput = props => {
|
|
|
- return (
|
|
|
- <DebounceSelect
|
|
|
- className="w-full"
|
|
|
- fetchOptions={queryInstitutionOptions}
|
|
|
- showSearch
|
|
|
- // options={institution?.map(item => ({ label: item.name, value: item.ID }))}
|
|
|
- {...props}
|
|
|
- />
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- const onMount = async () => {
|
|
|
- const {
|
|
|
- dataID,
|
|
|
- institutionID,
|
|
|
- institutionDisable = false,
|
|
|
- hiddenOrganization = false
|
|
|
- } = defaultFormData
|
|
|
-
|
|
|
- if (institutionID && type !== ModalType.PREVIEW) {
|
|
|
- const { code = -1, data: list = [] } = await queryOrganizationalStructureList({
|
|
|
- dataID: institutionID,
|
|
|
- structureType: '1'
|
|
|
- })
|
|
|
- if (code === consts.RET_CODE.SUCCESS) {
|
|
|
- setTimeout(() => {
|
|
|
- form.setSchemaByPath('organizationalStructureID', {
|
|
|
- type: 'string',
|
|
|
- widget: 'treeSelect',
|
|
|
- props: {
|
|
|
- treeDefaultExpandAll: true,
|
|
|
- treeData: list
|
|
|
- }
|
|
|
- })
|
|
|
- }, 80)
|
|
|
- }
|
|
|
- }
|
|
|
- if (dataID) {
|
|
|
- const { code = -1, data = {} } = await queryAccountDetail({ ID: dataID })
|
|
|
- if (code === consts.RET_CODE.SUCCESS) {
|
|
|
- const account = {
|
|
|
- ...data,
|
|
|
- institution: null,
|
|
|
- organizationalStructure: null,
|
|
|
- institutionID: data?.institution?.ID,
|
|
|
- organizationalStructureID: data?.organizationalStructure?.ID
|
|
|
+ if (!staffSchema) {
|
|
|
+ dispatch({
|
|
|
+ type: 'schemaBase/querySchema',
|
|
|
+ payload: {
|
|
|
+ columnType: BaseMenuEnum.STAFF
|
|
|
}
|
|
|
- if (type === ModalType.PREVIEW) {
|
|
|
- account.institutionID = data.institution.name
|
|
|
- account.organizationalStructureID = data.organizationalStructure?.name
|
|
|
- }
|
|
|
-
|
|
|
- setTimeout(() => {
|
|
|
- if (type === ModalType.UPDATE && !data.isCreated) {
|
|
|
- form.setSchemaByPath('isCreated', {
|
|
|
- hidden: true
|
|
|
- })
|
|
|
- }
|
|
|
- }, 80)
|
|
|
- form.setValues({
|
|
|
- ...account
|
|
|
- })
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (type === ModalType.ADD) {
|
|
|
- const values = {}
|
|
|
- if (institutionID) values.institutionID = institutionID
|
|
|
- form.setValues(values)
|
|
|
- }
|
|
|
- }
|
|
|
- setTimeout(() => {
|
|
|
- form.setSchemaByPath('accountType', {
|
|
|
- type: 'string',
|
|
|
- widget: 'select',
|
|
|
- enum: accountTypeList.map(item => item.value),
|
|
|
- enumNames: accountTypeList.map(item => item.label)
|
|
|
})
|
|
|
- form.setSchemaByPath('institutionID', {
|
|
|
- type: 'string',
|
|
|
- widget: 'site',
|
|
|
- disabled: institutionDisable
|
|
|
- })
|
|
|
- if (type === ModalType.UPDATE) {
|
|
|
- form.setSchemaByPath('account', {
|
|
|
- disabled: true
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- form.setSchemaByPath('organizationalStructureID', {
|
|
|
- disabled: hiddenOrganization,
|
|
|
- hidden: !institutionID
|
|
|
- })
|
|
|
- if (hiddenOrganization && (type === ModalType.UPDATE || type === ModalType.PREVIEW)) {
|
|
|
- form.setSchemaByPath('password', {
|
|
|
- hidden: true
|
|
|
- })
|
|
|
- } else {
|
|
|
- form.setSchemaByPath('password', {
|
|
|
- required: false
|
|
|
- })
|
|
|
- }
|
|
|
- }, 80)
|
|
|
- }
|
|
|
-
|
|
|
- const watch = {
|
|
|
- institutionID: val => {
|
|
|
- if (!defaultFormData?.institutionID && val) {
|
|
|
- queryOrganizationalStructureList({
|
|
|
- dataID: val,
|
|
|
- structureType: '1'
|
|
|
- }).then(organizationList => {
|
|
|
- if (organizationList) {
|
|
|
- form.setSchemaByPath('organizationalStructureID', {
|
|
|
- type: 'string',
|
|
|
- widget: 'treeSelect',
|
|
|
- props: {
|
|
|
- treeDefaultExpandAll: true,
|
|
|
- treeData: organizationList.data
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
}
|
|
|
- }
|
|
|
- const onFinish = async (formData, errors) => {
|
|
|
- if (errors?.length) return
|
|
|
+ }, [])
|
|
|
+
|
|
|
+ const onFinish = async formData => {
|
|
|
+ if ('institution' in formData) delete formData.institution
|
|
|
try {
|
|
|
// 执行表单提交
|
|
|
if (type === ModalType.ADD) {
|
|
|
await tryAddAccount(formData)
|
|
|
} else {
|
|
|
- await tryUpdateAccount(formData)
|
|
|
+ await tryUpdateAccount({ ...formData, ID: defaultFormData.ID })
|
|
|
}
|
|
|
onVisibleChange(false)
|
|
|
reload()
|
|
@@ -239,84 +95,130 @@ const StaffDrawer: React.FC<StaffModalProps> = ({
|
|
|
message.error(error)
|
|
|
}
|
|
|
}
|
|
|
+ const normalForm = createForm({
|
|
|
+ validateFirst: true,
|
|
|
+ readPretty: type === ModalType.PREVIEW,
|
|
|
+ initialValues: { ...otherValues, institutionID: institution.ID },
|
|
|
+ effects(form) {
|
|
|
+ onFieldMount('password', field => {
|
|
|
+ type !== ModalType.ADD && field.setDisplay('none')
|
|
|
+ })
|
|
|
+ onFieldMount('account', field => {
|
|
|
+ type !== ModalType.ADD && (field.disabled = true)
|
|
|
+ })
|
|
|
+ onFieldReact('isCreated', field => {
|
|
|
+ if (defaultFormData.ID) {
|
|
|
+ field.disabled = true
|
|
|
+ field.value &&
|
|
|
+ field.setDecoratorProps({
|
|
|
+ addonAfter: (
|
|
|
+ <div>
|
|
|
+ <span className="text-red-500 mr-2">需要移除请进入</span>
|
|
|
+ <Link to="/project/created" className="text-primary">
|
|
|
+ 项目创建人
|
|
|
+ </Link>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ return generateFieldIsCreated(field)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ onFieldMount('institutionID', field => {
|
|
|
+ field.dataSource = [{ label: institution?.name, value: institution?.ID }]
|
|
|
+ })
|
|
|
+ onFieldMount('accountType', field => {
|
|
|
+ field.dataSource = accountTypeList
|
|
|
+ })
|
|
|
+ onFieldReact('organizationalStructureID', async field => {
|
|
|
+ if (type === ModalType.PREVIEW) {
|
|
|
+ field.dataSource = [
|
|
|
+ {
|
|
|
+ label: defaultFormData.organizationalStructure.name,
|
|
|
+ value: defaultFormData.organizationalStructure.ID
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ } else {
|
|
|
+ const institutionID = form.values.institutionID
|
|
|
+ const dataSource = await loadOrganizationalStructureList({ dataID: institutionID })
|
|
|
+
|
|
|
+ field.dataSource = dataSource
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const SchemaField = createSchemaField({
|
|
|
+ components: {
|
|
|
+ FormLayout,
|
|
|
+ FormItem,
|
|
|
+ Input,
|
|
|
+ Switch,
|
|
|
+ Select,
|
|
|
+ TreeSelect
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
return (
|
|
|
- <div className="mt-6">
|
|
|
- {schema && (
|
|
|
- <FormRender
|
|
|
- className="max-w-402px"
|
|
|
- form={form}
|
|
|
- schema={schema}
|
|
|
- onFinish={onFinish}
|
|
|
- onMount={onMount}
|
|
|
- readOnly={type === ModalType.PREVIEW ? true : false}
|
|
|
- widgets={{ site: SiteInput }}
|
|
|
- watch={watch}
|
|
|
- />
|
|
|
- )}
|
|
|
- <div className="ml-120px">
|
|
|
- {type === ModalType.UPDATE ? (
|
|
|
- <ModalForm
|
|
|
- formRef={formRef}
|
|
|
- title="修改密码"
|
|
|
- modalProps={{ width: '30vw' }}
|
|
|
- isKeyPressSubmit
|
|
|
- trigger={<Button>重置密码</Button>}
|
|
|
- onFinish={async values => {
|
|
|
- try {
|
|
|
- await tryChangePsw({ ...values, ID: defaultFormData?.dataID })
|
|
|
- formRef.current?.resetFields()
|
|
|
- return true
|
|
|
- } catch (error) {
|
|
|
- return false
|
|
|
- }
|
|
|
- }}>
|
|
|
- <ProFormText.Password
|
|
|
- label="新密码"
|
|
|
- name="newPassword"
|
|
|
- rules={[
|
|
|
- { required: true, message: '请输入新密码' },
|
|
|
- () => ({
|
|
|
- validator(_, value) {
|
|
|
- if (!value) {
|
|
|
+ <Form form={normalForm} labelCol={5} className="max-w-500px mt-6">
|
|
|
+ <SchemaField schema={SchemaEnum?.[BaseMenuEnum.STAFF]} />
|
|
|
+ <SchemaField schema={staffSchema} />
|
|
|
+ <FormButtonGroup.Sticky>
|
|
|
+ <FormButtonGroup.FormItem>
|
|
|
+ {type === ModalType.UPDATE ? (
|
|
|
+ <ModalForm
|
|
|
+ formRef={formRef}
|
|
|
+ title="修改密码"
|
|
|
+ modalProps={{ width: '30vw' }}
|
|
|
+ isKeyPressSubmit
|
|
|
+ trigger={<Button>重置密码</Button>}
|
|
|
+ onFinish={async values => {
|
|
|
+ try {
|
|
|
+ await tryChangePsw({ ...values, ID: defaultFormData?.dataID })
|
|
|
+ return true
|
|
|
+ } catch (error) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <ProFormText.Password
|
|
|
+ label="新密码"
|
|
|
+ name="newPassword"
|
|
|
+ rules={[
|
|
|
+ { required: true, message: '请输入新密码' },
|
|
|
+ () => ({
|
|
|
+ validator(_, value) {
|
|
|
+ if (!value) {
|
|
|
+ return Promise.resolve()
|
|
|
+ }
|
|
|
+ if (!/(?=.*[a-zA-Z])(?=.*\d).{8,16}/.test(value)) {
|
|
|
+ return Promise.reject(new Error('密码长度最小8位且是数字和英文的组合'))
|
|
|
+ }
|
|
|
return Promise.resolve()
|
|
|
}
|
|
|
- if (!/(?=.*[a-zA-Z])(?=.*\d).{8,16}/.test(value)) {
|
|
|
- return Promise.reject(new Error('密码长度最小8位且是数字和英文的组合'))
|
|
|
- }
|
|
|
- return Promise.resolve()
|
|
|
- }
|
|
|
- })
|
|
|
- ]}
|
|
|
- />
|
|
|
- <ProFormText.Password
|
|
|
- label="确认新密码"
|
|
|
- name="confirmPassword"
|
|
|
- rules={[
|
|
|
- { required: true, message: '请输入新密码' },
|
|
|
- ({ getFieldValue }) => ({
|
|
|
- validator(_, value) {
|
|
|
- if (!value || getFieldValue('newPassword') === value) {
|
|
|
- return Promise.resolve()
|
|
|
+ })
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ <ProFormText.Password
|
|
|
+ label="确认新密码"
|
|
|
+ name="confirmPassword"
|
|
|
+ rules={[
|
|
|
+ { required: true, message: '请输入新密码' },
|
|
|
+ ({ getFieldValue }) => ({
|
|
|
+ validator(_, value) {
|
|
|
+ if (!value || getFieldValue('newPassword') === value) {
|
|
|
+ return Promise.resolve()
|
|
|
+ }
|
|
|
+ return Promise.reject(new Error('两次输入的密码不一致!'))
|
|
|
}
|
|
|
- return Promise.reject(new Error('两次输入的密码不一致!'))
|
|
|
- }
|
|
|
- })
|
|
|
- ]}
|
|
|
- />
|
|
|
- </ModalForm>
|
|
|
- ) : null}
|
|
|
- {type !== ModalType.PREVIEW && (
|
|
|
- <Button
|
|
|
- type="primary"
|
|
|
- className="ml-2"
|
|
|
- onClick={() => {
|
|
|
- form.submit()
|
|
|
- }}>
|
|
|
- 提交
|
|
|
- </Button>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ })
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ </ModalForm>
|
|
|
+ ) : null}
|
|
|
+ {type !== ModalType.PREVIEW ? <Submit onSubmit={onFinish}>提交</Submit> : null}
|
|
|
+ </FormButtonGroup.FormItem>
|
|
|
+ </FormButtonGroup.Sticky>
|
|
|
+ </Form>
|
|
|
)
|
|
|
}
|
|
|
|
|
@@ -333,6 +235,6 @@ export default connect(
|
|
|
value: item.value
|
|
|
})),
|
|
|
// organizationList: institutions.organizationType,
|
|
|
- schema: schemaBase.base[BaseMenuEnum.STAFF]?.schema
|
|
|
+ staffSchema: schemaBase.base[BaseMenuEnum.STAFF]
|
|
|
})
|
|
|
)(StaffDrawer)
|