Przeglądaj źródła

fix: request相关工具构建

lanjianrong 4 lat temu
rodzic
commit
6532570bfd

+ 1 - 0
.eslintrc.js

@@ -13,6 +13,7 @@ module.exports = {
     'comma-dangle': [2, 'never'],
     'react/prop-types': 0,
     'spaced-comment': 'error',
+    'react/no-array-index-key': 0,
     // 'array-bracket-spacing': ['error', 'always'], // 和prettier冲突
     'object-curly-spacing': ['error', 'always'],
     // 'no-use-before-define': ['error', { functions: false }], // 允许在未定义function前调用

+ 1 - 0
config/config.ts

@@ -34,6 +34,7 @@ export default defineConfig({
   targets: {
     ie: 11
   },
+  // request: { dataField: 'data' },
   // umi routes: https://umijs.org/docs/routing
   routes,
   // Theme for antd: https://ant.design/docs/react/customize-theme-cn

+ 0 - 593
config/oneapi.json

@@ -1,593 +0,0 @@
-{
-  "openapi": "3.0.1",
-  "info": {
-    "title": "Ant Design Pro",
-    "version": "1.0.0"
-  },
-  "servers": [
-    {
-      "url": "http://localhost:8000/"
-    },
-    {
-      "url": "https://localhost:8000/"
-    }
-  ],
-  "paths": {
-    "/api/currentUser": {
-      "get": {
-        "tags": ["api"],
-        "description": "获取当前的用户",
-        "operationId": "currentUser",
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/CurrentUser"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "x-swagger-router-controller": "api"
-    },
-    "/api/login/captcha": {
-      "post": {
-        "description": "发送验证码",
-        "operationId": "getFakeCaptcha",
-        "tags": ["login"],
-        "parameters": [
-          {
-            "name": "phone",
-            "in": "query",
-            "description": "手机号",
-            "schema": {
-              "type": "string"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/FakeCaptcha"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/api/login/outLogin": {
-      "post": {
-        "description": "登录接口",
-        "operationId": "outLogin",
-        "tags": ["login"],
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "object"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "x-swagger-router-controller": "api"
-    },
-    "/api/login/account": {
-      "post": {
-        "tags": ["login"],
-        "description": "登录接口",
-        "operationId": "login",
-        "requestBody": {
-          "description": "登录系统",
-          "content": {
-            "application/json": {
-              "schema": {
-                "$ref": "#/components/schemas/LoginParams"
-              }
-            }
-          },
-          "required": true
-        },
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/LoginResult"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        },
-        "x-codegen-request-body-name": "body"
-      },
-      "x-swagger-router-controller": "api"
-    },
-    "/api/notices": {
-      "summary": "getNotices",
-      "description": "NoticeIconItem",
-      "get": {
-        "tags": ["api"],
-        "operationId": "getNotices",
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/NoticeIconList"
-                }
-              }
-            }
-          }
-        }
-      }
-    },
-    "/api/rule": {
-      "get": {
-        "tags": ["rule"],
-        "description": "获取规则列表",
-        "operationId": "rule",
-        "parameters": [
-          {
-            "name": "current",
-            "in": "query",
-            "description": "当前的页码",
-            "schema": {
-              "type": "number"
-            }
-          },
-          {
-            "name": "pageSize",
-            "in": "query",
-            "description": "页面的容量",
-            "schema": {
-              "type": "number"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/RuleList"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "post": {
-        "tags": ["rule"],
-        "description": "新建规则",
-        "operationId": "addRule",
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/RuleListItem"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "put": {
-        "tags": ["rule"],
-        "description": "新建规则",
-        "operationId": "updateRule",
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/RuleListItem"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "delete": {
-        "tags": ["rule"],
-        "description": "删除规则",
-        "operationId": "removeRule",
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "object"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "Error",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/ErrorResponse"
-                }
-              }
-            }
-          }
-        }
-      },
-      "x-swagger-router-controller": "api"
-    },
-    "/swagger": {
-      "x-swagger-pipe": "swagger_raw"
-    }
-  },
-  "components": {
-    "schemas": {
-      "CurrentUser": {
-        "type": "object",
-        "properties": {
-          "name": {
-            "type": "string"
-          },
-          "avatar": {
-            "type": "string"
-          },
-          "userid": {
-            "type": "string"
-          },
-          "email": {
-            "type": "string"
-          },
-          "signature": {
-            "type": "string"
-          },
-          "title": {
-            "type": "string"
-          },
-          "group": {
-            "type": "string"
-          },
-          "tags": {
-            "type": "array",
-            "items": {
-              "type": "object",
-              "properties": {
-                "key": {
-                  "type": "string"
-                },
-                "label": {
-                  "type": "string"
-                }
-              }
-            }
-          },
-          "notifyCount": {
-            "type": "integer",
-            "format": "int32"
-          },
-          "unreadCount": {
-            "type": "integer",
-            "format": "int32"
-          },
-          "country": {
-            "type": "string"
-          },
-          "access": {
-            "type": "string"
-          },
-          "geographic": {
-            "type": "object",
-            "properties": {
-              "province": {
-                "type": "object",
-                "properties": {
-                  "label": {
-                    "type": "string"
-                  },
-                  "key": {
-                    "type": "string"
-                  }
-                }
-              },
-              "city": {
-                "type": "object",
-                "properties": {
-                  "label": {
-                    "type": "string"
-                  },
-                  "key": {
-                    "type": "string"
-                  }
-                }
-              }
-            }
-          },
-          "address": {
-            "type": "string"
-          },
-          "phone": {
-            "type": "string"
-          }
-        }
-      },
-      "LoginResult": {
-        "type": "object",
-        "properties": {
-          "status": {
-            "type": "string"
-          },
-          "type": {
-            "type": "string"
-          },
-          "currentAuthority": {
-            "type": "string"
-          }
-        }
-      },
-      "PageParams": {
-        "type": "object",
-        "properties": {
-          "current": {
-            "type": "number"
-          },
-          "pageSize": {
-            "type": "number"
-          }
-        }
-      },
-      "RuleListItem": {
-        "type": "object",
-        "properties": {
-          "key": {
-            "type": "integer",
-            "format": "int32"
-          },
-          "disabled": {
-            "type": "boolean"
-          },
-          "href": {
-            "type": "string"
-          },
-          "avatar": {
-            "type": "string"
-          },
-          "name": {
-            "type": "string"
-          },
-          "owner": {
-            "type": "string"
-          },
-          "desc": {
-            "type": "string"
-          },
-          "callNo": {
-            "type": "integer",
-            "format": "int32"
-          },
-          "status": {
-            "type": "integer",
-            "format": "int32"
-          },
-          "updatedAt": {
-            "type": "string",
-            "format": "datetime"
-          },
-          "createdAt": {
-            "type": "string",
-            "format": "datetime"
-          },
-          "progress": {
-            "type": "integer",
-            "format": "int32"
-          }
-        }
-      },
-      "RuleList": {
-        "type": "object",
-        "properties": {
-          "data": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/RuleListItem"
-            }
-          },
-          "total": {
-            "type": "integer",
-            "description": "列表的内容总数",
-            "format": "int32"
-          },
-          "success": {
-            "type": "boolean"
-          }
-        }
-      },
-      "FakeCaptcha": {
-        "type": "object",
-        "properties": {
-          "code": {
-            "type": "integer",
-            "format": "int32"
-          },
-          "status": {
-            "type": "string"
-          }
-        }
-      },
-      "LoginParams": {
-        "type": "object",
-        "properties": {
-          "username": {
-            "type": "string"
-          },
-          "password": {
-            "type": "string"
-          },
-          "autoLogin": {
-            "type": "boolean"
-          },
-          "type": {
-            "type": "string"
-          }
-        }
-      },
-      "ErrorResponse": {
-        "required": ["errorCode"],
-        "type": "object",
-        "properties": {
-          "errorCode": {
-            "type": "string",
-            "description": "业务约定的错误码"
-          },
-          "errorMessage": {
-            "type": "string",
-            "description": "业务上的错误信息"
-          },
-          "success": {
-            "type": "boolean",
-            "description": "业务上的请求是否成功"
-          }
-        }
-      },
-      "NoticeIconList": {
-        "type": "object",
-        "properties": {
-          "data": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/NoticeIconItem"
-            }
-          },
-          "total": {
-            "type": "integer",
-            "description": "列表的内容总数",
-            "format": "int32"
-          },
-          "success": {
-            "type": "boolean"
-          }
-        }
-      },
-      "NoticeIconItemType": {
-        "title": "NoticeIconItemType",
-        "description": "已读未读列表的枚举",
-        "type": "string",
-        "properties": {},
-        "enum": ["notification", "message", "event"]
-      },
-      "NoticeIconItem": {
-        "type": "object",
-        "properties": {
-          "id": {
-            "type": "string"
-          },
-          "extra": {
-            "type": "string",
-            "format": "any"
-          },
-          "key": { "type": "string" },
-          "read": {
-            "type": "boolean"
-          },
-          "avatar": {
-            "type": "string"
-          },
-          "title": {
-            "type": "string"
-          },
-          "status": {
-            "type": "string"
-          },
-          "datetime": {
-            "type": "string",
-            "format": "date"
-          },
-          "description": {
-            "type": "string"
-          },
-          "type": {
-            "extensions": {
-              "x-is-enum": true
-            },
-            "$ref": "#/components/schemas/NoticeIconItemType"
-          }
-        }
-      }
-    }
-  }
-}

