Pārlūkot izejas kodu

feat: 初始化登录页

lanjianrong 4 gadi atpakaļ
vecāks
revīzija
8d81f2cf70

+ 3 - 3
.env

@@ -1,8 +1,8 @@
 # port
-VITE_PORT = 3100
+VITE_PORT = 3200
 
 # spa-title
-VITE_GLOB_APP_TITLE = Vben Admin
+VITE_GLOB_APP_TITLE = 项目管理后台系统
 
 # spa shortname
-VITE_GLOB_APP_SHORT_NAME = vue_vben_admin
+VITE_GLOB_APP_SHORT_NAME = construction_management_console

+ 5 - 5
.env.development

@@ -1,24 +1,24 @@
-VITE_PORT = 3100
+VITE_PORT = 3200
 
 # Whether to open mock
-VITE_USE_MOCK = true
+VITE_USE_MOCK = false
 
 # public path
 VITE_PUBLIC_PATH = /
 
 # Cross-domain proxy, you can configure multiple
 # Please note that no line breaks
-VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3001/upload"]]
+VITE_PROXY = [["/api","http://localhost:6060/api"], ["/upload", "http://localhost:7070/api/upload"]]
 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
 
 # Delete console
 VITE_DROP_CONSOLE = false
 
 # Basic interface address SPA
-VITE_GLOB_API_URL=/basic-api
+VITE_GLOB_API_URL=
 
 # File upload address, optional
 VITE_GLOB_UPLOAD_URL=/upload
 
 # Interface prefix
-VITE_GLOB_API_URL_PREFIX=
+VITE_GLOB_API_URL_PREFIX=/api

+ 23 - 15
.eslintrc.js

@@ -1,11 +1,11 @@
 // @ts-check
-const { defineConfig } = require('eslint-define-config');
+const { defineConfig } = require('eslint-define-config')
 module.exports = defineConfig({
   root: true,
   env: {
     browser: true,
     node: true,
-    es6: true,
+    es6: true
   },
   parser: 'vue-eslint-parser',
   parserOptions: {
@@ -14,16 +14,24 @@ module.exports = defineConfig({
     sourceType: 'module',
     jsxPragma: 'React',
     ecmaFeatures: {
-      jsx: true,
-    },
+      jsx: true
+    }
   },
   extends: [
     'plugin:vue/vue3-recommended',
     'plugin:@typescript-eslint/recommended',
     'prettier',
-    'plugin:prettier/recommended',
+    'plugin:prettier/recommended'
   ],
   rules: {
+    'prettier/prettier': [
+      'error',
+      {
+        semi: false,
+        trailingComma: 'none',
+        arrowParens: 'avoid'
+      }
+    ],
     '@typescript-eslint/ban-ts-ignore': 'off',
     '@typescript-eslint/explicit-function-return-type': 'off',
     '@typescript-eslint/no-explicit-any': 'off',
@@ -40,15 +48,15 @@ module.exports = defineConfig({
       'error',
       {
         argsIgnorePattern: '^_',
-        varsIgnorePattern: '^_',
-      },
+        varsIgnorePattern: '^_'
+      }
     ],
     'no-unused-vars': [
       'error',
       {
         argsIgnorePattern: '^_',
-        varsIgnorePattern: '^_',
-      },
+        varsIgnorePattern: '^_'
+      }
     ],
     'space-before-function-paren': 'off',
 
@@ -66,11 +74,11 @@ module.exports = defineConfig({
         html: {
           void: 'always',
           normal: 'never',
-          component: 'always',
+          component: 'always'
         },
         svg: 'always',
-        math: 'always',
-      },
-    ],
-  },
-});
+        math: 'always'
+      }
+    ]
+  }
+})

+ 4 - 1
.vscode/settings.json

@@ -102,9 +102,11 @@
   // ================ Eslint ===================
   // ===========================================
   "eslint.alwaysShowStatus": true,
+  "eslint.packageManager": "yarn",
   "eslint.options": {
     "plugins": ["html", "vue", "javascript", "jsx", "typescript"],
     "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
+    // "configFile": "C:\\Users\\12442\\AppData\\Local\\Yarn\\Data\\global\\node_modules\\.eslintrc.js"
   },
   "eslint.validate": [
     "javascript",
@@ -176,7 +178,8 @@
   },
   "[vue]": {
     "editor.codeActionsOnSave": {
-      "source.fixAll.eslint": false
+      "source.fixAll.eslint": true,
+      "source.fixAll.stylelint": true
     }
   },
   "i18n-ally.localesPaths": ["src/locales/lang"],

+ 0 - 21
LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2020-present, Vben
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 4 - 0
package.json

@@ -81,7 +81,11 @@
     "eslint": "^7.25.0",
     "eslint-config-prettier": "^8.2.0",
     "eslint-define-config": "^1.0.8",
+    "eslint-plugin-html": "^6.1.2",
+    "eslint-plugin-javascript": "^1.3.4",
+    "eslint-plugin-jsx": "^0.1.0",
     "eslint-plugin-prettier": "^3.4.0",
+    "eslint-plugin-typescript": "^0.14.0",
     "eslint-plugin-vue": "^7.9.0",
     "esno": "^0.5.0",
     "fs-extra": "^9.1.0",

+ 5 - 5
prettier.config.js

@@ -2,19 +2,19 @@ module.exports = {
   printWidth: 100,
   tabWidth: 2,
   useTabs: false,
-  semi: true,
+  semi: false,
   vueIndentScriptAndStyle: true,
   singleQuote: true,
   quoteProps: 'as-needed',
   bracketSpacing: true,
-  trailingComma: 'es5',
+  trailingComma: 'none',
   jsxBracketSameLine: false,
   jsxSingleQuote: false,
-  arrowParens: 'always',
+  arrowParens: 'avoid',
   insertPragma: false,
   requirePragma: false,
   proseWrap: 'never',
   htmlWhitespaceSensitivity: 'strict',
   endOfLine: 'lf',
-  rangeStart: 0,
-};
+  rangeStart: 0
+}

+ 26 - 17
src/api/sys/model/userModel.ts

@@ -2,42 +2,51 @@
  * @description: Login interface parameters
  */
 export interface LoginParams {
-  username: string;
-  password: string;
+  username: string
+  password: string
 }
 
 /**
  * @description: Get user information
  */
 export interface GetUserInfoByUserIdParams {
-  userId: string | number;
+  code: string | number
 }
 
 export interface RoleInfo {
-  roleName: string;
-  value: string;
+  roleName: string
+  value: string
 }
 
 /**
  * @description: Login interface return value
  */
 export interface LoginResultModel {
-  userId: string | number;
-  token: string;
-  role: RoleInfo;
+  userId: string | number
+  token: string
+  role: RoleInfo
 }
 
 /**
  * @description: Get user information return value
  */
 export interface GetUserInfoByUserIdModel {
-  roles: RoleInfo[];
-  // 用户id
-  userId: string | number;
-  // 用户名
-  username: string;
-  // 真实名字
-  realName: string;
-  // 介绍
-  desc?: string;
+  // roles: RoleInfo[]
+  id: string
+  projectId: string
+  bidsectionId: string
+  account: string
+  password: string
+  name: string
+  company: string
+  position: string
+  role: string
+  mobile: string
+  telephone: string
+  isAdmin: number
+  accountGroup: number
+  enable: number
+  contractPermission: string
+  qualityPermission: string
+  safePermission: string
 }

+ 30 - 15
src/api/sys/user.ts

@@ -1,32 +1,34 @@
-import { defHttp } from '/@/utils/http/axios';
+import { defHttp } from '/@/utils/http/axios'
 import {
   LoginParams,
-  LoginResultModel,
+  // LoginResultModel,
   GetUserInfoByUserIdParams,
-  GetUserInfoByUserIdModel,
-} from './model/userModel';
+  GetUserInfoByUserIdModel
+} from './model/userModel'
 
-import { ErrorMessageMode } from '/@/utils/http/axios/types';
+import { ErrorMessageMode } from '/@/utils/http/axios/types'
 
 enum Api {
-  Login = '/login',
-  GetUserInfoById = '/getUserInfoById',
+  Login = '/backstage/login',
+  Logout = '/backstage/out',
+  GetUserInfoById = '/login/project/name',
   GetPermCodeByUserId = '/getPermCodeByUserId',
+  GetToken = '/login/project/name'
 }
 
 /**
  * @description: user login api
  */
 export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') {
