Parcourir la source

feat: 人员管理模块

lanjianrong il y a 3 ans
Parent
commit
eecc37f56b

+ 6 - 7
src/pages/Institutions/Company/components/CompanyModal.tsx

@@ -1,8 +1,7 @@
 import { useRequest } from 'umi'
 import { useRef, useEffect } from 'react'
-import ProForm, { ProFormSelect, ProFormText } from '@ant-design/pro-form'
+import ProForm, { ProFormText } from '@ant-design/pro-form'
 import { Col, message, Modal, Row } from 'antd'
-import { addProject, updateProject } from '@/services/api/project'
 import type { FormInstance } from 'antd'
 import { addInstitution, updateInstitution } from '@/services/api/institution'
 
@@ -92,7 +91,7 @@ const CompanyModal: React.FC<CompanyModalProps> = ({
               rules={[{ required: true, message: '请输入简称' }]}
             />
             <ProFormText
-              name="organization_code"
+              name="organizationCode"
               label="组织架构代码"
               rules={[{ required: true, message: '请输入组织架构代码' }]}
             />
@@ -110,22 +109,22 @@ const CompanyModal: React.FC<CompanyModalProps> = ({
           </Col>
           <Col span={12}>
             <ProFormText
-              name="enterprise_code"
+              name="enterpriseCode"
               label="企业代码"
               rules={[{ required: true, message: '请输入企业代码' }]}
             />
             <ProFormText
-              name="id_card"
+              name="idCard"
               label="身份证号码"
               rules={[{ required: true, message: '请输入身份证号码' }]}
             />
             <ProFormText
-              name="bank_account"
+              name="bankAccount"
               label="银行账号"
               rules={[{ required: true, message: '请输入银行账号' }]}
             />
             <ProFormText
-              name="legal_person"
+              name="legalPerson"
               label="法人代表"
               rules={[{ required: true, message: '请输入法人代表' }]}
             />

+ 3 - 1
src/pages/Institutions/Company/index.tsx

@@ -8,6 +8,7 @@ import type { ConnectProps } from 'umi'
 import type { ProjectModelState } from '../model'
 import CompanyModal, { ModalType } from './components/CompanyModal'
 import { queryInstitutionList } from '@/services/api/institution'
+import dayjs from 'dayjs'
 
 type ListProps = ConnectProps & {
   pTypeList: { label: string; value: string }[]
@@ -49,7 +50,8 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
     },
     {
       dataIndex: 'createdTime',
-      title: '创建时间'
+      title: '创建时间',
+      renderText: text => dayjs(text * 1000).format('YYYY-MM-DD')
     },
     // {
     //   dataIndex: 'project_type_id',

+ 72 - 0
src/pages/Institutions/Staff/components/DebounceSelect.tsx

@@ -0,0 +1,72 @@
+import { Select, Spin } from 'antd'
+import type { SelectProps } from 'antd'
+import { useRef, useState, useMemo } from 'react'
+import debounce from 'lodash/debounce'
+
+export interface DebounceSelectProps<ValueType = any>
+  extends Omit<SelectProps<ValueType>, 'options' | 'children'> {
+  fetchOptions: (search: string) => Promise<ValueType[]>
+  debounceTimeout?: number
+  defaultOptions?: ValueType[]
+}
+
+function DebounceSelect<
+  ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any
+>({
+  fetchOptions,
+  debounceTimeout = 800,
+  value: val,
+  onChange,
+  defaultOptions,
+  ...props
+}: DebounceSelectProps) {
+  console.log(val)
+
+  const [state, setState] = useState<{ val?: string; fetching: boolean; options: ValueType[] }>({
+    val,
+    fetching: false,
+    options: defaultOptions || []
+  })
+  const fetchRef = useRef(0)
+
+  const debounceFetcher = useMemo(() => {
+    const loadOptions = (value: string) => {
+      fetchRef.current += 1
+      const fetchId = fetchRef.current
+      setState({ ...state, options: [], fetching: true })
+
+      fetchOptions(value).then(newOptions => {
+        if (fetchId !== fetchRef.current) {
+          // for fetch callback order
+          return
+        }
+
+        setState({ ...state, options: newOptions, fetching: false })
+      })
+    }
+
+    return debounce(loadOptions, debounceTimeout)
+  }, [fetchOptions, debounceTimeout])
+
+  const triggerChange = v => {
+    setState({ ...state, val: v })
+    if (v) {
+      onChange(v)
+    }
+  }
+  console.log(state)
+
+  return (
+    <Select<ValueType>
+      value={state.val}
+      onChange={triggerChange}
+      filterOption={false}
+      onSearch={debounceFetcher}
+      notFoundContent={state.fetching ? <Spin size="small" /> : null}
+      {...props}
+      options={state.options}
+    />
+  )
+}
+
+export default DebounceSelect

+ 77 - 12
src/pages/Institutions/Staff/components/StaffModal.tsx

@@ -1,9 +1,11 @@
 import { useRequest } from 'umi'
 import { useRef, useEffect } from 'react'
 import ProForm, { ProFormSelect, ProFormText } from '@ant-design/pro-form'
-import { message, Modal } from 'antd'
+import { Col, message, Modal, Row, Form } from 'antd'
 import type { FormInstance } from 'antd'
-import { addAccount, updateAccount } from '@/services/api/institution'
+import { addAccount, queryInstitutionList, updateAccount } from '@/services/api/institution'
+import DebounceSelect from './DebounceSelect'
+import consts from '@/utils/consts'
 
 export enum ModalType {
   ADD = 0,
@@ -15,7 +17,7 @@ type StaffModalProps = {
   setVisible: (visible: boolean) => void
   type: ModalType
   defaultFormData?: API.AccountListItem
-  // pTypeList: API.ProjectTypeList
+  accountType: API.AccountType
   reloadTable: () => void
 }
 const StaffModal: React.FC<StaffModalProps> = ({
@@ -23,6 +25,7 @@ const StaffModal: React.FC<StaffModalProps> = ({
   setVisible,
   type,
   defaultFormData,
+  accountType,
   // pTypeList,
   reloadTable
 }) => {
@@ -31,15 +34,18 @@ const StaffModal: React.FC<StaffModalProps> = ({
     labelCol: { flex: '100px' }
   }
   const ref = useRef<FormInstance>(null)
+
   useEffect(() => {
     defaultFormData && ref.current?.setFieldsValue({ ...defaultFormData })
   }, [defaultFormData])
+
   const { run: tryUpdateAccount } = useRequest(updateAccount, {
     manual: true,
     onSuccess: () => {
       message.success('更新成功')
     }
   })
+
   const { run: tryAddAccount } = useRequest(addAccount, {
     manual: true,
     onSuccess: () => {
@@ -64,6 +70,19 @@ const StaffModal: React.FC<StaffModalProps> = ({
       }
     })
   }
+  const queryInstitutionOptions = async search => {
+    const { code = -1, data = {} } = await queryInstitutionList({
+      search,
+      current: 1,
+      pageSize: 100
+    })
+    if (code === consts.RET_CODE.SUCCESS) {
+      return data.items.map(item => ({ label: item.name, value: item.ID }))
+    }
+    return []
+  }
+  const { institution } = defaultFormData || {}
+
   return (
     <Modal
       width="35vw"
@@ -76,17 +95,63 @@ const StaffModal: React.FC<StaffModalProps> = ({
       onOk={() => handleOnFinish()}>
       <ProForm formRef={ref} submitter={{ render: false }} {...layout}>
         {type === ModalType.UPDATE ? <ProFormText name="ID" hidden /> : null}
-        <ProFormText
-          name="name"
-          label="名称"
-          rules={[{ required: true, message: '请输入账号名称' }]}
-        />
-        <ProFormSelect
+        <Form.Item
+          labelCol={{ flex: '150px' }}
           name="institutionID"
-          label="企事业单位"
+          label="所属企事业单位"
+          rules={[{ required: true, message: '请选择企事业单位' }]}>
+          <DebounceSelect
+            fetchOptions={queryInstitutionOptions}
+            showSearch
+            defaultOptions={institution && [{ label: institution.name, value: institution.ID }]}
+          />
+        </Form.Item>
+        {/* <ProFormSelect
+          labelCol={{ flex: '150px' }}
+          name="institutionID"
+          label="所属企事业单位"
           rules={[{ required: true, message: '请选择企事业单位' }]}
-        />
-        <ProFormText name="phone" label="手机号" />
+        /> */}
+        <Row>
+          <Col span={12}>
+            <ProFormText
+              name="account"
+              label="账号"
+              rules={[{ required: true, message: '请输入账号' }]}
+            />
+            <ProFormText
+              name="name"
+              label="姓名"
+              rules={[{ required: true, message: '请输入名称' }]}
+            />
+            <ProFormText name="phone" label="手机号" />
+          </Col>
+          <Col span={12}>
+            <ProFormSelect
+              name="accountType"
+              label="账号类型"
+              options={accountType.map(item => ({ label: item.name, value: item.value }))}
+              rules={[{ required: true, message: '请选择账号类型' }]}
+            />
+            {type === ModalType.ADD && (
+              <ProFormText
+                name="password"
+                label="密码"
+                rules={[{ required: true, message: '请输入密码' }]}
+              />
+            )}
+
+            <ProFormSelect
+              name="gender"
+              label="性别"
+              options={[
+                { label: '男', value: 0 },
+                { label: '女', value: 1 }
+              ]}
+              rules={[{ required: true, message: '请选择性别' }]}
+            />
+          </Col>
+        </Row>
       </ProForm>
     </Modal>
   )

+ 21 - 16
src/pages/Institutions/Staff/index.tsx

@@ -5,27 +5,28 @@ import consts from '@/utils/consts'
 import { useRef, useState, useEffect } from 'react'
 import { connect } from 'umi'
 import type { ConnectProps } from 'umi'
-import type { ProjectModelState } from '../model'
+import type { InstitutionsModelState } from '../model'
 import StaffModal, { ModalType } from './components/StaffModal'
 import { queryAcountList } from '@/services/api/institution'
 import dayjs from 'dayjs'
 
 type ListProps = ConnectProps & {
-  pTypeList: { label: string; value: string }[]
+  accountType: API.AccountType[]
 }
 
-const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
+const CompanyList: React.FC<ListProps> = ({ dispatch, accountType }) => {
   const tRef = useRef<ActionType>(null)
   useEffect(() => {
-    if (!pTypeList.length) {
+    if (!accountType.length) {
       dispatch({
-        type: 'project/queryProjectTypeList'
+        type: 'institutions/getAccountTypeList'
       })
     }
   }, [])
   const [state, setState] = useState({
     params: {
-      search: null
+      search: null,
+      accountType: 1
     },
     visible: false,
     currentModalType: ModalType.ADD,
@@ -46,7 +47,15 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
     },
     {
       dataIndex: 'accountType',
-      title: '账号类型'
+      title: '账号类型',
+      filters: true,
+      valueEnum: accountType.reduce((prev, curr) => {
+        const obj = { ...prev }
+        obj[curr.value] = {
+          text: curr.name
+        }
+        return obj
+      }, {})
     },
     {
       dataIndex: 'institution',
@@ -57,7 +66,7 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
     {
       dataIndex: 'createdTime',
       title: '创建时间',
-      renderText: text => dayjs(text).format('YYYY-MM-DD')
+      renderText: text => dayjs(text * 1000).format('YYYY-MM-DD')
     },
     {
       dataIndex: 'created',
@@ -78,10 +87,6 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
     //   }, {})
     // },
     {
-      dataIndex: 'created',
-      title: '创建人'
-    },
-    {
       title: '操作',
       dataIndex: 'operation',
       render: (_, record) => (
@@ -93,7 +98,7 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
                 ...state,
                 visible: true,
                 currentModalType: ModalType.UPDATE,
-                defaultFormData: record
+                defaultFormData: { ...record, institutionID: record.institution.ID }
               })
             }}>
             编辑
@@ -149,8 +154,8 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
       <StaffModal
         type={state.currentModalType}
         defaultFormData={state.defaultFormData}
-        pTypeList={pTypeList}
         visible={state.visible}
+        accountType={accountType}
         reloadTable={() => tRef.current?.reload()}
         setVisible={(visible: boolean) => setState({ ...state, visible })}
       />
@@ -158,6 +163,6 @@ const CompanyList: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
   )
 }
 
-export default connect(({ project }: { project: ProjectModelState }) => ({
-  pTypeList: project.projectTypeList.map(item => ({ label: item.name, value: item.ID }))
+export default connect(({ institutions }: { institutions: InstitutionsModelState }) => ({
+  accountType: institutions.accountType
 }))(CompanyList)

+ 18 - 2
src/pages/Institutions/model.ts

@@ -1,9 +1,12 @@
-import { getProjectTypeList } from '@/services/api/project'
+// import { getProjectTypeList } from '@/services/api/project'
+// import consts from '@/utils/consts'
+import { queryAccountTypeList } from '@/services/api/institution'
 import consts from '@/utils/consts'
 import type { Effect, Reducer } from 'umi'
 
 export interface InstitutionsModelState {
   list: API.InstitutionListItem[]
+  accountType: API.AccountType[]
 }
 
 export interface InstitutionsModelType {
@@ -11,6 +14,7 @@ export interface InstitutionsModelType {
   state: InstitutionsModelState
   effects: {
     query: Effect
+    queryAccountTypeList: Effect
   }
   reducers: {
     save: Reducer<InstitutionsModelState>
@@ -22,7 +26,8 @@ export interface InstitutionsModelType {
 const InstitutionsModel: InstitutionsModelType = {
   namespace: 'institutions',
   state: {
-    list: []
+    list: [],
+    accountType: []
   },
   effects: {
     *queryInstitutionTypeList({ payload }, { call, put }) {
@@ -35,6 +40,17 @@ const InstitutionsModel: InstitutionsModelType = {
       //     }
       //   })
       // }
+    },
+    *getAccountTypeList(_, { call, put }) {
+      const response = yield call(queryAccountTypeList)
+      if (response?.code === consts.RET_CODE.SUCCESS) {
+        yield put({
+          type: 'save',
+          payload: {
+            accountType: response.data
+          }
+        })
+      }
     }
   },
   reducers: {

+ 1 - 1
src/pages/Project/Management/index.tsx

@@ -44,7 +44,7 @@ const List: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
     {
       dataIndex: 'createdTime',
       title: '创建时间',
-      renderText: text => dayjs(text).format('YYYY-MM-DD')
+      renderText: text => dayjs(text * 1000).format('YYYY-MM-DD')
     },
     {
       dataIndex: 'projectTypeID',

+ 8 - 1
src/services/api/institution.ts

@@ -26,7 +26,7 @@ export async function addInstitution(params: API.InstitutionAddParams) {
 
 /** 新增企事业单位下账号 */
 export async function queryAcountList(params: API.InstitutionAddParams) {
-  return request('/Institution/add', {
+  return request('/account/list', {
     method: 'POST',
     data: params
   })
@@ -47,3 +47,10 @@ export async function addAccount(params: API.AcountAddParams) {
     data: params
   })
 }
+
+/** 获取账号类型 */
+export async function queryAccountTypeList() {
+  return request('/account/type', {
+    method: 'GET'
+  })
+}

+ 7 - 1
src/services/api/typings.d.ts

@@ -69,7 +69,7 @@ declare namespace API {
     address: string
     fax: string
     legalPerson: string
-    IDCard: string
+    idCard: string
     createdTime: string
     updatedTime: string
     ID: string
@@ -118,9 +118,15 @@ declare namespace API {
     password: string
     name: string
     phone?: string
+    gender: number
   }
 
   type AcountUpdateParams = Omit<AcountAddParams, 'account' | 'accountType' | 'password'> & {
     ID: string
   }
+
+  type AccountType = {
+    value: number
+    name: string
+  }
 }