+ 12 - 11
config/routes.ts

@@ -9,17 +9,17 @@
           {
             name: 'login',
             path: '/user/login',
-            component: './user/Login',
-          },
-        ],
-      },
-    ],
+            component: './user/Login'
+          }
+        ]
+      }
+    ]
   },
   {
     path: '/welcome',
     name: 'welcome',
     icon: 'HomeOutlined',
-    component: './Welcome',
+    component: './Welcome'
   },
   {
     path: '/role',
@@ -34,14 +34,15 @@
         path: '/role/system',
         name: 'system',
         component: './Role/System',
+        auth: ['admin', 'system']
       },
       {
         path: '/role/customer',
         name: 'customer',
-        component: './Role/Customer',
-      },
-    ],
-  },
+        component: './Role/Customer'
+      }
+    ]
+  }
   // {
   //   path: '/admin',
   //   name: 'admin',
@@ -70,4 +71,4 @@
   // {
   //   component: './404',
   // },
-];
+]

+ 4 - 3
package.json

@@ -1,6 +1,6 @@
 {
-  "name": "ant-design-pro",
-  "version": "5.0.0-beta.2",
+  "name": "cldv2_console",
+  "version": "0.0.1",
   "private": true,
   "description": "An out-of-box UI solution for enterprise applications",
   "scripts": {
@@ -55,6 +55,7 @@
     "@umijs/openapi": "^1.1.14",
     "@umijs/plugin-openapi": "^1.2.0",
     "@umijs/route-utils": "^1.0.36",
+    "ahooks": "^2.10.4",
     "antd": "^4.14.0",
     "classnames": "^2.2.6",
     "lodash": "^4.17.11",
@@ -65,7 +66,7 @@
     "react-dom": "^17.0.0",
     "react-helmet-async": "^1.0.4",
     "umi": "^3.4.0",
-    "umi-request": "^1.0.8"
+    "umi-request": "^1.3.9"
   },
   "devDependencies": {
     "@ant-design/pro-cli": "^2.0.2",

+ 45 - 10
src/app.tsx

@@ -5,8 +5,8 @@ import type { RequestConfig, RunTimeLayoutConfig } from 'umi'
 import { getIntl, getLocale, history, Link } from 'umi'
 import RightContent from '@/components/RightContent'
 import Footer from '@/components/Footer'
-import type { ResponseError } from 'umi-request'
-import { currentUser as queryCurrentUser } from './services/ant-design-pro/api'
+import type { RequestOptionsInit, ResponseError } from 'umi-request'
+import { currentUser as queryCurrentUser } from './services/user/api'
 import { BookOutlined, LinkOutlined } from '@ant-design/icons'
 
 const isDev = process.env.NODE_ENV === 'development'
@@ -25,9 +25,11 @@ export async function getInitialState(): Promise<{
   currentUser?: API.CurrentUser
   fetchUserInfo?: () => Promise<API.CurrentUser | undefined>
 }> {
+  // eslint-disable-next-line react-hooks/rules-of-hooks
   const fetchUserInfo = async () => {
     try {
       const currentUser = await queryCurrentUser()
+
       return currentUser
     } catch (error) {
       history.push(loginPath)
@@ -39,7 +41,7 @@ export async function getInitialState(): Promise<{
     const currentUser = await fetchUserInfo()
     return {
       fetchUserInfo,
-      currentUser,
+      currentUser: currentUser.data,
       settings: {}
     }
   }
@@ -49,6 +51,15 @@ export async function getInitialState(): Promise<{
   }
 }
 
+const authHeaderInterceptor = (url: string, options: RequestOptionsInit) => {
+  const token = window.localStorage.getItem('TOKEN_ID')
+  const authHeader = { Authorization: `Bearer ${JSON.parse(token)}` }
+  return {
+    url: `${url}`,
+    options: { ...options, interceptors: true, headers: authHeader }
+  }
+}
+
 /**
  * 异常处理程序
  const codeMessage = {
@@ -95,19 +106,43 @@ export const request: RequestConfig = {
     }
     throw error
   },
+  middlewares: [
+    // async (ctx, next) => {
+    //   await next()
+    //   const { req, res } = ctx
+    //   // @ts-ignore
+    //   if (req.options?.skipErrorHandler) {
+    //     return
+    //   }
+    //   const errorAdaptor = req.options?.errorConfig.adaptor || (resData => resData)
+    //   const { options } = req
+    //   const { getResponse } = options
+    //   const resData = getResponse ? res.data : res
+    //   const errorInfo = errorAdaptor(resData, ctx)
+    //   if (errorInfo.success === false) {
+    //     // 抛出错误到 errorHandler 中处理
+    //     const error: RequestError = new Error(errorInfo.errorMessage)
+    //     error.name = 'BizError'
+    //     error.data = resData
+    //     error.info = errorInfo
+    //     error.response = res
+    //     throw error
+    //   }
+    // }
+  ],
   prefix: '/backstage',
   errorConfig: {
     adaptor: resData => {
       return {
-        ...resData,
-        success: resData.code === 0,
+        success: true,
+        data: resData.data,
+        errorCode: resData.code,
         errorMessage: resData.msg
       }
     }
-  }
-  // requestInterceptors: [(url, options) => {
-  //   return { url, options: { ...options, prefix: '/api'}}
-  // }]
+  },
+  responseInterceptors: [],
+  requestInterceptors: [authHeaderInterceptor]
 }
 
 // ProLayout 支持的api https://procomponents.ant.design/components/layout
@@ -116,7 +151,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
     rightContentRender: () => <RightContent />,
     disableContentMargin: false,
     waterMarkProps: {
-      content: initialState?.currentUser?.name
+      content: initialState?.currentUser?.username
     },
     footerRender: () => <Footer />,
     onPageChange: () => {

+ 62 - 64
src/components/NoticeIcon/index.tsx

@@ -1,33 +1,33 @@
-import { useEffect, useState } from 'react';
-import { Tag, message } from 'antd';
-import { groupBy } from 'lodash';
-import moment from 'moment';
-import { useModel } from 'umi';
-import { getNotices } from '@/services/ant-design-pro/api';
+import { useEffect, useState } from 'react'
+import { Tag, message } from 'antd'
+import { groupBy } from 'lodash'
+import moment from 'moment'
+import { useModel } from 'umi'
+import { getNotices } from '@/services/user/api'
 
-import NoticeIcon from './NoticeIcon';
-import styles from './index.less';
+import NoticeIcon from './NoticeIcon'
+import styles from './index.less'
 
 export type GlobalHeaderRightProps = {
-  fetchingNotices?: boolean;
-  onNoticeVisibleChange?: (visible: boolean) => void;
-  onNoticeClear?: (tabName?: string) => void;
-};
+  fetchingNotices?: boolean
+  onNoticeVisibleChange?: (visible: boolean) => void
+  onNoticeClear?: (tabName?: string) => void
+}
 
 const getNoticeData = (notices: API.NoticeIconItem[]): Record<string, API.NoticeIconItem[]> => {
   if (!notices || notices.length === 0 || !Array.isArray(notices)) {
-    return {};
+    return {}
   }
 
-  const newNotices = notices.map((notice) => {
-    const newNotice = { ...notice };
+  const newNotices = notices.map(notice => {
+    const newNotice = { ...notice }
 
     if (newNotice.datetime) {
-      newNotice.datetime = moment(notice.datetime as string).fromNow();
+      newNotice.datetime = moment(notice.datetime as string).fromNow()
     }
 
     if (newNotice.id) {
-      newNotice.key = newNotice.id;
+      newNotice.key = newNotice.id
     }
 
     if (newNotice.extra && newNotice.status) {
@@ -35,92 +35,90 @@ const getNoticeData = (notices: API.NoticeIconItem[]): Record<string, API.Notice
         todo: '',
         processing: 'blue',
         urgent: 'red',
-        doing: 'gold',
-      }[newNotice.status];
+        doing: 'gold'
+      }[newNotice.status]
       newNotice.extra = (
         <Tag
           color={color}
           style={{
-            marginRight: 0,
-          }}
-        >
+            marginRight: 0
+          }}>
           {newNotice.extra}
         </Tag>
-      ) as any;
+      ) as any
     }
 
-    return newNotice;
-  });
-  return groupBy(newNotices, 'type');
-};
+    return newNotice
+  })
+  return groupBy(newNotices, 'type')
+}
 
 const getUnreadData = (noticeData: Record<string, API.NoticeIconItem[]>) => {
-  const unreadMsg: Record<string, number> = {};
-  Object.keys(noticeData).forEach((key) => {
-    const value = noticeData[key];
+  const unreadMsg: Record<string, number> = {}
+  Object.keys(noticeData).forEach(key => {
+    const value = noticeData[key]
 
     if (!unreadMsg[key]) {
-      unreadMsg[key] = 0;
+      unreadMsg[key] = 0
     }
 
     if (Array.isArray(value)) {
-      unreadMsg[key] = value.filter((item) => !item.read).length;
+      unreadMsg[key] = value.filter(item => !item.read).length
     }
-  });
-  return unreadMsg;
-};
+  })
+  return unreadMsg
+}
 
 const NoticeIconView = () => {
-  const { initialState } = useModel('@@initialState');
-  const { currentUser } = initialState || {};
-  const [notices, setNotices] = useState<API.NoticeIconItem[]>([]);
+  const { initialState } = useModel('@@initialState')
+  const { currentUser } = initialState || {}
+  const [notices, setNotices] = useState<API.NoticeIconItem[]>([])
 
   useEffect(() => {
-    getNotices().then(({ data }) => setNotices(data || []));
-  }, []);
+    getNotices().then(({ data }) => setNotices(data || []))
+  }, [])
 
-  const noticeData = getNoticeData(notices);
-  const unreadMsg = getUnreadData(noticeData || {});
+  const noticeData = getNoticeData(notices)
+  const unreadMsg = getUnreadData(noticeData || {})
 
   const changeReadState = (id: string) => {
     setNotices(
-      notices.map((item) => {
-        const notice = { ...item };
+      notices.map(item => {
+        const notice = { ...item }
         if (notice.id === id) {
-          notice.read = true;
+          notice.read = true
         }
-        return notice;
-      }),
-    );
-  };
+        return notice
+      })
+    )
+  }
 
   const clearReadState = (title: string, key: string) => {
     setNotices(
-      notices.map((item) => {
-        const notice = { ...item };
+      notices.map(item => {
+        const notice = { ...item }
         if (notice.type === key) {
-          notice.read = true;
+          notice.read = true
         }
-        return notice;
-      }),
-    );
-    message.success(`${'清空了'} ${title}`);
-  };
+        return notice
+      })
+    )
+    message.success(`${'清空了'} ${title}`)
+  }
 
   return (
     <NoticeIcon
       className={styles.action}
       count={currentUser && currentUser.unreadCount}
-      onItemClick={(item) => {
-        changeReadState(item.id!);
+      onItemClick={item => {
+        changeReadState(item.id!)
       }}
       onClear={(title: string, key: string) => clearReadState(title, key)}
       loading={false}
       clearText="清空"
       viewMoreText="查看更多"
       onViewMore={() => message.info('Click on view more')}
-      clearClose
-    >
+      clearClose>
       <NoticeIcon.Tab
         tabKey="notification"
         count={unreadMsg.notification}
@@ -146,7 +144,7 @@ const NoticeIconView = () => {
         showViewMore
       />
     </NoticeIcon>
-  );
-};
+  )
+}
 
-export default NoticeIconView;
+export default NoticeIconView

+ 48 - 41
src/components/RightContent/AvatarDropdown.tsx

@@ -1,54 +1,54 @@
-import React, { useCallback } from 'react';
-import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
-import { Avatar, Menu, Spin } from 'antd';
-import { history, useModel } from 'umi';
-import { stringify } from 'querystring';
-import HeaderDropdown from '../HeaderDropdown';
-import styles from './index.less';
-import { outLogin } from '@/services/ant-design-pro/api';
+import React, { useCallback } from 'react'
+import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons'
+import { Avatar, Menu, Spin } from 'antd'
+import { history, useModel } from 'umi'
+import { stringify } from 'querystring'
+import HeaderDropdown from '../HeaderDropdown'
+import styles from './index.less'
+import { outLogin } from '@/services/user/api'
 
 export type GlobalHeaderRightProps = {
-  menu?: boolean;
-};
+  menu?: boolean
+}
 
 /**
  * 退出登录,并且将当前的 url 保存
  */
 const loginOut = async () => {
-  await outLogin();
-  const { query = {}, pathname } = history.location;
-  const { redirect } = query;
+  await outLogin()
+  const { query = {}, pathname } = history.location
+  const { redirect } = query
   // Note: There may be security issues, please note
   if (window.location.pathname !== '/user/login' && !redirect) {
     history.replace({
       pathname: '/user/login',
       search: stringify({
-        redirect: pathname,
-      }),
-    });
+        redirect: pathname
+      })
+    })
   }
-};
+}
 
 const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