-  return defHttp.post<LoginResultModel>(
+  return defHttp.post<GetUserInfoByUserIdModel>(
     {
       url: Api.Login,
-      params,
+      params
     },
     {
-      errorMessageMode: mode,
+      errorMessageMode: mode
     }
-  );
+  )
 }
 
 /**
@@ -35,13 +37,26 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
 export function getUserInfoById(params: GetUserInfoByUserIdParams) {
   return defHttp.get<GetUserInfoByUserIdModel>({
     url: Api.GetUserInfoById,
-    params,
-  });
+    params
+  })
 }
 
 export function getPermCodeByUserId(params: GetUserInfoByUserIdParams) {
   return defHttp.get<string[]>({
     url: Api.GetPermCodeByUserId,
-    params,
-  });
+    params
+  })
+}
+
+export function getXsrfToken(code: string) {
+  return defHttp.get({
+    url: Api.GetToken,
+    params: { code }
+  })
+}
+
+export function logoutApi() {
+  return defHttp.post({
+    url: Api.Logout
+  })
 }

+ 0 - 28
src/router/routes/modules/about.ts

@@ -1,28 +0,0 @@
-import type { AppRouteModule } from '/@/router/types';
-
-import { LAYOUT } from '/@/router/constant';
-import { t } from '/@/hooks/web/useI18n';
-
-const dashboard: AppRouteModule = {
-  path: '/about',
-  name: 'About',
-  component: LAYOUT,
-  redirect: '/about/index',
-  meta: {
-    icon: 'simple-icons:about-dot-me',
-    title: t('routes.dashboard.about'),
-  },
-  children: [
-    {
-      path: 'index',
-      name: 'AboutPage',
-      component: () => import('/@/views/sys/about/index.vue'),
-      meta: {
-        title: t('routes.dashboard.about'),
-        icon: 'simple-icons:about-dot-me',
-      },
-    },
-  ],
-};
-
-export default dashboard;

+ 10 - 19
src/router/routes/modules/dashboard.ts

@@ -1,7 +1,7 @@
-import type { AppRouteModule } from '/@/router/types';
+import type { AppRouteModule } from '/@/router/types'
 
-import { LAYOUT } from '/@/router/constant';
-import { t } from '/@/hooks/web/useI18n';
+import { LAYOUT } from '/@/router/constant'
+import { t } from '/@/hooks/web/useI18n'
 
 const dashboard: AppRouteModule = {
   path: '/dashboard',
@@ -10,27 +10,18 @@ const dashboard: AppRouteModule = {
   redirect: '/dashboard/analysis',
   meta: {
     icon: 'ion:grid-outline',
-    title: t('routes.dashboard.dashboard'),
+    title: t('routes.dashboard.dashboard')
   },
   children: [
     {
-      path: 'analysis',
-      name: 'Analysis',
-      component: () => import('/@/views/dashboard/analysis/index.vue'),
-      meta: {
-        affix: true,
-        title: t('routes.dashboard.analysis'),
-      },
-    },
-    {
       path: 'workbench',
       name: 'Workbench',
       component: () => import('/@/views/dashboard/workbench/index.vue'),
       meta: {
-        title: t('routes.dashboard.workbench'),
-      },
-    },
-  ],
-};
+        title: t('routes.dashboard.workbench')
+      }
+    }
+  ]
+}
 
-export default dashboard;
+export default dashboard

+ 9 - 9
src/settings/designSetting.ts

@@ -1,8 +1,8 @@
-import { ThemeEnum } from '../enums/appEnum';
+import { ThemeEnum } from '../enums/appEnum'
 
-export const prefixCls = 'vben';
+export const prefixCls = 'zh'
 
-export const darkMode = ThemeEnum.LIGHT;
+export const darkMode = ThemeEnum.LIGHT
 
 // app theme preset color
 export const APP_PRESET_COLOR_LIST: string[] = [
@@ -14,8 +14,8 @@ export const APP_PRESET_COLOR_LIST: string[] = [
   '#ee4f12',
   '#0096c7',
   '#9c27b0',
-  '#ff9800',
-];
+  '#ff9800'
+]
 
 // header preset color
 export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
@@ -29,8 +29,8 @@ export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
   '#24292e',
   '#394664',
   '#001529',
-  '#383f45',
-];
+  '#383f45'
+]
 
 // sider preset color
 export const SIDE_BAR_BG_COLOR_LIST: string[] = [
@@ -44,5 +44,5 @@ export const SIDE_BAR_BG_COLOR_LIST: string[] = [
   '#001628',
   '#28333E',
   '#344058',
-  '#383f45',
-];
+  '#383f45'
+]

+ 70 - 62
src/store/modules/user.ts

@@ -1,30 +1,29 @@
-import type { UserInfo } from '/#/store';
-import type { ErrorMessageMode } from '/@/utils/http/axios/types';
+import type { UserInfo } from '/#/store'
+import type { ErrorMessageMode } from '/@/utils/http/axios/types'
+import { defineStore } from 'pinia'
+import { store } from '/@/store'
 
-import { defineStore } from 'pinia';
-import { store } from '/@/store';
+import { RoleEnum } from '/@/enums/roleEnum'
+import { PageEnum } from '/@/enums/pageEnum'
+import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum'
 
-import { RoleEnum } from '/@/enums/roleEnum';
-import { PageEnum } from '/@/enums/pageEnum';
-import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum';
-
-import { getAuthCache, setAuthCache } from '/@/utils/auth';
+import { getAuthCache, setAuthCache, getToken, removeAuthCache } from '/@/utils/auth'
 import {
   GetUserInfoByUserIdModel,
-  GetUserInfoByUserIdParams,
-  LoginParams,
-} from '/@/api/sys/model/userModel';
+  // GetUserInfoByUserIdParams,
+  LoginParams
+} from '/@/api/sys/model/userModel'
 
-import { getUserInfoById, loginApi } from '/@/api/sys/user';
+import { loginApi, getXsrfToken, logoutApi } from '/@/api/sys/user'
 
-import { useI18n } from '/@/hooks/web/useI18n';
-import { useMessage } from '/@/hooks/web/useMessage';
-import router from '/@/router';
+import { useI18n } from '/@/hooks/web/useI18n'
+import { useMessage } from '/@/hooks/web/useMessage'
+import router from '/@/router'
 
 interface UserState {
-  userInfo: Nullable<UserInfo>;
-  token?: string;
-  roleList: RoleEnum[];
+  userInfo: Nullable<UserInfo>
+  token?: string
+  roleList: RoleEnum[]
 }
 
 export const useUserStore = defineStore({
@@ -35,96 +34,105 @@ export const useUserStore = defineStore({
     // token
     token: undefined,
     // roleList
-    roleList: [],
+    roleList: []
   }),
   getters: {
     getUserInfo(): UserInfo {
-      return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
+      return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {}
     },
     getToken(): string {
-      return this.token || getAuthCache<string>(TOKEN_KEY);
+      return this.token || getAuthCache<string>(TOKEN_KEY)
     },
     getRoleList(): RoleEnum[] {
-      return this.roleList.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY);
-    },
+      return this.roleList.length > 0 ? this.roleList : getAuthCache<RoleEnum[]>(ROLES_KEY)
+    }
   },
   actions: {
     setToken(info: string) {
-      this.token = info;
-      setAuthCache(TOKEN_KEY, info);
+      this.token = info
+      setAuthCache(TOKEN_KEY, info)
     },
     setRoleList(roleList: RoleEnum[]) {
-      this.roleList = roleList;
-      setAuthCache(ROLES_KEY, roleList);
+      this.roleList = roleList
+      setAuthCache(ROLES_KEY, roleList)
     },
     setUserInfo(info: UserInfo) {
-      this.userInfo = info;
-      setAuthCache(USER_INFO_KEY, info);
+      this.userInfo = info
+      setAuthCache(USER_INFO_KEY, info)
     },
     resetState() {
-      this.userInfo = null;
-      this.token = '';
-      this.roleList = [];
+      this.userInfo = null
+      this.token = ''
+      this.roleList = []
     },
     /**
      * @description: login
      */
     async login(
       params: LoginParams & {
-        goHome?: boolean;
-        mode?: ErrorMessageMode;
+        goHome?: boolean
+        mode?: ErrorMessageMode
       }
     ): Promise<GetUserInfoByUserIdModel | null> {
       try {
-        const { goHome = true, mode, ...loginParams } = params;
-        const data = await loginApi(loginParams, mode);
-        const { token, userId } = data;
+        const { goHome = true, mode, ...loginParams } = params
+        await getXsrfToken('234')
+        const userInfo = await loginApi(loginParams, mode)
 
         // save token
-        this.setToken(token);
+        const token = getToken() as string
+        this.setToken(token)
         // get user info
-        const userInfo = await this.getUserInfoAction({ userId });
+        // const userInfo = await this.getUserInfoAction({ userId })
 
-        goHome && (await router.replace(PageEnum.BASE_HOME));
-        return userInfo;
+        goHome && (await router.replace(PageEnum.BASE_HOME))
+        const { isAdmin } = userInfo
+        if (isAdmin) {
+          this.setRoleList([RoleEnum.SUPER])
+        }
+        // const roleList = roles.map(item => item.value) as RoleEnum[]
+        this.setUserInfo(userInfo)
+        return userInfo
       } catch (error) {
-        return null;
+        return null
       }
     },
