lanjianrong před 3 roky
rodič
revize
27291dc0d1

+ 1 - 2
.eslintrc.js

@@ -4,8 +4,7 @@ module.exports = {
   extends: [require.resolve('@umijs/fabric/dist/eslint')],
   globals: {
     ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
-    page: true,
-    REACT_APP_ENV: true
+    page: true
   },
   rules: {
     semi: ['error', 'never'],

+ 1 - 0
.stylelintignore

@@ -0,0 +1 @@
+src/pages/Schema/Base/components/Designable

+ 2 - 4
.stylelintrc.js

@@ -1,7 +1,6 @@
-const fabric = require('@umijs/fabric')
-
 module.exports = {
-  ...fabric.stylelint,
+  extends: [require.resolve('@umijs/fabric/dist/stylelint')],
+  customSyntax: 'postcss-less',
   rules: {
     indentation: 2,
     'block-no-empty': null,
@@ -10,7 +9,6 @@ module.exports = {
     'max-empty-lines': 2,
     'rule-empty-line-before': null,
     'unit-no-unknown': null,
-    'unit-whitelist': ['px', 'em', 'rem', 's', '%', 'vw', 'vh', 'deg'],
     'selector-max-compound-selectors': 5,
     'at-rule-no-unknown': null,
     'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['global'] }]

+ 2 - 2
config/proxy.ts

@@ -4,8 +4,8 @@
 export default {
   dev: {
     '/api/': {
-      target: 'http://fabdev.com',
-      // target: 'http://fabqa.com',
+      // target: 'http://fabdev.com',
+      target: 'http://fabqa.com',
       changeOrigin: true,
       pathRewrite: { '^': '' }
     }

+ 0 - 10
jest.config.js

@@ -1,10 +0,0 @@
-module.exports = {
-  testURL: 'http://localhost:8000',
-  testEnvironment: './tests/PuppeteerEnvironment',
-  verbose: false,
-  extraSetupFiles: ['./tests/setupTests.js'],
-  globals: {
-    ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: false,
-    localStorage: null,
-  },
-};

+ 9 - 7
package.json

@@ -6,7 +6,6 @@
   "scripts": {
     "analyze": "cross-env ANALYZE=1 umi build",
     "build": "umi build",
-    "deploy:dev": "cross-env REACT_APP_ENV=dev auto-deploy build -t dev",
     "deploy:qa": "cross-env REACT_APP_ENV=dev auto-deploy build -t qa",
     "dev": "npm run start:dev",
     "gh-pages": "gh-pages -d dist",
@@ -18,8 +17,7 @@
     "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style",
     "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src",
     "lint:prettier": "prettier -c --write \"src/**/*\" --end-of-line auto",
-    "lint:style": "stylelint --fix \"src/**/*.less\" --syntax less",
-    "openapi": "umi openapi",
+    "lint:style": "stylelint --fix \"src/**/*.less\" --custom-syntax postcss-less",
     "precommit": "lint-staged",
     "prettier": "prettier -c --write \"src/**/*\"",
     "start": "cross-env UMI_ENV=dev umi dev",
@@ -58,9 +56,13 @@
     "@designable/formily-transformer": "^1.0.0-beta.43",
     "@designable/react": "^1.0.0-beta.43",
     "@designable/react-settings-form": "^1.0.0-beta.43",
+    "@designable/shared": "^1.0.0-beta.43",
     "@formily/antd": "^2.0.8",
     "@formily/core": "^2.0.8",
     "@formily/react": "^2.0.8",
+    "@formily/reactive": "^2.0.11",
+    "@formily/reactive-react": "^2.0.11",
+    "@formily/shared": "^2.0.11",
     "@umijs/route-utils": "^1.0.36",
     "ahooks": "^3.0.0",
     "antd": "^4.18.2",
@@ -91,12 +93,10 @@
     "@types/react": "^17.0.0",
     "@types/react-dom": "^17.0.0",
     "@types/react-helmet": "^6.1.0",
-    "@umijs/fabric": "^2.6.2",
+    "@umijs/fabric": "^2.10.1",
     "@umijs/plugin-blocks": "^2.0.5",
     "@umijs/plugin-esbuild": "^1.0.1",
-    "@umijs/plugin-openapi": "^1.2.0",
     "@umijs/preset-ant-design-pro": "^1.2.0",
-    "@umijs/preset-dumi": "^1.1.7",
     "@umijs/preset-react": "^1.8.17",
     "@umijs/yorkie": "^2.0.3",
     "babel-eslint": "^10.1.0",
@@ -117,9 +117,11 @@
     "gh-pages": "^3.0.0",
     "jsdom-global": "^3.0.2",
     "lint-staged": "^10.0.0",
+    "postcss": "^8.4.6",
+    "postcss-less": "^6.0.0",
     "prettier": "^2.3.2",
     "puppeteer-core": "^8.0.0",
-    "stylelint": "^13.0.0",
+    "stylelint": "13.0.0",
     "typescript": "^4.2.2",
     "windicss": "^3.2.0",
     "windicss-webpack-plugin": "^1.5.5"

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 21774 - 0
pnpm-lock.yaml


+ 1 - 1
src/global.less

@@ -131,7 +131,7 @@ ol {
 }
 
 .ant-pro-page-container-children-content {
-  height: calc(100vh - 122px);
+  // height: calc(100vh - 122px);
   margin: 0 24px 0;
 }
 

+ 16 - 9
src/pages/Institutions/Company/Detail/components/Organization.tsx

@@ -31,7 +31,7 @@ export enum ModalTypeEnum {
   MOVE = 5
 }
 
-const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) => {
+const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }) => {
   const tRef = useRef<ActionType>(null)
   const [state, setState] = useState({
     organizationList: [],
@@ -97,11 +97,12 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
       align: 'center',
       onHeaderCell: () => ({ style: { textAlign: 'center' } }),
       render: (_, record) => (
-        <div className="divide-x divide-bg-gray-400 flex flex-row">
+        <div className="divide-x divide-bg-gray-400 flex flex-row items-center justify-center">
           {record.isStart === false ? (
             <div
               className="px-2 text-primary cursor-pointer hover:text-hex-967bbd"
-              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'up' })}>
+              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'up' })}
+            >
               <Tooltip placement="top" title="上移">
                 <ArrowUpOutlined />
               </Tooltip>
@@ -110,7 +111,8 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
           {record.isEnd === false ? (
             <div
               className="px-2 text-primary cursor-pointer hover:text-hex-967bbd"
-              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'down' })}>
+              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'down' })}
+            >
               <Tooltip placement="top" title="下移">
                 <ArrowDownOutlined />
               </Tooltip>
@@ -126,7 +128,8 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
                   defaultFormData: record,
                   currentModalType: ModalTypeEnum.MOVE
                 })