-  const { initialState, setInitialState } = useModel('@@initialState');
+  const { initialState, setInitialState } = useModel('@@initialState')
 
   const onMenuClick = useCallback(
     (event: {
-      key: React.Key;
-      keyPath: React.Key[];
-      item: React.ReactInstance;
-      domEvent: React.MouseEvent<HTMLElement>;
+      key: React.Key
+      keyPath: React.Key[]
+      item: React.ReactInstance
+      domEvent: React.MouseEvent<HTMLElement>
     }) => {
-      const { key } = event;
+      const { key } = event
       if (key === 'logout' && initialState) {
-        setInitialState({ ...initialState, currentUser: undefined });
-        loginOut();
-        return;
+        setInitialState({ ...initialState, currentUser: undefined })
+        loginOut()
+        return
       }
-      history.push(`/account/${key}`);
+      history.push(`/account/${key}`)
     },
-    [initialState, setInitialState],
-  );
+    [initialState, setInitialState]
+  )
 
   const loading = (
     <span className={`${styles.action} ${styles.account}`}>
@@ -56,20 +56,20 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
         size="small"
         style={{
           marginLeft: 8,
-          marginRight: 8,
+          marginRight: 8
         }}
       />
     </span>
-  );
+  )
 
   if (!initialState) {
-    return loading;
+    return loading
   }
 