-    async getUserInfoAction({ userId }: GetUserInfoByUserIdParams) {
-      const userInfo = await getUserInfoById({ userId });
-      const { roles } = userInfo;
-      const roleList = roles.map((item) => item.value) as RoleEnum[];
-      this.setUserInfo(userInfo);
-      this.setRoleList(roleList);
-      return userInfo;
-    },
+    // async getUserInfoAction({ userId }: GetUserInfoByUserIdParams) {
+    //   const userInfo = await getUserInfoById({ userId })
+    //   const { roles } = userInfo
+    //   const roleList = roles.map(item => item.value) as RoleEnum[]
+    //   this.setUserInfo(userInfo)
+    //   this.setRoleList(roleList)
+    //   return userInfo
+    // },
     /**
      * @description: logout
      */
-    logout(goLogin = false) {
-      goLogin && router.push(PageEnum.BASE_LOGIN);
+    async logout(goLogin = false) {
+      await logoutApi()
+      removeAuthCache(TOKEN_KEY)
+      goLogin && router.push(PageEnum.BASE_LOGIN)
     },
 
     /**
      * @description: Confirm before logging out
      */
     confirmLoginOut() {
-      const { createConfirm } = useMessage();
-      const { t } = useI18n();
+      const { createConfirm } = useMessage()
+      const { t } = useI18n()
       createConfirm({
         iconType: 'warning',
         title: t('sys.app.logoutTip'),
         content: t('sys.app.logoutMessage'),
         onOk: async () => {
-          await this.logout(true);
-        },
-      });
-    },
-  },
-});
+          await this.logout(true)
+        }
+      })
+    }
+  }
+})
 
 // Need to be used outside the setup
 export function useUserStoreWidthOut() {
-  return useUserStore(store);
+  return useUserStore(store)
 }

+ 16 - 11
src/utils/auth/index.ts

@@ -1,21 +1,26 @@
-import { Persistent, BasicKeys } from '/@/utils/cache/persistent';
-import { CacheTypeEnum } from '/@/enums/cacheEnum';
-import projectSetting from '/@/settings/projectSetting';
-import { TOKEN_KEY } from '/@/enums/cacheEnum';
+import { Persistent, BasicKeys } from '/@/utils/cache/persistent'
+import { CacheTypeEnum } from '/@/enums/cacheEnum'
+import projectSetting from '/@/settings/projectSetting'
+import { TOKEN_KEY } from '/@/enums/cacheEnum'
 
-const { permissionCacheType } = projectSetting;
-const isLocal = permissionCacheType === CacheTypeEnum.LOCAL;
+const { permissionCacheType } = projectSetting
+const isLocal = permissionCacheType === CacheTypeEnum.LOCAL
 
 export function getToken() {
-  return getAuthCache(TOKEN_KEY);
+  return getAuthCache(TOKEN_KEY)
 }
 
 export function getAuthCache<T>(key: BasicKeys) {
-  const fn = isLocal ? Persistent.getLocal : Persistent.getSession;
-  return fn(key) as T;
+  const fn = isLocal ? Persistent.getLocal : Persistent.getSession
+  return fn(key) as T
 }
 
 export function setAuthCache(key: BasicKeys, value) {
-  const fn = isLocal ? Persistent.setLocal : Persistent.setSession;
-  return fn(key, value, true);
+  const fn = isLocal ? Persistent.setLocal : Persistent.setSession
+  return fn(key, value, true)
+}
+
+export function removeAuthCache(key: BasicKeys) {
+  const fn = isLocal ? Persistent.removeLocal : Persistent.removeSession
+  return fn(key)
 }

+ 85 - 78
src/utils/http/axios/index.ts

@@ -1,30 +1,31 @@
 // axios配置  可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动
 // The axios configuration can be changed according to the project, just change the file, other files can be left unchanged
 
-import type { AxiosResponse } from 'axios';
-import type { RequestOptions, Result } from './types';
-import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform';
+import type { AxiosResponse } from 'axios'
+import type { RequestOptions, Result } from './types'
+import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform'
 
-import { VAxios } from './Axios';
-import { checkStatus } from './checkStatus';
+import { VAxios } from './Axios'
+import { checkStatus } from './checkStatus'
 
-import { useGlobSetting } from '/@/hooks/setting';
-import { useMessage } from '/@/hooks/web/useMessage';
+import { useGlobSetting } from '/@/hooks/setting'
+import { useMessage } from '/@/hooks/web/useMessage'
 
-import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum';
+import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum'
 
-import { isString } from '/@/utils/is';
-import { getToken } from '/@/utils/auth';
-import { setObjToUrlParams, deepMerge } from '/@/utils';
-import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
+import { isString } from '/@/utils/is'
+import { getToken, setAuthCache } from '/@/utils/auth'
+import { setObjToUrlParams, deepMerge } from '/@/utils'
+import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog'
 
-import { errorResult } from './const';
-import { useI18n } from '/@/hooks/web/useI18n';
-import { createNow, formatRequestDate } from './helper';
+import { errorResult } from './const'
+import { useI18n } from '/@/hooks/web/useI18n'
+import { createNow, formatRequestDate } from './helper'
+import { TOKEN_KEY } from '/@/enums/cacheEnum'
 
-const globSetting = useGlobSetting();
-const prefix = globSetting.urlPrefix;
-const { createMessage, createErrorModal } = useMessage();
+const globSetting = useGlobSetting()
+const prefix = globSetting.urlPrefix
+const { createMessage, createErrorModal } = useMessage()
 
 /**
  * @description: 数据处理,方便区分多种处理方式
@@ -34,145 +35,151 @@ const transform: AxiosTransform = {
    * @description: 处理请求数据
    */
   transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
-    const { t } = useI18n();
-    const { isTransformRequestResult } = options;
+    const { t } = useI18n()
+    const { isTransformRequestResult } = options
     // 不进行任何处理,直接返回
     // 用于页面代码可能需要直接获取code,data,message这些信息时开启
     if (!isTransformRequestResult) {
-      return res.data;
+      return res.data
     }
     // 错误的时候返回
 
-    const { data } = res;
+    const { data } = res
     if (!data) {
       // return '[HTTP] Request has no return value';
-      return errorResult;
+      return errorResult
     }
     //  这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
-    const { code, result, message } = data;
+    const { code, data: result, msg: message } = data
 
     // 这里逻辑可以根据项目进行修改
-    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
+    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS
     if (!hasSuccess) {
       if (message) {
         // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
         if (options.errorMessageMode === 'modal') {
-          createErrorModal({ title: t('sys.api.errorTip'), content: message });
+          createErrorModal({ title: t('sys.api.errorTip'), content: message })
         } else if (options.errorMessageMode === 'message') {
-          createMessage.error(message);
+          createMessage.error(message)
         }
       }
-      Promise.reject(new Error(message));
-      return errorResult;
+      Promise.reject(new Error(message))
+      return errorResult
     }
 
     // 接口请求成功,直接返回结果
     if (code === ResultEnum.SUCCESS) {
-      return result;
+      // 保存x-csrf-token
+      if (res.config.method?.toLocaleUpperCase() === 'GET') {
+        const token = res?.headers['x-csrf-token']
+        setAuthCache(TOKEN_KEY, token)
+      }
+      return result
     }
     // 接口请求错误,统一提示错误信息
     if (code === ResultEnum.ERROR) {
       if (message) {
-        createMessage.error(data.message);
-        Promise.reject(new Error(message));
+        createMessage.error(message)
+        Promise.reject(new Error(message))
       } else {
-        const msg = t('sys.api.errorMessage');
-        createMessage.error(msg);
-        Promise.reject(new Error(msg));
+        const msg = t('sys.api.errorMessage')
+        createMessage.error(msg)
+        Promise.reject(new Error(msg))
       }
-      return errorResult;
+      return errorResult
     }
     // 登录超时
     if (code === ResultEnum.TIMEOUT) {
-      const timeoutMsg = t('sys.api.timeoutMessage');
+      const timeoutMsg = t('sys.api.timeoutMessage')
       createErrorModal({
         title: t('sys.api.operationFailed'),
-        content: timeoutMsg,
-      });
-      Promise.reject(new Error(timeoutMsg));
-      return errorResult;
+        content: timeoutMsg
+      })
+      Promise.reject(new Error(timeoutMsg))
+      return errorResult
     }
-    return errorResult;
+    return errorResult
   },
 
   // 请求之前处理config
   beforeRequestHook: (config, options) => {
-    const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
+    const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options
 
     if (joinPrefix) {
-      config.url = `${prefix}${config.url}`;
+      config.url = `${prefix}${config.url}`
     }
 
     if (apiUrl && isString(apiUrl)) {
-      config.url = `${apiUrl}${config.url}`;
+      config.url = `${apiUrl}${config.url}`
     }
-    const params = config.params || {};
+    const params = config.params || {}
     if (config.method?.toUpperCase() === RequestEnum.GET) {
       if (!isString(params)) {
         // 给 get 请求加上时间戳参数,避免从缓存中拿数据。
-        config.params = Object.assign(params || {}, createNow(joinTime, false));
+        config.params = Object.assign(params || {}, createNow(joinTime, false))
       } else {
         // 兼容restful风格
-        config.url = config.url + params + `${createNow(joinTime, true)}`;
-        config.params = undefined;
+        config.url = config.url + params + `${createNow(joinTime, true)}`
+        config.params = undefined
       }
     } else {
       if (!isString(params)) {
-        formatDate && formatRequestDate(params);
-        config.data = params;
-        config.params = undefined;
+        formatDate && formatRequestDate(params)
+        config.data = params
+        config.params = undefined
         if (joinParamsToUrl) {
-          config.url = setObjToUrlParams(config.url as string, config.data);
+          config.url = setObjToUrlParams(config.url as string, config.data)
         }
       } else {
         // 兼容restful风格
-        config.url = config.url + params;
-        config.params = undefined;
+        config.url = config.url + params
+        config.params = undefined
       }
     }
-    return config;
+    return config
   },
 
   /**
    * @description: 请求拦截器处理
    */
