Преглед изворни кода

feat: 预算业务表单处理请求接口参数

lanjianrong пре 2 година
родитељ
комит
da2aa1367a

+ 1 - 1
.gitignore

@@ -14,7 +14,7 @@ _roadhog-api-doc
 .DS_Store
 npm-debug.log*
 yarn-error.log
-/pnpm-locak.yaml
+pnpm-locak.yaml
 /coverage
 .idea
 yarn.lock

+ 29 - 19
config/routes.ts

@@ -58,6 +58,7 @@
       {
         path: '/project/verification',
         name: 'verification',
+        access: 'authRouteFilter',
         component: './Project/Verification'
       }
     ]
@@ -81,13 +82,15 @@
           },
           {
             path: 'list',
-            name: 'list',
+            name: 'company-list',
+            access: 'authRouteFilter',
             hideInMenu: true,
             component: './Institutions/Company/List'
           },
           {
             path: ':id',
-            name: 'detail',
+            name: 'company-detail',
+            access: 'authRouteFilter',
             hideInMenu: true,
             component: './Institutions/Company/Detail'
           }
@@ -96,11 +99,13 @@
       {
         path: 'staff',
         name: 'staff',
+        access: 'authRouteFilter',
         component: './Institutions/Staff'
       },
       {
         path: 'restrict',
         name: 'restrict',
+        access: 'authRouteFilter',
         component: './Institutions/Restrict'
       }
     ]
@@ -117,13 +122,13 @@
       {
         path: 'inventory',
         name: 'inventory',
+        access: 'authRouteFilter',
         component: './Business/Inventory'
       },
       {
         path: 'process',
         name: 'process',
         access: 'authRouteFilter',
-        validatePerm: true,
         component: './Business/Process'
       }
     ]
@@ -136,31 +141,35 @@
       {
         path: 'base',
         name: 'base',
+        access: 'authRouteFilter',
         icon: 'icon-schema',
         component: './Schema/Base/index.tsx'
       },
       {
         path: 'base/:id',
         name: 'baseDetail',
+        access: 'authRouteFilter',
         component: './Schema/Base/detail.tsx',
         hideInMenu: true
+      },
+      {
+        path: 'option',
+        name: 'option',
+        access: 'authRouteFilter',
+        component: './Schema/Option'
+      },
+      {
+        path: 'budget',
+        name: 'budget',
+        access: 'authRouteFilter',
+        component: './Schema/Budget'
+      },
+      {
+        path: 'budget/:id',
+        name: 'budgetDetail',
+        component: './Schema/Budget/detail',
+        hideInMenu: true
       }
-      // {
-      //   path: 'option',
-      //   name: 'option',
-      //   component: './Schema/Option'
-      // },
-      // {
-      //   path: 'budget',
-      //   name: 'budget',
-      //   component: './Schema/Budget'
-      // },
-      // {
-      //   path: 'budget/:id',
-      //   name: 'budgetDetail',
-      //   component: './Schema/Budget/detail',
-      //   hideInMenu: true
-      // }
     ]
   },
   {
@@ -196,6 +205,7 @@
       {
         path: 'admin',
         name: 'admin',
+        access: 'authRouteFilter',
         component: './System/Admin'
       }
     ]

+ 2 - 2
package.json

@@ -43,8 +43,8 @@
     "@formily/reactive": "^2.1.4",
     "@formily/reactive-react": "^2.1.4",
     "@formily/shared": "^2.1.4",
-    "@umijs/max": "4.0.0-canary.20220628.1",
-    "@umijs/plugins": "4.0.0-canary.20220628.1",
+    "@umijs/max": "4.0.3",
+    "@umijs/plugins": "4.0.3",
     "ahooks": "^3.0.0",
     "antd": "4.20.7",
     "array-move": "^4.0.0",

+ 3 - 0
src/access.ts

@@ -7,6 +7,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser | u
     if (route.name && permission.includes(route.name.match(/^(\w*)-/)?.[1] ?? route.name)) {
       return true
     }