-              }}>
+              }}
+            >
               <Tooltip placement="top" title="移动">
                 <SwapOutlined />
               </Tooltip>
@@ -141,12 +144,13 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
                 visible: true,
                 defaultFormData: {
                   dataID: dataID,
-                  structureType: structureType,
+                  structureType: 1,
                   parentID: record.ID
                 },
                 currentModalType: ModalTypeEnum.ADDITEM
               })
-            }}>
+            }}
+          >
             <Tooltip placement="top" title="添加子项">
               <PlusSquareOutlined />
             </Tooltip>
@@ -160,7 +164,8 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
                 defaultFormData: record,
                 currentModalType: ModalTypeEnum.UPDATE
               })
-            }}>
+            }}
+          >
             <Tooltip placement="top" title="重命名">
               <EditOutlined />
             </Tooltip>
@@ -220,6 +225,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
           actions: [
             <Button
               type="primary"
+              key="add"
               onClick={() =>
                 setState({
                   ...state,
@@ -231,7 +237,8 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType }) =>
                     parentID: state.parentID
                   }
                 })
-              }>
+              }
+            >
               添加组织
             </Button>
           ]

+ 8 - 4
src/pages/Institutions/Company/Detail/components/Role.tsx

@@ -26,9 +26,11 @@ const Role: FC<RoleProps> = ({ dataID, memberTotal, managerID }) => {
         wrapperCol={{ span: 6 }}
         onFinish={async values => {
           await trySave({ ...values, ID: dataID })
-        }}>
+        }}
+      >
         <ProFormSelect
-          label="单位管理员:管理员可在前台维护单位信息和维护单位下成员"
+          label="单位管理员:"
+          tooltip="管理员可在前台维护单位信息和维护单位下成员"
           name="accountID"
           rules={[{ required: true, message: '请选择单位管理员' }]}
           request={async () => {
@@ -45,9 +47,11 @@ const Role: FC<RoleProps> = ({ dataID, memberTotal, managerID }) => {
           }}
         />
         <Form.Item
-          label={`最大成员数量:已有成员${memberTotal}`}
+          label="最大成员数量:"
+          tooltip={`已有成员${memberTotal}`}
           name="memberTotal"
-          rules={[{ required: true, message: '请输入成员总数' }]}>
+          rules={[{ required: true, message: '请输入成员总数' }]}
+        >
           <InputNumber style={{ width: '100%' }} />
         </Form.Item>
       </ProForm>

+ 13 - 11
src/pages/Institutions/Company/Detail/components/Staff.tsx

@@ -14,17 +14,18 @@ import { generateColumns } from '@/utils/util'
 import { genderEum } from '@/pages/Institutions/Staff'
 import AnimateContent from '@/components/AnimateContent'
 import { ModalType } from '@/utils/enum'
-import { TeamOutlined } from '@ant-design/icons'
 
 type ListProps = ConnectProps & {
   accountType: API.AccountType[]
   memberTotal: number
   dataID: string
+  companyName: string
   managerID: string
 }
 const Staff: React.FC<ListProps> = ({
   schema,
   dataID,
+  companyName,
   dispatch,
   accountTypeList,
   memberTotal = 1,
@@ -174,13 +175,10 @@ const Staff: React.FC<ListProps> = ({
                 visible: true,
                 currentModalType: ModalType.UPDATE,
                 title: record.name,
-                defaultFormData: {
-                  dataID: record.ID,
-                  institutionID: record.institution.ID,
-                  institutionDisable: true
-                }
+                defaultFormData: record
               })
-            }}>
+            }}
+          >
             编辑
           </div>
         </div>
@@ -237,10 +235,14 @@ const Staff: React.FC<ListProps> = ({
                     title: '',
                     defaultFormData: {
                       institutionID: dataID,
-                      institutionDisable: true
+                      institution: {
+                        ID: dataID,
+                        name: companyName
+                      }
                     }
                   })
-                }}>
+                }}
+              >
                 添加人员
               </Button>
             )
