code4eat преди 2 месеца
ревизия
dcd13df97e
променени са 62 файла, в които са добавени 3040 реда и са изтрити 0 реда
  1. 16 0
      .editorconfig
  2. 20 0
      .gitignore
  3. 8 0
      .prettierignore
  4. 11 0
      .prettierrc
  5. 15 0
      README.md
  6. 37 0
      config/config.ts
  7. 18 0
      config/routes.ts
  8. 0 0
      mock/.gitkeep
  9. 42 0
      mock/qualification.ts
  10. 43 0
      package.json
  11. BIN
      public/images/add.png
  12. BIN
      public/images/alert.png
  13. BIN
      public/images/avatar.png
  14. BIN
      public/images/blueFile.png
  15. BIN
      public/images/box.png
  16. BIN
      public/images/editIcon.png
  17. BIN
      public/images/searchIcon.png
  18. BIN
      public/images/trash.png
  19. 229 0
      src/app.tsx
  20. 42 0
      src/components/KCModal/index.tsx
  21. 16 0
      src/components/KCModal/typing.d.ts
  22. 36 0
      src/components/MQPageContainer/index.tsx
  23. 49 0
      src/components/kcTable/index.tsx
  24. 2 0
      src/components/kcTable/style.less
  25. 17 0
      src/components/kcTable/typing.d.ts
  26. 112 0
      src/components/qualificationClassTree/index.tsx
  27. 111 0
      src/components/qualificationClassTree/style.less
  28. 44 0
      src/contant.ts
  29. 43 0
      src/global.less
  30. 8 0
      src/global.tsx
  31. 11 0
      src/models/model.ts
  32. BIN
      src/pages/personalCenter/myApplication/Modals/MineProfile/assets/avatar_empty.png
  33. 197 0
      src/pages/personalCenter/myApplication/Modals/MineProfile/index.tsx
  34. 93 0
      src/pages/personalCenter/myApplication/Modals/MineProfile/style.less
  35. 124 0
      src/pages/personalCenter/myApplication/Modals/Qualification/index.tsx
  36. 20 0
      src/pages/personalCenter/myApplication/Modals/Qualification/style.less
  37. 126 0
      src/pages/personalCenter/myApplication/index.tsx
  38. BIN
      src/pages/personalCenter/profile/components/qualificationCard/assets/corner-blue.png
  39. BIN
      src/pages/personalCenter/profile/components/qualificationCard/assets/corner-green.png
  40. BIN
      src/pages/personalCenter/profile/components/qualificationCard/assets/corner-orange.png
  41. BIN
      src/pages/personalCenter/profile/components/qualificationCard/assets/corner-red.png
  42. BIN
      src/pages/personalCenter/profile/components/qualificationCard/assets/corner-yellow.png
  43. 94 0
      src/pages/personalCenter/profile/components/qualificationCard/index.tsx
  44. 93 0
      src/pages/personalCenter/profile/components/qualificationCard/style.less
  45. 128 0
      src/pages/personalCenter/profile/index.tsx
  46. 243 0
      src/pages/personalCenter/profile/style.less
  47. 126 0
      src/pages/qualificationCheck/index.tsx
  48. 108 0
      src/pages/qualificationMana/qualificationClass/components/qualificationCard/index.tsx
  49. 91 0
      src/pages/qualificationMana/qualificationClass/components/qualificationCard/style.less
  50. 36 0
      src/pages/qualificationMana/qualificationClass/index.tsx
  51. 0 0
      src/pages/qualificationMana/qualificationClass/style.less
  52. 121 0
      src/pages/qualificationMana/qualificationEdit/index.tsx
  53. 89 0
      src/pages/qualificationMana/qualificationEdit/modals/qualificationEdit&add.tsx
  54. 49 0
      src/pages/qualificationMana/qualificationEdit/modals/qualificationImport.tsx
  55. 9 0
      src/pages/qualificationMana/qualificationEdit/modals/style.less
  56. 19 0
      src/pages/qualificationMana/qualificationEdit/style.less
  57. 215 0
      src/pages/qualificationReview/index.tsx
  58. 17 0
      src/pages/qualificationReview/style.less
  59. 39 0
      src/service/qualification.ts
  60. 26 0
      src/typings.d.ts
  61. 37 0
      tsconfig.json
  62. 10 0
      typings.d.ts

+ 16 - 0
.editorconfig

@@ -0,0 +1,16 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/npm-debug.log*
+/yarn-error.log
+/yarn.lock
+/package-lock.json
+
+# production
+/dist
+
+# misc
+.DS_Store
+
+# umi
+/src/.umi
+/src/.umi-production
+/src/.umi-test
+/.env.local

+ 8 - 0
.prettierignore

@@ -0,0 +1,8 @@
+**/*.md
+**/*.svg
+**/*.ejs
+**/*.html
+package.json
+.umi
+.umi-production
+.umi-test

+ 11 - 0
.prettierrc

@@ -0,0 +1,11 @@
+{
+  "singleQuote": true,
+  "trailingComma": "all",
+  "printWidth": 80,
+  "overrides": [
+    {
+      "files": ".prettierrc",
+      "options": { "parser": "json" }
+    }
+  ]
+}

+ 15 - 0
README.md

@@ -0,0 +1,15 @@
+# umi project
+
+## Getting Started
+
+Install dependencies,
+
+```bash
+$ yarn
+```
+
+Start the dev server,
+
+```bash
+$ yarn start
+```

+ 37 - 0
config/config.ts

@@ -0,0 +1,37 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-14 09:16:01
+ * @LastEditTime: 2022-02-15 16:17:58
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/config/config.ts
+ */
+
+import { defineConfig } from 'umi';
+
+import routes from './routes';
+
+export default defineConfig({
+      nodeModulesTransform: {
+        type: 'none',
+      },
+      routes: routes,
+      fastRefresh: {},
+      theme:{
+        '@primary-color': '#3376FE',
+      },
+      antd: {
+        config: {
+          prefixCls: 'mq-ant',
+        },
+      },
+      lessLoader: {
+        modifyVars: { '@ant-prefix': 'mq-ant' },
+      },
+      layout: {
+        name: '医资管理',
+        locale: true,
+        layout: 'side',
+        navTheme:'light'
+      },   
+});

+ 18 - 0
config/routes.ts

@@ -0,0 +1,18 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-15 15:37:07
+ * @LastEditTime: 2022-02-24 15:42:04
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/config/routes.ts
+ */
+
+
+export default [
+    {path: '/personalCenter/profile', component: '@/pages/personalCenter/profile/index' },
+    {path: '/personalCenter/myApply', component: '@/pages/personalCenter/myApplication' },
+    {path: '/qualificationCheck/qualificationCheck', component: '@/pages/qualificationCheck' },
+    {path: '/qualificationReview/qualificationReview', component: '@/pages/qualificationReview' },
+    {path: '/qualificationMana/qualificationClass', component: '@/pages/qualificationMana/qualificationClass' },
+    {path: '/qualificationMana/qualificationEdit', component: '@/pages/qualificationMana/qualificationEdit' },
+]

+ 0 - 0
mock/.gitkeep


+ 42 - 0
mock/qualification.ts

@@ -0,0 +1,42 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-17 10:56:44
+ * @LastEditTime: 2022-02-17 11:29:02
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/mock/qualification.ts
+ */
+
+import { Request, Response } from 'express';
+
+const getList = (req: Request, res: Response, u: string) => {
+  const dataSource = [
+    {
+      id:1,
+      qualificationNum: '资质编号',
+      qualificationName: '资质名',
+      supportMaterial:'佐证材料',
+      authorBasis:'授权依据',
+      qualificationType:'资质类型',
+      qualificationAudit:'资质审核',
+      qualificationStatus:1,
+      applyDate:'2022-02-17',
+      
+    }
+  ];
+  const result = {
+    data: {
+      list: dataSource,
+      totalCount: dataSource.length,
+      current: 1,
+    },
+    success: true,
+    status: 200,
+  };
+
+  return res.json(result);
+};
+
+export default {
+    'GET /api/getMineQualifiApply': getList,
+};

+ 43 - 0
package.json

@@ -0,0 +1,43 @@
+{
+  "private": true,
+  "scripts": {
+    "start": "umi dev",
+    "build": "umi build",
+    "postinstall": "umi generate tmp",
+    "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
+    "test": "umi-test",
+    "test:coverage": "umi-test --coverage"
+  },
+  "gitHooks": {
+    "pre-commit": "lint-staged"
+  },
+  "lint-staged": {
+    "*.{js,jsx,less,md,json}": [
+      "prettier --write"
+    ],
+    "*.ts?(x)": [
+      "prettier --parser=typescript --write"
+    ]
+  },
+  "dependencies": {
+    "@ant-design/pro-layout": "^6.5.0",
+    "@ant-design/pro-table": "^2.63.6",
+    "react": "17.x",
+    "react-dom": "17.x",
+    "umi": "^3.5.20"
+  },
+  "devDependencies": {
+    "@types/express": "^4.17.13",
+    "@types/react": "^17.0.0",
+    "@types/react-dom": "^17.0.0",
+    "@umijs/fabric": "^2.10.1",
+    "@umijs/preset-react": "1.x",
+    "@umijs/test": "^3.5.20",
+    "eslint": "^7.32.0",
+    "express": "^4.17.3",
+    "lint-staged": "^10.0.7",
+    "prettier": "^2.2.0",
+    "typescript": "^4.1.2",
+    "yorkie": "^2.0.0"
+  }
+}

BIN
public/images/add.png


BIN
public/images/alert.png


BIN
public/images/avatar.png


BIN
public/images/blueFile.png


BIN
public/images/box.png


BIN
public/images/editIcon.png


BIN
public/images/searchIcon.png


BIN
public/images/trash.png


+ 229 - 0
src/app.tsx