+    if (initialState?.currentUser?.account === 'admin') {
+      return true
+    }
     return false
   }
   return {

+ 4 - 4
src/locales/zh-CN/menu.ts

@@ -17,8 +17,8 @@ export default {
   'menu.account.logout': '退出登录',
   'menu.project': '项目审批设置',
   'menu.project.management': '项目管理',
-  'menu.project.management.list': '项目列表',
-  'menu.project.management.detail': '项目详情',
+  'menu.project.management.management-list': '项目列表',
+  'menu.project.management.management-detail': '项目详情',
   'menu.project.created': '项目创建人',
   'menu.project.verification': '审批流程模板',
   'menu.institutions': '企事业单位',
@@ -28,8 +28,8 @@ export default {
   'menu.business': '业务审批设置',
   'menu.business.inventory': '资料签收清单模板',
   'menu.business.process': '流程用户设置',
-  'menu.institutions.company.list': '单位列表',
-  'menu.institutions.company.detail': '单位详情',
+  'menu.institutions.company.company-list': '单位列表',
+  'menu.institutions.company.company-detail': '单位详情',
   'menu.schema': '表单设置',
   'menu.schema.base': '基础数据设置',
   'menu.schema.option': '数据源设置',

+ 22 - 0
src/pages/Business/Inventory/hooks/useRowScript.tsx

@@ -0,0 +1,22 @@
+import { queryProfileTemplateList } from '@/services/api/business'
+import { useRequest } from '@umijs/max'
+import { useState } from 'react'
+
+interface IState {
+  list?: API.ProfileTemplateItem[]
+}
+
+export function useRowScript() {
+  const [state, setState] = useState<IState>({})
+
+  const { refresh } = useRequest(queryProfileTemplateList, {
+    onSuccess: (result: API.ProfileTemplateItem[]) => {
+      setState({ ...state, list: result?.children || [] })
+    }
+  })
+
+  return {
+    list: state.list,
+    refresh
+  }
+}

+ 65 - 2
src/pages/Business/Inventory/index.tsx

@@ -1,8 +1,71 @@
 import { PageContainer } from '@ant-design/pro-layout'
-import React from 'react'
+import { Table } from 'antd'
+import { ColumnsType } from 'antd/lib/table'
+import { useRowScript } from './hooks/useRowScript'
+
+enum TemplateMode {
+  PAPER = 'paper',
+  UPLOAD = 'upload',
+  ALL = 'all'
+}
 
 const Inventory = () => {
-  return <PageContainer title={false}>资料清单接收模板</PageContainer>
+  const { list } = useRowScript()
+  const columns: ColumnsType<API.ProfileTemplateItem> = [
+    {
+      title: '序号',
+      dataIndex: 'sort',
+      width: 120
+    },
+    {
+      title: '目录文件名称',
+      dataIndex: 'name'
+    },
+    {
+      title: '状态',
+      dataIndex: 'enable',
+      render: text =>
+        text ? <span className="text-green">启用</span> : <span className="text-red">停用</span>
+    },
+    {
+      title: '是否必填',
+      dataIndex: 'required',
+      render: text => (text ? '是' : '否')
+    },
+    {
+      title: '资料提供方式',
+      dataIndex: 'mode',
+      render: (mode: TemplateMode) => (
+        <div>
+          {[TemplateMode.PAPER, TemplateMode.ALL].includes(mode) && (
+            <span className="border border-hex-91d5ff text-blue bg-hex-e6f7ff rounded-1 px-1 text-sm">
+              纸质
+            </span>
+          )}
+          {[TemplateMode.UPLOAD, TemplateMode.ALL].includes(mode) && (
+            <span className="border border-hex-9fede5 text-hex-13c2c2 bg-hex-e6fffb rounded-1 px-1 ml-2 text-sm">
+              上传
+            </span>
+          )}
+        </div>
+      )
+    }
+  ]
+  return (
+    <PageContainer title={false}>
+      {list?.length && (
+        <Table
+          rowKey="ID"
+          columns={columns}
+          dataSource={list}
+          pagination={false}
+          size="small"
+          bordered
+          expandable={{ defaultExpandAllRows: true }}
+        />
+      )}
+    </PageContainer>
+  )
 }
 
 export default Inventory

+ 34 - 18
src/pages/Permission/Role/components/PermTabs/index.tsx

@@ -260,8 +260,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4 className="pt-3">审批流程模板</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewApporvalTemplate')}
-                      checked={state.backstagePermission.includes('viewApporvalTemplate')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'verification')}
+                      checked={state.backstagePermission.includes('verification')}>
                       查看流程
                     </Checkbox>
                     <Checkbox
@@ -286,8 +286,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4>单位管理</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewCompany')}
-                      checked={state.backstagePermission.includes('viewCompany')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'company')}
+                      checked={state.backstagePermission.includes('company')}>
                       查看单位
                     </Checkbox>
                     <Checkbox
@@ -320,8 +320,24 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4 className="pt-3">人员管理</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewAccount')}
-                      checked={state.backstagePermission.includes('viewAccount')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'staff')}
+                      checked={state.backstagePermission.includes('staff')}>
+                      查看人员
+                    </Checkbox>
+                    <Checkbox
+                      onChange={e => handleBackOnchange(e.target.checked, 'editBa5')}
+                      checked={state.backstagePermission.includes('updatePsw')}
+                      disabled>
+                      编辑人员
+                    </Checkbox>
+                  </div>
+                </div>
+                <div>
+                  <h4 className="pt-3">限制登录</h4>
+                  <div className="my-2">
+                    <Checkbox
+                      onChange={e => handleBackOnchange(e.target.checked, 'restrict')}
+                      checked={state.backstagePermission.includes('restrict')}>
                       查看人员
                     </Checkbox>
                     <Checkbox