-  requestInterceptors: (config) => {
+  requestInterceptors: config => {
     // 请求之前处理config
-    const token = getToken();
+    const token = getToken()
     if (token) {
       // jwt token
-      config.headers.Authorization = token;
+      // config.headers.Authorization = token
+      config.headers['x-csrf-token'] = token
     }
-    return config;
+    return config
   },
 
   /**
    * @description: 响应错误处理
    */
   responseInterceptorsCatch: (error: any) => {
-    const { t } = useI18n();
-    const errorLogStore = useErrorLogStoreWithOut();
-    errorLogStore.addAjaxErrorInfo(error);
-    const { response, code, message } = error || {};
-    const msg: string = response?.data?.error?.message ?? '';
-    const err: string = error?.toString?.() ?? '';
+    const { t } = useI18n()
+    const errorLogStore = useErrorLogStoreWithOut()
+    errorLogStore.addAjaxErrorInfo(error)
+    const { response, code, message } = error || {}
+    const msg: string = response?.data?.error?.message ?? ''
+    const err: string = error?.toString?.() ?? ''
     try {
       if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
-        createMessage.error(t('sys.api.apiTimeoutMessage'));
+        createMessage.error(t('sys.api.apiTimeoutMessage'))
       }
       if (err?.includes('Network Error')) {
         createErrorModal({
           title: t('sys.api.networkException'),
-          content: t('sys.api.networkExceptionMsg'),
-        });
+          content: t('sys.api.networkExceptionMsg')
+        })
       }
     } catch (error) {
-      throw new Error(error);
+      throw new Error(error)
     }
-    checkStatus(error?.response?.status, msg);
-    return Promise.reject(error);
-  },
-};
+    checkStatus(error?.response?.status, msg)
+    return Promise.reject(error)
+  }
+}
 
 function createAxios(opt?: Partial<CreateAxiosOptions>) {
   return new VAxios(
@@ -205,14 +212,14 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
           //  是否加入时间戳
           joinTime: true,
           // 忽略重复请求
-          ignoreCancelToken: true,
-        },
+          ignoreCancelToken: true
+        }
       },
       opt || {}
     )
-  );
+  )
 }
-export const defHttp = createAxios();
+export const defHttp = createAxios()
 
 // other api url
 // export const otherHttp = createAxios({

+ 18 - 18
src/utils/http/axios/types.ts

@@ -1,39 +1,39 @@
-export type ErrorMessageMode = 'none' | 'modal' | 'message' | undefined;
+export type ErrorMessageMode = 'none' | 'modal' | 'message' | undefined
 
 export interface RequestOptions {
   // Splicing request parameters to url
-  joinParamsToUrl?: boolean;
+  joinParamsToUrl?: boolean
   // Format request parameter time
-  formatDate?: boolean;
+  formatDate?: boolean
   //  Whether to process the request result
-  isTransformRequestResult?: boolean;
+  isTransformRequestResult?: boolean
   // Whether to join url
-  joinPrefix?: boolean;
+  joinPrefix?: boolean
   // Interface address, use the default apiUrl if you leave it blank
-  apiUrl?: string;
+  apiUrl?: string
   // Error message prompt type
-  errorMessageMode?: ErrorMessageMode;
+  errorMessageMode?: ErrorMessageMode
   // Whether to add a timestamp
-  joinTime?: boolean;
-  ignoreCancelToken?: boolean;
+  joinTime?: boolean
+  ignoreCancelToken?: boolean
 }
 
 export interface Result<T = any> {
-  code: number;
-  type: 'success' | 'error' | 'warning';
-  message: string;
-  result: T;
+  code: number
+  // type: 'success' | 'error' | 'warning';
+  msg: string
+  data: T
 }
 
 // multipart/form-data: upload file
 export interface UploadFileParams {
   // Other parameters
-  data?: Recordable;
+  data?: Recordable
   // File parameter interface field name
-  name?: string;
+  name?: string
   // file name
-  file: File | Blob;
+  file: File | Blob
   // file name
-  filename?: string;
-  [key: string]: any;
+  filename?: string
+  [key: string]: any
 }

+ 0 - 43
src/views/dashboard/analysis/components/GrowCard.vue

@@ -1,43 +0,0 @@
-<template>
-  <div class="md:flex">
-    <template v-for="(item, index) in growCardList" :key="item.title">
-      <Card
-        size="small"
-        :loading="$attrs.loading"
-        :title="item.title"
-        class="md:w-1/4 w-full !md:mt-0 !mt-4"
-        :class="[index + 1 < 4 && '!md:mr-4']"
-        :canExpan="false"
-      >
-        <template #extra>
-          <Tag :color="item.color">{{ item.action }}</Tag>
-        </template>
-
-        <div class="py-4 px-4 flex justify-between">
-          <CountTo prefix="$" :startVal="1" :endVal="item.value" class="text-2xl" />
-          <Icon :icon="item.icon" :size="40" />
-        </div>
-
-        <div class="p-2 px-4 flex justify-between">
-          <span>总{{ item.title }}</span>
-          <CountTo prefix="$" :startVal="1" :endVal="item.total" />
-        </div>
-      </Card>
-    </template>
-  </div>
-</template>
-<script lang="ts">
-  import { defineComponent } from 'vue';
-
-  import { CountTo } from '/@/components/CountTo/index';
-  import { Icon } from '/@/components/Icon';
-  import { Tag, Card } from 'ant-design-vue';
-
-  import { growCardList } from '../data';
-  export default defineComponent({
-    components: { CountTo, Tag, Card, Icon },
-    setup() {
-      return { growCardList };
-    },
-  });
-</script>

+ 0 - 69
src/views/dashboard/analysis/components/SalesProductPie.vue

@@ -1,69 +0,0 @@
-<template>
-  <Card title="成交占比" :loading="loading">
-    <div ref="chartRef" :style="{ width, height }"></div>
-  </Card>
-</template>
-<script lang="ts">
-  import { defineComponent, Ref, ref, watch } from 'vue';
-
-  import { Card } from 'ant-design-vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  export default defineComponent({
-    components: { Card },
-    props: {
-      loading: Boolean,
-      width: {
-        type: String as PropType<string>,
-        default: '100%',
-      },
-      height: {
-        type: String as PropType<string>,
-        default: '300px',
-      },
-    },
-    setup(props) {
-      const chartRef = ref<HTMLDivElement | null>(null);
-      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-      watch(
-        () => props.loading,
-        () => {
-          if (props.loading) {
-            return;
-          }
-          setOptions({
-            tooltip: {
-              trigger: 'item',
-            },
-
-            series: [
-              {
-                name: '访问来源',
-                type: 'pie',
-                radius: '80%',
-                center: ['50%', '50%'],
-                color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
-                data: [
-                  { value: 500, name: '电子产品' },
-                  { value: 310, name: '服装' },
-                  { value: 274, name: '化妆品' },
-                  { value: 400, name: '家居' },
-                ].sort(function (a, b) {
-                  return a.value - b.value;
-                }),
-                roseType: 'radius',
-                animationType: 'scale',
-                animationEasing: 'exponentialInOut',
-                animationDelay: function () {
-                  return Math.random() * 400;
-                },
-              },
-            ],
-          });
-        },
-        { immediate: true }
-      );
-      return { chartRef };
-    },
-  });
-</script>

+ 0 - 46
src/views/dashboard/analysis/components/SiteAnalysis.vue

@@ -1,46 +0,0 @@
-<template>
-  <Card
-    :tab-list="tabListTitle"
-    v-bind="$attrs"
-    :active-tab-key="activeKey"
-    @tabChange="onTabChange"
-  >
-    <p v-if="activeKey === 'tab1'">
-      <VisitAnalysis />
-    </p>
-    <p v-if="activeKey === 'tab2'">
-      <VisitAnalysisBar />
-    </p>
-  </Card>
-</template>
-<script lang="ts">
-  import { defineComponent, ref } from 'vue';
-
-  import { Card } from 'ant-design-vue';
-
-  import VisitAnalysis from './VisitAnalysis.vue';
-  import VisitAnalysisBar from './VisitAnalysisBar.vue';
-
-  export default defineComponent({
-    components: { Card, VisitAnalysis, VisitAnalysisBar },
-    setup() {
-      const activeKey = ref('tab1');
-
-      const tabListTitle = [
-        {
-          key: 'tab1',
-          tab: '流量趋势',
-        },
-        {
-          key: 'tab2',
-          tab: '访问量',
-        },
-      ];
-
-      function onTabChange(key) {
-        activeKey.value = key;
-      }
-      return { tabListTitle, activeKey, onTabChange };
-    },
-  });
-</script>