-  const { currentUser } = initialState;
+  const { currentUser } = initialState
 
-  if (!currentUser || !currentUser.name) {
-    return loading;
+  if (!currentUser || !currentUser.staffId) {
+    return loading
   }
 
   const menuHeaderDropdown = (
@@ -93,15 +93,22 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
         退出登录
       </Menu.Item>
     </Menu>
-  );
+  )
+  console.log(`http://cld.smartcost.com.cn${currentUser.avatar}_2.jpg`)
+
   return (
     <HeaderDropdown overlay={menuHeaderDropdown}>
       <span className={`${styles.action} ${styles.account}`}>
-        <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
-        <span className={`${styles.name} anticon`}>{currentUser.name}</span>
+        <Avatar
+          size="small"
+          className={styles.avatar}
+          src={`http://cld.smartcost.com.cn${currentUser.avatar}_2.jpg`}
+          alt="avatar"
+        />
+        <span className={`${styles.name} anticon`}>{currentUser.username}</span>
       </span>
     </HeaderDropdown>
-  );
-};
+  )
+}
 
-export default AvatarDropdown;
+export default AvatarDropdown

+ 11 - 0
src/models/user.ts

@@ -0,0 +1,11 @@
+import { useLocalStorageState } from 'ahooks'
+// import { history } from 'umi'
+
+export default () => {
+  const [, setTokenId] = useLocalStorageState('TOKEN_ID')
+  function setAuthToken(t: string) {
+    setTokenId(t)
+  }
+
+  return { setAuthToken }
+}