@@ -336,7 +352,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
             </div>
             <div className="shadow-md mb-4">
               <Card size="small" type="inner" title="业务审批设置">
-                <div>
+                {/* <div>
                   <h4>业务管理</h4>
                   <div className="my-2">
                     <Checkbox
@@ -345,7 +361,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                       查看信息
                     </Checkbox>
                   </div>
-                </div>
+                </div> */}
                 <div>
                   <h4 className="pt-3">流程用户配置</h4>
                   <div className="my-2">
@@ -360,8 +376,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4 className="pt-3">资料清单配置</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewDataList')}
-                      checked={state.backstagePermission.includes('viewDataList')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'inventory')}
+                      checked={state.backstagePermission.includes('inventory')}>
                       查看信息
                     </Checkbox>
                   </div>
@@ -374,8 +390,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4>基础数据设置</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewFormProject')}
-                      checked={state.backstagePermission.includes('viewFormProject')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'base')}
+                      checked={state.backstagePermission.includes('base')}>
                       查看项目信息
                     </Checkbox>
                     <Checkbox
@@ -414,8 +430,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4 className="pt-3">数据源设置</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewDataSource')}
-                      checked={state.backstagePermission.includes('viewDataSource')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'option')}
+                      checked={state.backstagePermission.includes('option')}>
                       查看信息
                     </Checkbox>
                     <Checkbox
@@ -430,8 +446,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4 className="pt-3">预算业务表单设置</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'viewBudget')}
-                      checked={state.backstagePermission.includes('viewBudget')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'budget')}
+                      checked={state.backstagePermission.includes('budget')}>
                       查看信息
                     </Checkbox>
                   </div>
@@ -444,8 +460,8 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                   <h4>管理员设置</h4>
                   <div className="my-2">
                     <Checkbox
-                      onChange={e => handleBackOnchange(e.target.checked, 'accessBa9')}
-                      checked={state.backstagePermission.includes('updatePsw')}>
+                      onChange={e => handleBackOnchange(e.target.checked, 'admin')}
+                      checked={state.backstagePermission.includes('admin')}>
                       查看信息
                     </Checkbox>
                     <Checkbox

+ 6 - 15
src/pages/Schema/Base/index.tsx

@@ -2,8 +2,8 @@
 import { PageContainer } from '@ant-design/pro-layout'
 import LeftMenu from './components/LeftMenu'
 import { useState, useEffect } from 'react'