+ 0 - 146
src/views/dashboard/analysis/components/VisitAnalysis.vue

@@ -1,146 +0,0 @@
-<template>
-  <div ref="chartRef" :style="{ height, width }"></div>
-</template>
-<script lang="ts">
-  import { defineComponent, onMounted, ref, Ref } from 'vue';
-
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  import { basicProps } from './props';
-  export default defineComponent({
-    props: basicProps,
-    setup() {
-      const chartRef = ref<HTMLDivElement | null>(null);
-      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-
-      onMounted(() => {
-        setOptions({
-          tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-              lineStyle: {
-                width: 1,
-                color: '#019680',
-              },
-            },
-          },
-          xAxis: {
-            type: 'category',
-            boundaryGap: false,
-            data: [
-              '6:00',
-              '7:00',
-              '8:00',
-              '9:00',
-              '10:00',
-              '11:00',
-              '12:00',
-              '13:00',
-              '14:00',
-              '15:00',
-              '16:00',
-              '17:00',
-              '18:00',
-              '19:00',
-              '20:00',
-              '21:00',
-              '22:00',
-              '23:00',
-            ],
-            splitLine: {
-              show: true,
-              lineStyle: {
-                width: 1,
-                type: 'solid',
-                color: 'rgba(226,226,226,0.5)',
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-          yAxis: [
-            {
-              type: 'value',
-              max: 80000,
-              splitNumber: 4,
-              axisTick: {
-                show: false,
-              },
-              splitArea: {
-                show: true,
-                areaStyle: {
-                  color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'],
-                },
-              },
-            },
-          ],
-          grid: { left: '1%', right: '1%', top: '2  %', bottom: 0, containLabel: true },
-          series: [
-            {
-              smooth: true,
-              data: [
-                111,
-                222,
-                4000,
-                18000,
-                33333,
-                55555,
-                66666,
-                33333,
-                14000,
-                36000,
-                66666,
-                44444,
-                22222,
-                11111,
-                4000,
-                2000,
-                500,
-                333,
-                222,
-                111,
-              ],
-              type: 'line',
-              areaStyle: {},
-              itemStyle: {
-                color: '#5ab1ef',
-              },
-            },
-            {
-              smooth: true,
-              data: [
-                33,
-                66,
-                88,
-                333,
-                3333,
-                5000,
-                18000,
-                3000,
-                1200,
-                13000,
-                22000,
-                11000,
-                2221,
-                1201,
-                390,
-                198,
-                60,
-                30,
-                22,
-                11,
-              ],
-              type: 'line',
-              areaStyle: {},
-              itemStyle: {
-                color: '#019680',
-              },
-            },
-          ],
-        });
-      });
-      return { chartRef };
-    },
-  });
-</script>

+ 0 - 62
src/views/dashboard/analysis/components/VisitAnalysisBar.vue

@@ -1,62 +0,0 @@
-<template>
-  <div ref="chartRef" :style="{ height, width }"></div>
-</template>
-<script lang="ts">
-  import { defineComponent, onMounted, ref, Ref } from 'vue';
-
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  import { basicProps } from './props';
-  export default defineComponent({
-    props: basicProps,
-    setup() {
-      const chartRef = ref<HTMLDivElement | null>(null);
-      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-
-      onMounted(() => {
-        setOptions({
-          tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-              lineStyle: {
-                width: 1,
-                color: '#019680',
-              },
-            },
-          },
-          grid: { left: '1%', right: '1%', top: '2  %', bottom: 0, containLabel: true },
-          xAxis: {
-            type: 'category',
-            data: [
-              '1月',
-              '2月',
-              '3月',
-              '4月',
-              '5月',
-              '6月',
-              '7月',
-              '8月',
-              '9月',
-              '10月',
-              '11月',
-              '12月',
-            ],
-          },
-          yAxis: {
-            type: 'value',
-            max: 8000,
-            splitNumber: 4,
-          },
-          series: [
-            {
-              data: [3000, 2000, 3333, 5000, 3200, 4200, 3200, 2100, 3000, 5100, 6000, 3200, 4800],
-              type: 'bar',
-              barMaxWidth: 80,
-            },
-          ],
-        });
-      });
-      return { chartRef };
-    },
-  });
-</script>

+ 0 - 106
src/views/dashboard/analysis/components/VisitRadar.vue

@@ -1,106 +0,0 @@
-<template>
-  <Card title="转化率" :loading="loading">
-    <div ref="chartRef" :style="{ width, height }"></div>
-  </Card>
-</template>
-<script lang="ts">
-  import { defineComponent, Ref, ref, watch } from 'vue';
-
-  import { Card } from 'ant-design-vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  export default defineComponent({
-    components: { Card },
-    props: {
-      loading: Boolean,
-      width: {
-        type: String as PropType<string>,
-        default: '100%',
-      },
-      height: {
-        type: String as PropType<string>,
-        default: '300px',
-      },
-    },
-    setup(props) {
-      const chartRef = ref<HTMLDivElement | null>(null);
-      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-      watch(
-        () => props.loading,
-        () => {
-          if (props.loading) {
-            return;
-          }
-          setOptions({
-            legend: {
-              bottom: 0,
-              data: ['访问', '购买'],
-            },
-            tooltip: {},
-            radar: {
-              radius: '60%',
-              splitNumber: 8,
-              indicator: [
-                {
-                  text: '电脑',
-                  max: 100,
-                },
-                {
-                  text: '充电器',
-                  max: 100,
-                },
-                {
-                  text: '耳机',
-                  max: 100,
-                },
-                {
-                  text: '手机',
-                  max: 100,
-                },
-                {
-                  text: 'Ipad',
-                  max: 100,
-                },
-                {
-                  text: '耳机',
-                  max: 100,
-                },
-              ],
-            },
-            series: [
-              {
-                type: 'radar',
-                symbolSize: 0,
-                areaStyle: {
-                  shadowBlur: 0,
-                  shadowColor: 'rgba(0,0,0,.2)',
-                  shadowOffsetX: 0,
-                  shadowOffsetY: 10,
-                  opacity: 1,
-                },
-                data: [
-                  {
-                    value: [90, 50, 86, 40, 50, 20],
-                    name: '访问',
-                    itemStyle: {
-                      color: '#b6a2de',
-                    },
-                  },
-                  {
-                    value: [70, 75, 70, 76, 20, 85],
-                    name: '购买',
-                    itemStyle: {
-                      color: '#5ab1ef',
-                    },
-                  },
-                ],
-              },
-            ],
-          });
-        },
-        { immediate: true }
-      );
-      return { chartRef };
-    },
-  });
-</script>

+ 0 - 88
src/views/dashboard/analysis/components/VisitSource.vue

@@ -1,88 +0,0 @@
-<template>
-  <Card title="访问来源" :loading="loading">
-    <div ref="chartRef" :style="{ width, height }"></div>
-  </Card>
-</template>
-<script lang="ts">
-  import { defineComponent, Ref, ref, watch } from 'vue';
-
-  import { Card } from 'ant-design-vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  export default defineComponent({
-    components: { Card },
-    props: {
-      loading: Boolean,
-      width: {
-        type: String as PropType<string>,
-        default: '100%',
-      },
-      height: {
-        type: String as PropType<string>,
-        default: '300px',
-      },
-    },
-    setup(props) {
-      const chartRef = ref<HTMLDivElement | null>(null);
-      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-      watch(
-        () => props.loading,
-        () => {
-          if (props.loading) {
-            return;
-          }
-          setOptions({
-            tooltip: {
-              trigger: 'item',
-            },
-            legend: {
-              bottom: '1%',
-              left: 'center',
-            },
-            series: [
-              {
-                color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
-                name: '访问来源',
-                type: 'pie',
-                radius: ['40%', '70%'],
-                avoidLabelOverlap: false,
-                itemStyle: {
-                  borderRadius: 10,
-                  borderColor: '#fff',
-                  borderWidth: 2,
-                },
-                label: {
-                  show: false,
-                  position: 'center',
-                },
-                emphasis: {
-                  label: {
-                    show: true,
-                    fontSize: '12',
-                    fontWeight: 'bold',
-                  },
-                },
-                labelLine: {
-                  show: false,
-                },
-                data: [
-                  { value: 1048, name: '搜索引擎' },
-                  { value: 735, name: '直接访问' },
-                  { value: 580, name: '邮件营销' },
-                  { value: 484, name: '联盟广告' },
-                ],
-                animationType: 'scale',
-                animationEasing: 'exponentialInOut',
-                animationDelay: function () {
-                  return Math.random() * 100;
-                },
-              },
-            ],
-          });
-        },
-        { immediate: true }
-      );
-      return { chartRef };
-    },
-  });
-</script>

+ 0 - 16
src/views/dashboard/analysis/components/props.ts