+ 1 - 1
src/pages/TableList/index.tsx

@@ -10,7 +10,7 @@ import type { ProDescriptionsItemProps } from '@ant-design/pro-descriptions'
 import ProDescriptions from '@ant-design/pro-descriptions'
 import type { FormValueType } from './components/UpdateForm'
 import UpdateForm from './components/UpdateForm'
-import { rule, addRule, updateRule, removeRule } from '@/services/ant-design-pro/api'
+import { rule, addRule, updateRule, removeRule } from '@/services/user/api'
 
 /**
  * 添加节点

+ 14 - 33
src/pages/user/Login/index.tsx

@@ -11,10 +11,11 @@ import React, { useState } from 'react'
 import ProForm, { ProFormCheckbox, ProFormText } from '@ant-design/pro-form'
 import { useIntl, Link, history, FormattedMessage, SelectLang, useModel } from 'umi'
 import Footer from '@/components/Footer'
-import { login } from '@/services/user'
+import { login } from '@/services/user/api'
 // import { getFakeCaptcha } from '@/services/ant-design-pro/login'
 
 import styles from './index.less'
+import consts from '@/utils/consts'
 
 const LoginMessage: React.FC<{
   content: string
@@ -40,6 +41,7 @@ const goto = () => {
 }
 
 const Login: React.FC = () => {
+  const { setAuthToken } = useModel('user')
   const [submitting, setSubmitting] = useState(false)
   const [userLoginState, setUserLoginState] = useState<API.LoginResult>({})
   const [type, setType] = useState<string>('account')
@@ -52,7 +54,7 @@ const Login: React.FC = () => {
     if (userInfo) {
       setInitialState({
         ...initialState,
-        currentUser: userInfo
+        currentUser: userInfo.data
       })
     }
   }
@@ -61,30 +63,22 @@ const Login: React.FC = () => {
     setSubmitting(true)
     try {
       // 登录
-      const msg = await login({ ...values, type })
-
-      if (msg.status === 'ok') {
-        const defaultloginSuccessMessage = intl.formatMessage({
-          id: 'pages.login.success',
-          defaultMessage: '登录成功'
-        })
-        message.success(defaultloginSuccessMessage)
+      const res = await login({ ...values, type })
+      if (res?.code === consts.RET_CODE.SUCCESS) {
+        setAuthToken(res.data.token)
+        message.success('登录成功')
         await fetchUserInfo()
         goto()
         return
       }
       // 如果失败去设置用户错误信息
-      setUserLoginState(msg)
+      setUserLoginState(res.data)
     } catch (error) {
-      // const defaultloginFailureMessage = intl.formatMessage({
-      //   id: 'pages.login.failure',
-      //   defaultMessage: '登录失败,请重试!'
-      // })
-      // message.error(defaultloginFailureMessage)
+      message.error('登录失败,请重试')
     }
     setSubmitting(false)
   }
-  const { status, type: loginType } = userLoginState
+  const { code } = userLoginState
 
   return (
     <div className={styles.container}>
@@ -143,14 +137,7 @@ const Login: React.FC = () => {
               /> */}
             </Tabs>
 