@@ -255,9 +257,9 @@ const Staff: React.FC<ListProps> = ({
           </>
         }
         visible={state.visible}
-        onVisibleChange={visible => setState({ ...state, visible })}>
+        onVisibleChange={visible => setState({ ...state, visible })}
+      >
         <StaffDetail
-          visible={state.visible}
           onVisibleChange={(visible: boolean) => setState({ ...state, visible })}
           type={state.currentModalType}
           defaultFormData={{ ...state.defaultFormData }}

+ 44 - 17
src/pages/Institutions/Company/Detail/index.tsx

@@ -1,10 +1,12 @@
-import React, { useState } from 'react'
+import React, { useEffect, useState } from 'react'
 import Staff from './components/Staff'
 import Organization from './components/Organization'
 import Role from './components/Role'
 import { PageContainer } from '@ant-design/pro-layout'
 import type { RouteComponentProps } from 'react-router'
 import type { InstitutionDetailProps } from '../List'
+import { useRequest } from 'umi'
+import { queryInstitution } from '@/services/api/institution'
 
 export enum TabEnum {
   STAFF = '0',
@@ -15,8 +17,17 @@ export enum TabEnum {
 type CompanyDetailProps = RouteComponentProps
 
 const CompanyDetail: React.FC<CompanyDetailProps> = ({ location }) => {
-  const { dataID, structureType, name, memberTotal, managerID } =
-    location.state as InstitutionDetailProps
+  const { dataID } = location.state as InstitutionDetailProps
+  const [company, setCompany] = useState<Nullable<API.InstitutionListItem>>(null)
+  const { run: tryQueryCompany } = useRequest(queryInstitution, {
+    manual: true,
+    onSuccess: result => {
+      setCompany(result)
+    }
+  })
+  useEffect(() => {
+    dataID && tryQueryCompany({ ID: dataID })
+  }, [dataID])
 
   const menuMap: Record<string, string> = {
     [TabEnum.STAFF]: '人员管理',
@@ -28,28 +39,44 @@ const CompanyDetail: React.FC<CompanyDetailProps> = ({ location }) => {
   const renderChildren = () => {
     switch (selectKey) {
       case TabEnum.STAFF:
-        return <Staff dataID={dataID} memberTotal={memberTotal} managerID={managerID} />
+        return (
+          <Staff
+            dataID={dataID}
+            companyName={company?.name}
+            memberTotal={company?.memberTotal}
+            managerID={company?.manager?.ID}
+          />
+        )
       case TabEnum.ORGANIZATION:
-        return <Organization dataID={dataID} structureType={structureType} />
+        return <Organization dataID={dataID} />
       case TabEnum.ROLE:
-        return <Role dataID={dataID} memberTotal={memberTotal} managerID={managerID} />
+        return (
+          <Role
+            dataID={dataID}
+            memberTotal={company?.memberTotal}
+            managerID={company?.manager?.ID}
+          />
+        )
       default:
         return null
     }
   }
 
   return (
-    <PageContainer
-      title={name}
-      fixedHeader
-      tabList={[
-        { tab: menuMap[TabEnum.STAFF], key: TabEnum.STAFF },
-        { tab: menuMap[TabEnum.ORGANIZATION], key: TabEnum.ORGANIZATION },
-        { tab: menuMap[TabEnum.ROLE], key: TabEnum.ROLE }
-      ]}
-      onTabChange={key => setSelectKey(key)}>
-      {renderChildren()}
-    </PageContainer>
+    company && (
+      <PageContainer
+        title={company.name}
+        fixedHeader
+        tabList={[
+          { tab: menuMap[TabEnum.STAFF], key: TabEnum.STAFF },
+          { tab: menuMap[TabEnum.ORGANIZATION], key: TabEnum.ORGANIZATION },
+          { tab: menuMap[TabEnum.ROLE], key: TabEnum.ROLE }
+        ]}
+        onTabChange={key => setSelectKey(key)}
+      >
+        {renderChildren()}
+      </PageContainer>
+    )
   )
 }
 

+ 45 - 41
src/pages/Institutions/Company/List/components/CompanyDrawer.tsx

@@ -1,34 +1,56 @@
 import { connect, useRequest } from 'umi'
 import { useEffect } from 'react'
-import FormRender, { useForm } from 'form-render'
-import { message, Button } from 'antd'
+import { message } from 'antd'
 import { addInstitution, updateInstitution } from '@/services/api/institution'
-import { BaseMenuEnum } from '@/pages/Schema/Base'
 import { ModalType } from '@/utils/enum'
 import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
 import type { ConnectProps } from 'umi'
+import { BaseMenuEnum, SchemaEnum } from '@/pages/Schema/Base'
+import { createForm } from '@formily/core'
+import {
+  Form,
+  FormButtonGroup,
+  Submit,
+  FormLayout,
+  FormItem,
+  Input,
+  Select,
+  FormGrid
+} from '@formily/antd'
+import { createSchemaField } from '@formily/react'
 
 type CompanyModalProps = ConnectProps & {
-  visible: boolean
   setVisible: (visible: boolean) => void
   type: ModalType
   defaultFormData?: API.InstitutionListItem
   reload: () => void
-  schema?: Record<string, any> | null
+  companySchema?: Record<string, any> | null
 }
 
 const CompanyDrawer: React.FC<CompanyModalProps> = ({
-  visible,
+  dispatch,
   setVisible,
   type,
   defaultFormData,
-  schema,
-  // pTypeList,
+  companySchema,
   reload
 }) => {
-  const form = useForm()
+  const formInstance = createForm({
+    validateFirst: true,
+    initialValues: type === ModalType.UPDATE ? defaultFormData : null
+  })
+
+  const SchemaField = createSchemaField({
+    components: {
+      FormLayout,
+      FormItem,
+      FormGrid,
+      Input,
+      Select
+    }
+  })
   useEffect(() => {
-    if (visible && !schema) {
+    if (!companySchema) {
       dispatch({
         type: 'schemaBase/querySchema',
         payload: {
@@ -36,7 +58,7 @@ const CompanyDrawer: React.FC<CompanyModalProps> = ({
         }
       })
     }
-  }, [visible])
+  }, [])
   const { run: tryUpdateInstitution } = useRequest(updateInstitution, {
     manual: true,
     onSuccess: () => {
@@ -50,8 +72,7 @@ const CompanyDrawer: React.FC<CompanyModalProps> = ({
     }
   })
 
-  const onFinish = async (formData, errors) => {
-    if (errors?.length) return
+  const onFinish = async formData => {
     try {
       // 执行表单提交
       if (type === ModalType.ADD) {
@@ -61,45 +82,28 @@ const CompanyDrawer: React.FC<CompanyModalProps> = ({
       }
       setVisible(false)
       reload()
-      // ref.current?.resetFields()
     } catch (error) {
       message.error(error)
     }
   }
 
-  const onMount = () => {
-    // console.log(defaultFormData)
-    form.setValues(type === ModalType.ADD ? {} : { ...defaultFormData })
-    // form.setValues({ ...defaultFormData })
-    // delay().then(() => {
-    //   form.setSchemaByPath('projectTypeID', {
-    //     enum: pTypeList.map(item => item.value),
-    //     enumNames: pTypeList.map(item => item.label)
-    //   })
-    // })
-  }
   return (
     <div className="mt-6">
-      <div className="max-w-964px">
-        {schema && <FormRender form={form} schema={schema} onFinish={onFinish} onMount={onMount} />}
-      </div>
-      <div className="ml-137px">
-        <Button type="primary" onClick={form.submit}>
-          提交
-        </Button>
+      <div className="max-w-800px">
+        <Form form={formInstance}>
+          <SchemaField schema={SchemaEnum?.[BaseMenuEnum.COMPANY]} />
+          <SchemaField schema={companySchema} />
+          <FormButtonGroup.Sticky>
+            <FormButtonGroup.FormItem labelCol={4}>
+              <Submit onSubmit={onFinish}>提交</Submit>
+            </FormButtonGroup.FormItem>
+          </FormButtonGroup.Sticky>
+        </Form>
       </div>
-      {/* <Form>
-        {schema && <FormRender form={form} schema={schema} onFinish={onFinish} onMount={onMount} />}
-        <div className="ml-120px">
-          <Button type="primary" onClick={form.submit}>
-            提交
-          </Button>
-        </div>
-      </Form> */}
     </div>
   )
 }
 
 export default connect(({ schemaBase }: { schemaBase: SchemaBaseModelState }) => ({
-  schema: schemaBase.base[BaseMenuEnum.COMPANY]?.schema
+  companySchema: schemaBase.base[BaseMenuEnum.COMPANY]
 }))(CompanyDrawer)

+ 51 - 54
src/pages/Institutions/Company/List/index.tsx

@@ -2,56 +2,50 @@ import dayjs from 'dayjs'
 import ProTable from '@ant-design/pro-table'
 import consts from '@/utils/consts'
 import { Button } from 'antd'
-import { useRef, useState, useEffect } from 'react'
-import { connect, history } from 'umi'
+import { useRef, useState } from 'react'
+import { history } from 'umi'
 import { queryInstitutionList } from '@/services/api/institution'
 import type { ProColumnType, ActionType } from '@ant-design/pro-table'
-import type { ConnectProps } from 'umi'
-import type { ProjectModelState } from '../../model'
-import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
-import { BaseMenuEnum } from '@/pages/Schema/Base'
 import { PageContainer } from '@ant-design/pro-layout'
 import CompanyDrawer from './components/CompanyDrawer'
 import { ModalType } from '@/utils/enum'
-import { generateColumns } from '@/utils/util'
 import AnimateContent from '@/components/AnimateContent'
 
-type ListProps = ConnectProps & {
-  pTypeList: { label: string; value: string }[]
-  base: Record<string, any>
-}
+// type ListProps = ConnectProps & {
+//   pTypeList: { label: string; value: string }[]
+//   base: Record<string, any>
+// }
 
 export type InstitutionDetailProps = {
   dataID: string
-  structureType: string
-  name: string
-  memberTotal: number
-  managerID: string
+  // structureType: string
+  // name: string
+  // memberTotal: number
+  // managerID: string
 }
 
-const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
+const CompanyList = () => {
   const tRef = useRef<ActionType>(null)
-  const schema = base?.[BaseMenuEnum.COMPANY]?.schema
-  useEffect(() => {
-    if (!pTypeList.length) {
-      dispatch({
-        type: 'project/queryProjectTypeList'
-      })
-    }
-    if (!base[BaseMenuEnum.COMPANY]) {
-      dispatch({
-        type: 'schemaBase/querySchema',
-        payload: {
-          columnType: BaseMenuEnum.COMPANY
-        }
-      })
-    }
-  }, [])
+  // const schema = base?.[BaseMenuEnum.COMPANY]?.schema
+  // useEffect(() => {
+  // if (!pTypeList.length) {
+  //   dispatch({
+  //     type: 'project/queryProjectTypeList'
+  //   })
+  // }
+  // if (!base[BaseMenuEnum.COMPANY]) {
+  //   dispatch({
+  //     type: 'schemaBase/querySchema',
+  //     payload: {
+  //       columnType: BaseMenuEnum.COMPANY
+  //     }
+  //   })
+  // }
+  // }, [])
   const [state, setState] = useState({
     params: {
       search: null
     },
-    structureType: 1,
     visible: false,
     currentModalType: ModalType.ADD,
     defaultFormData: null
@@ -79,14 +73,15 @@ const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
         <span
           onClick={() =>
             goToDetail({
-              dataID: record.ID,
-              structureType: state.structureType,
-              name: record.name,
-              memberTotal: record.memberTotal,
-              managerID: record.manager.ID
+              dataID: record.ID
+              // structureType: state.structureType,
+              // name: record.name,
+              // memberTotal: record.memberTotal,
+              // managerID: record.manager.ID
             })
           }
-          className="text-primary cursor-pointer">
+          className="text-primary cursor-pointer"
+        >
           {name}
         </span>
       )
@@ -151,7 +146,8 @@ const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
                 currentModalType: ModalType.UPDATE,
                 defaultFormData: record
               })
-            }}>
+            }}
+          >
             编辑
           </div>
           {/* <Popconfirm
@@ -175,8 +171,8 @@ const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
         rowKey="ID"
         params={state.params}
         actionRef={tRef}
-        scroll={{ y: document.body.clientHeight - 313 }}
-        columns={generateColumns(columns, schema)}
+        scroll={{ y: document.body.clientHeight - 291 }}
+        columns={columns}
         request={async (params, filter, sorter) => {
           const { code = -1, data: { items = [], total = 0 } = {} } = await queryInstitutionList({
             ...params,
@@ -195,10 +191,10 @@ const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
           },
           actions: [
             <Button
+              key="add"
               type="primary"
-              onClick={() =>
-                setState({ ...state, visible: true, currentModalType: ModalType.ADD })
-              }>
+              onClick={() => setState({ ...state, visible: true, currentModalType: ModalType.ADD })}
+            >
               新建企事业单位
             </Button>
           ]
@@ -208,12 +204,12 @@ const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
       <AnimateContent
         title={state.currentModalType === ModalType.ADD ? '新增企事业单位' : '编辑企事业单位'}
         visible={state.visible}
-        onVisibleChange={visible => setState({ ...state, visible })}>
+        onVisibleChange={visible => setState({ ...state, visible })}
+      >
         <CompanyDrawer
           type={state.currentModalType}
           defaultFormData={state.defaultFormData}
-          pTypeList={pTypeList}
-          visible={state.visible}
+          // pTypeList={pTypeList}
           reload={() => tRef.current?.reload()}
           setVisible={(visible: boolean) => setState({ ...state, visible })}
         />
@@ -222,9 +218,10 @@ const CompanyList: React.FC<ListProps> = ({ base, dispatch, pTypeList }) => {
   )
 }
 
-export default connect(
-  ({ project, schemaBase }: { project: ProjectModelState; schemaBase: SchemaBaseModelState }) => ({
-    pTypeList: project.projectTypeList.map(item => ({ label: item.name, value: item.ID })),
-    base: schemaBase.base
-  })
-)(CompanyList)
+// export default connect(
+//   ({ project, schemaBase }: { project: ProjectModelState; schemaBase: SchemaBaseModelState }) => ({
+//     pTypeList: project.projectTypeList.map(item => ({ label: item.name, value: item.ID }))
+//     // base: schemaBase.base
+//   })
+// )(CompanyList)
+export default CompanyList

+ 153 - 251
src/pages/Institutions/Staff/components/StaffDetail.tsx

@@ -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)

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

@@ -1,7 +1,6 @@
 import ProTable from '@ant-design/pro-table'
 import type { ProColumnType, ActionType } from '@ant-design/pro-table'
 import { PageContainer } from '@ant-design/pro-layout'
-import { Button } from 'antd'
 import consts from '@/utils/consts'
 import { useRef, useState, useEffect } from 'react'
 import { connect } from 'umi'
@@ -11,15 +10,11 @@ import type { InstitutionsModelState } from '../model'
 import { queryAcountList } from '@/services/api/institution'
 import dayjs from 'dayjs'
 import StaffDetail from './components/StaffDetail'
-import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
-import { BaseMenuEnum } from '@/pages/Schema/Base'
-import { generateColumns } from '@/utils/util'
 import AnimateContent from '@/components/AnimateContent'
 import { ModalType } from '@/utils/enum'
 
 type ListProps = ConnectProps & {
   accountTypeList: { label: string; value: string }[]
-  schema?: Record<string, any> | null
 }
 
 export const genderEum = {
@@ -27,7 +22,7 @@ export const genderEum = {
   1: '女'
 }
 
-const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList }) => {
+const CompanyList: React.FC<ListProps> = ({ dispatch, accountTypeList }) => {
   // console.log(accountTypeList)
 
   const tRef = useRef<ActionType>(null)
@@ -37,12 +32,6 @@ const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList })
         type: 'institutions/queryAccountTypeList'
       })
     }
-    dispatch({
-      type: 'schemaBase/querySchema',
-      payload: {
-        columnType: BaseMenuEnum.STAFF
-      }
-    })
   }, [])
   const [state, setState] = useState({
     params: {
@@ -72,14 +61,10 @@ const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList })
               visible: true,
               currentModalType: ModalType.PREVIEW,
               title: record.name,
-              defaultFormData: {
-                dataID: record.ID,
-                institutionID: record.institution.ID,
-                institutionDisable: true,
-                hiddenOrganization: true
-              }
+              defaultFormData: record
             })
-          }}>
+          }}
+        >
           {name}
         </div>
       )
@@ -187,14 +172,10 @@ const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList })
                 visible: true,
                 currentModalType: ModalType.UPDATE,
                 title: record.name,
-                defaultFormData: {
-                  dataID: record.ID,
-                  institutionID: record.institution.ID,
-                  institutionDisable: true,
-                  hiddenOrganization: true
-                }
+                defaultFormData: record
               })
-            }}>
+            }}
+          >
             编辑
           </div>
           {/* <Popconfirm
@@ -219,7 +200,7 @@ const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList })
         params={state.params}
         actionRef={tRef}
         scroll={{ y: document.body.clientHeight - 313 }}
-        columns={generateColumns(columns, schema)}
+        columns={columns}
         request={async (params, filter, sorter) => {
           const { code = -1, data: { items = [], total = 0 } = {} } = await queryAcountList({
             ...params,
@@ -263,13 +244,13 @@ const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList })
       <AnimateContent
         title={
           <>
-            {state.currentModalType === ModalType.ADD ? '新增账号' : null}
             {state.currentModalType === ModalType.UPDATE ? `编辑账号(${state.title})` : null}
             {state.currentModalType === ModalType.PREVIEW ? `员工详情(${state.title})` : null}
           </>
         }
         visible={state.visible}
-        onVisibleChange={visible => setState({ ...state, visible })}>
+        onVisibleChange={visible => setState({ ...state, visible })}
+      >
         <StaffDetail
           type={state.currentModalType}
           defaultFormData={state.defaultFormData}
@@ -282,18 +263,9 @@ const CompanyList: React.FC<ListProps> = ({ schema, dispatch, accountTypeList })
   )
 }
 
-export default connect(
-  ({
-    institutions,
-    schemaBase
-  }: {
-    institutions: InstitutionsModelState
-    schemaBase: SchemaBaseModelState
-  }) => ({
-    accountTypeList: institutions.accountType.map(item => ({
-      label: item.name,
-      value: item.value
-    })),
-    schema: schemaBase.base[BaseMenuEnum.STAFF]?.schema
-  })
-)(CompanyList)
+export default connect(({ institutions }: { institutions: InstitutionsModelState }) => ({
+  accountTypeList: institutions.accountType.map(item => ({
+    label: item.name,
+    value: item.value
+  }))
+}))(CompanyList)

+ 3 - 20
src/pages/Project/Management/Detail/components/ProjectInfo.tsx

@@ -1,11 +1,10 @@
 import { createForm, onFieldMount } from '@formily/core'
-import { createSchemaField, Field, FormProvider } from '@formily/react'
+import { createSchemaField, FormProvider } from '@formily/react'
 import { FormLayout, FormItem, Input, Select } from '@formily/antd'
 import { BaseMenuEnum, SchemaEnum } from '@/pages/Schema/Base'
 import type { ConnectProps } from 'umi'
 import { connect } from 'umi'
 import { useEffect } from 'react'
-import { connectSchema } from '@/utils/schema'
 import { Card } from 'antd'
 
 type ProjectInfoProps = ConnectProps & {
@@ -59,24 +58,8 @@ const ProjectInfo: React.FC<ProjectInfoProps> = ({
     <Card>
       <div className="max-w-560px ">
         <FormProvider form={formInstance}>
-          <SchemaField
-            schema={connectSchema(SchemaEnum?.[BaseMenuEnum.PROJECT], projectSchema)}
-            // scope={{ useAsyncDataSource }}
-          />
-          {/* <Field
-            name="created"
-            title="创建人"
-            initialValue={defaultFormData.created ? `${defaultFormData.created?.name}(${defaultFormData.created?.institution.name})` : null}
-            component={[Input]}
-            decorator={[FormItem, { labelCol: 6, wrapperCol: 8 }]}
-          />
-          <Field
-            name="reportAccount"
-            title="编辑者"
-            initialValue={'111'}
-            component={[Input]}
-            decorator={[FormItem, { labelCol: 6, wrapperCol: 8 }]}
-          /> */}
+          <SchemaField schema={SchemaEnum?.[BaseMenuEnum.PROJECT]} />
+          <SchemaField schema={projectSchema} />
         </FormProvider>
       </div>
     </Card>

+ 5 - 4
src/pages/Project/Management/List/components/ProjectModal.tsx

@@ -5,7 +5,6 @@ import { BaseMenuEnum, SchemaEnum } from '@/pages/Schema/Base'
 import { createForm, onFieldMount } from '@formily/core'
 import { Form, FormButtonGroup, Submit, FormLayout, FormItem, Input, Select } from '@formily/antd'
 import { createSchemaField } from '@formily/react'
-import { connectSchema } from '@/utils/schema'
 
 import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
 import type { ConnectProps } from 'umi'
@@ -20,7 +19,6 @@ export enum ModalType {
 type ProjectModalProps = ConnectProps & {
   visible: boolean
   setVisible: (visible: boolean) => void
-  readOnly: boolean
   type: ModalType
   defaultFormData: Record<string, any> | null
   pTypeList: API.ProjectTypeList
@@ -39,7 +37,9 @@ const ProjectModal: React.FC<ProjectModalProps> = ({
     validateFirst: true,
     initialValues: type === ModalType.UPDATE ? defaultFormData : null,
     effects() {
-      onFieldMount('projectTypeID', field => (field.dataSource = pTypeList))
+      onFieldMount('projectTypeID', field => {
+        field.dataSource = pTypeList
+      })
     }
   })
 
@@ -83,7 +83,8 @@ const ProjectModal: React.FC<ProjectModalProps> = ({
   return (
     <div className="max-w-800px mt-20px">
       <Form form={formInstance} labelCol={6} wrapperCol={8}>
-        <SchemaField schema={connectSchema(SchemaEnum?.[BaseMenuEnum.PROJECT], projectSchema)} />
+        <SchemaField schema={SchemaEnum?.[BaseMenuEnum.PROJECT]} />
+        <SchemaField schema={projectSchema} />
         <FormButtonGroup.Sticky>
           <FormButtonGroup.FormItem>
             <Submit onSubmit={onFinish}>提交</Submit>

+ 19 - 9
src/pages/Project/Management/List/index.tsx

@@ -9,9 +9,7 @@ import ProjectModal, { ModalType } from './components/ProjectModal'
 import dayjs from 'dayjs'
 import { PageContainer } from '@ant-design/pro-layout'
 import { BaseMenuEnum } from '@/pages/Schema/Base'
-import Detail from './components/Detail'
 import AnimateContent from '@/components/AnimateContent'
-import { transformToSchemaData } from '@/utils/schema'
 import type { ProColumnType, ActionType } from '@ant-design/pro-table'
 import type { ConnectProps } from 'umi'
 import type { ProjectModelState } from '../../model'
@@ -80,7 +78,8 @@ const List: React.FC<ListProps> = ({ schema, dispatch, pTypeList }) => {
             //   title: record.name,
             //   defaultFormData: record
             // })
-          }}>
+          }}
+        >
           {text}
         </span>
       )
@@ -156,16 +155,18 @@ const List: React.FC<ListProps> = ({ schema, dispatch, pTypeList }) => {
                 visible: true,
                 currentModalType: ModalType.UPDATE,
                 title: record.name,
-                defaultFormData: transformToSchemaData(record, BaseMenuEnum.PROJECT, schema)
+                defaultFormData: record
               })
-            }}>
+            }}
+          >
             编辑
           </div>
           <Popconfirm
             title="确认删除吗?"
             okText="确认"
             cancelText="取消"
-            onConfirm={() => tryDelProject({ ID: record.ID })}>
+            onConfirm={() => tryDelProject({ ID: record.ID })}
+          >
             <div className="pl-2 text-hex-fd3995 cursor-pointer hover:text-hex-e7026e">
               <DeleteOutlined />
             </div>
@@ -204,10 +205,18 @@ const List: React.FC<ListProps> = ({ schema, dispatch, pTypeList }) => {
           actions: [
             // <Button onClick={() => history.push('/project/management/add')}>新建项目</Button>
             <Button
+              key="add"
               type="primary"
               onClick={() =>
-                setState({ ...state, visible: true, currentModalType: ModalType.ADD, title: '' })
-              }>
+                setState({
+                  ...state,
+                  visible: true,
+                  currentModalType: ModalType.ADD,
+                  title: null
+                  // defaultFormData: transformToSchemaData(record, BaseMenuEnum.PROJECT, schema)
+                })
+              }
+            >
               新建项目
             </Button>
           ]
@@ -224,7 +233,8 @@ const List: React.FC<ListProps> = ({ schema, dispatch, pTypeList }) => {
           </>
         }
         visible={state.visible}
-        onVisibleChange={onAnimateChange}>
+        onVisibleChange={onAnimateChange}
+      >
         <ProjectModal
           type={state.currentModalType}
           defaultFormData={state.defaultFormData}

+ 32 - 35
src/pages/Schema/Base/index.tsx

@@ -1,17 +1,17 @@
+/* eslint-disable react/no-unescaped-entities */
 import { PageContainer } from '@ant-design/pro-layout'
 import LeftMenu from './components/LeftMenu'
 import { useState, useEffect } from 'react'
-import { history, connect } from 'umi'
+import { history, connect, Link } from 'umi'
 import type { ProjectModelState, SchemaBaseModelState } from 'umi'
 import { createForm, onFieldMount, onFieldReact } from '@formily/core'
-import { FormProvider, createSchemaField } from '@formily/react'
-import { FormItem, Input, Switch, Select, FormGrid, FormLayout } from '@formily/antd'
+import { createSchemaField } from '@formily/react'
+import { FormItem, Input, Switch, Select, FormGrid, FormLayout, Form } from '@formily/antd'
 
 import {
   projectSchema,
   institutionSchema,
   staffSchema,
-  connectSchema,
   useAsyncDataSource,
   loadAccountTypeData,
   loadProjectTypeData
@@ -40,33 +40,28 @@ type BaseProps = ConnectProps & {
 }
 
 export const generateFieldIsCreated = (field: GeneralField) => {
-  if (field.query('ID')?.get('value')) {
-    if (!field.value) {
-      field.setDecoratorProps({
-        addonAfter: (
-          <span>
-            开启后,该账号添加成功后将成为 "
-            <Link to="/project/created" className="text-primary">
-              项目创建人
-            </Link>
-            "
-          </span>
-        )
-      })
-    } else {
-      field.setPattern('readPretty')
-      field.setDecoratorProps({
-        addonAfter: (
-          <div>
-            <span className="text-red-500">需要移除请进入</span>"
-            <Link to="/project/created" className="text-primary">
-              项目创建人
-            </Link>
-            "
-          </div>
-        )
-      })
-    }
+  if (!field.value) {
+    field.setDecoratorProps({
+      addonAfter: (
+        <span>
+          开启后,该账号添加成功后将成为
+          <Link to="/project/created" className="text-primary">
+            "项目创建人"
+          </Link>
+        </span>
+      )
+    })
+  } else {
+    field.setDecoratorProps({
+      addonAfter: (
+        <div>
+          <span className="text-red-500">需要移除请进入</span>
+          <Link to="/project/created" className="text-primary">
+            "项目创建人"
+          </Link>
+        </div>
+      )
+    })
   }
 }
 
@@ -120,12 +115,13 @@ const Index: React.FC<BaseProps> = ({ base, pTypeList, dispatch }) => {
       }
     })
     return (
-      <FormProvider form={normalForm}>
+      <Form form={normalForm} labelCol={4} wrapperCol={8}>
         <SchemaField
-          schema={connectSchema(SchemaEnum?.[state.activeKey], currentSchema)}
+          schema={SchemaEnum?.[state.activeKey]}
           scope={{ useAsyncDataSource, loadAccountTypeData, loadProjectTypeData }}
         />
-      </FormProvider>
+        <SchemaField schema={currentSchema} />
+      </Form>
     )
   }
 
@@ -142,7 +138,8 @@ const Index: React.FC<BaseProps> = ({ base, pTypeList, dispatch }) => {
           <div className="flex flex-row-reverse mb-4 w-full">
             <div
               onClick={() => gotoDetail(state.activeKey)}
-              className="w-14px h-14px rounded-1/2 hover:bg-dark-50 hover:cursor-pointer"></div>
+              className="w-14px h-14px rounded-1/2 hover:bg-dark-50 hover:cursor-pointer"
+            />
           </div>
           <div className="max-w-800px">{renderForm()}</div>
         </div>

+ 1 - 1
src/pages/Schema/Base/model.ts

@@ -56,7 +56,7 @@ const SchemaBaseModel: SchemaBaseType = {
     save(state, action) {
       return {
         ...state,
-        base: { ...state?.base, [action.payload.columnType]: action.payload?.schema.properties }
+        base: { ...state?.base, [action.payload.columnType]: action.payload?.schema }
       }
     }
 

+ 7 - 0
src/services/api/institution.ts

@@ -8,6 +8,13 @@ export async function queryInstitutionList(params: API.InstitutionListParams) {
   })
 }
 
+/** 企事业详情 */
+export async function queryInstitution(params: { ID: string }) {
+  return request('/Institution/detail', {
+    method: 'GET',
+    params
+  })
+}
 /** 编辑企事业单位 */
 export async function updateInstitution(params: API.InstitutionUpdateParams) {
   return request('/Institution/update', {

+ 0 - 1
src/utils/enum.ts

@@ -1,7 +1,6 @@
 // 适用于抽屉/弹窗表单
 export enum ModalType {
   ADD = 0,
-  // UPDATE = 1,
   ADDITEM = 1,
   UPDATE = 2,
   DEL = 3,

+ 139 - 190
src/utils/schema.ts

@@ -1,4 +1,4 @@
-import { getAccountTypeList } from '@/services/api/institution'
+import { getAccountTypeList, queryOrganizationalStructureList } from '@/services/api/institution'
 import { getProjectTypeList } from '@/services/api/project'
 import { action } from '@formily/reactive'
 import consts from './consts'
@@ -10,40 +10,29 @@ import type { ISchema } from '@formily/react'
 export const projectSchema = {
   type: 'object',
   properties: {
-    layout: {
-      type: 'void',
-      'x-component': 'FormLayout',
-      'x-component-props': {
-        labelCol: 6,
-        wrapperCol: 8,
-        layout: 'horizontal'
-      },
-      properties: {
-        name: {
-          type: 'string',
-          title: '名称',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 1
-        },
-        shortName: {
-          type: 'string',
-          title: '项目简称',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 2
-        },
-        projectTypeID: {
-          type: 'string',
-          title: '项目类型',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Select',
-          'x-index': 3
-        }
-      }
+    name: {
+      type: 'string',
+      title: '名称',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 1
+    },
+    shortName: {
+      type: 'string',
+      title: '项目简称',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 2
+    },
+    projectTypeID: {
+      type: 'string',
+      title: '项目类型',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Select',
+      'x-index': 3
     }
   }
 }
@@ -52,14 +41,6 @@ export const projectSchema = {
 export const institutionSchema = {
   type: 'object',
   properties: {
-    ID: {
-      type: 'string',
-      title: 'ID',
-      'x-display': 'none',
-      'x-decorator': 'FormItem',
-      'x-component': 'Input',
-      'x-index': 0
-    },
     name: {
       type: 'string',
       title: '企事业单位名称',
@@ -69,15 +50,13 @@ export const institutionSchema = {
       'x-decorator-props': {
         // labelWidth: '131px'
         labelCol: 4
-      },
-      'x-index': 1
+      }
     },
     layout: {
       type: 'void',
       'x-component': 'FormLayout',
       'x-component-props': {
         labelCol: 8,
-        wrapperCol: 16,
         layout: 'horizontal'
       },
       properties: {
@@ -95,72 +74,62 @@ export const institutionSchema = {
               title: '企事业单位简称',
               required: true,
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 2
+              'x-component': 'Input'
             },
             enterpriseCode: {
               type: 'string',
               title: '企业编码',
               required: true,
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 3
+              'x-component': 'Input'
             },
             phone: {
               type: 'string',
               title: '办公电话',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 4
+              'x-component': 'Input'
             },
             address: {
               type: 'string',
               title: '地址',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 5
+              'x-component': 'Input'
             },
             fax: {
               type: 'string',
               title: '传真号码',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 6
+              'x-component': 'Input'
             },
             organizationCode: {
               type: 'string',
               title: '组织架构代码',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 7
+              'x-component': 'Input'
             },
             bank: {
               type: 'string',
               title: '银行',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 8
+              'x-component': 'Input'
             },
             idCard: {
               type: 'string',
               title: '身份证号码',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 9
+              'x-component': 'Input'
             },
             bankAccount: {
               type: 'string',
               title: '银行账号',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 10
+              'x-component': 'Input'
             },
             legalPerson: {
               type: 'string',
               title: '法人代表',
               'x-decorator': 'FormItem',
-              'x-component': 'Input',
-              'x-index': 11
+              'x-component': 'Input'
             }
           }
         }
@@ -173,109 +142,89 @@ export const institutionSchema = {
 export const staffSchema = {
   type: 'object',
   properties: {
-    layout: {
-      type: 'void',
-      'x-component': 'FormLayout',
-      'x-component-props': {
-        labelCol: 4,
-        wrapperCol: 8,
-        layout: 'horizontal'
-      },
-      properties: {
-        ID: {
-          type: 'string',
-          title: 'ID',
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-display': 'none',
-          'x-index': 0
-        },
-        enable: {
-          type: 'boolean',
-          title: '账号启用',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Switch',
-          'x-index': 1
-        },
-        isCreated: {
-          type: 'boolean',
-          title: '项目创建人',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Switch',
-          'x-index': 2
-        },
-        institutionID: {
-          type: 'string',
-          title: '事业单位',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 3
-        },
-        account: {
-          type: 'string',
-          title: '账号',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 4
-        },
-        name: {
-          type: 'string',
-          title: '姓名',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 5
-        },
-        password: {
-          type: 'string',
-          title: '密码',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 6
-        },
-        accountType: {
-          type: 'string',
-          title: '账号类型',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Select',
-          'x-index': 7,
-          enum: [],
-          'x-reactions': ['{{useAsyncDataSource(loadAccountTypeData)}}']
-        },
-        organizationalStructureID: {
-          type: 'string',
-          title: '组织架构',
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 8
-        },
-        gender: {
-          type: 'string',
-          title: '性别',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Select',
-          'x-index': 9,
-          enum: [
-            { label: '男', value: 0 },
-            { label: '女', value: 1 }
-          ]
-        },
-        phone: {
-          type: 'string',
-          title: '手机',
-          required: true,
-          'x-decorator': 'FormItem',
-          'x-component': 'Input',
-          'x-index': 10
-        }
-      }
+    enable: {
+      type: 'boolean',
+      title: '账号启用',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Switch',
+      'x-index': 0
+    },
+    isCreated: {
+      type: 'boolean',
+      title: '项目创建人',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Switch',
+      'x-index': 1
+    },
+    institutionID: {
+      type: 'string',
+      title: '事业单位',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Select',
+      'x-disabled': true,
+      'x-index': 2
+    },
+    account: {
+      type: 'string',
+      title: '账号',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 3
+    },
+    name: {
+      type: 'string',
+      title: '姓名',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 4
+    },
+    password: {
+      type: 'string',
+      title: '密码',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 5
+    },
+    accountType: {
+      type: 'string',
+      title: '账号类型',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Select',
+      'x-index': 6
+    },
+    organizationalStructureID: {
+      type: 'string',
+      title: '组织架构',
+      'x-decorator': 'FormItem',
+      'x-component': 'TreeSelect',
+      'x-index': 7
+    },
+    gender: {
+      type: 'string',
+      title: '性别',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Select',
+      'x-index': 8,
+      enum: [
+        { label: '男', value: '0' },
+        { label: '女', value: '1' }
+      ]
+    },
+    phone: {
+      type: 'string',
+      title: '手机',
+      required: true,
+      'x-decorator': 'FormItem',
+      'x-component': 'Input',
+      'x-index': 9
     }
   }
 }
@@ -283,31 +232,18 @@ export const staffSchema = {
 /** 组合schema */
 export const connectSchema = (initialSchemas, schemas) => {
   if (!schemas) return initialSchemas
-  let startIdx = Object.keys(initialSchemas.properties).length
+  const startIdx = Object.keys(initialSchemas.properties).length
   let i = 0
   const b = { ...initialSchemas }
-
-  if ('layout' in initialSchemas.properties) {
-    startIdx = Object.keys(initialSchemas.properties.layout.properties).length
-    for (const key in schemas) {
-      if (Object.prototype.hasOwnProperty.call(schemas, key)) {
-        const schema = schemas[key]
-        schema['x-index'] = startIdx + i
-        i++
-      }
-    }
-    const properties = Object.assign(b.properties.layout.properties, schemas)
-    b.properties.layout.properties = properties
-  } else {
-    for (const key in schemas) {
-      if (Object.prototype.hasOwnProperty.call(schemas, key)) {
-        const schema = schemas[key]
-        schema['x-index'] = startIdx + i
-        i++
-      }
+  for (const key in schemas) {
+    if (Object.prototype.hasOwnProperty.call(schemas, key)) {
+      schemas[key]['x-index'] = startIdx + i
+      i++
     }
-    b.properties = { ...schemas, ...b.properties }
   }
+  b.properties = { ...b.properties, ...schemas }
+  console.log(b)
+
   return b
 }
 
@@ -376,3 +312,16 @@ export const loadProjectTypeData = async () => {
   }
   return []
 }
+
+/** 加载组织架构 */
+export const loadOrganizationalStructureList = async ({ dataID }) => {
+  if (!dataID) return []
+  const { code = -1, data = [] } = await queryOrganizationalStructureList({
+    dataID,
+    structureType: '1'
+  })
+  if (code === consts.RET_CODE.SUCCESS) {
+    return data
+  }
+  return []
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 17036
yarn.lock