@@ -1,16 +0,0 @@
-import { PropType } from 'vue';
-
-export interface BasicProps {
-  width: string;
-  height: string;
-}
-export const basicProps = {
-  width: {
-    type: String as PropType<string>,
-    default: '100%',
-  },
-  height: {
-    type: String as PropType<string>,
-    default: '280px',
-  },
-};

+ 0 - 43
src/views/dashboard/analysis/data.ts

@@ -1,43 +0,0 @@
-export interface GrowCardItem {
-  icon: string;
-  title: string;
-  value: number;
-  total: number;
-  color: string;
-  action: string;
-}
-
-export const growCardList: GrowCardItem[] = [
-  {
-    title: '访问数',
-    icon: 'visit-count|svg',
-    value: 2000,
-    total: 120000,
-    color: 'green',
-    action: '月',
-  },
-  {
-    title: '成交额',
-    icon: 'total-sales|svg',
-    value: 20000,
-    total: 500000,
-    color: 'blue',
-    action: '月',
-  },
-  {
-    title: '下载数',
-    icon: 'download-count|svg',
-    value: 8000,
-    total: 120000,
-    color: 'orange',
-    action: '周',
-  },
-  {
-    title: '成交数',
-    icon: 'transaction|svg',
-    value: 5000,
-    total: 50000,
-    color: 'purple',
-    action: '年',
-  },
-];

+ 0 - 39
src/views/dashboard/analysis/index.vue

@@ -1,39 +0,0 @@
-<template>
-  <div class="p-4">
-    <GrowCard :loading="loading" class="enter-y" />
-    <SiteAnalysis class="!my-4 enter-y" :loading="loading" />
-
-    <div class="md:flex enter-y">
-      <VisitRadar class="md:w-1/3 w-full" :loading="loading" />
-
-      <VisitSource class="md:w-1/3 !md:mx-4 !md:my-0 !my-4 w-full" :loading="loading" />
-      <SalesProductPie class="md:w-1/3 w-full" :loading="loading" />
-    </div>
-  </div>
-</template>
-<script lang="ts">
-  import { defineComponent, ref } from 'vue';
-  import GrowCard from './components/GrowCard.vue';
-  import SiteAnalysis from './components/SiteAnalysis.vue';
-  import VisitSource from './components/VisitSource.vue';
-  import VisitRadar from './components/VisitRadar.vue';
-  import SalesProductPie from './components/SalesProductPie.vue';
-
-  export default defineComponent({
-    components: {
-      GrowCard,
-      SiteAnalysis,
-      VisitRadar,
-      VisitSource,
-      SalesProductPie,
-    },
-    setup() {
-      const loading = ref(true);
-
-      setTimeout(() => {
-        loading.value = false;
-      }, 1500);
-      return { loading };
-    },
-  });
-</script>

+ 0 - 118
src/views/demo/form/AppendForm.vue

@@ -1,118 +0,0 @@
-<template>
-  <PageWrapper title="表单增删示例">
-    <CollapseContainer title="表单增删">
-      <BasicForm @register="register" @submit="handleSubmit">
-        <template #add="{ field }">
-          <Button v-if="Number(field) === 0" @click="add">+</Button>
-          <Button v-if="field > 0" @click="del(field)">-</Button>
-        </template>
-      </BasicForm>
-    </CollapseContainer>
-  </PageWrapper>
-</template>
-<script lang="ts">
-  import { defineComponent, ref } from 'vue';
-  import { BasicForm, useForm } from '/@/components/Form/index';
-  import { CollapseContainer } from '/@/components/Container/index';
-  import { Input } from 'ant-design-vue';
-  import { PageWrapper } from '/@/components/Page';
-  import { Button } from '/@/components/Button';
-
-  export default defineComponent({
-    components: { BasicForm, CollapseContainer, PageWrapper, [Input.name]: Input, Button },
-    setup() {
-      const [register, { appendSchemaByField, removeSchemaByFiled, validate }] = useForm({
-        schemas: [
-          {
-            field: 'field0a',
-            component: 'Input',
-            label: '字段0',
-            colProps: {
-              span: 8,
-            },
-            required: true,
-          },
-          {
-            field: 'field0b',
-            component: 'Input',
-            label: '字段0',
-            colProps: {
-              span: 8,
-            },
-            required: true,
-          },
-          {
-            field: '0',
-            component: 'Input',
-            label: ' ',
-            colProps: {
-              span: 8,
-            },
-            slot: 'add',
-          },
-        ],
-        labelWidth: 100,
-        actionColOptions: { span: 24 },
-      });
-
-      async function handleSubmit() {
-        try {
-          const data = await validate();
-          console.log(data);
-        } catch (e) {
-          console.log(e);
-        }
-      }
-
-      const n = ref(1);
-
-      function add() {
-        appendSchemaByField(
-          {
-            field: `field${n.value}a`,
-            component: 'Input',
-            label: '字段' + n.value,
-            colProps: {
-              span: 8,
-            },
-            required: true,
-          },
-          ''
-        );
-        appendSchemaByField(
-          {
-            field: `field${n.value}b`,
-            component: 'Input',
-            label: '字段' + n.value,
-            colProps: {
-              span: 8,
-            },
-            required: true,
-          },
-          ''
-        );
-
-        appendSchemaByField(
-          {
-            field: `${n.value}`,
-            component: 'Input',
-            label: ' ',
-            colProps: {
-              span: 8,
-            },
-            slot: 'add',
-          },
-          ''
-        );
-        n.value++;
-      }
-
-      function del(field) {
-        removeSchemaByFiled([`field${field}a`, `field${field}b`, `${field}`]);
-        n.value--;
-      }
-
-      return { register, handleSubmit, add, del };
-    },
-  });
-</script>

+ 29 - 29
src/views/sys/login/Login.vue

@@ -34,10 +34,10 @@
             class="my-auto mx-auto xl:ml-20 xl:bg-transparent px-5 py-8 sm:px-8 xl:p-4 rounded-md shadow-md xl:shadow-none w-full sm:w-3/4 lg:w-2/4 xl:w-auto enter-x relative"
           >
             <LoginForm />
-            <ForgetPasswordForm />
-            <RegisterForm />
-            <MobileForm />
-            <QrCodeForm />
+            <!-- <ForgetPasswordForm /> -->
+            <!-- <RegisterForm /> -->
+            <!-- <MobileForm /> -->
+            <!-- <QrCodeForm /> -->
           </div>
         </div>
       </div>
@@ -45,47 +45,47 @@
   </div>
 </template>
 <script lang="ts">
-  import { defineComponent, computed } from 'vue';
+  import { defineComponent, computed } from 'vue'
 
-  import { AppLogo } from '/@/components/Application';
-  import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
-  import LoginForm from './LoginForm.vue';
-  import ForgetPasswordForm from './ForgetPasswordForm.vue';
-  import RegisterForm from './RegisterForm.vue';
-  import MobileForm from './MobileForm.vue';
-  import QrCodeForm from './QrCodeForm.vue';
+  import { AppLogo } from '/@/components/Application'
+  import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'
+  import LoginForm from './LoginForm.vue'
+  // import ForgetPasswordForm from './ForgetPasswordForm.vue'
+  // import RegisterForm from './RegisterForm.vue'
+  // import MobileForm from './MobileForm.vue'
+  // import QrCodeForm from './QrCodeForm.vue'
 
-  import { useGlobSetting } from '/@/hooks/setting';
-  import { useI18n } from '/@/hooks/web/useI18n';
-  import { useDesign } from '/@/hooks/web/useDesign';
-  import { useLocaleStore } from '/@/store/modules/locale';
+  import { useGlobSetting } from '/@/hooks/setting'
+  import { useI18n } from '/@/hooks/web/useI18n'
+  import { useDesign } from '/@/hooks/web/useDesign'
+  import { useLocaleStore } from '/@/store/modules/locale'
 
   export default defineComponent({
     name: 'Login',
     components: {
       AppLogo,
       LoginForm,
-      ForgetPasswordForm,
-      RegisterForm,
-      MobileForm,
-      QrCodeForm,
+      // ForgetPasswordForm,
+      // RegisterForm,
+      // MobileForm,
+      // QrCodeForm,
       AppLocalePicker,
-      AppDarkModeToggle,
+      AppDarkModeToggle
     },
     setup() {
-      const globSetting = useGlobSetting();
-      const { prefixCls } = useDesign('login');
-      const { t } = useI18n();
-      const localeStore = useLocaleStore();
+      const globSetting = useGlobSetting()
+      const { prefixCls } = useDesign('login')
+      const { t } = useI18n()
+      const localeStore = useLocaleStore()
 
       return {
         t,
         prefixCls,
         title: computed(() => globSetting?.title ?? ''),
-        showLocale: localeStore.getShowPicker,
-      };
-    },
-  });
+        showLocale: localeStore.getShowPicker
+      }
+    }
+  })
 </script>
 <style lang="less">
   @prefix-cls: ~'@{namespace}-login';

+ 33 - 20
types/store.ts