@@ -0,0 +1,229 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-14 09:14:49
+ * @LastEditTime: 2022-02-24 15:44:26
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/app.tsx
+ */
+
+
+import React from 'react';
+import { notification, Modal } from 'antd';
+import type { RequestOptionsInit } from 'umi-request';
+
+import {
+  BasicLayoutProps,
+  Settings as LayoutSettings,
+} from '@ant-design/pro-layout';
+
+import { history, RequestConfig } from 'umi';
+
+
+
+
+
+const requestInterceptorsHandle = (url: string, options: RequestOptionsInit) => {
+  const userData = localStorage.getItem('userData');
+  let authHeader = { token: '' };
+
+  if (userData) {
+    const { token } = JSON.parse(userData);
+    authHeader.token = token;
+  }
+
+  return {
+    url: `${url}`,
+    options: { ...options, interceptors: true, headers: authHeader },
+  };
+};
+
+const responseInterceptorsHandle = async (response: Response, options: RequestOptionsInit) => {
+  const _response: {
+    data?: any;
+    status: number;
+    success?: boolean;
+    msg?: string;
+  } = await response.clone().json();
+
+  if (_response.status == 200) {
+    if (_response.data) {
+      return _response.data;
+    }
+
+    notification.success({
+      message: `操作成功!`,
+    });
+    return {
+      status: _response.status,
+      success: true,
+    };
+  } else {
+    return {
+      ..._response,
+    };
+  }
+};
+
+interface ErrorInfoStructure {
+  success: boolean; // if request is success
+  data?: any; // response data
+  status?: number;
+  errorCode: number;
+  errorMessage: string;
+  showType?: number;
+  traceId?: string;
+  host?: string;
+}
+
+interface ResponseErr extends Error {
+  data?: any; // 这里是后端返回的原始数据
+  info: ErrorInfoStructure;
+}
+
+const errorHandlerFunc = (error: ResponseErr) => {
+
+  try {
+    const { info } = error;
+    const { errorCode, errorMessage } = info;
+
+    if (errorCode == 499) {
+      //token过期
+      Modal.confirm({
+        title: '抱歉,你的登录已过期,请重新登录!',
+        closable: false,
+        maskClosable: false,
+        // cancelButtonProps:
+        onOk: () => {
+          localStorage.removeItem('userData');
+          return true;
+        }
+      });
+
+      return;
+    }
+
+    if (errorMessage.length > 20) {
+      notification.error({
+        message: ` ${errorCode}:出现错误!`,
+        description: errorMessage,
+      });
+    } else {
+      notification.error({
+        message: ` ${errorCode}:${errorMessage}`,
+      });
+    }
+  } catch (err) {
+    console.log({ errorHandlerFunc: err });
+    notification.error({
+      message: '遇到未知错误,查看控制台!',
+    });
+  }
+};
+
+export const request: RequestConfig = {
+  timeout: 10000,
+  errorConfig: {
+    adaptor: (resData) => {
+      if (!resData.success && resData.status != 200) {
+        // console.log({resData});
+        return {
+          ...resData,
+          // success:false,
+        };
+      } else {
+        return {
+          success: true,
+          status: 200,
+        };
+      }
+    },
+  },
+  errorHandler: (err: any) => errorHandlerFunc(err),
+  middlewares: [
+    async function middlewareA(ctx, next) {
+      await next();
+    },
+    async function middlewareB(ctx, next) {
+
+      await next();
+    },
+  ],
+  requestInterceptors: [requestInterceptorsHandle],
+  responseInterceptors: [responseInterceptorsHandle],
+};
+
+
+
+
+
+
+
+export const layout = ({
+  initialState,
+}: {
+  initialState: { settings?: LayoutSettings; currentUser?: any };
+}): BasicLayoutProps => {
+  return {
+    headerRender: false,
+    footerRender: false,
+    onPageChange: () => { },
+    menu: {
+      request: async (params, defaultMenuData) => {
+
+        return [
+          {
+            path: '/personalCenter',
+            name: '个人中心',
+            routes: [
+              {
+                name: '我的档案',
+                path: '/personalCenter/profile'
+              },
+              {
+                name: '我的申请',
+                path: '/personalCenter/myApply'
+              }
+            ]
+          },
+          {
+            path:'/qualificationCheck',
+            name: '资质查询',
+            routes: [
+              {
+                name: '资质查询',
+                path: '/qualificationCheck/qualificationCheck'
+              },
+            ]
+          },
+          {
+            path:'/qualificationReview',
+            name: '资质审核',
+            routes: [
+              {
+                name: '资质审核',
+                path: '/qualificationReview/qualificationReview'
+              },
+            ]
+          },
+          {
+            path:'/qualificationMana',
+            name: '资质管理',
+            routes: [
+              {
+                name: '资质类目',
+                path: '/qualificationMana/qualificationClass'
+              },
+              {
+                name: '资质编辑',
+                path: '/qualificationMana/qualificationEdit'
+              },
+            ]
+          },
+        ];
+      },
+    },
+    menuHeaderRender: () => null,
+    ...initialState?.settings,
+  };
+};

+ 42 - 0
src/components/KCModal/index.tsx

@@ -0,0 +1,42 @@
+/*
+ * @Author: your name
+ * @Date: 2022-01-12 15:26:43
+ * @LastEditTime: 2022-02-18 15:00:15
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/src/components/KCModal/index.tsx
+ */
+
+import React, { useState, useEffect } from 'react';
+import { ModalForm } from '@ant-design/pro-form';
+import { KCModalType } from './typing';
+
+const KCModal: React.FC<KCModalType.KCModalProps> = ({
+  visible = false,
+  modalProps,
+  ...props
+}) => {
+  const [modalVisible, setModalVisible] = useState(false);
+
+  useEffect(() => {
+    setModalVisible(visible);
+  }, [visible]);
+
+  return (
+    <ModalForm
+      visible={modalVisible}
+      modalProps={{
+        destroyOnClose: true,
+        maskClosable:false,
+        bodyStyle: {
+          maxHeight: '72vh',
+          overflowY: 'auto',
+        },
+        ...modalProps,
+      }}
+      {...props}
+    />
+  );
+};
+
+export default KCModal;

+ 16 - 0
src/components/KCModal/typing.d.ts

@@ -0,0 +1,16 @@
+/*
+ * @Author: your name
+ * @Date: 2022-01-12 15:29:17
+ * @LastEditTime: 2022-01-13 10:24:17
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/src/components/KCModal/typing.d.ts
+ */
+
+import { ModalFormProps } from '@ant-design/pro-form';
+
+declare namespace KCModalType {
+  export interface KCModalProps extends ModalFormProps {
+    reload?: boolean;
+  }
+}

+ 36 - 0
src/components/MQPageContainer/index.tsx

@@ -0,0 +1,36 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-15 16:54:11
+ * @LastEditTime: 2022-02-15 17:12:20
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/components/MQPageContainer/index.tsx
+ */
+
+
+
+import react from 'react';
+import { PageContainer, PageContainerProps } from '@ant-design/pro-layout';
+
+export interface MQPageContainerPropsType extends PageContainerProps {
+
+}
+
+const MQPageContainer: react.FC<MQPageContainerPropsType> = ({ children,...rest }) => {
+
+    return (
+        <PageContainer
+            header={{
+                title: null,
+            }}
+            {...rest}
+        >
+            <div style={{height:'calc(100vh - 50px)'}}>
+                {children}
+            </div>
+        </PageContainer>
+    )
+}
+
+
+export default MQPageContainer;

+ 49 - 0
src/components/kcTable/index.tsx

@@ -0,0 +1,49 @@
+/*
+ * @Author: your name
+ * @Date: 2022-01-11 16:03:24
+ * @LastEditTime: 2022-02-17 10:08:12
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/src/components/kcTable/index.tsx
+ */
+
+import React, { useState, useEffect, useRef } from 'react';
+import ProTable, { ActionType, ProColumns } from '@ant-design/pro-table';
+import { KCTableType } from './typing';
+import './style.less';
+
+const KCTable: React.FC<KCTableType.KCTableProps<any, {}>> = ({
+  columns,
+  reload,
+  ...restProps
+}) => {
+  const [tableColumns, setTableColumns] = useState<ProColumns[]>([]);
+  const actionRef = useRef<ActionType>();
+
+  useEffect(() => {
+    setTableColumns(
+      columns.map((t) => ({
+        hideInSearch: true,
+        ...t,
+      })),
+    );
+  }, [columns]);
+
+  useEffect(() => {
+    if (reload) {
+      actionRef.current?.reload();
+    }
+  }, [reload]);
+
+  return (
+    <ProTable
+      className="KCTable"
+      actionRef={actionRef}
+      columns={tableColumns}
+      pagination={{ defaultPageSize: 10 }}
+      {...restProps}
+    />
+  );
+};
+
+export default KCTable;

+ 2 - 0
src/components/kcTable/style.less

@@ -0,0 +1,2 @@
+.KCTable {
+}

+ 17 - 0
src/components/kcTable/typing.d.ts

@@ -0,0 +1,17 @@
+/*
+ * @Author: your name
+ * @Date: 2022-01-11 16:24:23
+ * @LastEditTime: 2022-02-17 10:33:57
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/src/components/kcTable/typing.d.ts
+ */
+
+import { ProColumns, ProTableProps } from '@ant-design/pro-table';
+
+declare namespace KCTableType {
+  export interface KCTableProps<T, U> extends ProTableProps<T, U> {
+    columns: ProColumns<T>[];
+    reload?: boolean;
+  }
+}

+ 112 - 0
src/components/qualificationClassTree/index.tsx