-            {status === 'error' && loginType === 'account' && (
-              <LoginMessage
-                content={intl.formatMessage({
-                  id: 'pages.login.accountLogin.errorMessage',
-                  defaultMessage: '账户或密码错误(admin/ant.design)'
-                })}
-              />
-            )}
+            {code === consts.RET_CODE.ERROR && <LoginMessage content={'账户或密码错误'} />}
             {type === 'account' && (
               <>
                 <ProFormText
@@ -159,10 +146,7 @@ const Login: React.FC = () => {
                     size: 'large',
                     prefix: <UserOutlined className={styles.prefixIcon} />
                   }}
-                  placeholder={intl.formatMessage({
-                    id: 'pages.login.username.placeholder',
-                    defaultMessage: '用户名: admin or user'
-                  })}
+                  placeholder="用户名:"
                   rules={[
                     {
                       required: true,
@@ -181,10 +165,7 @@ const Login: React.FC = () => {
                     size: 'large',
                     prefix: <LockOutlined className={styles.prefixIcon} />
                   }}
-                  placeholder={intl.formatMessage({
-                    id: 'pages.login.password.placeholder',
-                    defaultMessage: '密码: ant.design'
-                  })}
+                  placeholder="密码:"
                   rules={[
                     {
                       required: true,

+ 0 - 83
src/services/ant-design-pro/api.ts

@@ -1,83 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-import { request } from 'umi';
-
-/** 获取当前的用户 GET /api/currentUser */
-export async function currentUser(options?: { [key: string]: any }) {
-  return request<API.CurrentUser>('/api/currentUser', {
-    method: 'GET',
-    ...(options || {}),
-  });
-}
-
-/** 退出登录接口 POST /api/login/outLogin */
-export async function outLogin(options?: { [key: string]: any }) {
-  return request<Record<string, any>>('/api/login/outLogin', {
-    method: 'POST',
-    ...(options || {}),
-  });
-}
-
-/** 登录接口 POST /api/login/account */
-export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
-  return request<API.LoginResult>('/api/login/account', {
-    method: 'POST',
-    headers: {
-      'Content-Type': 'application/json',
-    },
-    data: body,
-    ...(options || {}),
-  });
-}
-
-/** 此处后端没有提供注释 GET /api/notices */
-export async function getNotices(options?: { [key: string]: any }) {
-  return request<API.NoticeIconList>('/api/notices', {
-    method: 'GET',
-    ...(options || {}),
-  });
-}
-
-/** 获取规则列表 GET /api/rule */
-export async function rule(
-  params: {
-    // query
-    /** 当前的页码 */
-    current?: number;
-    /** 页面的容量 */
-    pageSize?: number;
-  },
-  options?: { [key: string]: any },
-) {
-  return request<API.RuleList>('/api/rule', {
-    method: 'GET',
-    params: {
-      ...params,
-    },
-    ...(options || {}),
-  });
-}
-
-/** 新建规则 PUT /api/rule */
-export async function updateRule(options?: { [key: string]: any }) {
-  return request<API.RuleListItem>('/api/rule', {
-    method: 'PUT',
-    ...(options || {}),
-  });
-}
-
-/** 新建规则 POST /api/rule */
-export async function addRule(options?: { [key: string]: any }) {
-  return request<API.RuleListItem>('/api/rule', {
-    method: 'POST',
-    ...(options || {}),
-  });
-}
-
-/** 删除规则 DELETE /api/rule */
-export async function removeRule(options?: { [key: string]: any }) {
-  return request<Record<string, any>>('/api/rule', {
-    method: 'DELETE',
-    ...(options || {}),
-  });
-}

+ 0 - 21
src/services/ant-design-pro/login.ts

@@ -1,21 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-import { request } from 'umi';
-
-/** 发送验证码 POST /api/login/captcha */
-export async function getFakeCaptcha(
-  params: {
-    // query
-    /** 手机号 */
-    phone?: string;
-  },
-  options?: { [key: string]: any },
-) {
-  return request<API.FakeCaptcha>('/api/login/captcha', {
-    method: 'POST',
-    params: {
-      ...params,
-    },
-    ...(options || {}),
-  });
-}

+ 0 - 101
src/services/ant-design-pro/typings.d.ts

@@ -1,101 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-
-declare namespace API {
-  type CurrentUser = {
-    name?: string;
-    avatar?: string;
-    userid?: string;
-    email?: string;
-    signature?: string;
-    title?: string;
-    group?: string;
-    tags?: { key?: string; label?: string }[];
-    notifyCount?: number;
-    unreadCount?: number;
-    country?: string;
-    access?: string;
-    geographic?: {
-      province?: { label?: string; key?: string };
-      city?: { label?: string; key?: string };
-    };
-    address?: string;
-    phone?: string;
-  };
-
-  type LoginResult = {
-    status?: string;
-    type?: string;
-    currentAuthority?: string;
-  };
-
-  type PageParams = {
-    current?: number;
-    pageSize?: number;
-  };
-
-  type RuleListItem = {
-    key?: number;
-    disabled?: boolean;
-    href?: string;
-    avatar?: string;
-    name?: string;
-    owner?: string;
-    desc?: string;
-    callNo?: number;
-    status?: number;
-    updatedAt?: string;
-    createdAt?: string;
-    progress?: number;
-  };
-
-  type RuleList = {
-    data?: RuleListItem[];
-    /** 列表的内容总数 */
-    total?: number;
-    success?: boolean;
-  };
-
-  type FakeCaptcha = {
-    code?: number;
-    status?: string;
-  };
-
-  type LoginParams = {
-    username?: string;
-    password?: string;
-    autoLogin?: boolean;
-    type?: string;
-  };
-
-  type ErrorResponse = {
-    /** 业务约定的错误码 */
-    errorCode: string;
-    /** 业务上的错误信息 */
-    errorMessage?: string;
-    /** 业务上的请求是否成功 */
-    success?: boolean;
-  };
-
-  type NoticeIconList = {
-    data?: NoticeIconItem[];
-    /** 列表的内容总数 */
-    total?: number;
-    success?: boolean;
-  };
-
-  type NoticeIconItemType = 'notification' | 'message' | 'event';
-
-  type NoticeIconItem = {
-    id?: string;
-    extra?: string;
-    key?: string;
-    read?: boolean;
-    avatar?: string;
-    title?: string;
-    status?: string;
-    datetime?: string;
-    description?: string;
-    type?: NoticeIconItemType;
-  };
-}

+ 0 - 0
src/services/index.ts


+ 0 - 9
src/services/typings.d.ts

@@ -1,9 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-
-declare namespace API {
-  type User = {
-    username: string
-    account: string
-  }
-}

+ 0 - 28
src/services/user.ts

@@ -1,28 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-import { request } from 'umi'
-
-/** 获取当前的用户 GET /api/currentUser */
-export async function currentUser(options?: { [key: string]: any }) {
-  return request<API.CurrentUser>('/api/currentUser', {
-    method: 'GET',
-    ...(options || {})
-  })
-}
-
-/** 退出登录接口 POST /api/login/outLogin */
-export async function outLogin(options?: { [key: string]: any }) {
-  return request<Record<string, any>>('/outLogin', {
-    method: 'POST',
-    ...(options || {})
-  })
-}
-
-/** 登录接口 POST /api/login/account */
-export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
-  return request<API.LoginResult>('/login', {
-    method: 'POST',
-    data: body,
-    ...(options || {})
-  })
-}

+ 80 - 0
src/services/user/api.ts

@@ -0,0 +1,80 @@
+// @ts-ignore
+/* eslint-disable */
+import { request } from 'umi'
+
+/** 获取当前的用户 GET /backstage/currentUser */
+export async function currentUser(options?: { [key: string]: any }) {
+  return request<API.CurrentUser>('/login/currentUser', {
+    method: 'GET',
+    ...(options || {})
+  })
+}
+
+/** 退出登录接口 POST /login/outLogin */
+export async function outLogin(options?: { [key: string]: any }) {
+  return request<Record<string, any>>('/login/outLogin', {
+    method: 'POST',
+    ...(options || {})
+  })
+}
+
+/** 登录接口 POST /login */
+export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
+  return request<API.LoginResult>('/login', {
+    method: 'POST',
+    data: body,
+    ...(options || {})
+  })
+}
+
+/** 此处后端没有提供注释 GET /api/notices */
+// export async function getNotices(options?: { [key: string]: any }) {
+//   return request<API.NoticeIconList>('/api/notices', {
+//     method: 'GET',
+//     ...(options || {}),
+//   });
+// }
+
+/** 获取规则列表 GET /api/rule */
+export async function rule(
+  params: {
+    // query
+    /** 当前的页码 */
+    current?: number
+    /** 页面的容量 */
+    pageSize?: number
+  },
+  options?: { [key: string]: any }
+) {
+  return request<API.RuleList>('/api/rule', {
+    method: 'GET',
+    params: {
+      ...params
+    },
+    ...(options || {})
+  })
+}
+
+// /** 新建规则 PUT /api/rule */
+// export async function updateRule(options?: { [key: string]: any }) {
+//   return request<API.RuleListItem>('/api/rule', {
+//     method: 'PUT',
+//     ...(options || {}),
+//   });
+// }
+
+// /** 新建规则 POST /api/rule */
+// export async function addRule(options?: { [key: string]: any }) {
+//   return request<API.RuleListItem>('/api/rule', {
+//     method: 'POST',
+//     ...(options || {}),
+//   });
+// }
+
+// /** 删除规则 DELETE /api/rule */
+// export async function removeRule(options?: { [key: string]: any }) {
+//   return request<Record<string, any>>('/api/rule', {
+//     method: 'DELETE',
+//     ...(options || {}),
+//   });
+// }

+ 3 - 5
src/services/ant-design-pro/index.ts

@@ -2,9 +2,7 @@
 /* eslint-disable */
 // API 更新时间:
 // API 唯一标识:
-import * as api from './api';
-import * as login from './login';
+import * as login from './login'
 export default {
-  api,
-  login,
-};
+  login
+}

+ 95 - 0
src/services/user/typings.d.ts

@@ -0,0 +1,95 @@
+// @ts-ignore
+/* eslint-disable */
+
+declare namespace API {
+  type CurrentUser = {
+    staffId: string
+    categoryId: string
+    departmentId: string
+    departmentName: string
+    username: string
+    category: string
+    avatar: string
+    qq: string
+    qualifications: string
+    isAdmin: number
+  }
+
+  type LoginResult = {
+    code: number
+    msg: number
+    data?: {
+      token: string
+    }
+  }
+
+  type PageParams = {
+    current?: number
+    pageSize?: number
+  }
+
+  type RuleListItem = {
+    key?: number
+    disabled?: boolean
+    href?: string
+    avatar?: string
+    name?: string
+    owner?: string
+    desc?: string
+    callNo?: number
+    status?: number
+    updatedAt?: string
+    createdAt?: string
+    progress?: number
+  }
+
+  type RuleList = {
+    data?: RuleListItem[]
+    /** 列表的内容总数 */
+    total?: number
+    success?: boolean
+  }
+
+  type FakeCaptcha = {
+    code?: number
+    status?: string
+  }
+
+  type LoginParams = {
+    username?: string
+    password?: string
+    autoLogin?: boolean
+    type?: string
+  }
+
+  type ErrorResponse = {
+    /** 业务约定的错误码 */
+    errorCode: string
+    /** 业务上的错误信息 */
+    errorMessage?: string
+    /** 业务上的请求是否成功 */
+    success?: boolean
+  }
+
+  type NoticeIconList = {
+    data?: NoticeIconItem[]
+    /** 列表的内容总数 */
+    total?: number
+    success?: boolean
+  }
+
+  type NoticeIconItemType = 'notification' | 'message' | 'event'
+
+  type NoticeIconItem = {
+    id?: string
+    extra?: string
+    key?: string
+    read?: boolean
+    avatar?: string
+    title?: string
+    status?: string
+    datetime?: string
+    description?: string
+    type?: NoticeIconItemType
+  }
+}

+ 34 - 32
src/typings.d.ts

@@ -1,45 +1,47 @@
-declare module 'slash2';
-declare module '*.css';
-declare module '*.less';
-declare module '*.scss';
-declare module '*.sass';
-declare module '*.svg';
-declare module '*.png';
-declare module '*.jpg';
-declare module '*.jpeg';
-declare module '*.gif';
-declare module '*.bmp';
-declare module '*.tiff';
-declare module 'omit.js';
-declare module 'numeral';
-declare module '@antv/data-set';
-declare module 'mockjs';
-declare module 'react-fittext';
-declare module 'bizcharts-plugin-slider';
+declare module 'slash2'
+declare module '*.css'
+declare module '*.less'
+declare module '*.scss'
+declare module '*.sass'
+declare module '*.svg'
+declare module '*.png'
+declare module '*.jpg'
+declare module '*.jpeg'
+declare module '*.gif'
+declare module '*.bmp'
+declare module '*.tiff'
+declare module 'omit.js'
+declare module 'numeral'
+declare module '@antv/data-set'
+declare module 'mockjs'
+declare module 'react-fittext'
+declare module 'bizcharts-plugin-slider'
 
 // google analytics interface
 type GAFieldsObject = {
-  eventCategory: string;
-  eventAction: string;
-  eventLabel?: string;
-  eventValue?: number;
-  nonInteraction?: boolean;
-};
+  eventCategory: string
+  eventAction: string
+  eventLabel?: string
+  eventValue?: number
+  nonInteraction?: boolean
+}
 
 type Window = {
   ga: (
     command: 'send',
     hitType: 'event' | 'pageview',
-    fieldsObject: GAFieldsObject | string,
-  ) => void;
-  reloadAuthorized: () => void;
-  routerBase: string;
-};
+    fieldsObject: GAFieldsObject | string
+  ) => void
+  reloadAuthorized: () => void
+  routerBase: string
+}
 