-import { history, connect, Link } from '@umijs/max'
-import type { ProjectModelState, SchemaBaseModelState } from '@umijs/max'
+import { history, connect } from '@umijs/max'
+import type { SchemaBaseModelState } from '@umijs/max'
 import { createForm } from '@formily/core'
 import { createSchemaField } from '@formily/react'
 import {
@@ -45,10 +45,9 @@ export const menuOptions = [
 ]
 type BaseProps = ConnectProps & {
   base: SchemaBaseModelState
-  pTypeList: { label: string; value: string }[]
 }
 
-const Index: React.FC<BaseProps> = ({ base, pTypeList, dispatch }) => {
+const Index: React.FC<BaseProps> = ({ base, dispatch }) => {
   const [state, setState] = useState({
     activeKey: BaseMenuEnum.PROJECT
   })
@@ -64,11 +63,6 @@ const Index: React.FC<BaseProps> = ({ base, pTypeList, dispatch }) => {
         }
       })
     }
-    if (!pTypeList.length) {
-      dispatch({
-        type: 'project/queryProjectTypeList'
-      })
-    }
   }, [state.activeKey])
 
   const gotoDetail = columnType => {
@@ -127,9 +121,6 @@ const Index: React.FC<BaseProps> = ({ base, pTypeList, dispatch }) => {
   )
 }
 
-export default connect(
-  ({ project, schemaBase }: { project: ProjectModelState; schemaBase: SchemaBaseModelState }) => ({
-    pTypeList: project.projectTypeList.map(item => ({ label: item.name, value: item.ID })),
-    base: schemaBase.base
-  })
-)(Index)
+export default connect(({ schemaBase }: { schemaBase: SchemaBaseModelState }) => ({
+  base: schemaBase.base
+}))(Index)

+ 5 - 5
src/pages/Schema/Budget/components/Designable/widgets/ActionsWidget.tsx

@@ -6,7 +6,7 @@ import { observer } from '@formily/react'
 import { loadInitialSchema } from '../service'
 import { useDispatch, history, useParams, useRequest } from '@umijs/max'
 import { transformToSchema } from '@designable/formily-transformer'
