fix: 抽取前端后端的常用变量

This commit is contained in:
bypanghu 2024-11-25 15:06:03 +08:00
parent 39212666c5
commit b89d1021c9
12 changed files with 127 additions and 62 deletions

17
server/const/const.go Normal file
View File

@ -0,0 +1,17 @@
package _const
// gva 常量文件,用于定义一些常量 , 如果修改此处,请自行修改前端中的/src/const/index.js 中对应的
const TOKEN_NAME = "x-token" // token 此处是存储在localStorage中的token名称
const USER_INFO = "x-user" // 用户信息
const REQUEST_HEAER_TOKEN_NAME = TOKEN_NAME // 请求头 token 名称 , 此处是后端可以从请求头中获取token的名称
const REQUEST_USER_ID = "x-user-id" // 请求头 用户ID 名称
const REQUSET_COOKIE_TOKEN_NAME = TOKEN_NAME // cookie token 名称, 修改此处,请同时修改后端 cookie 的 name
const NEW_TOKEN_NAME = "new-token" // 请求头中新token的名称
const OS_TYPE_NAME = "os-type" // 请求头中操作系统类型的名称, 同时存储在localStorage中
const OS_TYPE_WIN = "WIN" // windows 操作系统
const OS_TYPE_MAC = "MAC" // mac 操作系统
const TOP_ACTIVE = "topActive" // 顶部菜单激活项
const LOCAL_HISTORY = "historys" // 存储的菜单
const TAB_ACTIVE_NAME = "activeValue" // 当前活跃的菜单
const JWT_CLAIMS = "claims" // jwt 中的 claims
const NEW_TOKEN_EXPIRES_AT = "new-expires-at"

7
server/const/errors.go Normal file
View File

@ -0,0 +1,7 @@
package _const
const (
JWT_NO_AUTH = 6
ERROR = 7
SUCCESS = 0
)

View File

