diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..f8ee73a --- /dev/null +++ b/.env.production @@ -0,0 +1,5 @@ +# 生产环境API基础URL(根据实际情况选择) +VITE_API_BASE=http://192.140.164.137:18080 + +# 前端基础URL(用于生成分享链接) +VITE_BASE_URL=https://2.uzi0.cc/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3dad8cd..911f95d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.1.4", + "terser": "^5.43.1", "vite": "^5.4.6" } }, @@ -498,12 +499,55 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@popperjs/core": { "name": "@sxzz/popperjs-es", "version": "2.11.7", @@ -1031,6 +1075,19 @@ } } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", @@ -1054,6 +1111,13 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -1079,6 +1143,13 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -1568,6 +1639,16 @@ "fsevents": "~2.3.2" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1577,6 +1658,36 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser": { + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.14.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/vite": { "version": "5.4.19", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", diff --git a/package.json b/package.json index 2fa24c4..d7b9bcb 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.1.4", + "terser": "^5.43.1", "vite": "^5.4.6" } } diff --git a/src/config/links.js b/src/config/links.js index 6d9465d..7e16e79 100644 --- a/src/config/links.js +++ b/src/config/links.js @@ -2,8 +2,8 @@ // 链接地址生成规则 export const LINK_CONFIG = { - // 基础域名 - BASE_URL: 'http://localhost:5173', + // 基础域名 - 生产环境需要修改为实际域名 + BASE_URL: import.meta.env.VITE_BASE_URL || window.location.origin, // 游戏页面路径 GAME_PATH: '/play', diff --git a/src/plugins/http.js b/src/plugins/http.js index ed6740a..523fc11 100644 --- a/src/plugins/http.js +++ b/src/plugins/http.js @@ -1,6 +1,7 @@ import axios from 'axios' import { getAccessToken, getRefreshToken, getTokenType, setTokens, clearTokens } from '../utils/auth' import { showErrorMessage } from '@/utils/error' +import router from '@/router' const baseURL = import.meta.env?.VITE_API_BASE || '/' @@ -24,6 +25,11 @@ function onRefreshed(newToken, tokenType) { pendingQueue = [] } +function onRefreshFailed() { + pendingQueue.forEach((cb) => cb(null, null)) + pendingQueue = [] +} + // 请求拦截:附加 Authorization http.interceptors.request.use( (config) => { @@ -89,17 +95,31 @@ http.interceptors.response.use( } catch (e) { isRefreshing = false clearTokens() + onRefreshFailed() + // 跳转到登录页面,保存当前路径用于登录后重定向 + const currentPath = router.currentRoute.value.fullPath + if (currentPath !== '/login') { + router.replace({ + name: 'Login', + query: { redirect: currentPath } + }) + } return Promise.reject(error) } } // 返回一个新的 Promise,等待刷新完成后重试原请求 - return new Promise((resolve) => { + return new Promise((resolve, reject) => { subscribeTokenRefresh((newToken, tokenType) => { - const retryConfig = { ...config } - retryConfig.headers = retryConfig.headers || {} - retryConfig.headers.Authorization = `${tokenType || 'Bearer'} ${newToken}` - resolve(http.request(retryConfig)) + if (newToken) { + const retryConfig = { ...config } + retryConfig.headers = retryConfig.headers || {} + retryConfig.headers.Authorization = `${tokenType || 'Bearer'} ${newToken}` + resolve(http.request(retryConfig)) + } else { + // token刷新失败,拒绝请求 + reject(error) + } }) }) } diff --git a/src/views/Login.vue b/src/views/Login.vue index bd3a9bb..f9522b2 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -27,13 +27,7 @@ - + @@ -49,7 +43,6 @@ import { showErrorMessage, showSuccessMessage } from '@/utils/error' const formRef = ref() const loading = ref(false) const remember = ref(false) -const notice = ref('') const form = ref({ username: 'admin', @@ -73,9 +66,6 @@ onMounted(() => { if (remember.value && savedUser) { form.value.username = savedUser } - notice.value = import.meta?.env?.VITE_API_BASE - ? `当前 API: ${import.meta.env.VITE_API_BASE}` - : '未配置 VITE_API_BASE,默认使用 /' }) function onForget() { @@ -151,5 +141,4 @@ async function onSubmit() { margin: -4px 0 8px; } .submit { width: 100%; } -.notice { margin-top: 8px; } diff --git a/src/views/Play.vue b/src/views/Play.vue index 9d54244..a2babe7 100644 --- a/src/views/Play.vue +++ b/src/views/Play.vue @@ -107,20 +107,20 @@