-import { updateSchema } from '@/services/api/schema'
+import { saveBudgetTemplate } from '@/services/api/schema'
 
 export const ActionsWidget = observer(({ schema }) => {
   const designer = useDesigner()
@@ -16,12 +16,12 @@ export const ActionsWidget = observer(({ schema }) => {
     GlobalRegistry.setDesignerLanguage('zh-cn')
   }, [schema])
   const dispatch = useDispatch()
-  const { run: tryUpdateSchema } = useRequest(updateSchema, {
+  const { run: tryUpdateSchema } = useRequest(saveBudgetTemplate, {
     manual: true,
-    onSuccess: result => {
+    onSuccess: (result: { schema: string }) => {
       message.success('更新成功')
       dispatch({
-        type: 'schemaBase/changeSchemaByColumnType',
+        type: 'templateSchema/changeSchemaByColumnType',
         payload: {
           columnType,
           schema: result.schema
@@ -32,7 +32,7 @@ export const ActionsWidget = observer(({ schema }) => {
 
   const saveSchema = () => {
     tryUpdateSchema({
-      columnType,
+      action: columnType,
       schema: JSON.stringify(transformToSchema(designer.getCurrentTree()).schema)
     })
   }

+ 38 - 29
src/pages/Schema/Budget/index.tsx

@@ -1,6 +1,6 @@
 import { queryTemplateList } from '@/services/api/schema'
 import { PageContainer } from '@ant-design/pro-layout'
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useMemo, useState } from 'react'
 import { history, useRequest, connect, useDispatch } from '@umijs/max'
 import { createForm } from '@formily/core'
 import { createSchemaField } from '@formily/react'
@@ -22,6 +22,7 @@ import {
 } from '@formily/antd'
 import { Button } from 'antd'
 import LeftMenu from '../Base/components/LeftMenu'
+import { isString } from '@/utils/is'
 
 type iState = {
   menuData?: API.TemplateListItem[]
@@ -51,31 +52,43 @@ const Budget: React.FC = () => {
       })
     }
   })
-  const onSelect = (key: string) => {
-    setState({ ...state, activeID: key })
-  }
 
-  const form = createForm({
-    initialValues: {},
-    effects() {}
-  })
-  const SchemaField = createSchemaField({
-    components: {
-      FormLayout,
-      FormItem,
-      FormGrid,
-      Input,
-      Switch,
-      Select,
-      Radio,
-      Checkbox,
-      NumberPicker,
-      Password,
-      DatePicker,
-      TimePicker,
-      TreeSelect
+  const currentSchema = useMemo(() => {
+    const schema = state.menuData?.find(item => item.action === state.activeKey)?.schema
+    if (schema && isString(schema)) {
+      return JSON.parse(schema)
     }
-  })
+    return {}
+  }, [state.activeKey])
+  const renderForm = () => {
+    const normalForm = createForm({
+      validateFirst: true,
+      pattern: 'readOnly'
+    })
+
+    const SchemaField = createSchemaField({
+      components: {
+        FormLayout,
+        FormItem,
+        FormGrid,
+        Input,
+        Switch,
+        Select,
+        Radio,
+        Checkbox,
+        NumberPicker,
+        Password,
+        DatePicker,
+        TimePicker,
+        TreeSelect
+      }
+    })
+    return (
+      <Form form={normalForm} labelCol={4} wrapperCol={8}>
+        <SchemaField schema={currentSchema} />
+      </Form>
+    )
+  }
 
   return (
     <PageContainer title={false}>
@@ -97,11 +110,7 @@ const Budget: React.FC = () => {
               </Button>
             )}
           </div>
-          <div className="w-600px">
-            <Form form={form} labelCol={8}>
-              <SchemaField />
-            </Form>
-          </div>
+          <div className="w-600px">{renderForm()}</div>
         </div>
       </div>
     </PageContainer>

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

@@ -59,7 +59,7 @@ const TemplateSchemaModel: TemplateSchemaType = {
         const schema = action.payload?.schema && JSON.parse(action.payload?.schema)
         return {
           ...state,
-          [action.payload.action]: { ...action.payload, schema }
+          [action.payload.action]: { ...state[action.payload.action], ...action.payload, schema }
         }
       }
     }

+ 56 - 0
src/services/api/business.ts

@@ -0,0 +1,56 @@
+import { request } from '@umijs/max'
+
+/** 清单模板 列表 */
+export async function queryProfileTemplateList() {
+  return request<API.ProfileTemplateItem[]>('/form/v1/profile/template/list')
+}
+
+/** 清单模板 创建目录 */
+export async function createTemplateFolder(params: { name: string; parentID: string }) {
+  return request('/form/v1/profile/template/folder/create', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 清单模板 创建文件 */
+export async function createTemplateFile(
+  params: Required<Omit<API.ProfileTemplateItem, 'ID' | 'sort' | 'folder' | 'children'>>
+) {
+  return request('/form/v1/profile/template/file/create', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 清单模板 编辑名称 */
+export async function updateProfileTemplate(params: { name: string; ID: string }) {
+  return request('/form/v1/profile/template/update', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 清单模板 删除 */
+export async function delProfileTemplate(params: { ID: string }) {
+  return request('/form/v1/profile/template/delete', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 清单模板 上下移动 */
+export async function moveTemplateWithOperation(params: { ID: string; operation: 'up' | 'down' }) {
+  return request('/form/v1/profile/template/updown', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 清单模板 移动 */
+export async function moveTemplate(params: { ID: string; moveID: string }) {
+  return request('/form/v1/profile/template/move', {
+    method: 'POST',
+    data: params
+  })
+}

+ 8 - 0
src/services/api/schema.ts

@@ -70,3 +70,11 @@ export async function queryBudgetTemplateDetail(params: Omit<API.TemplateListIte
     params
   })
 }
+
+/** 预算业务表单-保存模板 */
+export async function saveBudgetTemplate(params: Omit<API.TemplateListItem, 'name'>) {
+  return request('/form/v1/template/save', {
+    method: 'POST',
+    data: params
+  })
+}

+ 13 - 0
src/services/api/typings.d.ts

@@ -363,6 +363,7 @@ declare namespace API {
   type TemplateListItem = {
     action?: string
     name?: string
+    schema?: string
   }
 
   type SaveApprovalParams = {
@@ -375,4 +376,16 @@ declare namespace API {
     institutionID: string
     accountIDs: []
   }
+
+  type ProfileTemplateItem = {
+    ID?: string
+    parentID?: string
+    name?: string
+    enable?: boolean
+    required?: boolean
+    mode?: 'paper' | 'upload' | 'all'
+    sort?: number
+    folder?: boolean
+    children?: ProfileTemplateItem[]
+  }
 }