@@ -1,44 +1,57 @@
-import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
-import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
+import { ErrorTypeEnum } from '/@/enums/exceptionEnum'
+import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'
 
 // Lock screen information
 export interface LockInfo {
   // Password required
-  pwd?: string | undefined;
+  pwd?: string | undefined
   // Is it locked?
-  isLock?: boolean;
+  isLock?: boolean
 }
 
 // Error-log information
 export interface ErrorLogInfo {
   // Type of error
-  type: ErrorTypeEnum;
+  type: ErrorTypeEnum
   // Error file
-  file: string;
+  file: string
   // Error name
-  name?: string;
+  name?: string
   // Error message
-  message: string;
+  message: string
   // Error stack
-  stack?: string;
+  stack?: string
   // Error detail
-  detail: string;
+  detail: string
   // Error url
-  url: string;
+  url: string
   // Error time
-  time?: string;
+  time?: string
 }
 
 export interface UserInfo {
-  userId: string | number;
-  username: string;
-  realName: string;
-  desc?: string;
+  id: string
+  projectId: string
+  bidsectionId: string
+  account: string
+  password: string
+  name: string
+  company: string
+  position: string
+  role: string
+  mobile: string
+  telephone: string
+  isAdmin: number
+  accountGroup: number
+  enable: number
+  contractPermission: string
+  qualityPermission: string
+  safePermission: string
 }
 
 export interface BeforeMiniState {
-  menuCollapsed?: boolean;
-  menuSplit?: boolean;
-  menuMode?: MenuModeEnum;
-  menuType?: MenuTypeEnum;
+  menuCollapsed?: boolean
+  menuSplit?: boolean
+  menuMode?: MenuModeEnum
+  menuType?: MenuTypeEnum
 }

+ 210 - 5
yarn.lock

@@ -83,6 +83,15 @@
     jsesc "^2.5.1"
     source-map "^0.5.0"
 
+"@babel/generator@^7.14.0":
+  version "7.14.1"
+  resolved "https://registry.nlark.com/@babel/generator/download/@babel/generator-7.14.1.tgz#1f99331babd65700183628da186f36f63d615c93"
+  integrity sha1-H5kzG6vWVwAYNijaGG829j1hXJM=
+  dependencies:
+    "@babel/types" "^7.14.1"
+    jsesc "^2.5.1"
+    source-map "^0.5.0"
+
 "@babel/helper-annotate-as-pure@^7.12.13":
   version "7.12.13"
   resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab"
@@ -257,6 +266,11 @@
   resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
   integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
 
+"@babel/helper-validator-identifier@^7.14.0":
+  version "7.14.0"
+  resolved "https://registry.nlark.com/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.14.0.tgz?cache=0&sync_timestamp=1619727412592&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288"
+  integrity sha1-0mytikfGUoaxXfFUcxml0Lzycog=
+
 "@babel/helper-validator-option@^7.12.17":
   version "7.12.17"
   resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831"
@@ -295,6 +309,11 @@
   resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz#8e66775fb523599acb6a289e12929fa5ab0954d8"
   integrity sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ==
 
+"@babel/parser@^7.14.0", "@babel/parser@^7.7.0":
+  version "7.14.1"
+  resolved "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.14.1.tgz#1bd644b5db3f5797c4479d89ec1817fe02b84c47"
+  integrity sha1-G9ZEtds/V5fER52J7BgX/gK4TEc=
+
 "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12":
   version "7.13.12"
   resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz#a3484d84d0b549f3fc916b99ee4783f26fabad2a"
@@ -896,6 +915,20 @@
     debug "^4.1.0"
     globals "^11.1.0"
 
+"@babel/traverse@^7.7.0":
+  version "7.14.0"
+  resolved "https://registry.nlark.com/@babel/traverse/download/@babel/traverse-7.14.0.tgz?cache=0&sync_timestamp=1619727392425&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Ftraverse%2Fdownload%2F%40babel%2Ftraverse-7.14.0.tgz#cea0dc8ae7e2b1dec65f512f39f3483e8cc95aef"
+  integrity sha1-zqDciufisd7GX1EvOfNIPozJWu8=
+  dependencies:
+    "@babel/code-frame" "^7.12.13"
+    "@babel/generator" "^7.14.0"
+    "@babel/helper-function-name" "^7.12.13"
+    "@babel/helper-split-export-declaration" "^7.12.13"
+    "@babel/parser" "^7.14.0"
+    "@babel/types" "^7.14.0"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
 "@babel/types@^7.0.0", "@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.4.4":
   version "7.13.14"
   resolved "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz#c35a4abb15c7cd45a2746d78ab328e362cbace0d"
@@ -905,6 +938,14 @@
     lodash "^4.17.19"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.14.0", "@babel/types@^7.14.1", "@babel/types@^7.7.0":
+  version "7.14.1"
+  resolved "https://registry.nlark.com/@babel/types/download/@babel/types-7.14.1.tgz#095bd12f1c08ab63eff6e8f7745fa7c9cc15a9db"
+  integrity sha1-CVvRLxwIq2Pv9uj3dF+nycwVqds=
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.0"
+    to-fast-properties "^2.0.0"
+
 "@commitlint/cli@^12.1.1":
   version "12.1.1"
   resolved "https://registry.npmjs.org/@commitlint/cli/-/cli-12.1.1.tgz#740370e557a8a17f415052821cdd5276ecb0ab98"
@@ -1048,6 +1089,11 @@
   resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f"
   integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==
 
+"@ember-data/rfc395-data@^0.0.4":
+  version "0.0.4"
+  resolved "https://registry.npm.taobao.org/@ember-data/rfc395-data/download/@ember-data/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843"
+  integrity sha1-7Lhu/fXXczp2/xTqZRobDtH4qEM=
+
 "@eslint/eslintrc@^0.4.0":
   version "0.4.0"
   resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547"
@@ -2024,6 +2070,18 @@ axios@^0.21.1:
   dependencies:
     follow-redirects "^1.10.0"
 
+babel-eslint@10.1.0:
+  version "10.1.0"
+  resolved "https://registry.nlark.com/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1618846971799&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
+  integrity sha1-aWjlaKkQt4+zd5zdi2rC9HmUMjI=
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/parser" "^7.7.0"
+    "@babel/traverse" "^7.7.0"
+    "@babel/types" "^7.7.0"
+    eslint-visitor-keys "^1.0.0"
+    resolve "^1.12.0"
+
 babel-plugin-dynamic-import-node@^2.3.3:
   version "2.3.3"
   resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
@@ -3404,6 +3462,13 @@ domhandler@^4.0.0, domhandler@^4.1.0:
   dependencies:
     domelementtype "^2.2.0"
 
+domhandler@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.npm.taobao.org/domhandler/download/domhandler-4.2.0.tgz?cache=0&sync_timestamp=1618563954924&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomhandler%2Fdownload%2Fdomhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059"
+  integrity sha1-+XaKXwNL5gqJonwuTQ9066DYsFk=
+  dependencies:
+    domelementtype "^2.2.0"
+
 domutils@^1.5.1, domutils@^1.7.0:
   version "1.7.0"
   resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
@@ -3421,6 +3486,15 @@ domutils@^2.4.3:
     domelementtype "^2.2.0"
     domhandler "^4.1.0"
 
+domutils@^2.5.2:
+  version "2.6.0"
+  resolved "https://registry.nlark.com/domutils/download/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7"
+  integrity sha1-LhXAQYXUP7Fq5wV8t2Qzxu25OLc=
+  dependencies:
+    dom-serializer "^1.0.1"
+    domelementtype "^2.2.0"
+    domhandler "^4.2.0"
+
 dot-case@^3.0.4:
   version "3.0.4"
   resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
@@ -3528,6 +3602,11 @@ electron-to-chromium@^1.3.649:
   resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.712.tgz#ae467ffe5f95961c6d41ceefe858fc36eb53b38f"
   integrity sha512-3kRVibBeCM4vsgoHHGKHmPocLqtFAGTrebXxxtgKs87hNUzXrX2NuS3jnBys7IozCnw7viQlozxKkmty2KNfrw==
 
+ember-rfc176-data@^0.3.12:
+  version "0.3.17"
+  resolved "https://registry.npm.taobao.org/ember-rfc176-data/download/ember-rfc176-data-0.3.17.tgz#d4fc6c33abd6ef7b3440c107a28e04417b49860a"
+  integrity sha1-1PxsM6vW73s0QMEHoo4EQXtJhgo=
+
 emoji-regex@^7.0.1:
   version "7.0.3"
   resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -3670,6 +3749,69 @@ eslint-define-config@^1.0.8:
   resolved "https://registry.npmjs.org/eslint-define-config/-/eslint-define-config-1.0.8.tgz#56cb61f1bcba8ec7a29beec58a85d2ce9299297a"
   integrity sha512-Vfjv/3l112BQ0s+Ua+WGNxtEyxj++IaFCiBkhjT1wlBWtbHpuZcI0t8eCnJZnJrdv0b9n2GK0mcmQsPRRjVCXg==
 