@@ -0,0 +1,112 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-24 15:53:38
+ * @LastEditTime: 2022-02-28 10:02:15
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/components/qualificationClassTree/index.tsx
+ */
+
+
+import react, { useState } from 'react';
+import { Input } from 'antd';
+
+import './style.less';
+
+
+const treeData = [
+    {
+        title: 'parent 1',
+        key: '0-0',
+        children: [
+            {
+                title: 'parent 1-0',
+                key: '0-0-0',
+                disabled: true,
+                children: [
+                    {
+                        title: 'leaf',
+                        key: '0-0-0-0',
+                        disableCheckbox: true,
+                    },
+                    {
+                        title: 'leaf',
+                        key: '0-0-0-1',
+                    },
+                ],
+            },
+            {
+                title: 'parent 1-1',
+                key: '0-0-1',
+                children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-0-1-0' }],
+            },
+        ],
+    },
+];
+
+
+export interface QualificationClassTreePropsType {
+
+}
+
+
+export interface TreeType {
+    [key: string]: any;
+    children?: TreeType[]
+}
+
+
+const TreeNode = (data: TreeType, index: number, indent: number) => {
+
+    const [ifShowChild, setifShowChild] = useState(false);
+
+    const parentsNodeClickhandle = (e: react.MouseEvent) => {
+        e.preventDefault();
+        setifShowChild(!ifShowChild);
+    }
+
+    return (
+
+        data.children ? (
+            <div className='parents' key={index}>
+                <div className={ifShowChild?'parentsNode open':'parentsNode'} style={{ paddingLeft: `${indent * 10}px` }} onClick={(e) => parentsNodeClickhandle(e)}>
+                    <div className='parentsTitle'>{data.title}</div>
+                </div>
+
+
+                <div className='childrenWraper' style={{ height: ifShowChild ? '100%' :0}}>
+                    {
+                        data.children.map((item, i) => (TreeNode(item, i, indent + 1)))
+                    }
+                </div>
+
+            </div>
+        ) : (<div className='child' key={index}>{data.title}</div>)
+
+    )
+
+}
+
+
+const QualificationClassTree: react.FC<QualificationClassTreePropsType> = () => {
+
+    return (
+        <div className='QualificationClassTree'>
+            <div className='searchArea'>
+                <Input className='inputArea' placeholder="请输入类目名称" /><img className='searchIcon' alt="" />
+            </div>
+            <div className='treeContainer'>
+                {
+                    treeData.map((data, index) => {
+                        return (
+                            TreeNode(data, index, 0)
+                        )
+                    })
+                }
+            </div>
+        </div>
+    )
+}
+
+
+export default QualificationClassTree;

+ 111 - 0
src/components/qualificationClassTree/style.less

@@ -0,0 +1,111 @@
+.QualificationClassTree {
+  height: 100%;
+  padding: 8px;
+  padding-top: 16px;
+  .searchArea {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 8px;
+    padding: 0 8px;
+    .inputArea {}
+  }
+
+  .treeContainer {
+    padding: 0 8px;
+    .parents {
+      cursor: pointer;
+      .parentsNode {
+        display: flex;
+        width: 100%;
+        flex-direction: row;
+        height: 36px;
+        justify-content: flex-start;
+        align-items: center;
+        background: #FFFFFF;
+        border-radius: 4px;
+        padding: 0 8px;
+
+        .parentsTitle {
+          height: 14px;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #17181A;
+          line-height: 14px;
+
+          &::before {
+            position: relative;
+            display: inline-block;
+            content: '+';
+            top:-1px;
+            cursor: pointer;
+            text-align: center;
+            color: #99A6BF;
+            width: 12px;
+            height: 12px;
+            font-size: 10px;
+            margin-right: 8px;
+            line-height: 10px;
+            background: #F0F2F5;
+            border-radius: 2px;
+          }
+        }
+
+        &.open {
+            .parentsTitle {
+                &::before {
+                    position: relative;
+                    display: inline-block;
+                    content: '-';
+                    top:-1px;
+                    cursor: pointer;
+                    text-align: center;
+                    color: #99A6BF;
+                    width: 12px;
+                    height: 12px;
+                    font-size: 10px;
+                    margin-right: 8px;
+                    line-height: 10px;
+                    background: #F0F2F5;
+                    border-radius: 2px;
+                  }
+            }
+        }
+      }
+      .childrenWraper {
+          overflow-y: hidden;
+        //   transition: all 0.3s ease-in;
+      }
+
+      .child {
+        height: 36px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+        line-height: 36px;
+        border-radius: 4px;
+        padding-left: 40px;
+        &:hover {
+          background: #F0F2F5;
+        }
+      }
+
+      .childWrap {
+        
+      }
+    }
+
+    .child {
+      height: 14px;
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #17181A;
+      line-height: 14px;
+      border-radius: 4px;
+    }
+  }
+}

+ 44 - 0
src/contant.ts

@@ -0,0 +1,44 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-28 11:14:53
+ * @LastEditTime: 2022-02-28 15:08:17
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/contant.ts
+ */
+
+
+
+//资质审核类别
+export const AuditType = [
+    {
+        label: '无需审核,本人授权', value: 1
+    },
+    {
+        label: '需科室审批授权', value: 2
+    },
+    {
+        label: '需医务部审批授权', value: 3
+    },
+    {
+        label: '需院级审批授权', value: 4
+    }
+]
+
+
+//资质授权时间
+
+export const ValidityPeriod = [
+    {
+        label: '永久', value: -1
+    },
+    {
+        label: '三年', value: 2
+    },
+    {
+        label: '三个月', value: 3
+    },
+    {
+        label: '自定义', value: 4
+    }
+]

+ 43 - 0
src/global.less

@@ -0,0 +1,43 @@
+
+@borderRadius:4px;
+
+.mq-ant-page-header {
+    background-color: #f0f2f5;
+}
+
+.mq-ant-pro-page-container {
+    .mq-ant-pro-page-container-children-content {
+      margin: 0;
+      margin-left: 24px;
+      margin-right: 24px;
+    }
+}
+
+.mq-ant-input-affix-wrapper {
+  border-radius: @borderRadius;
+}
+
+.mq-ant-btn {
+  border-radius: @borderRadius;
+}
+
+.mq-ant-select-selector {
+  border-radius: @borderRadius !important;
+}
+
+.mq-ant-picker {
+  border-radius: @borderRadius;    
+}
+
+.mq-ant-input {
+  border-radius: @borderRadius; 
+}
+.mq-ant-input-number-input {
+  border-radius: @borderRadius; 
+}
+.mq-ant-input-number {
+  border-radius: @borderRadius; 
+}
+
+
+

+ 8 - 0
src/global.tsx

@@ -0,0 +1,8 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-15 17:00:30
+ * @LastEditTime: 2022-02-15 17:00:31
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/global.tsx
+ */

+ 11 - 0
src/models/model.ts

@@ -0,0 +1,11 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-15 17:24:57
+ * @LastEditTime: 2022-02-15 17:24:57
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/models/model.ts
+ */
+
+
+

BIN
src/pages/personalCenter/myApplication/Modals/MineProfile/assets/avatar_empty.png


+ 197 - 0
src/pages/personalCenter/myApplication/Modals/MineProfile/index.tsx