-declare let ga: () => void;
+declare let ga: () => void
 
 // preview.pro.ant.design only do not use in your production ;
 // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
-declare let ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: 'site' | undefined;
+declare let ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: 'site' | undefined
 
-declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false;
+declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false
+
+declare type Nullable<T> = T | null

+ 3 - 0
src/utils/consts.ts

@@ -0,0 +1,3 @@
+export default {
+  RET_CODE: { SUCCESS: 0, ERROR: -1 }
+}

+ 10 - 9
src/utils/utils.ts

@@ -1,20 +1,21 @@
 /* eslint no-useless-escape:0 import/prefer-default-export:0 */
-const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
+const reg =
+  /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/
 
-export const isUrl = (path: string): boolean => reg.test(path);
+export const isUrl = (path: string): boolean => reg.test(path)
 
 export const isAntDesignPro = (): boolean => {
   if (ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') {
-    return true;
+    return true
   }
-  return window.location.hostname === 'preview.pro.ant.design';
-};
+  return window.location.hostname === 'preview.pro.ant.design'
+}
 
 // 给官方演示站点用,用于关闭真实开发环境不需要使用的特性
 export const isAntDesignProOrDev = (): boolean => {
-  const { NODE_ENV } = process.env;
+  const { NODE_ENV } = process.env
   if (NODE_ENV === 'development') {
-    return true;
+    return true
   }
-  return isAntDesignPro();
-};
+  return isAntDesignPro()
+}