+eslint-plugin-ember@7.11.0:
+  version "7.11.0"
+  resolved "https://registry.nlark.com/eslint-plugin-ember/download/eslint-plugin-ember-7.11.0.tgz#b770b0c68a18bbba4b66d32921750af143a4abf9"
+  integrity sha1-t3CwxooYu7pLZtMpIXUK8UOkq/k=
+  dependencies:
+    "@ember-data/rfc395-data" "^0.0.4"
+    ember-rfc176-data "^0.3.12"
+    snake-case "^3.0.3"
+
+eslint-plugin-es@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.npm.taobao.org/eslint-plugin-es/download/eslint-plugin-es-3.0.1.tgz?cache=0&sync_timestamp=1605772184308&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-es%2Fdownload%2Feslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893"
+  integrity sha1-dafN/czdwFiZNK7rOEF18iHFeJM=
+  dependencies:
+    eslint-utils "^2.0.0"
+    regexpp "^3.0.0"
+
+eslint-plugin-html@^6.1.2:
+  version "6.1.2"
+  resolved "https://registry.npm.taobao.org/eslint-plugin-html/download/eslint-plugin-html-6.1.2.tgz#fa26e4804428956c80e963b6499c192061c2daf3"
+  integrity sha1-+ibkgEQolWyA6WO2SZwZIGHC2vM=
+  dependencies:
+    htmlparser2 "^6.0.1"
+
+eslint-plugin-javascript@^1.3.4:
+  version "1.3.4"
+  resolved "https://registry.npm.taobao.org/eslint-plugin-javascript/download/eslint-plugin-javascript-1.3.4.tgz#4c133cd2093f41dbc2f54f584077e1dfe67262dc"
+  integrity sha1-TBM80gk/QdvC9U9YQHfh3+ZyYtw=
+  dependencies:
+    babel-eslint "10.1.0"
+    eslint-plugin-ember "7.11.0"
+    eslint-plugin-json "2.1.1"
+    eslint-plugin-node "11.0.0"
+
+eslint-plugin-json@2.1.1:
+  version "2.1.1"
+  resolved "https://registry.nlark.com/eslint-plugin-json/download/eslint-plugin-json-2.1.1.tgz#7b9c4da2121f6f48d44efceb9a99ac0d4d12b299"
+  integrity sha1-e5xNohIfb0jUTvzrmpmsDU0Sspk=
+  dependencies:
+    lodash "^4.17.15"
+    vscode-json-languageservice "^3.5.1"
+
+eslint-plugin-jsx@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.npm.taobao.org/eslint-plugin-jsx/download/eslint-plugin-jsx-0.1.0.tgz#6d0dc2a519d7102b17a9774a231b3548077f2a52"
+  integrity sha1-bQ3CpRnXECsXqXdKIxs1SAd/KlI=
+  dependencies:
+    eslint-plugin-react "3.4.2"
+    html-tags "1"
+    svg-tags "1"
+
+eslint-plugin-node@11.0.0:
+  version "11.0.0"
+  resolved "https://registry.nlark.com/eslint-plugin-node/download/eslint-plugin-node-11.0.0.tgz#365944bb0804c5d1d501182a9bc41a0ffefed726"
+  integrity sha1-NllEuwgExdHVARgqm8QaD/7+1yY=
+  dependencies:
+    eslint-plugin-es "^3.0.0"
+    eslint-utils "^2.0.0"
+    ignore "^5.1.1"
+    minimatch "^3.0.4"
+    resolve "^1.10.1"
+    semver "^6.1.0"
+
 eslint-plugin-prettier@^3.4.0:
   version "3.4.0"
   resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz#cdbad3bf1dbd2b177e9825737fe63b476a08f0c7"
@@ -3677,6 +3819,18 @@ eslint-plugin-prettier@^3.4.0:
   dependencies:
     prettier-linter-helpers "^1.0.0"
 
+eslint-plugin-react@3.4.2:
+  version "3.4.2"
+  resolved "https://registry.npm.taobao.org/eslint-plugin-react/download/eslint-plugin-react-3.4.2.tgz#9e6ef8a8054f8ac3b87b97236e7b849e5835dc6c"
+  integrity sha1-nm74qAVPisO4e5cjbnuEnlg13Gw=
+
+eslint-plugin-typescript@^0.14.0:
+  version "0.14.0"
+  resolved "https://registry.npm.taobao.org/eslint-plugin-typescript/download/eslint-plugin-typescript-0.14.0.tgz#068549c3f4c7f3f85d88d398c29fa96bf500884c"
+  integrity sha1-BoVJw/TH8/hdiNOYwp+pa/UAiEw=
+  dependencies:
+    requireindex "~1.1.0"
+
 eslint-plugin-vue@^7.9.0:
   version "7.9.0"
   resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.9.0.tgz#f8e83a2a908f4c43fc8304f5401d4ff671f3d560"
@@ -3702,7 +3856,7 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0:
   dependencies:
     eslint-visitor-keys "^1.1.0"
 
-eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
+eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
   version "1.3.0"
   resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
   integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
@@ -4798,6 +4952,11 @@ html-minifier-terser@^5.1.1:
     relateurl "^0.2.7"
     terser "^4.6.3"
 
+html-tags@1:
+  version "1.2.0"
+  resolved "https://registry.npm.taobao.org/html-tags/download/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98"
+  integrity sha1-x43mW1Zjqll5id0rerSSANfk25g=
+
 html-tags@^3.1.0:
   version "3.1.0"
   resolved "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
@@ -4815,6 +4974,16 @@ htmlparser2@^3.10.0, htmlparser2@^3.8.3:
     inherits "^2.0.1"
     readable-stream "^3.1.1"
 
+htmlparser2@^6.0.1:
+  version "6.1.0"
+  resolved "https://registry.nlark.com/htmlparser2/download/htmlparser2-6.1.0.tgz?cache=0&sync_timestamp=1618846794076&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
+  integrity sha1-xNditsM3GgXb5l6UrkOp+EX7j7c=
+  dependencies:
+    domelementtype "^2.0.1"
+    domhandler "^4.0.0"
+    domutils "^2.5.2"
+    entities "^2.0.0"
+
 http-cache-semantics@3.8.1:
   version "3.8.1"
   resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
@@ -7617,6 +7786,11 @@ require-main-filename@^2.0.0:
   resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
   integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
 
+requireindex@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npm.taobao.org/requireindex/download/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
+  integrity sha1-5UBLgVV+91225JxacgBIk/4D4WI=
+
 requires-port@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
@@ -7657,7 +7831,7 @@ resolve-url@^0.2.1:
   resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0:
   version "1.20.0"
   resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
   integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
@@ -7846,7 +8020,7 @@ semver@7.3.5, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
   dependencies:
     lru-cache "^6.0.0"
 
-semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
+semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -7967,7 +8141,7 @@ slice-ansi@^4.0.0:
     astral-regex "^2.0.0"
     is-fullwidth-code-point "^3.0.0"
 
-snake-case@^3.0.4:
+snake-case@^3.0.3, snake-case@^3.0.4:
   version "3.0.4"
   resolved "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c"
   integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==
@@ -8500,7 +8674,7 @@ svg-baker@1.7.0:
     query-string "^4.3.2"
     traverse "^0.6.6"
 
-svg-tags@^1.0.0:
+svg-tags@1, svg-tags@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
   integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
@@ -9286,6 +9460,37 @@ vite@2.1.5:
   optionalDependencies:
     fsevents "~2.3.1"
 
+vscode-json-languageservice@^3.5.1:
+  version "3.11.0"
+  resolved "https://registry.nlark.com/vscode-json-languageservice/download/vscode-json-languageservice-3.11.0.tgz#ad574b36c4346bd7830f1d34b5a5213d3af8d232"
+  integrity sha1-rVdLNsQ0a9eDDx00taUhPTr40jI=
+  dependencies:
+    jsonc-parser "^3.0.0"
+    vscode-languageserver-textdocument "^1.0.1"
+    vscode-languageserver-types "3.16.0-next.2"
+    vscode-nls "^5.0.0"
+    vscode-uri "^2.1.2"
+
+vscode-languageserver-textdocument@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npm.taobao.org/vscode-languageserver-textdocument/download/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f"
+  integrity sha1-F4Fo6H761hcbNyrdHeo09T5dMw8=
+
+vscode-languageserver-types@3.16.0-next.2:
+  version "3.16.0-next.2"
+  resolved "https://registry.npm.taobao.org/vscode-languageserver-types/download/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083"
+  integrity sha1-lAvRXJkilaZeroq2uFaKHo2qMIM=
+
+vscode-nls@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.npm.taobao.org/vscode-nls/download/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840"
+  integrity sha1-mfDaC9nqfNpE5WWnTFSx8rwleEA=
+
+vscode-uri@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.npm.taobao.org/vscode-uri/download/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
+  integrity sha1-yNQN6T61evMfPHFd1lDiyiwJbxw=
+
 vue-demi@latest:
   version "0.7.4"
   resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.7.4.tgz#4c6be525788e1f6b3fd5d4f5f9f2148cf6645979"