Răsfoiți Sursa

feat: 新增退出登录接口,新增全局接口封装,修改登录接口内容

奔跑的面条 3 ani în urmă
părinte
comite
5b8dda60bd

+ 9 - 0
src/api/axios.config.ts

@@ -0,0 +1,9 @@
+import { ModuleTypeEnum } from '@/enums/httpEnum'
+
+// 接口白名单(免登录)
+export const fetchAllowList = [
+  `${ModuleTypeEnum.SYSTEM}/login`
+]
+
+// 接口黑名单
+export const fetchBlockList = []

+ 32 - 6
src/api/axios.ts

@@ -1,8 +1,12 @@
 import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
-import { ResultEnum } from "@/enums/httpEnum"
-import { ErrorPageNameMap } from "@/enums/pageEnum"
-import { redirectErrorPage } from '@/utils'
+import { ResultEnum, RequestHttpHeaderEnum } from "@/enums/httpEnum"
+import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
+import { StorageEnum } from '@/enums/storageEnum'
 import { axiosPre } from '@/settings/httpSetting'
+import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
+import { redirectErrorPage, getLocalStorage, routerTurnByName } from '@/utils'
+import { fetchAllowList } from './axios.config'
+import includes from 'lodash/includes'
 
 interface MyResponseType {
   code: number;
@@ -17,7 +21,15 @@ const axiosInstance = axios.create({
 
 axiosInstance.interceptors.request.use(
   (config: AxiosRequestConfig) => {
-    config.headers = {}
+    // 白名单校验
+    if (includes(fetchAllowList, config.url)) return config
+    // 获取 token
+    const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
+    // 重新登录
+    if (!info) return routerTurnByName(PageEnum.BASE_LOGIN_NAME)
+    config.headers = {
+      [RequestHttpHeaderEnum.TOKEN]: info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_TOKEN] || ''
+    }
     return config
   },
   (error: AxiosRequestConfig) => {
@@ -29,9 +41,23 @@ axiosInstance.interceptors.request.use(
 axiosInstance.interceptors.response.use(
   (res: AxiosResponse) => {
     const { code } = res.data as { code: number }
-    if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
+
+    // 成功
+    if (code === ResultEnum.DATA_SUCCESS) {
+      return Promise.resolve(res.data)
+    }
+
+    // 登录过期
+    if (code === ResultEnum.SERVER_FORBIDDEN) {
+      routerTurnByName(PageEnum.BASE_LOGIN_NAME)
+      return Promise.reject(res.data)
+    }
+
     // 重定向
-    if (ErrorPageNameMap.get(code)) redirectErrorPage(code)
+    if (ErrorPageNameMap.get(code)) {
+      redirectErrorPage(code)
+    }
+
     return Promise.resolve(res.data)
   },
   (err: AxiosResponse) => {

+ 5 - 4
src/api/http.ts

@@ -1,25 +1,26 @@
 import axiosInstance from './axios'
 import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
 
-export const get = (url: string) => {
+export const get = (url: string, params?: object) => {
   return axiosInstance({
     url: url,
     method: RequestHttpEnum.GET,
+    params: params,
   })
 }
 
-export const post = (url: string, params: object, headersType?: string) => {
+export const post = (url: string, data?: object, headersType?: string) => {
   return axiosInstance({
     url: url,
     method: RequestHttpEnum.POST,
-    data: params,
+    data: data,
     headers: {
       'Content-Type': headersType || ContentTypeEnum.JSON
     }
   })
 }
 
-export const del = (url: string, params: object) => {
+export const del = (url: string, params?: object) => {
   return axiosInstance({
     url: url,
     method: RequestHttpEnum.DELETE,

+ 3 - 0
src/api/path/photo.ts

@@ -0,0 +1,3 @@
+import { http } from '@/api/http'
+import { httpErrorHandle } from '@/utils'
+import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'

+ 4 - 4
src/views/login/api/index.ts → src/api/path/project.ts

@@ -2,10 +2,10 @@ import { http } from '@/api/http'
 import { httpErrorHandle } from '@/utils'
 import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
 
-// 登录
-export const loginRequest = async (data: object) => {
-  try {
-    const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/login`, data);
+// * 新增项目
+export const createProjectApi = async (data: object) => {
+  try { 
+    const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/project/create`, data);
     return res;
   } catch {
     httpErrorHandle();

+ 23 - 0
src/api/path/system.api.ts

@@ -0,0 +1,23 @@
+import { http } from '@/api/http'
+import { httpErrorHandle } from '@/utils'
+import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
+
+// * 登录
+export const loginApi = async (data: object) => {
+  try {
+    const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/login`, data);
+    return res;
+  } catch {
+    httpErrorHandle();
+  }
+}
+
+// * 登出
+export const logoutApi = async () => {
+  try {
+    const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`);
+    return res;
+  } catch(err) {
+    httpErrorHandle();
+  }
+}

+ 7 - 0
src/enums/httpEnum.ts

@@ -11,6 +11,7 @@ export enum ResultEnum {
   SERVER_ERROR = 500,
   SERVER_FORBIDDEN = 403,
   NOT_FOUND = 404,
+  TOKEN_OVERDUE = 886,
   TIMEOUT = 10042,
 }
 
@@ -22,6 +23,12 @@ export enum RequestDataTypeEnum {
   AJAX = 1,
 }
 
+// 头部
+export enum RequestHttpHeaderEnum {
+  TOKEN = 'Token',
+  COOKIE = 'Cookie'
+}
+
 // 请求方法
 export enum RequestHttpEnum {
   GET = 'get',

+ 1 - 0
src/i18n/en/index.ts

@@ -11,6 +11,7 @@ const global = {
   help: 'Help',
   contact: 'Contact Us',
   logout: 'Logout',
+  logout_success: 'Logout success',
   // system setting
   sys_set: 'System Setting',
   lang_set: 'Language Setting',

+ 2 - 0
src/store/modules/systemStore/systemStore.d.ts

@@ -2,12 +2,14 @@ export enum SystemStoreUserInfoEnum {
   USER_TOKEN = 'userToken',
   USER_ID = 'userId',
   USER_NAME = 'userName',
+  NICK_NAME = 'nickName',
 }
 
 export interface UserInfoType {
   [SystemStoreUserInfoEnum.USER_TOKEN]?: string,
   [SystemStoreUserInfoEnum.USER_ID]?: string,
   [SystemStoreUserInfoEnum.USER_NAME]?: string,
+  [SystemStoreUserInfoEnum.NICK_NAME]?: string,
 }
 
 export enum SystemStoreEnum {

+ 2 - 1
src/store/modules/systemStore/systemStore.ts

@@ -14,7 +14,8 @@ export const useSystemStore = defineStore({
     userInfo: {
       userId: undefined,
       userName: undefined,
-      userToken: undefined
+      userToken: undefined,
+      nickName: undefined
     }
   },
   getters: {},

+ 10 - 4
src/utils/router.ts

@@ -1,11 +1,12 @@
 import { useRoute } from 'vue-router'
-import { ResultEnum } from '@/enums/httpEnum'
+import { ResultEnum, RequestHttpHeaderEnum } from '@/enums/httpEnum'
 import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum'
 import { docPath, giteeSourceCodePath } from '@/settings/pathConst'
 import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
 import { StorageEnum } from '@/enums/storageEnum'
-import { clearLocalStorage, getLocalStorage } from './storage'
+import { clearLocalStorage, getLocalStorage, clearCookie } from './storage'
 import router from '@/router'
+import { logoutApi } from '@/api/path/system.api'
 
 /**
  * * 根据名字跳转路由
@@ -101,9 +102,14 @@ export const reloadRoutePage = () => {
 }
 
 /**
- * * 退出
+ * * 退出登录
  */
-export const logout = () => {
+export const logout = async () => {
+  const res:any = await logoutApi()
+  if(res.code === ResultEnum.SUCCESS) {
+    window['$message'].success((`${window.$t('global.logout_success')}!`))
+  }
+  clearCookie(RequestHttpHeaderEnum.COOKIE)
   clearLocalStorage(StorageEnum.GO_SYSTEM_STORE)
   routerTurnByName(PageEnum.BASE_LOGIN_NAME)
 }

+ 41 - 3
src/utils/storage.ts

@@ -5,7 +5,7 @@
  * @param v 键值(无需stringiiy)
  * @returns RemovableRef
  */
- export const setLocalStorage = <T>(k: string, v: T) => {
+export const setLocalStorage = <T>(k: string, v: T) => {
   try {
     window.localStorage.setItem(k, JSON.stringify(v))
   } catch (error) {
@@ -18,7 +18,7 @@
  * @param k 键名
  * @returns any
  */
- export const getLocalStorage = (k: string) => {
+export const getLocalStorage = (k: string) => {
   const item = window.localStorage.getItem(k)
   try {
     return item ? JSON.parse(item) : item
@@ -31,7 +31,7 @@
  * * 清除本地会话数据
  * @param name 
  */
- export const clearLocalStorage = (name: string) => {
+export const clearLocalStorage = (name: string) => {
   window.localStorage.removeItem(name)
 }
 
@@ -68,4 +68,42 @@ export const getSessionStorage: (k: string) => any = (k: string) => {
  */
 export const clearSessioStorage = (name: string) => {
   window.sessionStorage.removeItem(name)
+}
+
+/**
+ * * 设置 cookie
+ * @param name 键名
+ * @param cvalue 键值
+ * @param exdays 过期时间
+ */
+export const setCookie = (name: string, cvalue: string, exdays: number) => {
+  const d = new Date();
+  d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
+  const expires = "expires=" + d.toUTCString();
+  document.cookie = name + "=" + cvalue + "; " + expires;
+}
+
+/**
+ * * 获取 cookie
+ * @param cname 键名
+ * @returns string
+ */
+export const getCookie = (cname: string) => {
+  const name = cname + "=";
+  const ca = document.cookie.split(';');
+  for (let i = 0; i < ca.length; i++) {
+    let c = ca[i];
+    while (c.charAt(0) == ' ') c = c.substring(1);
+    if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
+  }
+  return "";
+}
+
+/**
+ * * 清除 cookie 
+ * @param name 键名
+ * @returns string
+ */
+export const clearCookie = (name: string) => {
+  setCookie(name, "", -1);
 }

+ 9 - 4
src/views/login/index.vue

@@ -128,7 +128,7 @@ import { PageEnum } from '@/enums/pageEnum'
 import { icon } from '@/plugins'
 import { StorageEnum } from '@/enums/storageEnum'
 import { routerTurnByName } from '@/utils'
-import { loginRequest } from './api/index'
+import { loginApi } from '@/api/path/system.api'
 
 interface FormState {
   username: string
@@ -213,17 +213,22 @@ const handleSubmit = async (e: Event) => {
       const { username, password } = formInline
       loading.value = true
       // 提交请求
-      const res:any = await loginRequest({
+      const res:any = await loginApi({
         username,
         password
       })
       if(res.data) {
-        const { tokenValue, loginId } = res.data
+        const { tokenValue } = res.data.token
+        const { nickname, username, id } = res.data.userinfo
+
+        // 存储到 pinia 
         systemStore.setItem(SystemStoreEnum.USER_INFO, {
           userToken: tokenValue,
-          userId: loginId,
+          userId: id,
           userName: username,
+          nickName: nickname,
         })
+        
         window['$message'].success(`${t('login.login_success')}!`)
         routerTurnByName(PageEnum.BASE_HOME_NAME, true)
       }

+ 1 - 1
src/views/project/items/components/ProjectItemsList/hooks/useData.hook.ts

@@ -45,7 +45,7 @@ export const useDataListInit = () => {
       onPositiveCallback: () =>
         new Promise(res => setTimeout(() => res(1), 1000)),
       promiseResCallback: (e: any) => {
-        window.$message.success('删除成功')
+        window['$message'].success('删除成功')
         list.value.splice(index, 1)
       }
     })

+ 12 - 8
src/views/project/layout/components/ProjectLayoutCreate/components/CreateModal/index.vue

@@ -18,7 +18,7 @@
             :disabled="item.disabled"
             v-for="item in typeList"
             :key="item.key"
-            @click="btnHandle"
+            @click="btnHandle(item.key)"
           >
             <component :is="item.title"></component>
             <template #icon>
@@ -35,7 +35,7 @@
 </template>
 
 <script lang="ts" setup>
-import { watch, reactive } from 'vue'
+import { watch } from 'vue'
 import { icon } from '@/plugins'
 import { PageEnum, ChartEnum } from '@/enums/pageEnum'
 import { fetchPathByName, routerTurnByPath, renderLang, getUUID } from '@/utils'
@@ -48,7 +48,7 @@ const props = defineProps({
   show: Boolean
 })
 
-const typeList = reactive([
+const typeList = [
   {
     title: renderLang('project.new_project'),
     key: ChartEnum.CHART_HOME_NAME,
@@ -67,7 +67,7 @@ const typeList = reactive([
     icon: StoreIcon,
     disabled: true
   }
-])
+]
 
 // 解决点击模态层不会触发 @on-after-leave 的问题
 watch(props, newValue => {
@@ -83,10 +83,14 @@ const closeHandle = () => {
 
 // 处理按钮点击
 const btnHandle = (key: string) => {
-  closeHandle()
-  const id = getUUID()
-  const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
-  routerTurnByPath(path, [id], undefined, true)
+  switch (key) {
+    case ChartEnum.CHART_HOME_NAME:
+      const id = getUUID()
+      const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
+      routerTurnByPath(path, [id], undefined, true)
+      closeHandle()
+      break;
+  }
 }
 </script>
 <style lang="scss" scoped>