@ -2,6 +2,7 @@ package middleware
import (
"errors"
_const "github.com/flipped-aurora/gin-vue-admin/server/const"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/golang-jwt/jwt/v4"
@ -55,14 +56,14 @@ func JWTAuth() gin.HandlerFunc {
// response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c)
// c.Abort()
//}
c.Set("claims", claims)
c.Set(_const.JWT_CLAIMS, claims)
if claims.ExpiresAt.Unix()-time.Now().Unix() < claims.BufferTime {
dr, _ := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(dr))
newToken, _ := j.CreateTokenByOldToken(token, *claims)
newClaims, _ := j.ParseToken(newToken)
c.Header("new-token", newToken)
c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt.Unix(), 10))
c.Header(_const.NEW_TOKEN_NAME, newToken)
c.Header(_const.NEW_TOKEN_EXPIRES_AT, strconv.FormatInt(newClaims.ExpiresAt.Unix(), 10))
utils.SetToken(c, newToken, int(dr.Seconds()))
if global.GVA_CONFIG.System.UseMultipoint {
// 记录新的活跃jwt
@ -71,11 +72,11 @@ func JWTAuth() gin.HandlerFunc {
}
c.Next()
if newToken, exists := c.Get("new-token"); exists {
c.Header("new-token", newToken.(string))
if newToken, exists := c.Get(_const.NEW_TOKEN_NAME); exists {
c.Header(_const.NEW_TOKEN_NAME, newToken.(string))
}
if newExpiresAt, exists := c.Get("new-expires-at"); exists {
c.Header("new-expires-at", newExpiresAt.(string))
if newExpiresAt, exists := c.Get(_const.NEW_TOKEN_EXPIRES_AT); exists {
c.Header(_const.NEW_TOKEN_EXPIRES_AT, newExpiresAt.(string))
}
}
}

View File

@ -3,13 +3,13 @@ package middleware
import (
"context"
"errors"
_const "github.com/flipped-aurora/gin-vue-admin/server/const"
"net/http"
"time"
"go.uber.org/zap"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/gin-gonic/gin"
)
@ -27,7 +27,7 @@ type LimitConfig struct {
func (l LimitConfig) LimitWithTime() gin.HandlerFunc {
return func(c *gin.Context) {
if err := l.CheckOrMark(l.GenerationKey(c), l.Expire, l.Limit); err != nil {
c.JSON(http.StatusOK, gin.H{"code": response.ERROR, "msg": err})
c.JSON(http.StatusOK, gin.H{"code": _const.ERROR, "msg": err})
c.Abort()
return
} else {

View File

@ -1,6 +1,7 @@
package response
import (
_const "github.com/flipped-aurora/gin-vue-admin/server/const"
"net/http"
"github.com/gin-gonic/gin"
@ -12,11 +13,6 @@ type Response struct {
Msg string `json:"msg"`
}
const (
ERROR = 7
SUCCESS = 0
)
func Result(code int, data interface{}, msg string, c *gin.Context) {
// 开始时间
c.JSON(http.StatusOK, Response{
@ -27,37 +23,37 @@ func Result(code int, data interface{}, msg string, c *gin.Context) {
}
func Ok(c *gin.Context) {
Result(SUCCESS, map[string]interface{}{}, "操作成功", c)
Result(_const.SUCCESS, map[string]interface{}{}, "操作成功", c)
}
func OkWithMessage(message string, c *gin.Context) {
Result(SUCCESS, map[string]interface{}{}, message, c)
Result(_const.SUCCESS, map[string]interface{}{}, message, c)
}
func OkWithData(data interface{}, c *gin.Context) {
Result(SUCCESS, data, "成功", c)
Result(_const.SUCCESS, data, "成功", c)
}
func OkWithDetailed(data interface{}, message string, c *gin.Context) {
Result(SUCCESS, data, message, c)
Result(_const.SUCCESS, data, message, c)
}
func Fail(c *gin.Context) {
Result(ERROR, map[string]interface{}{}, "操作失败", c)
Result(_const.ERROR, map[string]interface{}{}, "操作失败", c)
}
func FailWithMessage(message string, c *gin.Context) {
Result(ERROR, map[string]interface{}{}, message, c)
Result(_const.ERROR, map[string]interface{}{}, message, c)
}
func NoAuth(message string, c *gin.Context) {
c.JSON(http.StatusUnauthorized, Response{
7,
_const.JWT_NO_AUTH,
nil,
message,
})
}
func FailWithDetailed(data interface{}, message string, c *gin.Context) {
Result(ERROR, data, message, c)
Result(_const.ERROR, data, message, c)
}

View File

@ -1,6 +1,7 @@
package utils
import (
_const "github.com/flipped-aurora/gin-vue-admin/server/const"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
@ -18,9 +19,9 @@ func ClearToken(c *gin.Context) {
}
if net.ParseIP(host) != nil {
c.SetCookie("x-token", "", -1, "/", "", false, false)
c.SetCookie(_const.REQUSET_COOKIE_TOKEN_NAME, "", -1, "/", "", false, false)
} else {
c.SetCookie("x-token", "", -1, "/", host, false, false)
c.SetCookie(_const.REQUSET_COOKIE_TOKEN_NAME, "", -1, "/", host, false, false)
}
}
@ -32,17 +33,17 @@ func SetToken(c *gin.Context, token string, maxAge int) {
}
if net.ParseIP(host) != nil {
c.SetCookie("x-token", token, maxAge, "/", "", false, false)
c.SetCookie(_const.REQUSET_COOKIE_TOKEN_NAME, token, maxAge, "/", "", false, false)
} else {
c.SetCookie("x-token", token, maxAge, "/", host, false, false)
c.SetCookie(_const.REQUSET_COOKIE_TOKEN_NAME, token, maxAge, "/", host, false, false)
}
}
func GetToken(c *gin.Context) string {
token, _ := c.Cookie("x-token")
token, _ := c.Cookie(_const.REQUSET_COOKIE_TOKEN_NAME)
if token == "" {
j := NewJWT()
token = c.Request.Header.Get("x-token")
token = c.Request.Header.Get(_const.REQUEST_HEAER_TOKEN_NAME)
claims, err := j.ParseToken(token)
if err != nil {
global.GVA_LOG.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在x-token且claims是否为规定结构")
@ -65,7 +66,7 @@ func GetClaims(c *gin.Context) (*systemReq.CustomClaims, error) {
// GetUserID 从Gin的Context中获取从jwt解析出来的用户ID
func GetUserID(c *gin.Context) uint {
if claims, exists := c.Get("claims"); !exists {
if claims, exists := c.Get(_const.JWT_CLAIMS); !exists {
if cl, err := GetClaims(c); err != nil {
return 0
} else {
@ -79,7 +80,7 @@ func GetUserID(c *gin.Context) uint {
// GetUserUuid 从Gin的Context中获取从jwt解析出来的用户UUID
func GetUserUuid(c *gin.Context) uuid.UUID {
if claims, exists := c.Get("claims"); !exists {
if claims, exists := c.Get(_const.JWT_CLAIMS); !exists {
if cl, err := GetClaims(c); err != nil {
return uuid.UUID{}
} else {
@ -93,7 +94,7 @@ func GetUserUuid(c *gin.Context) uuid.UUID {
// GetUserAuthorityId 从Gin的Context中获取从jwt解析出来的用户角色id
func GetUserAuthorityId(c *gin.Context) uint {
if claims, exists := c.Get("claims"); !exists {
if claims, exists := c.Get(_const.JWT_CLAIMS); !exists {
if cl, err := GetClaims(c); err != nil {
return 0
} else {
@ -107,7 +108,7 @@ func GetUserAuthorityId(c *gin.Context) uint {
// GetUserInfo 从Gin的Context中获取从jwt解析出来的用户角色id
func GetUserInfo(c *gin.Context) *systemReq.CustomClaims {
if claims, exists := c.Get("claims"); !exists {
if claims, exists := c.Get(_const.JWT_CLAIMS); !exists {
if cl, err := GetClaims(c); err != nil {
return nil
} else {
@ -121,7 +122,7 @@ func GetUserInfo(c *gin.Context) *systemReq.CustomClaims {
// GetUserName 从Gin的Context中获取从jwt解析出来的用户名
func GetUserName(c *gin.Context) string {
if claims, exists := c.Get("claims"); !exists {
if claims, exists := c.Get(_const.JWT_CLAIMS); !exists {
if cl, err := GetClaims(c); err != nil {
return ""
} else {

40
web/src/const/index.js Normal file
View File

@ -0,0 +1,40 @@
// 此处维护 gva 项目的常量
const TOKEN_NAME = 'x-token' // token 此处是存储在localStorage中的token名称
const USER_INFO = 'x-user' // 用户信息
const REQUEST_HEAER_TOKEN_NAME = TOKEN_NAME // 请求头 token 名称 , 此处是后端可以从请求头中获取token的名称
const REQUEST_USER_ID = 'x-user-id' // 请求头 用户ID 名称
const REQUSET_COOKIE_TOKEN_NAME = TOKEN_NAME // cookie token 名称, 修改此处,请同时修改后端 cookie 的 name
const NEW_TOKEN_NAME = 'new-token' // 请求头中新token的名称
const OS_TYPE_NAME = 'os-type' // 请求头中操作系统类型的名称, 同时存储在localStorage中
const OS_TYPE_WIN = 'WIN' // windows 操作系统
const OS_TYPE_MAC = 'MAC' // mac 操作系统
const TOP_ACTIVE = 'topActive' // 顶部菜单激活项
const LOCAL_HISTORY = 'historys' // 存储的菜单
const TAB_ACTIVE_NAME = 'activeValue' // 当前活跃的菜单
// emmiter 事件名称
const EMITTER_EVENT_SET_KEEP_ALIVE = 'setKeepAlive'
const EMITTER_EVENT_CLOSE_THIS_PAGE = 'closeThisPage'
const EMITTER_EVENT_CLOSE_ALL_PAGE = 'closeAllPage'
const EMITTER_EVENT_SWITCH_TAB = 'switchTab'
const GVA_CONST = {
TOKEN_NAME,
USER_INFO,
REQUEST_HEAER_TOKEN_NAME,
REQUEST_USER_ID,
REQUSET_COOKIE_TOKEN_NAME,
NEW_TOKEN_NAME,
OS_TYPE_NAME,
OS_TYPE_WIN,
OS_TYPE_MAC,
TAB_ACTIVE_NAME,
TOP_ACTIVE,
LOCAL_HISTORY,
EMITTER_EVENT_SET_KEEP_ALIVE,
EMITTER_EVENT_SWITCH_TAB,
EMITTER_EVENT_CLOSE_ALL_PAGE,
EMITTER_EVENT_CLOSE_THIS_PAGE
}
export default GVA_CONST

View File

@ -4,6 +4,7 @@ import { asyncMenu } from '@/api/menu'
import { defineStore } from 'pinia'
import { ref, watchEffect } from 'vue'
import pathInfo from '@/pathInfo.json'
import GVA_CONST from '@/const'
const notLayoutRouterArr = []
const keepAliveRoutersArr = []
@ -58,7 +59,7 @@ export const useRouterStore = defineStore('router', () => {
})
keepAliveRouters.value = Array.from(new Set(keepArrTemp))
}
emitter.on('setKeepAlive', setKeepAliveRouters)
emitter.on(GVA_CONST.EMITTER_EVENT_SET_KEEP_ALIVE, setKeepAliveRouters)
const asyncRouters = ref([])
@ -71,7 +72,7 @@ export const useRouterStore = defineStore('router', () => {
const topActive = ref('')
const setLeftMenu = (name) => {
sessionStorage.setItem('topActive', name)
sessionStorage.setItem(GVA_CONST.TOP_ACTIVE, name)
topActive.value = name
if (menuMap[name]?.children) {
leftMenu.value = menuMap[name].children
@ -80,7 +81,7 @@ export const useRouterStore = defineStore('router', () => {
}
watchEffect(() => {
let topActive = sessionStorage.getItem('topActive')
let topActive = sessionStorage.getItem(GVA_CONST.TOP_ACTIVE)
let firstHasChildren = ''
asyncRouters.value[0]?.children.forEach((item) => {
if (item.hidden) return

View File

@ -6,6 +6,7 @@ import { defineStore } from 'pinia'
import { ref, watch } from 'vue'
import { useRouterStore } from './router'
import cookie from 'js-cookie'
import GVA_CONST from "@/const"
import { useAppStore } from '@/pinia'
@ -20,7 +21,7 @@ export const useUserStore = defineStore('user', () => {
authority: {}
})
const token = ref(
window.localStorage.getItem('token') || cookie.get('x-token') || ''
window.localStorage.getItem(GVA_CONST.TOKEN_NAME) || cookie.get(GVA_CONST.REQUSET_COOKIE_TOKEN_NAME) || ''
)
const setUserInfo = (val) => {
userInfo.value = val
@ -37,7 +38,7 @@ export const useUserStore = defineStore('user', () => {
const NeedInit = async () => {
token.value = ''
window.localStorage.removeItem('token')
window.localStorage.removeItem(GVA_CONST.TOKEN_NAME)
await router.push({ name: 'Init', replace: true })
}
@ -92,9 +93,9 @@ export const useUserStore = defineStore('user', () => {
const isWin = ref(/windows/i.test(navigator.userAgent))
if (isWin.value) {
window.localStorage.setItem('osType', 'WIN')
window.localStorage.setItem(GVA_CONST.OS_TYPE_NAME, GVA_CONST.OS_TYPE_WIN)
} else {
window.localStorage.setItem('osType', 'MAC')
window.localStorage.setItem(GVA_CONST.OS_TYPE_NAME, GVA_CONST.OS_TYPE_MAC)
}
// 全部操作均结束关闭loading并返回
@ -120,15 +121,15 @@ export const useUserStore = defineStore('user', () => {
const ClearStorage = async () => {
token.value = ''
sessionStorage.clear()
window.localStorage.removeItem('token')
cookie.remove('x-token')
window.localStorage.removeItem(GVA_CONST.TOKEN_NAME)
cookie.remove(GVA_CONST.REQUSET_COOKIE_TOKEN_NAME)
localStorage.removeItem('originSetting')
}
watch(
() => token.value,
() => {
window.localStorage.setItem('token', token.value)
window.localStorage.setItem(GVA_CONST.TOKEN_NAME, token.value)
}
)

View File

@ -3,7 +3,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { useUserStore } from '@/pinia/modules/user'
import router from '@/router/index'
import { ElLoading } from 'element-plus'
import GVA_CONST from '@/const'
const service = axios.create({
baseURL: import.meta.env.VITE_BASE_API,
timeout: 99999
@ -45,10 +45,10 @@ service.interceptors.request.use(
const userStore = useUserStore()
config.headers = {
'Content-Type': 'application/json',
'x-token': userStore.token,
'x-user-id': userStore.userInfo.ID,
...config.headers
}
config.headers[GVA_CONST.REQUEST_HEAER_TOKEN_NAME] = userStore.token
config.headers[GVA_CONST.REQUEST_USER_ID] = userStore.userInfo.ID
return config
},
(error) => {
@ -71,8 +71,8 @@ service.interceptors.response.use(
if (!response.config.donNotShowLoading) {
closeLoading()
}
if (response.headers['new-token']) {
userStore.setToken(response.headers['new-token'])
if (response.headers[GVA_CONST.NEW_TOKEN_NAME]) {
userStore.setToken(response.headers[GVA_CONST.NEW_TOKEN_NAME])
}
if (response.data.code === 0 || response.headers.success === 'true') {
if (response.headers.msg) {

View File

@ -63,6 +63,7 @@
import { useRoute, useRouter } from 'vue-router'
import { useUserStore } from '@/pinia/modules/user'
import { fmtTitle } from '@/utils/fmtRouterTitle'
import GVA_CONST from "@/const"
defineOptions({
name: 'HistoryComponent'
@ -120,7 +121,7 @@
]
router.push({ name: defaultRouter.value })
contextMenuVisible.value = false
sessionStorage.setItem('historys', JSON.stringify(historys.value))
sessionStorage.setItem(GVA_CONST.LOCAL_HISTORY, JSON.stringify(historys.value))
}
const closeLeft = () => {
let right
@ -137,7 +138,7 @@
if (rightIndex > activeIndex) {
router.push(right)
}
sessionStorage.setItem('historys', JSON.stringify(historys.value))
sessionStorage.setItem(GVA_CONST.LOCAL_HISTORY, JSON.stringify(historys.value))
}
const closeRight = () => {
let right
@ -154,7 +155,7 @@
if (leftIndex < activeIndex) {
router.push(right)
}
sessionStorage.setItem('historys', JSON.stringify(historys.value))
sessionStorage.setItem(GVA_CONST.LOCAL_HISTORY, JSON.stringify(historys.value))
}
const closeOther = () => {
let right
@ -199,7 +200,7 @@
obj.params = route.params
historys.value.push(obj)
}
window.sessionStorage.setItem('activeValue', getFmtString(route))
window.sessionStorage.setItem(GVA_CONST.TAB_ACTIVE_NAME, getFmtString(route))
}
const historyMap = ref({})
@ -261,8 +262,8 @@
}
historys.value = historys.value.filter((item) => !item.meta.closeTab)
setTab(to)
sessionStorage.setItem('historys', JSON.stringify(historys.value))
activeValue.value = window.sessionStorage.getItem('activeValue')
sessionStorage.setItem(GVA_CONST.LOCAL_HISTORY, JSON.stringify(historys.value))
activeValue.value = window.sessionStorage.getItem(GVA_CONST.TAB_ACTIVE_NAME)
},
{ deep: true }
)
@ -270,12 +271,12 @@
watch(
() => historys.value,
() => {
sessionStorage.setItem('historys', JSON.stringify(historys.value))
sessionStorage.setItem(GVA_CONST.LOCAL_HISTORY, JSON.stringify(historys.value))
historyMap.value = {}
historys.value.forEach((item) => {
historyMap.value[getFmtString(item)] = item
})
emitter.emit('setKeepAlive', historys.value)
emitter.emit(GVA_CONST.EMITTER_EVENT_SET_KEEP_ALIVE, historys.value)
},
{
deep: true
@ -311,10 +312,10 @@
'',
`${currentUrl}?${currentSearchParams}`
)
sessionStorage.setItem('historys', JSON.stringify(historys.value))
sessionStorage.setItem(GVA_CONST.LOCAL_HISTORY, JSON.stringify(historys.value))
})
emitter.on('switchTab', async (data) => {
emitter.on(GVA_CONST.EMITTER_EVENT_SWITCH_TAB, async (data) => {
const index = historys.value.findIndex((item) => item.name === data.name)
if (index < 0) {
return
@ -343,11 +344,11 @@
]
setTab(route)
historys.value =
JSON.parse(sessionStorage.getItem('historys')) || initHistorys
if (!window.sessionStorage.getItem('activeValue')) {
JSON.parse(sessionStorage.getItem(GVA_CONST.LOCAL_HISTORY)) || initHistorys
if (!window.sessionStorage.getItem(GVA_CONST.TAB_ACTIVE_NAME)) {
activeValue.value = getFmtString(route)
} else {
activeValue.value = window.sessionStorage.getItem('activeValue')
activeValue.value = window.sessionStorage.getItem(GVA_CONST.TAB_ACTIVE_NAME)
}
if (window.sessionStorage.getItem('needCloseAll') === 'true') {
closeAll()

View File

@ -68,7 +68,7 @@ export default ({ mode }) => {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VITE_BASE_API]: {
// 需要代理的路径 例如 '/api'
target: `${process.env.VITE_BASE_PATH}:${process.env.VITE_SERVER_PORT}/`, // 代理到 目标路径
target: `${process.env.VITE_BASE_PATH}:${process.env.VITE_SERVER_PORT}/`, // 代理到
changeOrigin: true,
rewrite: (path) =>
path.replace(new RegExp('^' + process.env.VITE_BASE_API), '')