Forráskód Böngészése

feat: 执行者列表增改查删

lanjianrong 2 éve
szülő
commit
e1bd3ed114

+ 61 - 35
src/pages/Business/Process/components/MemberItem.tsx

@@ -1,9 +1,10 @@
-import { queryAccountList } from '@/services/api/institution'
+import { queryAcountListByInstitutionID } from '@/services/api/institution'
 import { queryInstitutionRoleList } from '@/services/api/project'
 import consts from '@/utils/consts'
+import { isArray } from '@/utils/is'
 import { useRequest } from '@umijs/max'
 import { Select, TreeSelect } from 'antd'
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
 
 enum AuditType {
   ACCOUNT = 'account',
@@ -11,6 +12,11 @@ enum AuditType {
   ROLE = 'role'
 }
 
+const auditAbbr = {
+  a_: AuditType.ACCOUNT,
+  i_: AuditType.INSTITUTION,
+  r_: AuditType.ROLE
+}
 const auditTypeOptions = [
   { label: '用户', value: AuditType.ACCOUNT },
   { label: '单位角色', value: AuditType.INSTITUTION }
@@ -30,39 +36,48 @@ type iState = {
 
 const filterTreeNodes = (mode: AuditType, tree: string[]) =>
   tree.map(item => {
-    const newItem = { ...item }
+    const newItem = { title: item.name || item.institutionName }
     // 重新拼装id, 根据AuditType加上不同的前缀(后端同步前缀格式)
     switch (mode) {
       case AuditType.ACCOUNT:
-        newItem.ID = `a_${newItem.ID}`
+        newItem.value = `a_${item.ID}`
+        newItem.key = `a_${item.ID}`
         break
       case AuditType.INSTITUTION:
-        newItem.ID = `i_${newItem.ID}`
+        newItem.value = `i_${item.ID}`
         break
       default:
-        newItem.ID = `r_${newItem.ID}`
+        newItem.value = `r_${item.ID}`
         break
     }
-    if (newItem.children) {
+    if (isArray(item.children)) {
       newItem.disabled = true
-      newItem.children = filterTreeNodes(newItem.children)
+      newItem.children = filterTreeNodes(mode, item.children)
       return newItem
     }
     return newItem
   })
-
 const MemberItem: React.FC<MemberItemProps> = ({ value, onChange }) => {
   const [state, setState] = useState<iState>({
     auditType: AuditType.ACCOUNT,
     memberOptions: [],
     members: value
   })
+  useEffect(() => {
+    const findAuditType = () => {
+      const abbr = value?.[0].slice(0, 2)
+      if (auditAbbr[abbr]) {
+        setState({ ...state, auditType: auditAbbr[abbr] })
+      }
+    }
+    findAuditType()
+  }, [])
   useRequest(
     () => {
       let requestFn: Nullable<() => Promise<void>> = null
       switch (state.auditType) {
         case AuditType.ACCOUNT:
-          requestFn = () => queryAccountList({ pageSize: consts.MAX_PAGE_SIZE })
+          requestFn = () => queryAcountListByInstitutionID({ pageSize: consts.MAX_PAGE_SIZE })
           break
         case AuditType.INSTITUTION:
           requestFn = () => queryInstitutionRoleList({ pageSize: consts.MAX_PAGE_SIZE })
@@ -75,7 +90,17 @@ const MemberItem: React.FC<MemberItemProps> = ({ value, onChange }) => {
     {
       refreshDeps: [state.auditType],
       onSuccess(data: { items: any[] }) {
-        setState({ ...state, memberOptions: filterTreeNodes(state.auditType, data.items) })
+        console.log(
+          filterTreeNodes(state.auditType, state.auditType === AuditType.ACCOUNT ? data : data.items)
+        )
+
+        setState({
+          ...state,
+          memberOptions: filterTreeNodes(
+            state.auditType,
+            state.auditType === AuditType.ACCOUNT ? data : data.items
+          )
+        })
       }
     }
   )
@@ -88,30 +113,31 @@ const MemberItem: React.FC<MemberItemProps> = ({ value, onChange }) => {
   const toggleAuditType = (value: AuditType) => setState({ ...state, auditType: value, members: [] })
 
   return (
-    <div className="ant-form-item">
-      <div className="ant-row ant-form-item-row">
-        <div className="ant-col ant-col-5 ant-form-item-label">
-          <label className="ant-form-item-required">成员</label>
-        </div>
-        <div className="ant-col ant-form-item-control">
-          <div className="ant-form-item-control-input">
-            <div className="ant-form-item-control-input-content">
-              <Select
-                defaultValue={state.auditType}
-                options={auditTypeOptions}
-                onChange={toggleAuditType}
-                style={{ width: '100%' }}
-              />
-              <TreeSelect
-                value={state.members}
-                options={state.memberOptions}
-                onChange={toggleChange}
-                style={{ width: '100%', marginTop: '4px' }}
-              />
-            </div>
-          </div>
-        </div>
-      </div>
+    <div>
+      <Select
+        value={state.auditType}
+        options={auditTypeOptions}
+        onChange={toggleAuditType}
+        style={{ width: '100%' }}
+      />
+      {state.auditType === AuditType.ACCOUNT ? (
+        <TreeSelect
+          value={state.members}
+          treeData={state.memberOptions}
+          onChange={toggleChange}
+          multiple
+          maxTagCount="responsive"
+          style={{ width: '100%', marginTop: '4px' }}
+        />
+      ) : (
+        <Select
+          value={state.members}
+          options={state.memberOptions}
+          onChange={toggleChange}
+          fieldNames={{ label: 'title' }}
+          style={{ width: '100%', marginTop: '4px' }}
+        />
+      )}
     </div>
   )
 }

+ 35 - 16
src/pages/Business/Process/hooks/useScripts.tsx

@@ -2,8 +2,8 @@ import MemberItem from '../components/MemberItem'
 import consts from '@/utils/consts'
 import { useState } from 'react'
 import { useRequest } from 'ahooks'
-import { addExecutor, queryExecutorList, updateExecutor } from '@/services/api/business'
-import { ApprovalType, ExecutorSetType } from '@/enums/gc'
+import { addExecutor, delExecutor, queryExecutorList, updateExecutor } from '@/services/api/business'
+import { ApprovalType, BusinessType, ExecutorSetType } from '@/enums/gc'
 import { ExclamationCircleFilled } from '@ant-design/icons'
 import { Form, message, Tooltip } from 'antd'
 import ProForm, { ProFormRadio, ProFormText } from '@ant-design/pro-form'
@@ -36,18 +36,19 @@ const setTypeOptions = [
 ]
 
 type iState = {
-  list: API.ExecutorItem[]
+  items: API.ExecutorItem[]
   total: number
 }
 const approvalTypeOptions = [{ label: '指定用户', value: ApprovalType.TARGET }]
-export default function useScripts(modal: ModalAction) {
+
+export default function useScripts(modal: ModalAction, business: BusinessType) {
   const [state, seState] = useState<iState>({
-    list: [],
+    items: [],
     total: 0
   })
-  const { refresh, loading } = useRequest(queryExecutorList, {
-    onSuccess: (result?: iState) => {
-      seState(result)
+  const { refresh, loading } = useRequest(() => queryExecutorList({ businessType: BusinessType.BUDGET }), {
+    onSuccess: result => {
+      seState(result.data)
     }
   })
 
@@ -58,13 +59,13 @@ export default function useScripts(modal: ModalAction) {
       okText: '确定',
       cancelText: '取消',
       type: 'form',
-      initialValues: initialValues ?? {},
+      initialValues: initialValues ?? {
+        setType: ExecutorSetType.PRESET_MEMBER,
+        approvalType: ApprovalType.TARGET
+      },
       children: (
-        <ProForm<API.ExecutorItem>
-          submitter={false}
-          layout="horizontal"
-          labelCol={{ span: 5 }}
-          isKeyPressSubmit>
+        <ProForm submitter={false} layout="horizontal" labelCol={{ span: 5 }} isKeyPressSubmit>
+          <ProFormText hidden name="ID" />
           <ProFormText
             label="执行者名称"
             name="name"
@@ -83,7 +84,7 @@ export default function useScripts(modal: ModalAction) {
             options={approvalTypeOptions}
             rules={[{ required: true, message: '请选择' }]}
           />
-          <Form.Item noStyle name="members" rules={[{ required: true, message: '请选择' }]}>
+          <Form.Item label="成员" name="members" rules={[{ required: true, message: '请选择' }]}>
             <MemberItem />
           </Form.Item>
         </ProForm>
@@ -92,6 +93,7 @@ export default function useScripts(modal: ModalAction) {
         let requestFn: Nullable<() => Promise<viod>> = null
         if (mode === 'add') {
           requestFn = addExecutor
+          values.businessType = business
         } else {
           requestFn = updateExecutor
         }
@@ -104,5 +106,22 @@ export default function useScripts(modal: ModalAction) {
       }
     })
   }
-  return { data: state, loading, addOrEdit }
+
+  const del = (ID: string) => {
+    modal.open({
+      title: '删除执行者',
+      okText: '确定',
+      cancelText: '取消',
+      children: <div>确定删除该执行者吗?</div>,
+      onOk: async () => {
+        const { code = -1 } = await delExecutor({ ID })
+        if (code === consts.RET_CODE.SUCCESS) {
+          refresh()
+          modal.close()
+          message.success('删除成功')
+        }
+      }
+    })
+  }
+  return { data: state, loading, addOrEdit, del }
 }

+ 38 - 8
src/pages/Business/Process/index.tsx

@@ -1,11 +1,11 @@
 import LeftMenu from './components/LeftMenu'
-import ProTable, { ProColumnType } from '@ant-design/pro-table'
 import useModal from '@/components/Modal'
 import { useState } from 'react'
 import { PageContainer } from '@ant-design/pro-layout'
 import { BusinessType, ApprovalType } from '@/enums/gc'
 import useScripts from './hooks/useScripts'
 import { Button } from 'antd'
+import ProTable, { ProColumnType } from '@ant-design/pro-table'
 
 export const menuOptions = [{ label: '预算业务审批', value: BusinessType.BUDGET }]
 
@@ -18,24 +18,27 @@ const Process = () => {
     activeKey: BusinessType.BUDGET
   })
   const [modal, ModalDOM] = useModal()
-  const { data, loading, addOrEdit } = useScripts(modal)
+  const { data, loading, addOrEdit, del } = useScripts(modal, state.activeKey)
 
   const columns: ProColumnType<API.ExecutorItem>[] = [
     {
       dataIndex: 'name',
       title: '执行者名称',
       width: 120,
+      align: 'center',
       ellipsis: true
     },
     {
       dataIndex: 'setType',
       title: '配置方式',
-      width: 80
+      align: 'center',
+      width: 100
     },
     {
       dataIndex: 'approvalType',
       title: '审批模式',
-      width: 80,
+      width: 100,
+      align: 'center',
       valueEnum: {
         [ApprovalType.TARGET]: { text: '指定用户' }
       }
@@ -43,14 +46,40 @@ const Process = () => {
     {
       dataIndex: 'members',
       title: '成员',
-      renderText: (record: { name: string; ID: string }[]) => (
-        <div className="children:mx-1">{record.map(item => item.name)}</div>
+      width: 240,
+      onHeaderCell: () => ({ style: { textAlign: 'center' } }),
+      ellipsis: true,
+      renderText: (_, record) => (
+        <div className="children:mx-1">
+          {record?.members.map(item => (
+            <span key={item?.ID}>{item?.name}</span>
+          ))}
+        </div>
       )
     },
     {
       dataIndex: 'step',
       title: '步骤',
-      renderText: (record: { name: string; ID: string }) => record.name
+      onHeaderCell: () => ({ style: { textAlign: 'center' } })
+    },
+    {
+      dataIndex: 'opreate',
+      title: '操作',
+      align: 'center',
+      renderText: (_, record) => (
+        <div className="divide-x divide-bg-gray-400 flex flex-row justify-center">
+          <span
+            className="pr-2 text-primary cursor-pointer hover:text-hex-967bbd"
+            onClick={() => addOrEdit('edit', record)}>
+            编辑
+          </span>
+          <span
+            className={'pl-2 text-red-500 cursor-pointer hover:text-red-600'}
+            onClick={() => del(record.ID)}>
+            删除
+          </span>
+        </div>
+      )
     }
   ]
   return (
@@ -71,9 +100,10 @@ const Process = () => {
                 </Button>
               ]
             }}
+            rowKey="ID"
             search={false}
             columns={columns}
-            dataSource={data.list}
+            dataSource={data.items}
             loading={loading}
             pagination={{ total: data.total }}
           />

+ 0 - 11
src/pages/Dashboard/index.tsx

@@ -1,11 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout'
-
-const Dashboard = () => {
-  return (
-    <PageContainer>
-      <div className="w-20 h-20 rounded-3xl border"></div>
-    </PageContainer>
-  )
-}
-
-export default Dashboard

+ 0 - 231
src/pages/Project/Created/index.tsx

@@ -1,231 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout'
-import { useState, useEffect, useRef, useMemo } from 'react'
-import ProTable from '@ant-design/pro-table'
-import type { ActionType } from '@ant-design/pro-table'
-import { ModalForm } from '@ant-design/pro-form'
-import type { ProFormInstance } from '@ant-design/pro-form'
-import type { ProFormColumnsType } from '@ant-design/pro-form'
-import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'
-import { queryAccountList } from '@/services/api/institution'
-import consts from '@/utils/consts'
-import { Button, Form, message, Table } from 'antd'
-import { saveCreator } from '@/services/api/user'
-import { useRequest } from '@umijs/max'
-import { getProjectList } from '@/services/api/project'
-import TreeNodeSelect from '../Management/List/components/TreeNodeSelect'
-import type { ColumnsStateType } from '@ant-design/pro-table/lib/typing'
-
-enum CreatedModalType {
-  ADD = '1',
-  DEL = '2'
-}
-
-const Created = () => {
-  const tRef = useRef<ActionType>(null)
-  const mRef = useRef<ProFormInstance>(null)
-  const [state, setState] = useState({
-    dataID: null,
-    modalType: CreatedModalType.ADD,
-    options: [],
-    projectList: [],
-    modalVisible: false
-  })
-  const { run: tryQueryProjectList } = useRequest(
-    createdID => getProjectList({ current: 1, pageSize: 21300, createdID }),
-    {
-      manual: true,
-      onSuccess: ({ items }) => {
-        setState({ ...state, projectList: items })
-      }
-    }
-  )
-
-  useEffect(() => {
-    if (state.dataID && state.modalType === CreatedModalType.DEL) {
-      tryQueryProjectList(state.dataID)
-    }
-  }, [state.dataID, state.modalType])
-
-  const columns: ProFormColumnsType<AccountListItem>[] = [
-    {
-      dataIndex: 'account',
-      title: '账号',
-      width: 116,
-      onHeaderCell: () => ({ style: { textAlign: 'center' } })
-    },
-    {
-      dataIndex: 'name',
-      title: '名称',
-      width: 86,
-      onHeaderCell: () => ({ style: { textAlign: 'center' } })
-    },
-    {
-      dataIndex: 'institutionID',
-      title: '企事业单位',
-      width: 286,
-      onHeaderCell: () => ({ style: { textAlign: 'center' } }),
-      renderText: (_, record) => record?.institution?.name
-    },
-    {
-      dataIndex: 'organizationalStructureID',
-      title: '组织架构',
-      width: 146,
-      align: 'center',
-      onHeaderCell: () => ({ style: { textAlign: 'center' } }),
-      renderText: (_, record) => record?.organizationalStructure?.name
-    },
-    {
-      dataIndex: 'opreate',
-      title: '操作',
-      width: 61,
-      align: 'center',
-      onHeaderCell: () => ({ style: { textAlign: 'center' } }),
-      render: (_, record) => (
-        <div
-          className="text-hex-fd3995 cursor-pointer hover:text-hex-e7026e"
-          onClick={() =>
-            setState({
-              ...state,
-              dataID: record.ID,
-              modalType: CreatedModalType.DEL,
-              modalVisible: true
-            })
-          }>
-          <DeleteOutlined />
-        </div>
-      )
-    }
-  ]
-
-  const { run: trySaveCreator } = useRequest(saveCreator, {
-    manual: true,
-    onSuccess: () => {
-      tRef?.current?.reload()
-      return message.success('操作成功')
-    }
-  })
-  const onFinish = async formData => {
-    try {
-      if (state.modalType === CreatedModalType.ADD) {
-        await trySaveCreator({ ...formData, isCreated: 1 })
-      } else {
-        await trySaveCreator({ ID: state.dataID, isCreated: 0 })
-      }
-      tRef?.current?.reload()
-      mRef?.current?.resetFields()
-      setState({ ...state, modalVisible: false })
-      return true
-    } catch (error) {
-      return false
-    }
-  }
-
-  const columnsState: ColumnsStateType = useMemo(
-    () => ({
-      persistenceKey: 'project_creator_column_key',
-      persistenceType: 'localStorage'
-    }),
-    []
-  )
-  return (
-    <PageContainer title={false}>
-      <ProTable
-        rowKey="ID"
-        actionRef={tRef}
-        columns={columns}
-        search={false}
-        columnsState={columnsState}
-        toolbar={{
-          actions: [
-            <Button
-              key="add_created_btn"
-              type="primary"
-              icon={<PlusOutlined />}
-              onClick={() => setState({ ...state, modalVisible: true, modalType: CreatedModalType.ADD })}>
-              添加创建人
-            </Button>
-          ]
-        }}
-        scroll={{ y: document.body.clientHeight - 313 }}
-        request={async (params, filter, sort) => {
-          const {
-            code = -1,
-            data: { items, total }
-          } = await queryAccountList({ ...params, ...filter, ...sort, isCreated: 1 })
-          return {
-            success: code === consts.RET_CODE.SUCCESS,
-            data: items,
-            total
-          }
-        }}
-      />
-      <ModalForm
-        title={state.modalType === CreatedModalType.ADD ? '添加创建人' : '移除创建人'}
-        onFinish={onFinish}
-        formRef={mRef}
-        submitter={{
-          submitButtonProps: {
-            danger: state.modalType === CreatedModalType.ADD ? false : true
-          }
-        }}
-        isKeyPressSubmit
-        visible={state.modalVisible}
-        onVisibleChange={visible => setState({ ...state, modalVisible: visible })}>
-        {state.modalType === CreatedModalType.ADD ? (
-          <>
-            {/* <p className="mb-4">创建人可在前台创建项目、上传项目数据、编制项目等</p> */}
-            <Form.Item
-              name="ID"
-              label="创建人可在前台创建项目、上传项目数据、编制项目等"
-              rules={[{ required: true, message: '请选择创建人' }]}>
-              <TreeNodeSelect params={{ isCreated: 0 }} />
-            </Form.Item>
-            {/* <ProFormSelect
-              name="ID"
-              request={async () => {
-                const {
-                  code = -1,
-                  data: { items }
-                } = await queryAcountListByInstitutionID({
-                  current: 1,
-                  pageSize: 21400,
-                  isCreated: '0'
-                })
-                return code === consts.RET_CODE.SUCCESS
-                  ? items.map(item => ({
-                      label: `${item.name} - ${item?.institution?.name}`,
-                      value: item.ID
-                    }))
-                  : []
-              }}
-            /> */}
-          </>
-        ) : (
-          <>
-            <p className="text-red-500">当前创建人已经管理以下项目,移除后,这些项目对应创建人也将被移除。</p>
-            <div className="mt-7">
-              <Table
-                rowKey="ID"
-                columns={[
-                  // {
-                  //   dataIndex: 'sort',
-                  //   title: '序号',
-                  //   render: (_, __, idx) => idx + 1,
-                  //   width: '10%'
-                  // },
-                  { dataIndex: 'name', title: '项目名称' }
-                ]}
-                size="small"
-                scroll={{ y: 250 }}
-                dataSource={state.projectList}
-                pagination={false}
-              />
-            </div>
-          </>
-        )}
-      </ModalForm>
-    </PageContainer>
-  )
-}
-
-export default Created

+ 2 - 3
src/services/api/business.ts

@@ -73,10 +73,9 @@ export async function updateRuleCode(params: API.RuleCodeUpdateParams) {
 }
 
 /** 获取执行者列表 */
-export async function queryExecutorList(params: { bussinessType: BusinessType }) {
+export async function queryExecutorList(params: { businessType: BusinessType }) {
   return request('/executor/list', {
-    method: 'GET',
-    data: params
+    params
   })
 }