@@ -0,0 +1,197 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-17 15:50:33
+ * @LastEditTime: 2022-02-18 15:04:08
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/personalCenter/myApplication/Modals/mineProfile.tsx
+ */
+
+import KCModal from '@/components/KCModal';
+import react, { useState } from 'react';
+import { Upload, message, Button, Spin } from 'antd';
+import { UploadOutlined, LoadingOutlined } from '@ant-design/icons';
+
+import './style.less';
+import { ProFormDateTimePicker, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+
+
+interface MineProfileModalPropsType {
+  visible: boolean,
+  onVisibleChange: (bool: boolean) => void
+}
+
+const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
+
+
+
+const MineProfileModal: react.FC<MineProfileModalPropsType> = ({ visible, onVisibleChange }) => {
+
+  const [avatarUrl, setAvatarUrl] = useState<string>('');
+  const [loadAvatar, setLoadAvatar] = useState(false);
+
+  const props = {
+    name: 'file',
+    maxCount: 1,
+    showUploadList: false,
+    onChange(info: { file: { originFileObj: File, status: string; name: any; }; fileList: any; }) {
+
+      setLoadAvatar(true);
+
+      if (info.file.status !== 'uploading') {
+        // console.log(info.file, info.fileList);
+        const reader = new FileReader();
+        reader.readAsDataURL(info.file.originFileObj);//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
+        reader.onload = function (event) {
+          if (event.target && typeof event.target.result == 'string') {
+            setAvatarUrl(event.target.result);//base64
+          }
+        }
+      }
+      if (info.file.status === 'done') {
+        setLoadAvatar(false);
+      } else if (info.file.status === 'error') {
+        message.error(`${info.file.name} 上传失败!`);
+      }
+    },
+  }
+
+  return (
+    <KCModal
+      title='个人档案'
+      visible={visible}
+      onVisibleChange={onVisibleChange}
+      className='MineProfileModal'
+      layout='horizontal'
+      labelCol={{ span: 5 }}
+      wrapperCol={{ span: 18 }}
+    >
+      <div className='wraper'>
+        <div className='left'>
+          <div className='avatarContainer'>
+            <span>个人照片:</span>
+            <div className='avatar'>
+              {avatarUrl && <img src={avatarUrl} alt="avatar" />}
+              {loadAvatar && <Spin className='spin' indicator={antIcon} />}
+            </div>
+            <Upload {...props} className='UploadBtn'>
+              <Button icon={<UploadOutlined />}>上传照片(100*130)</Button>
+            </Upload>
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="a"
+              label="所学专业:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+              rules={[{ required: true, message: '请选择专业!' }]}
+            />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="b"
+              label="职务:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+              rules={[{ required: true, message: '请选择职务!' }]}
+            />
+          </div>
+          <div className='formItem'>
+            <ProFormText name="text" label="手机号:" placeholder="请输入" />
+          </div>
+          <div className='formItem'>
+            <ProFormText name="text" label="资格证号:" placeholder="请输入" />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="a"
+              label="医师级别:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+            />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="a"
+              label="执业科目:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+            />
+          </div>
+        </div>
+        <div className='right'>
+          <div className='formItem'>
+            <ProFormText name="text" label="姓名:" placeholder="请输入" rules={[{ required: true, message: '请输入姓名!' }]} />
+          </div>
+          <div className='formItem'>
+            <ProFormText name="text" label="工号:" placeholder="请输入" rules={[{ required: true, message: '请输入工号!' }]} />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="b"
+              label="性别:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+              rules={[{ required: true, message: '请选择性别!' }]}
+            />
+          </div>
+          <div className='formItem'>
+            <ProFormText name="text" label="科室:" placeholder="请输入" rules={[{ required: true, message: '请输入工号!' }]} />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="b"
+              label="职称:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+              rules={[{ required: true, message: '请选择职称!' }]}
+            />
+          </div>
+          <div className='formItem'>
+            <ProFormDateTimePicker name="datetime" label="入职时间" placeholder={'请选择日期'} />
+          </div>
+          <div className='formItem'>
+            <ProFormText name="text" label="执业证号:" placeholder="请输入" />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="b"
+              label="执业类别:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+            />
+          </div>
+          <div className='formItem'>
+            <ProFormSelect
+              name="b"
+              label="执业状态:"
+              request={async () => [
+                { label: '全部', value: 'all' },
+              ]}
+              placeholder="请选择"
+            />
+          </div>
+        </div>
+      </div>
+      <div className='remarkArea' >
+         <ProFormTextArea width="xl" label="备注:" name="remark" />
+      </div>
+    </KCModal>
+  )
+}
+
+export default MineProfileModal;

+ 93 - 0
src/pages/personalCenter/myApplication/Modals/MineProfile/style.less

@@ -0,0 +1,93 @@
+.MineProfileModal {
+  .wraper {
+    display: flex;
+    flex-direction: row;
+
+    .left {
+      width: 50%;
+
+      .avatarContainer {
+        display: flex;
+        flex-direction: row;
+        margin-bottom: 42px;
+        margin-left: 11px;
+
+        .avatar {
+          position: relative;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          width: 96px;
+          height: 128px;
+          border-radius: 4px;
+          background-image: url(./assets/avatar_empty.png);
+          background-size: cover;
+
+          .spin {
+            position: absolute;
+            top: 45%;
+            left: 0;
+            bottom: 0;
+            right: 0;
+          }
+
+          &>img {
+            width: 100%;
+          }
+        }
+
+        .UploadBtn {
+          margin-left: 18px;
+          margin-top: 45px;
+        }
+
+        &>span {
+          height: 14px;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #17181A;
+          line-height: 14px;
+          margin-top: 5px;
+          margin-right: 10px;
+        }
+      }
+
+      .formItem {
+
+        // margin-bottom: 16px;
+        .mq-ant-form-item {
+          // margin-bottom: 0;
+        }
+      }
+    }
+
+    .right {
+      width: 50%;
+
+      .formItem {
+
+        // margin-bottom: 16px;
+        .mq-ant-form-item {
+          .mq-ant-picker {
+            width: 100%;
+          }
+        }
+      }
+    }
+  }
+  .remarkArea {
+    .mq-ant-col-5 {
+      flex: 0 0 10%;
+    }
+    .mq-ant-col-18 {
+      max-width: 100%;
+      .pro-field-xl {
+          width: 662px;
+      }
+    }
+    .pro-field-xl {
+      width: 100%;
+    }
+  }
+}

+ 124 - 0
src/pages/personalCenter/myApplication/Modals/Qualification/index.tsx

@@ -0,0 +1,124 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-18 15:20:29
+ * @LastEditTime: 2022-02-18 16:54:20
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/personalCenter/myApplication/Modals/Qualification/index.tsx
+ */
+
+
+import KCModal from '@/components/KCModal';
+import react, { useState } from 'react';
+import { message, Form, Popover, Space } from 'antd';
+import { LoadingOutlined } from '@ant-design/icons';
+
+import './style.less';
+import { ProFormUploadButton, ProFormSelect, ProFormTextArea } from '@ant-design/pro-form';
+
+import Alert from '../../../../../../public/images/alert.png';
+
+interface QualificationModalPropsType {
+    visible: boolean,
+    onVisibleChange: (bool: boolean) => void
+}
+
+const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
+
+
+const content =<div style={{width:'336px',height:'320px',overflowY:'scroll'}} dangerouslySetInnerHTML={{
+    __html:`I级:能够独立处理本专业绝大多数复杂病人,具备专业学科带头人或专家资格。原则上医院要严格限制这一级别的授权。<br /></br>
+
+    Ⅱ级:能够处理本专业大多数复杂病人,具有独立操作和指导下级医师操作的资格,相当于副主任医师以上资格。<br /></br>
+    
+    Ⅲ级:能够独立处理本专业常见病人,但多数复杂病人需要上级医师和专家的指导,能指导下级医师进行常规的诊疗操作,相当于主治医师资格。绝大多数复杂病人需要上级医师和专家的指导,相当于住院医师资格。<br /></br>
+    
+    Ⅳ级:能够处理本专业简单的病人,可承担值班任务,但不具备指导他人操作的资格,大学本科毕业后未取得《中华人民共和国执业医师资格证书》的助理医师水平。<br /></br>
+    
+    Ⅴ级:不具备独立诊疗操作的资格,必须在上级医师的指导下进行诊疗操作,相当于医师授权工作程序`
+}}></div>
+
+
+const QualificationModal: react.FC<QualificationModalPropsType> = ({ visible, onVisibleChange }) => {
+
+    const [avatarUrl, setAvatarUrl] = useState<string>('');
+    const [loadAvatar, setLoadAvatar] = useState(false);
+
+    const props = {
+        name: 'file',
+        maxCount: 1,
+        showUploadList: false,
+        onChange(info: { file: { originFileObj: File, status: string; name: any; }; fileList: any; }) {
+
+            setLoadAvatar(true);
+
+            if (info.file.status !== 'uploading') {
+                // console.log(info.file, info.fileList);
+                const reader = new FileReader();
+                reader.readAsDataURL(info.file.originFileObj);//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
+                reader.onload = function (event) {
+                    if (event.target && typeof event.target.result == 'string') {
+                        setAvatarUrl(event.target.result);//base64
+                    }
+                }
+            }
+            if (info.file.status === 'done') {
+                setLoadAvatar(false);
+            } else if (info.file.status === 'error') {
+                message.error(`${info.file.name} 上传失败!`);
+            }
+        },
+    }
+
+    return (
+        <KCModal
+            width={600}
+            title='新增申请'
+            visible={visible}
+            onVisibleChange={onVisibleChange}
+            className='QualificationModal'
+            layout='horizontal'
+            labelCol={{ span: 5 }}
+            wrapperCol={{ span: 18 }}
+        >
+            <ProFormSelect
+                name="a"
+                label="资质类目:"
+                request={async () => [
+                    { label: '全部', value: 'all' },
+                ]}
+                placeholder="请选择"
+            />
+            <ProFormSelect
+                name="a"
+                label="资质名称:"
+                request={async () => [
+                    { label: '全部', value: 'all' },
+                ]}
+                placeholder="请选择"
+                rules={[{ required: true, message: '请选择资质!' }]}
+            />
+            <Form.Item label="申请等级:" style={{marginBottom:0}}>
+                <Space>
+                    <ProFormSelect
+                        width={'md'}
+                        request={async () => [
+                            { label: '全部', value: 'all' },
+                        ]}
+                        placeholder="请选择"
+                        rules={[{ required: true, message: '请选择申请等级!' }]}
+                    />
+                    <Popover placement="bottomLeft" content={content} title={()=><div className='levelDesc' ><img style={{width:'16px',marginRight:'5px',marginTop:'-2px'}} src={Alert} />等级说明</div>}>
+                        <div className='levelDesc' >说明</div>
+                    </Popover>
+                </Space>
+            </Form.Item>
+            
+            <ProFormTextArea width="xl" label="授权依据:" name="remark" />
+            <ProFormUploadButton {...props} label="佐证材料:" name="upload" action="upload.do" />
+
+        </KCModal>
+    )
+}
+
+export default QualificationModal;

+ 20 - 0
src/pages/personalCenter/myApplication/Modals/Qualification/style.less

@@ -0,0 +1,20 @@
+
+
+
+.QualificationModal {
+    .levelDesc {
+        margin-top: -23px;
+        cursor: pointer;
+        &::before {
+            position: relative;
+            display: inline-block;
+            content: '';
+            top:3px;
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
+            background-image: url(../../../../../../public//images/alert.png);
+            background-size: cover;
+        }
+    }
+}

+ 126 - 0
src/pages/personalCenter/myApplication/index.tsx

@@ -0,0 +1,126 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-17 09:56:05
+ * @LastEditTime: 2022-02-28 15:10:34
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/personalCenter/myApplication/index.tsx
+ */
+
+import {useEffect, useState} from 'react'
+import KCTable from "@/components/kcTable";
+import MQPageContainer from "@/components/MQPageContainer";
+import { getMineQualifiApplyList, QualificationDataType } from "@/service/qualification";
+import { ProColumns } from "@ant-design/pro-table";
+import { Divider,Button } from 'antd';
+import MineProfileModal from './Modals/MineProfile';
+import QualificationModal from './Modals/Qualification';
+
+// import './style.less';
+
+
+
+export default () => {
+
+    const columns:ProColumns<QualificationDataType>[] = [
+        {
+            title: 'id',
+            dataIndex: 'id',
+            hideInTable:true
+        },
+        {
+            title: '资质编号',
+            dataIndex: 'qualificationNum',
+        },
+        {
+            title: '资质名称',
+            dataIndex: 'qualificationName',
+            hideInSearch:false
+        },
+        {
+            title: '佐证材料',
+            dataIndex: 'supportMaterial',
+        },
+        {
+            title: '授权依据',
+            dataIndex: 'authorBasis',
+        },
+        {
+            title: '资质类型',
+            dataIndex: 'qualificationType',
+        },
+        {
+            title: '审核',
+            dataIndex: 'qualificationAudit',
+        },
+        {
+            title: '状态',
+            dataIndex: 'qualificationStatus',
+            hideInSearch:false
+        },
+        {
+            title: '申请日期',
+            dataIndex: 'applyDate',
+        },
+        {
+            title: '操作',
+            key: 'option',
+            valueType: 'option',
+            render: () => [
+                <a key="act1">编辑</a>,
+                <Divider key="act2" type="vertical" />,
+                <a key="act3">删除</a>,
+            ],
+        }
+    ]
+
+    const [profileModalVisible,setProfileModalVisible] = useState(false);
+    const [qualificationModalVisible,setQualificationModalVisible] = useState(false);
+
+    const getTableData =async (params:any) => {
+        const resp = await getMineQualifiApplyList(params);
+        if(resp){
+            const {list=[],current,totalCount} = resp;
+            return {
+               data:list,
+               success:true,
+               total: totalCount,
+            }
+        } 
+        return {
+            data:[],
+            success:false
+        }
+    }
+
+    const onVisibleChangeHandle = (bool:boolean,key:'profile'|'qualification')=>{
+        if(key=='profile'){
+            setProfileModalVisible(bool);
+        }
+        if(key=='qualification'){
+            setQualificationModalVisible(bool);
+        }
+    }
+
+    useEffect(()=>{
+    
+    },[])
+
+    return (
+        <MQPageContainer className="myApplication">
+            <MineProfileModal visible={profileModalVisible} onVisibleChange={bool=>onVisibleChangeHandle(bool,'profile')} />
+            <QualificationModal visible={qualificationModalVisible} onVisibleChange={bool=>onVisibleChangeHandle(bool,'qualification')} />
+            <KCTable 
+               columns={columns} 
+               request={(params)=>getTableData(params)} 
+               rowKey='id' 
+               toolbar={{
+                actions:[
+                    <Button key="Default" type="default" onClick={()=>setProfileModalVisible(true)}>个人档案</Button>,
+                    <Button key="primary" type="primary"  onClick={()=>setQualificationModalVisible(true)}>资质申请</Button>,
+                ]
+               }}
+            />
+        </MQPageContainer>
+    );
+}

BIN
src/pages/personalCenter/profile/components/qualificationCard/assets/corner-blue.png


BIN
src/pages/personalCenter/profile/components/qualificationCard/assets/corner-green.png


BIN
src/pages/personalCenter/profile/components/qualificationCard/assets/corner-orange.png


BIN
src/pages/personalCenter/profile/components/qualificationCard/assets/corner-red.png


BIN
src/pages/personalCenter/profile/components/qualificationCard/assets/corner-yellow.png


+ 94 - 0
src/pages/personalCenter/profile/components/qualificationCard/index.tsx

@@ -0,0 +1,94 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-16 16:16:48
+ * @LastEditTime: 2022-02-16 17:38:10
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/personalCenter/profile/components/qualificationCard/index.tsx
+ */
+
+
+import react from 'react';
+import { Badge } from 'antd';
+import './style.less';
+
+
+export type CardDataType = {
+    title:string;
+    date:string;
+    desc:string;
+    level:number;
+    status:number;
+}
+
+export interface QualificationCardType  {
+    data:CardDataType[]
+}
+
+
+//'I','II','III','IV','V'
+const level = [
+    {
+        level:'I',bgClass:'red'
+    },
+    {
+        level:'II',bgClass:'orange'
+    },
+    {
+        level:'III',bgClass:'yellow'
+    },
+    {
+        level:'IV',bgClass:'green'
+    },
+    {
+        level:'V',bgClass:'blue'
+    }
+]
+
+const getStatusRender = (num:number)=>{
+    const colors = [
+        {
+            color:'#29CC7A',text:'已授权'
+        },
+        {
+            color:'#FFBB34',text:'审核中'
+        },
+        {
+            color:'#A3B8CC',text:'暂存中'
+        },
+        {
+            color:'#FF4060',text:'已驳回'
+        },
+        {
+            color:'#29CC7A',text:'临时授权'
+        }
+    ];
+
+    return (
+        <Badge color={colors[num].color} text={colors[num].text} />
+    )
+}
+
+const QualificationCard: react.FC<QualificationCardType> = ({data=[]}) => {
+    
+    return (
+       <div className='qualificationCard'>
+            {
+                data.map((t,index)=>{
+                    return (
+                         <div className='card' key={index}>
+                                 <div className={`levelTag ${level[t.level].bgClass}`}>{level[t.level].level}级</div>
+                                 <div className='title'>{t.title}</div>
+                                 <div className='info'>准入日期:<span>{t.date}</span></div>
+                                 <div className='info'>授权依据:<span>{t.desc}</span></div>
+                                 <div className='status'>{getStatusRender(t.status)}</div>
+                         </div>
+                    )
+                })
+            }
+       </div>
+    )
+}
+
+
+export default QualificationCard;

+ 93 - 0
src/pages/personalCenter/profile/components/qualificationCard/style.less

@@ -0,0 +1,93 @@
+.qualificationCard {
+  display: flex;
+  flex: 1;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  flex-wrap: wrap;
+
+  .card {
+    position: relative;
+    width: 32%;
+    height: 162px;
+    background: #FFFFFF;
+    border-radius: 4px;
+    padding: 24px 24px;
+    margin-right: 2%;
+    margin-bottom: 24px;
+    .levelTag {
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 52px;
+      height: 22px;
+      font-size: 14px;
+      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+      font-weight: 500;
+      color: #FFFFFF;
+      text-align: center;
+      line-height: 22px;
+      padding-left: 2px;
+      background-image: url('./assets/corner-red.png');
+      &.orange {
+        background-image: url('./assets/corner-orange.png');
+      }
+      &.yellow {
+        background-image: url('./assets/corner-yellow.png');
+      }
+      &.green {
+        background-image: url('./assets/corner-green.png');
+      }
+      &.blue {
+        background-image: url('./assets/corner-blue.png');
+      }
+      background-size: cover;
+    }
+
+    .title {
+      height: 16px;
+      font-size: 16px;
+      font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+      font-weight: bold;
+      color: #17181A;
+      line-height: 16px;
+      margin-bottom: 16px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+
+    .info {
+      height: 14px;
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #666E80;
+      line-height: 14px;
+      margin-bottom: 16px;
+
+      span {
+        display: inline-block;
+        vertical-align: middle;
+        color: #17181A;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    .status {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-end;
+    }
+
+    &:nth-child(3n) {
+      margin-right: 0;
+    }
+  }
+}

+ 128 - 0
src/pages/personalCenter/profile/index.tsx

@@ -0,0 +1,128 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-15 16:35:08
+ * @LastEditTime: 2022-02-16 17:34:10
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/personalCenter/profile/index.tsx
+ */
+
+import { useState } from 'react';
+import MQPageContainer from "@/components/MQPageContainer";
+import './style.less';
+import { Skeleton, Divider } from 'antd';
+import avatar from '../../../../public/images/avatar.png';
+import QualificationCard, { CardDataType } from './components/qualificationCard';
+
+
+//个人档案
+export default () => {
+
+    const [loading, setLoading] = useState(false);
+    const [qualificationCardData,setQualificationCardData] = useState<CardDataType[]>([
+          {
+              title:'ACLS',
+              date:'2021-11-12',
+              desc:'参加培训并取得合格人员',
+              status:1,
+              level:1
+          },
+          {
+            title:'ACLS',
+            date:'2021-11-12',
+            desc:'参加培训并取得合格人员',
+            status:1,
+            level:1
+          },
+          {
+            title:'ACLS',
+            date:'2021-11-12',
+            desc:'参加培训并取得合格人员',
+            status:1,
+            level:1
+          },
+          {
+            title:'ACLS',
+            date:'2021-11-12',
+            desc:'参加培训并取得合格人员',
+            status:2,
+            level:2
+          }
+    ]);
+
+    return (
+        <MQPageContainer className="myProfile">
+            <div className="profileCard">
+                <Skeleton loading={loading} active avatar>
+                    <div className='wraper'>
+                        <div className="avatar">
+                            <img src={avatar} alt="头像" />
+                        </div>
+                        <div className="description">
+                            <div className="rowOne">
+                                <div className="info">
+                                    <div className="name">张梓涵</div>
+                                    <div className="baseInfo">
+                                        女|副院长|副主任医师|临床医学
+                                    </div>
+                                </div>
+                                <div className='staffBaseInfo'>
+                                    <div className='staffBaseInfoSpan'>
+                                        <span className='spanName'>人员工号</span>
+                                        <span className='spanValue'>10008</span>
+                                    </div>
+                                    <Divider type="vertical" className='Divider' />
+                                    <div className='staffBaseInfoSpan'>
+                                        <span className='spanName'>人员类别</span>
+                                        <span className='spanValue'>医生</span>
+                                    </div>
+                                    <Divider type="vertical" className='Divider' />
+                                    <div className='staffBaseInfoSpan'>
+                                        <span className='spanName'>所属科室</span>
+                                        <span className='spanValue'>心内科</span>
+                                    </div>
+                                    <Divider type="vertical" className='Divider' />
+                                    <div className='staffBaseInfoSpan'>
+                                        <span className='spanName'>进院日期</span>
+                                        <span className='spanValue'>1998-08-01</span>
+                                    </div>
+                                    <Divider type="vertical" className='Divider' />
+                                    <div className='staffBaseInfoSpan'>
+                                        <span className='spanName'>状态</span>
+                                        <span className='spanValue status'>审核中</span>
+                                    </div>
+                                </div>
+                            </div>
+                            <div className="rowTwo">
+                                <div className='medicalInfoSpan'>
+                                    <div className='span'>资格证号:<span>200134499292083202302</span></div>
+                                    <div className='span'>执业证号:<span>200134499292083202302</span></div>
+                                </div>
+                                <div className='medicalInfoSpan'>
+                                    <div className='span'>医师级别:<span>执业医师</span></div>
+                                    <div className='span'>执业状态:<span>已注册</span></div>
+                                </div>
+                                <div className='medicalInfoSpan'>
+                                    <div className='span'>执业科目:<span>心血管内科</span></div>
+                                    <div className='span'>备注:<span>这里是一条备注</span></div>
+                                </div>
+                                <div className='medicalInfoSpan'>
+                                    <div className='span'>执业类别:<span>临床</span></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div className='profileFooter'>
+                           <div className='flowInstruction'>流程说明</div>
+                           <div className='action'>
+                                <div className='editProfile'>编辑档案</div>
+                                <div className='qualificationApply'>资质申请</div>
+                           </div>
+                    </div>
+                </Skeleton>
+            </div>
+            <div className='qualificationTitle'>基本授权</div>
+            <QualificationCard data={qualificationCardData} />
+        </MQPageContainer>
+    );
+}

+ 243 - 0
src/pages/personalCenter/profile/style.less

@@ -0,0 +1,243 @@
+.myProfile {
+  .profileCard {
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-start;
+    padding: 32px;
+    background: #FFFFFF;
+    border-radius: 4px;
+
+    .wraper {
+      display: flex;
+      flex: 1;
+
+      .avatar {
+        width: 80px;
+        height: 80px;
+        margin-right: 24px;
+
+        img {
+          width: 100%;
+        }
+      }
+
+      .description {
+        width: calc(100% - 104px);
+
+        .rowOne {
+          display: flex;
+          flex: 1;
+          flex-direction: row;
+          justify-content: space-between;
+          align-items: flex-start;
+          padding-top: 16px;
+
+          .info {
+            .name {
+              height: 20px;
+              font-size: 20px;
+              font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+              font-weight: bold;
+              color: #17181A;
+              line-height: 30px;
+              margin-bottom: 16px;
+            }
+
+            .baseInfo {
+              height: 14px;
+              font-size: 14px;
+              font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+              font-weight: 400;
+              color: #666E80;
+              line-height: 21px;
+            }
+          }
+
+          .staffBaseInfo {
+            display: flex;
+            flex: 1;
+            flex-direction: row;
+            justify-content: flex-end;
+            align-items: flex-start;
+
+            .staffBaseInfoSpan {
+              display: flex;
+              flex-direction: column;
+              justify-content: center;
+              align-items: center;
+
+              .spanName {
+                height: 14px;
+                font-size: 14px;
+                font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                font-weight: 400;
+                color: #666E80;
+                line-height: 14px;
+                margin-bottom: 16px;
+              }
+
+              .spanValue {
+                height: 20px;
+                font-size: 20px;
+                font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+                font-weight: bold;
+                color: #17181A;
+                line-height: 20px;
+
+                &.status {
+                  color: #FFB54D;
+                }
+              }
+            }
+
+            .Divider {
+              height: 24px;
+              margin-left: 5%;
+              margin-right: 5%;
+              margin-top: 10px;
+            }
+          }
+        }
+
+        .rowTwo {
+          display: flex;
+          flex: 1;
+          margin-top: 45px;
+          flex-direction: row;
+          justify-content: flex-start;
+          align-items: center;
+
+          .medicalInfoSpan {
+            display: flex;
+            height: 45px;
+            flex-direction: column;
+            align-items: flex-start;
+            margin-right: 10%;
+
+            .span {
+              height: 14px;
+              font-size: 14px;
+              font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+              font-weight: 400;
+              color: #666E80;
+              line-height: 14px;
+              margin-bottom: 16px;
+
+              span {
+                color: #17181A;
+              }
+
+              &:last-child {
+                margin-bottom: 0;
+              }
+            }
+
+            &:last-child {
+              margin-right: 0;
+            }
+          }
+        }
+      }
+    }
+
+    .profileFooter {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      padding-top: 25px;
+      margin-top: 32px;
+      border-top: 1px solid #DFE3EB;
+
+      .flowInstruction {
+        height: 14px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+        line-height: 14px;
+        cursor: pointer;
+
+        &::before {
+          position: relative;
+          display: inline-block;
+          content: '';
+          top: 2px;
+          width: 16px;
+          height: 16px;
+          margin-right: 8px;
+          background-image: url('../../../../public/images/alert.png');
+          background-size: cover;
+        }
+      }
+
+      .action {
+        display: flex;
+        flex-direction: row;
+
+        .editProfile {
+          height: 14px;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #26334D;
+          line-height: 14px;
+          margin-right: 32px;
+          cursor: pointer;
+
+          &::before {
+            position: relative;
+            display: inline-block;
+            content: '';
+            top: 3px;
+            width: 16px;
+            height: 16px;
+            margin-right: 8px;
+            background-image: url('../../../../public/images/box.png');
+            background-size: cover;
+          }
+        }
+
+        .qualificationApply {
+          height: 14px;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #26334D;
+          line-height: 14px;
+          cursor: pointer;
+
+          &::before {
+            position: relative;
+            display: inline-block;
+            content: '';
+            top: 3px;
+            width: 16px;
+            height: 16px;
+            margin-right: 8px;
+            background-image: url('../../../../public/images/blueFile.png');
+            background-size: cover;
+          }
+        }
+      }
+    }
+  }
+
+  .qualificationTitle {
+    font-size: 16px;
+    font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+    font-weight: bold;
+    color: #17181A;
+    margin-top: 24px;
+    margin-bottom: 16px;
+    &::before {
+      position: relative;
+      display: inline-block;
+      content: '';
+      top:2px;
+      width: 4px;
+      height: 16px;
+      margin-right:8px;
+      background: #3376FE;
+    }
+  }
+}

+ 126 - 0
src/pages/qualificationCheck/index.tsx

@@ -0,0 +1,126 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-21 08:57:49
+ * @LastEditTime: 2022-02-24 14:41:51
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationCheck/index.tsx
+ */
+
+
+import {useEffect, useState} from 'react'
+import KCTable from "@/components/kcTable";
+import MQPageContainer from "@/components/MQPageContainer";
+import { getMineQualifiApplyList, QualificationDataType } from "@/service/qualification";
+import { ProColumns } from "@ant-design/pro-table";
+import { Button } from 'antd';
+
+// import './style.less';
+
+
+
+export default () => {
+
+    const columns:ProColumns<QualificationDataType>[] = [
+        {
+            title: 'id',
+            dataIndex: 'id',
+            hideInTable:true
+        },
+        {
+            title: '资质类目',
+            dataIndex: 'qualificationClass',
+            hideInSearch:false,
+            valueType:'cascader'
+        },
+        {
+            title: '资质编号',
+            dataIndex: 'qualificationNum',
+        },
+        {
+            title: '资质名称',
+            dataIndex: 'qualificationName',
+            hideInSearch:false
+        },
+        {
+            title: '被授予人',
+            dataIndex: '',
+            hideInSearch:false
+        },
+        {
+            title: '佐证材料',
+            dataIndex: 'supportMaterial',
+        },
+        {
+            title: '授权依据',
+            dataIndex: 'authorBasis',
+        },
+        {
+            title: '科审',
+            dataIndex: '1',
+        },
+        {
+            title: '医务审',
+            dataIndex: '2',
+        },
+        {
+            title: '院审',
+            dataIndex: '3',
+        },
+        {
+            title: '申请日期',
+            dataIndex: 'applyDate',
+            hideInSearch:false,
+            valueType:'dateRange'
+        }
+    ]
+
+    const [profileModalVisible,setProfileModalVisible] = useState(false);
+    const [qualificationModalVisible,setQualificationModalVisible] = useState(false);
+
+    const getTableData =async (params:any) => {
+        const resp = await getMineQualifiApplyList({params});
+        if(resp){
+            const {list=[],current,totalCount} = resp;
+            return {
+               data:list,
+               success:true,
+               total: totalCount,
+            }
+        } 
+        return {
+            data:[],
+            success:false
+        }
+    }
+
+    const onVisibleChangeHandle = (bool:boolean,key:'profile'|'qualification')=>{
+        if(key=='profile'){
+            setProfileModalVisible(bool);
+        }
+        if(key=='qualification'){
+            setQualificationModalVisible(bool);
+        }
+    }
+
+    useEffect(()=>{
+    
+    },[])
+
+    return (
+        <MQPageContainer className="myApplication">
+            {/* <MineProfileModal visible={profileModalVisible} onVisibleChange={bool=>onVisibleChangeHandle(bool,'profile')} />
+            <QualificationModal visible={qualificationModalVisible} onVisibleChange={bool=>onVisibleChangeHandle(bool,'qualification')} /> */}
+            <KCTable 
+               columns={columns} 
+               request={(params)=>getTableData(params)} 
+               rowKey='id' 
+               toolbar={{
+                actions:[
+                    <Button key="primary" type="primary"  onClick={()=>setQualificationModalVisible(true)}>新增</Button>,
+                ]
+               }}
+            />
+        </MQPageContainer>
+    );
+}

+ 108 - 0
src/pages/qualificationMana/qualificationClass/components/qualificationCard/index.tsx

@@ -0,0 +1,108 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-24 13:52:44
+ * @LastEditTime: 2022-02-24 15:34:25
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationMana/qualificationClass/components/qualificationCard/index.tsx
+ */
+
+
+
+import React, { useState, useEffect } from 'react';
+import { ProFormText, ProFormSelect } from '@ant-design/pro-form'
+import './style.less';
+import addIcon from '../../../../../../public/images/add.png';
+import editIcon from '../../../../../../public/images/editIcon.png';
+import trashIcon from '../../../../../../public/images/trash.png';
+import KCModal from '@/components/KCModal';
+
+
+
+
+export type QualifiCardListType = {
+    name: string;
+}
+export type QualifiCardPropsType = {
+    color?: string;
+    title: string;
+    list: QualifiCardListType[],
+    modalCommitFunc?:(formData:any)=>boolean;
+}
+
+type ActType = 'ADD' | 'EDIT';
+
+const QualifiCard: React.FC<QualifiCardPropsType> = ({ title, list = [], color = '#6179F2',modalCommitFunc }) => {
+
+    const [visible, setVisible] = useState(false);
+    const [data, setData] = useState<QualifiCardListType[]>([]);
+    const [modalType, setModalType] = useState<ActType | undefined>(undefined);
+
+    const openModalHandle = (key: ActType) => {
+        setVisible(true);
+        setModalType(key);
+    }
+
+    const onVisibleChangehandle = (bool: boolean) => {
+        setVisible(bool);
+    }
+
+
+    const delHandle = (index: number) => {
+        let _data = data;
+        _data.splice(index, 1);
+        console.log({ _data });
+        setData([..._data]);
+    }
+
+    const modalCommithandle = (vals:any)=>{
+        if(modalCommitFunc){
+            modalCommitFunc(vals);
+        }
+         return Promise.resolve();
+    }
+
+    useEffect(() => {
+        setData(list);
+    }, []);
+
+    return (
+        <div className='QualifiCard'>
+            <KCModal title={modalType == 'ADD' ? `新增${title}` : `编辑${title}`} visible={visible} width={500} layout='horizontal' 
+               onVisibleChange={onVisibleChangehandle}
+               onFinish={values=>modalCommithandle(values)}
+               >
+                <ProFormText name="text" label="类目名称:" placeholder="请输入名称" rules={[{ required: true, message: '请填写资质名称' }]} />
+                <ProFormSelect
+                    name="select"
+                    label="资质类目:"
+                    valueEnum={{
+                        open: '未解决',
+                        closed: '已解决',
+                    }}
+                    placeholder="请选择"
+                    rules={[{ required: true, message: '请选择资质类目!' }]}
+                />
+            </KCModal>
+            <div className='header'>
+                <div className='title'><span className='colorDot' style={{ background: `${color}` }}></span>{title}</div>
+                <img src={addIcon} alt="" className='addIcon' onClick={() => openModalHandle('ADD')} />
+            </div>
+            <div className='wraper'>
+                {
+                    data.map((item, index) => (
+                        <div className='list' key={index}>
+                            <div className='name'>{item.name}</div>
+                            <div className='action'>
+                                <img className='actionIcon editIcon' src={editIcon} alt="" onClick={() => openModalHandle('EDIT')} />
+                                <img className='actionIcon' src={trashIcon} alt="" onClick={() => delHandle(index)} />
+                            </div>
+                        </div>
+                    ))
+                }
+            </div>
+        </div>
+    );
+};
+
+export default QualifiCard;

+ 91 - 0
src/pages/qualificationMana/qualificationClass/components/qualificationCard/style.less

@@ -0,0 +1,91 @@
+.QualifiCard {
+  width: 278px;
+  height: 97%;
+  background: #FFFFFF;
+  border-radius: 4px;
+  padding: 8px;
+
+  .header {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    height: 40px;
+    padding: 0 16px;
+
+    .title {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      height: 16px;
+      font-size: 16px;
+      font-family: SourceHanSansCN-Bold, SourceHanSansCN;
+      font-weight: bold;
+      color: #17181A;
+      line-height: 16px;
+      .colorDot {
+        width: 8px;
+        height: 8px;
+        border-radius: 2px;
+        margin-right: 16px;
+      }
+    }
+
+    .addIcon {
+      width: 16px;
+      height: 16px;
+      cursor: pointer;
+    }
+  }
+
+  .wraper {
+    height: calc(100% - 40px);
+
+    .list {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      width: 100%;
+      height: 40px;
+      background: #FFFFFF;
+      border-radius: 4px;
+      margin-top: 4px;
+      padding: 0 16px;
+      border-radius: 4px;
+
+      .name {
+
+        height: 14px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+        line-height: 14px;
+      }
+
+      .action {
+         display: none;
+        .actionIcon {
+          width: 16px;
+          height: 16px;
+          cursor: pointer;
+        }
+        .editIcon {
+            margin-right: 15px;
+        }
+      }
+
+      &:hover {
+        .name {
+          font-weight: 500;
+        }
+        .action {
+            display: block;
+        }
+
+        background: #F0F2F5;
+      }
+    }
+  }
+}

+ 36 - 0
src/pages/qualificationMana/qualificationClass/index.tsx

@@ -0,0 +1,36 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-23 15:18:26
+ * @LastEditTime: 2022-02-24 14:33:29
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationMana/qualificationClass/index.tsx
+ */
+
+
+import { useEffect, useState } from 'react'
+
+import MQPageContainer from "@/components/MQPageContainer";
+
+import './style.less';
+import QualifiCard from './components/qualificationCard';
+
+
+const data = [
+    {name:'病历书写'},
+    {name:'处方权'},
+    {name:'中医'}
+]
+
+export default () => {
+
+    useEffect(() => {
+
+    }, [])
+
+    return (
+        <MQPageContainer className="QualificationApplication">
+                  <QualifiCard title='一级类目' list={data}/>
+        </MQPageContainer>
+    );
+}

+ 0 - 0
src/pages/qualificationMana/qualificationClass/style.less


+ 121 - 0
src/pages/qualificationMana/qualificationEdit/index.tsx

@@ -0,0 +1,121 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-24 15:40:52
+ * @LastEditTime: 2022-02-28 17:44:43
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationMana/qualificationEdit/index.tsx
+ */
+
+
+import { useEffect, useState } from 'react'
+
+import MQPageContainer from "@/components/MQPageContainer";
+import './style.less'
+import QualificationClassTree from '@/components/qualificationClassTree';
+import KCTable from '@/components/kcTable';
+import { ProColumns } from '@ant-design/pro-table';
+import { Button } from 'antd'
+import QualificationModal from './modals/qualificationEdit&add';
+import QualificationImportModal from './modals/qualificationImport';
+
+
+
+type ACT = 'QUALIFI_IMPORT'|'QUALIFI_ADD'|'QUALIFI_EDIT';
+
+export default () => {
+
+    const columns: ProColumns[] = [
+        {
+            title: 'id',
+            dataIndex: 'a',
+            hideInTable: true
+        },
+        {
+            title: '资质编号',
+            dataIndex: 'b',
+            hideInSearch:false
+        },
+        {
+            title: '资质名称',
+            dataIndex: 'c',
+            hideInSearch:false
+        },
+        {
+            title: '授权依据',
+            dataIndex: 'd',
+        },
+        {
+            title: '审核类型',
+            dataIndex: 'e',
+        },
+        {
+            title: '有效期',
+            dataIndex: 'f',
+        },
+        {
+            title: '资质类型',
+            dataIndex: 'g',
+        },
+        {
+            title: '操作',
+            valueType: 'option',
+            render: (text, record, _, action) => [
+                <a
+                    key="editable"
+                    onClick={() => openModalHandle('QUALIFI_EDIT')}
+                >
+                    编辑
+                </a>,
+                <a  key="del">
+                    删除
+                </a>
+            ],
+        },
+    ]
+
+    const [editModalVisible,seteditModalVisible] = useState(false);
+    const [importModalVisible,setimportModalVisible] = useState(false);
+
+    const openModalHandle = (type:ACT)=>{
+        type == 'QUALIFI_ADD'&&seteditModalVisible(true);
+        type == 'QUALIFI_IMPORT'&&setimportModalVisible(true);
+    }
+
+    const editModalVisibleChangeHandle = (bool:boolean)=>{
+        seteditModalVisible(bool);
+    }
+
+    const importModalVisibleChangeHandle = (bool:boolean)=>{
+        setimportModalVisible(bool);
+    }
+
+    useEffect(() => {
+
+    }, [])
+
+    return (
+        <MQPageContainer >
+            <QualificationModal visible={editModalVisible} onVisibleChange={editModalVisibleChangeHandle} />
+            <QualificationImportModal visible={importModalVisible} onVisibleChange={importModalVisibleChangeHandle} />
+            <div className="QualificationEdit">
+                <div className='qualificationClassTree'>
+                    <QualificationClassTree />
+                </div>
+                <div className='qualificationTable'>
+                    <KCTable
+                        columns={columns}
+                        toolBarRender={() => [
+                            <Button key="default" onClick={() => openModalHandle('QUALIFI_IMPORT')}>
+                                资质导入
+                            </Button>,
+                            <Button key="primary" type="primary" onClick={() => openModalHandle('QUALIFI_ADD')}>
+                                新增
+                            </Button>,
+                        ]}
+                    />
+                </div>
+            </div>
+        </MQPageContainer>
+    );
+}

+ 89 - 0
src/pages/qualificationMana/qualificationEdit/modals/qualificationEdit&add.tsx

@@ -0,0 +1,89 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-28 10:26:30
+ * @LastEditTime: 2022-02-28 16:37:38
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationMana/qualificationEdit/modals/qualificationEdit&add.tsx
+ */
+
+
+import KCModal from '@/components/KCModal';
+import react, { useState } from 'react';
+import { Form, InputNumber, Select } from 'antd';
+
+import './style.less';
+import { ProFormSelect, ProFormText, ProFormDependency,ProFormTextArea } from '@ant-design/pro-form';
+import { AuditType, ValidityPeriod } from '@/contant';
+
+
+interface QualificationModalPropsType {
+    visible: boolean,
+    onVisibleChange: (bool: boolean) => void
+}
+
+
+
+const QualificationModal: react.FC<QualificationModalPropsType> = ({ visible, onVisibleChange }) => {
+
+
+    return (
+        <KCModal
+            width={600}
+            title='新增资质'
+            visible={visible}
+            onVisibleChange={onVisibleChange}
+            className='QualificationModal'
+            layout='horizontal'
+            labelCol={{ span: 5 }}
+            wrapperCol={{ span: 18 }}
+        >
+            <ProFormText name='b' label='资质编号' placeholder='请输入' rules={[{ required: true, message: '请输入编号!' }]} />
+            <ProFormText name='c' label='资质名称' placeholder='请输入' rules={[{ required: true, message: '请输入名称!' }]} />
+            <ProFormSelect
+                name="a"
+                label="审核类别"
+                request={async () => AuditType}
+                placeholder="请选择"
+                rules={[{ required: true, message: '请选择类别!' }]}
+            />
+            <Form.Item name='time' label="有效期" rules={[{ required: true, message: '请填写' }]}>
+                <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}>
+                    <ProFormSelect
+                        className='ProFormSelect'
+                        name='selectTime'
+                        request={async () => ValidityPeriod}
+                        placeholder="请选择"
+                        width={240}
+                        style={{ marginBottom: 0 }}
+                        rules={[{ required: true, message: '请选择类别!' }]}
+                    />
+                    <ProFormDependency name={['selectTime']}>
+                        {
+                            ({ selectTime }) => {
+                                return selectTime == 4 && (
+                                    <InputNumber style={{ width: '40%', marginBottom: 0 }} min={1} addonAfter='天' placeholder='手动输入' />
+                                )
+                            }
+                        }
+                    </ProFormDependency>
+
+                </div>
+            </Form.Item>
+            <ProFormSelect
+                name="a"
+                label="资质类型"
+                request={async () => AuditType}
+                placeholder="请选择"
+                rules={[{ required: true, message: '请选择类型!' }]}
+            />
+            <ProFormTextArea
+                name="text"
+                label="授权依据"
+                placeholder="请输入"
+            />
+        </KCModal>
+    )
+}
+
+export default QualificationModal;

+ 49 - 0
src/pages/qualificationMana/qualificationEdit/modals/qualificationImport.tsx

@@ -0,0 +1,49 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-28 16:43:12
+ * @LastEditTime: 2022-02-28 17:36:00
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationMana/qualificationEdit/modals/qualificationImport.tsx
+ */
+
+
+import KCModal from '@/components/KCModal';
+import react, { useState } from 'react';
+import { Form, InputNumber, Select } from 'antd';
+
+import './style.less';
+import { ProFormSelect, ProFormText, ProFormDependency,ProFormTextArea } from '@ant-design/pro-form';
+import { AuditType, ValidityPeriod } from '@/contant';
+
+
+interface QualificationImportModalPropsType {
+    visible: boolean,
+    onVisibleChange: (bool: boolean) => void
+}
+
+
+
+const QualificationImportModal: react.FC<QualificationImportModalPropsType> = ({ visible, onVisibleChange }) => {
+
+
+    return (
+        <KCModal
+            width={600}
+            title='资质导入'
+            visible={visible}
+            onVisibleChange={onVisibleChange}
+            className='QualificationModal'
+            layout='horizontal'
+            labelCol={{ span: 5 }}
+            wrapperCol={{ span: 18 }}
+        >
+           <div className='header'>
+                 <span>文件上传</span>
+                 <span>模板下载</span>
+           </div>
+        </KCModal>
+    )
+}
+
+export default QualificationImportModal;

+ 9 - 0
src/pages/qualificationMana/qualificationEdit/modals/style.less

@@ -0,0 +1,9 @@
+
+
+
+
+#time {
+    .mq-ant-form-item {
+        margin-bottom: 0 !important;
+    }
+}

+ 19 - 0
src/pages/qualificationMana/qualificationEdit/style.less

@@ -0,0 +1,19 @@
+
+
+.QualificationEdit {
+      display: flex;
+      height: 100%;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: flex-start;
+      .qualificationClassTree {
+        width: 220px;
+        height: 97%;
+        background: #FFFFFF;
+        border-radius: 4px;
+        margin-right: 24px;
+      }
+      .qualificationTable {
+          width: calc(100% - 248px);
+      }
+}

+ 215 - 0
src/pages/qualificationReview/index.tsx

@@ -0,0 +1,215 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-21 09:40:09
+ * @LastEditTime: 2022-02-21 11:42:38
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/pages/qualificationReview/index.tsx
+ */
+
+
+import { useEffect, useState } from 'react'
+import KCTable from "@/components/kcTable";
+import MQPageContainer from "@/components/MQPageContainer";
+import { getMineQualifiApplyList, QualificationDataType } from "@/service/qualification";
+import { ProColumns } from "@ant-design/pro-table";
+import { ProFormRadio, ProFormCheckbox, ProFormDependency, ProFormTextArea,ProFormDigit } from '@ant-design/pro-form';
+import { Button, Form } from 'antd';
+import KCModal from '@/components/KCModal';
+
+import './style.less';
+
+
+
+export default () => {
+
+    const columns: ProColumns<QualificationDataType>[] = [
+        {
+            title: 'id',
+            dataIndex: 'id',
+            hideInTable: true
+        },
+        {
+            title: '资质类目',
+            dataIndex: 'qualificationClass',
+            hideInSearch: false,
+            valueType: 'cascader'
+        },
+        {
+            title: '资质编号',
+            dataIndex: 'qualificationNum',
+        },
+        {
+            title: '资质名称',
+            dataIndex: 'qualificationName',
+            hideInSearch: false
+        },
+        {
+            title: '被授予人',
+            dataIndex: '',
+            hideInSearch: false
+        },
+        {
+            title: '佐证材料',
+            dataIndex: 'supportMaterial',
+        },
+        {
+            title: '授权依据',
+            dataIndex: 'authorBasis',
+        },
+        {
+            title: '科审',
+            dataIndex: '1',
+        },
+        {
+            title: '医务审',
+            dataIndex: '2',
+        },
+        {
+            title: '院审',
+            dataIndex: '3',
+        },
+        {
+            title: '申请日期',
+            dataIndex: 'applyDate',
+            hideInSearch: false,
+            valueType: 'dateRange'
+        }
+    ]
+
+    const [modalVisible, setModalVisible] = useState(false);
+    const [modalActType, setModalActType] = useState<'review' | 'authorize' | undefined>(undefined);
+
+    const getTableData = async (params: any) => {
+        const resp = await getMineQualifiApplyList({ params });
+        if (resp) {
+            const { list = [], current, totalCount } = resp;
+            return {
+                data: list,
+                success: true,
+                total: totalCount,
+            }
+        }
+        return {
+            data: [],
+            success: false
+        }
+    }
+
+    const onVisibleChangeHandle = (bool: boolean) => {
+        setModalVisible(bool);
+    }
+
+    const showModalHandle = (type: 'review' | 'authorize') => {
+        setModalVisible(true);
+        setModalActType(type)
+    }
+
+    useEffect(() => {
+
+    }, [])
+
+    return (
+        <MQPageContainer className="QualificationApplication">
+            <KCModal className='QualificationApplicationModal' visible={modalVisible} onVisibleChange={onVisibleChangeHandle} width={600}
+                title={modalActType == 'authorize' ? '临时授权' : '审核操作'} layout='horizontal'>
+
+                {
+                    modalActType == 'review' ? (
+                        //审核操作
+                        <>
+                            <ProFormRadio.Group
+                                name="radio-group"
+                                label="选择操作"
+                                options={[
+                                    {
+                                        label: '通过',
+                                        value: 'a',
+                                    },
+                                    {
+                                        label: '驳回',
+                                        value: 'b',
+                                    },
+                                ]}
+                            />
+                            <ProFormDependency name={['name']}>
+                                {
+                                    ({ name }) => {
+                                        return (
+                                            <>
+                                                <ProFormCheckbox.Group
+                                                    name="checkbox"
+                                                    label="驳回原因"
+                                                    options={['农业', '制造业', '互联网']}
+                                                />
+                                                <ProFormTextArea
+                                                    name="text"
+                                                    label="其他驳回原因"
+                                                    placeholder="请输入"
+                                                    fieldProps={{}}
+                                                />
+                                            </>
+                                        )
+                                    }
+                                }
+                            </ProFormDependency>
+                        </>
+
+                    ) : (
+                        <>
+                            <ProFormRadio.Group
+                                name="radio-group"
+                                label="选择操作"
+                                options={[
+                                    {
+                                        label: '三个月',
+                                        value: 'a',
+                                    },
+                                    {
+                                        label: '自定义',
+                                        value: 'b',
+                                    },
+                                ]}
+                            />
+                            <ProFormDependency name={['name']}>
+                                {
+                                    ({ name }) => {
+                                        return (
+                                            <Form.Item wrapperCol={{span:12}}>
+                                                <ProFormDigit
+                                                    label="自定义天数"
+                                                    name="input-number"
+                                                    min={1}
+                                                    max={360}
+                                                    placeholder='请输入数字'
+                                                    fieldProps={{
+                                                         precision: 0,
+                                                         addonAfter:'天'
+                                                    }}
+                                                />
+                                            </Form.Item>
+                                        )
+                                    }
+                                }
+                            </ProFormDependency>
+                            <div className='bottomTip' dangerouslySetInnerHTML={{__html:'* 确定要给予选择的 <span>16个</span> 资质临时授,起止时间为<span>16个</span>到<span>16个</span>'}}></div>
+                        </>
+                    )
+                }
+
+            </KCModal>
+
+            <KCTable
+                columns={columns}
+                request={(params) => getTableData(params)}
+                rowKey='id'
+                toolbar={{
+                    actions: [
+                        <Button key="primary" onClick={() => showModalHandle('authorize')}>临时授权</Button>,
+                        <Button key="primary" type="primary" onClick={() => showModalHandle('review')}>院审批</Button>,
+                    ]
+                }}
+            />
+        </MQPageContainer>
+    );
+}

+ 17 - 0
src/pages/qualificationReview/style.less

@@ -0,0 +1,17 @@
+
+
+.QualificationApplicationModal {
+    .bottomTip {
+       font-size: 12px;
+       font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+       font-weight: 400;
+       color: #666F80;
+       span {
+           color: #FF8C1A;
+       }
+    }
+}
+
+.QualificationApplication {
+     
+}

+ 39 - 0
src/service/qualification.ts

@@ -0,0 +1,39 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-17 11:07:07
+ * @LastEditTime: 2022-02-21 09:27:29
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/service/qualification.ts
+ */
+
+
+
+import { request } from 'umi';
+
+//获取我申请的资质列表
+
+export type QualificationDataType = {
+      id:number;
+      qualificationNum: string,
+      qualificationName: string,
+      supportMaterial:string,
+      authorBasis:string,
+      qualificationType:string,
+      qualificationAudit:string,
+      qualificationStatus:number,
+      applyDate:string,
+}
+
+
+
+export const getMineQualifiApplyList = async (params:{}) => {
+    return request<{
+        list:QualificationDataType[],
+        totalCount:number,
+        current:number
+    }>('/api/getMineQualifiApply', {
+      method: 'GET',
+      params:params
+    });
+};

+ 26 - 0
src/typings.d.ts

@@ -0,0 +1,26 @@
+/*
+ * @Author: your name
+ * @Date: 2022-02-21 09:50:24
+ * @LastEditTime: 2022-02-21 09:50:25
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /MedicalQualificationMana/src/typings.d.ts
+ */
+
+
+export type TableRequestParamsType = {
+    //KCtable组件request params
+    pageSize?: number | undefined;
+    current?: number | undefined;
+    keyword?: string | undefined;
+    [key: string]: any;
+};
+
+export type TableResponseDataType = {
+    //KCtable组件response data
+    totalCount?: number | undefined;
+    pageSize?: number | undefined;
+    totalPage?: string | undefined;
+    current?: string | undefined;
+    [key: string]: any;
+};

+ 37 - 0
tsconfig.json

@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "target": "esnext",
+    "module": "esnext",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "importHelpers": true,
+    "jsx": "react-jsx",
+    "esModuleInterop": true,
+    "sourceMap": true,
+    "baseUrl": "./",
+    "strict": true,
+    "paths": {
+      "@/*": ["src/*"],
+      "@@/*": ["src/.umi/*"]
+    },
+    "allowSyntheticDefaultImports": true
+  },
+  "include": [
+    "mock/**/*",
+    "src/**/*",
+    "config/**/*",
+    ".umirc.ts",
+    "typings.d.ts"
+  ],
+  "exclude": [
+    "node_modules",
+    "lib",
+    "es",
+    "dist",
+    "typings",
+    "**/__test__",
+    "test",
+    "docs",
+    "tests"
+  ]
+}

+ 10 - 0
typings.d.ts

@@ -0,0 +1,10 @@
+declare module '*.css';
+declare module '*.less';
+declare module '*.png';
+declare module '*.svg' {
+  export function ReactComponent(
+    props: React.SVGProps<SVGSVGElement>,
+  ): React.ReactElement;
+  const url: string;
+  export default url;
+}