1
This commit is contained in:
@@ -6,7 +6,7 @@ import http from '@/plugins/http'
|
||||
|
||||
// 获取链接状态
|
||||
export function getLinkStatus(code) {
|
||||
return http.get('/api/link/status', {
|
||||
return http.get(`/api/link/status?t=${Date.now()}`, {
|
||||
params: { code }
|
||||
})
|
||||
}
|
||||
@@ -34,12 +34,12 @@ export function pollLoginStatus(code) {
|
||||
|
||||
// 获取游戏界面数据
|
||||
export function getGameInterface(code) {
|
||||
return http.get(`/api/link/${code}/game-interface`)
|
||||
return http.get(`/api/link/${code}/game-interface?t=${Date.now()}`)
|
||||
}
|
||||
|
||||
// 获取二维码图片(可选,用于代理二维码避免混合内容问题)
|
||||
export function getQRCode(code) {
|
||||
return http.get('/api/link/qr.png', {
|
||||
return http.get(`/api/link/qr.png?t=${Date.now()}`, {
|
||||
params: { code },
|
||||
responseType: 'blob'
|
||||
})
|
||||
|
||||
@@ -110,23 +110,10 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isWaitingQr(newVal) {
|
||||
if (newVal && this.mecmachineId) {
|
||||
this.startQrProbe()
|
||||
} else {
|
||||
this.stopQrProbe()
|
||||
}
|
||||
},
|
||||
mecmachineId(newVal) {
|
||||
if (this.isWaitingQr && newVal) {
|
||||
this.startQrProbe()
|
||||
}
|
||||
}
|
||||
// 移除二维码探测逻辑,确保必须等待指定时间
|
||||
},
|
||||
mounted() {
|
||||
if (this.isWaitingQr && this.mecmachineId) {
|
||||
this.startQrProbe()
|
||||
}
|
||||
// 移除二维码探测逻辑,确保必须等待指定时间
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.stopQrProbe()
|
||||
@@ -137,21 +124,7 @@ export default {
|
||||
const secs = seconds % 60
|
||||
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
||||
},
|
||||
startQrProbe() {
|
||||
this.stopQrProbe()
|
||||
const attemptLoad = () => {
|
||||
if (!this.mecmachineId) return
|
||||
const testImg = new Image()
|
||||
testImg.onload = () => {
|
||||
this.$emit('qrImageLoad')
|
||||
this.stopQrProbe()
|
||||
}
|
||||
testImg.onerror = () => {}
|
||||
testImg.src = `https://uzi1.cn/image/${this.mecmachineId}/二维码.png?t=${Date.now()}`
|
||||
}
|
||||
attemptLoad()
|
||||
this.probeTimer = setInterval(attemptLoad, 1000)
|
||||
},
|
||||
// 移除二维码探测方法,确保必须等待指定时间后才显示二维码
|
||||
stopQrProbe() {
|
||||
if (this.probeTimer) {
|
||||
clearInterval(this.probeTimer)
|
||||
|
||||
@@ -197,38 +197,8 @@ export default {
|
||||
}
|
||||
|
||||
const handleQrReadyEarly = async () => {
|
||||
try {
|
||||
if (!state.isWaitingQr) return
|
||||
if (!state.mecmachineId) return
|
||||
if (state.qrInfo && state.qrInfo.url) return
|
||||
// 结束等待并清理相关定时器
|
||||
state.isWaitingQr = false
|
||||
clearQrDelayCountdown()
|
||||
if (typeof clearQrDelayTimeout === 'function') {
|
||||
clearQrDelayTimeout(state)
|
||||
}
|
||||
// 立即拉取二维码并开始倒计时与登录轮询
|
||||
await fetchQrCodeAfterDelay(
|
||||
state,
|
||||
countdown,
|
||||
state.mecmachineId,
|
||||
state.qrCreatedAt,
|
||||
state.qrExpireAt
|
||||
)
|
||||
if (state.status === 'USING') {
|
||||
startCountdown()
|
||||
startLoginPolling(state.code, handleLoggedInStatus, handleCompletedStatus)
|
||||
startProgressPolling(state.code, (progressData) => {
|
||||
state.currentPoints = progressData.currentPoints || state.currentPoints
|
||||
state.totalPoints = progressData.totalPoints || state.totalPoints
|
||||
if (progressData.completedPoints !== undefined) {
|
||||
state.completedPoints = progressData.completedPoints
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提前获取二维码失败:', error)
|
||||
}
|
||||
// 移除提前显示二维码的逻辑,确保必须等待指定时间后才显示
|
||||
console.log('二维码提前就绪事件被忽略,必须等待指定时间后才显示')
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
282
部署指南.md
Normal file
282
部署指南.md
Normal file
@@ -0,0 +1,282 @@
|
||||
# 游戏平台前端项目部署指南
|
||||
|
||||
## 项目概述
|
||||
|
||||
本项目是一个基于 Vue 3 + Vite 的单页应用(SPA),包含管理后台和游戏功能。项目使用 Element Plus 作为 UI 组件库,Axios 进行 HTTP 请求。
|
||||
|
||||
## 📋 环境要求
|
||||
|
||||
### 开发环境
|
||||
- Node.js 版本:>= 16.0.0
|
||||
- npm 版本:>= 8.0.0 或 yarn >= 1.22.0
|
||||
|
||||
### 生产环境
|
||||
- Web 服务器:Nginx(推荐)或 Apache
|
||||
- 后端 API 服务:需要运行在 `http://192.140.164.137:18080`
|
||||
|
||||
## 🚀 快速部署
|
||||
|
||||
### 1. 准备工作
|
||||
|
||||
```bash
|
||||
# 克隆项目(如果需要)
|
||||
git clone <repository-url>
|
||||
cd login_task_web
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 验证开发环境
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 2. 构建生产版本
|
||||
|
||||
```bash
|
||||
# 构建项目
|
||||
npm run build
|
||||
|
||||
# 构建完成后,dist 目录包含所有静态文件
|
||||
```
|
||||
|
||||
构建产物说明:
|
||||
- `dist/index.html` - 主页面文件
|
||||
- `dist/assets/` - 静态资源(JS、CSS、图片等)
|
||||
|
||||
### 3. 部署到服务器
|
||||
|
||||
将 `dist` 目录下的所有文件上传到 Web 服务器的网站根目录。
|
||||
|
||||
## 🔧 服务器配置
|
||||
|
||||
由于本项目是单页应用(SPA),需要正确配置服务器以支持:
|
||||
1. **路由回退**:所有前端路由都应返回 `index.html`
|
||||
2. **API 代理**:代理 `/api/*` 请求到后端服务器
|
||||
3. **CORS 处理**:解决跨域问题
|
||||
|
||||
### 🌟 方式一:Nginx 配置(推荐)
|
||||
|
||||
#### 使用项目提供的配置文件
|
||||
|
||||
1. **复制 Nginx 配置**
|
||||
```bash
|
||||
cp nginx.conf /etc/nginx/sites-available/your-site.conf
|
||||
```
|
||||
|
||||
2. **修改配置文件中的路径**
|
||||
```nginx
|
||||
# 修改为您的实际部署路径
|
||||
root /var/www/your-site/dist;
|
||||
```
|
||||
|
||||
3. **启用站点并重载**
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/your-site.conf /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo nginx -s reload
|
||||
```
|
||||
|
||||
#### 完整 Nginx 配置示例
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
root /var/www/your-site/dist;
|
||||
index index.html;
|
||||
|
||||
# 静态资源缓存
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# API 代理
|
||||
location /api/ {
|
||||
proxy_pass http://192.140.164.137:18080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# CORS 设置
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
|
||||
|
||||
# 处理预检请求
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
|
||||
add_header Access-Control-Max-Age 1728000;
|
||||
add_header Content-Type 'text/plain; charset=utf-8';
|
||||
add_header Content-Length 0;
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
# SPA 路由配置(关键!)
|
||||
location / {
|
||||
try_files $uri $uri/ @fallback;
|
||||
}
|
||||
|
||||
location @fallback {
|
||||
rewrite ^.*$ /index.html last;
|
||||
}
|
||||
|
||||
# 错误页面
|
||||
error_page 404 /index.html;
|
||||
}
|
||||
```
|
||||
|
||||
### 🛠️ 方式二:宝塔面板部署
|
||||
|
||||
参考项目中的 `宝塔面板操作步骤.md` 文件,关键步骤:
|
||||
|
||||
1. **上传文件**
|
||||
- 将 `dist` 目录下所有文件上传到网站根目录
|
||||
|
||||
2. **修改 Nginx 配置**
|
||||
- 登录宝塔面板 → 网站 → 设置 → 配置文件
|
||||
- 在 `#REWRITE-END` 后添加 API 代理配置
|
||||
- 添加 SPA 路由回退配置
|
||||
|
||||
3. **保存并重载配置**
|
||||
|
||||
### 🔨 方式三:Apache 配置
|
||||
|
||||
1. **复制 .htaccess 文件**
|
||||
```bash
|
||||
cp apache.htaccess dist/.htaccess
|
||||
```
|
||||
|
||||
2. **确保 Apache 模块已启用**
|
||||
```bash
|
||||
sudo a2enmod rewrite
|
||||
sudo a2enmod headers
|
||||
sudo a2enmod proxy
|
||||
sudo a2enmod proxy_http
|
||||
sudo systemctl restart apache2
|
||||
```
|
||||
|
||||
### ☁️ 方式四:Netlify 部署
|
||||
|
||||
1. **复制重定向文件**
|
||||
```bash
|
||||
cp _redirects dist/
|
||||
```
|
||||
|
||||
2. **部署到 Netlify**
|
||||
- 上传 `dist` 目录到 Netlify
|
||||
- 或连接 Git 仓库自动部署
|
||||
|
||||
## 🧪 部署验证
|
||||
|
||||
### 功能测试清单
|
||||
|
||||
- [ ] 主页访问:`http://your-domain.com/`
|
||||
- [ ] 直接路由访问:`http://your-domain.com/play?code=xxx`
|
||||
- [ ] 页面刷新:在任意页面刷新不应出现 404
|
||||
- [ ] API 请求:检查网络面板,确认 API 请求正常
|
||||
- [ ] 登录功能:测试用户登录流程
|
||||
- [ ] 游戏功能:测试游戏相关功能
|
||||
|
||||
### 验证命令
|
||||
|
||||
```bash
|
||||
# 测试 Nginx 配置
|
||||
sudo nginx -t
|
||||
|
||||
# 查看错误日志
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
|
||||
# 测试 API 连通性
|
||||
curl -I http://your-domain.com/api/health
|
||||
```
|
||||
|
||||
## 🚨 常见问题及解决方案
|
||||
|
||||
### 问题 1:直接访问路由出现 404
|
||||
**原因**:Web 服务器未配置 SPA 路由回退
|
||||
**解决**:按照上述配置添加路由回退规则
|
||||
|
||||
### 问题 2:API 请求失败 (CORS 错误)
|
||||
**原因**:跨域配置不正确
|
||||
**解决**:
|
||||
1. 检查 API 代理配置
|
||||
2. 确认后端服务 `http://192.140.164.137:18080` 可访问
|
||||
3. 检查 CORS 头部设置
|
||||
|
||||
### 问题 3:静态资源加载失败
|
||||
**原因**:资源路径配置问题
|
||||
**解决**:
|
||||
1. 检查 `vite.config.js` 中的 `base` 配置
|
||||
2. 确认所有文件都已正确上传
|
||||
|
||||
### 问题 4:页面空白
|
||||
**原因**:通常是 JavaScript 错误
|
||||
**解决**:
|
||||
1. 打开浏览器开发者工具查看控制台错误
|
||||
2. 检查网络请求是否正常
|
||||
3. 确认构建过程无错误
|
||||
|
||||
## 📊 性能优化建议
|
||||
|
||||
### 1. 启用 Gzip 压缩
|
||||
```nginx
|
||||
# 在 Nginx 配置中添加
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/javascript application/json;
|
||||
```
|
||||
|
||||
### 2. 配置缓存策略
|
||||
- 静态资源(JS、CSS、图片):长期缓存
|
||||
- HTML 文件:短期缓存或无缓存
|
||||
|
||||
### 3. CDN 加速
|
||||
考虑使用 CDN 服务加速静态资源访问
|
||||
|
||||
## 🔒 安全建议
|
||||
|
||||
1. **HTTPS 配置**:生产环境应启用 HTTPS
|
||||
2. **API 安全**:确保后端 API 有适当的安全验证
|
||||
3. **访问控制**:配置防火墙规则
|
||||
4. **定期更新**:保持依赖库和服务器软件更新
|
||||
|
||||
## 📱 移动端适配
|
||||
|
||||
项目已包含移动端检测,确保在移动设备上访问体验良好。
|
||||
|
||||
## 🔄 更新部署
|
||||
|
||||
```bash
|
||||
# 1. 拉取最新代码
|
||||
git pull origin main
|
||||
|
||||
# 2. 安装/更新依赖
|
||||
npm install
|
||||
|
||||
# 3. 重新构建
|
||||
npm run build
|
||||
|
||||
# 4. 上传新的构建文件
|
||||
# 替换服务器上的 dist 目录内容
|
||||
|
||||
# 5. 重载服务器配置(如有必要)
|
||||
sudo nginx -s reload
|
||||
```
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如果在部署过程中遇到问题:
|
||||
|
||||
1. 首先查看上述常见问题
|
||||
2. 检查服务器错误日志
|
||||
3. 确认网络和防火墙配置
|
||||
4. 验证后端服务可用性
|
||||
|
||||
---
|
||||
|
||||
**注意**:本文档基于当前项目配置编写,如果项目配置有变更,请相应更新此文档。
|
||||
Reference in New Issue
Block a user