优化游戏界面

main
wang 2 months ago committed by 李冠威
parent 1bedce8fb8
commit c2ff1817f9

@ -17,49 +17,88 @@
- **数据库**MySQL
- **部署**Docker、Nginx
## 快速开始 (Docker)
## Docker部署说明
本项目已完全支持Docker部署只需几个简单的步骤即可运行
### 环境要求
- Docker
- Docker Compose
- Docker 20.10+
- Docker Compose 2.0+
### 部署步骤
1. 克隆仓库
1. 克隆项目代码:
```bash
git clone https://github.com/yourusername/goldminer.git
git clone <仓库地址>
cd goldminer
```
2. 启动服务 (Linux/Mac)
2. 创建环境配置文件(可选):
```bash
chmod +x start.sh
./start.sh
```
# 复制示例配置
cp .env.example .env
Windows系统:
# 根据需要编辑配置
nano .env # 或使用其他编辑器
```
3. 启动服务:
```bash
# Windows用户
start.bat
# Linux/Mac用户
bash start.sh
```
3. 访问游戏
- 打开浏览器访问: http://localhost:8080
- 管理员初始账号: admin
- 管理员初始密码: admin
或者手动启动:
### 环境变量配置
```bash
# 构建并启动容器
docker-compose up -d --build
```
4. 访问服务:
- 前端网页http://localhost:8080
- 管理员初始账号admin
- 管理员初始密码admin
### 环境变量说明
系统使用`.env`文件管理环境变量,首次运行会自动创建。主要配置项:
可以通过创建`.env`文件或设置环境变量来自定义配置:
| 变量名 | 描述 | 默认值 |
| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| PORT | 前端服务端口 | 8080 |
| DB_HOST | 数据库主机名 | mysql2.sqlpub.com |
| PORT | 网站访问端口 | 8080 |
| FLASK_ENV | Flask环境 | production |
| DB_HOST | 数据库主机 | mysql2.sqlpub.com |
| DB_PORT | 数据库端口 | 3307 |
| DB_USER | 数据库用户名 | goldminer |
| DB_PASSWORD | 数据库密码 | nBAWq9DDwJ14Fugq |
| SECRET_KEY | Flask会话密钥 | dev_key_for_goldminer |
| ADMIN_SETUP_KEY | 管理员初始化密钥 | goldminer_admin_setup_key |
| DB_NAME | 数据库名称 | goldminer |
| SECRET_KEY | 应用密钥 | dev_key_for_goldminer |
| ADMIN_SETUP_KEY | 管理员设置密钥 | goldminer_admin_setup_key |
### 常见问题排查
1. 如果无法访问前端页面,请检查:
- 确认容器是否正常运行:`docker-compose ps`
- 查看前端日志:`docker-compose logs frontend`
- 检查端口是否被占用:`netstat -ano | findstr 8080`
2. 如果图片资源无法显示:
- 确认项目根目录下是否存在`images`文件夹
- 确保`images`文件夹中包含必要的图片资源
- 查看nginx日志`docker-compose logs frontend`
3. 如果后端API无法连接
- 检查后端服务是否正常:`docker-compose logs backend`
- 确认数据库连接信息是否正确
## 手动开发环境搭建

@ -7,6 +7,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
python3-dev \
default-libmysqlclient-dev \
curl \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
@ -15,6 +16,9 @@ COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 创建日志目录
RUN mkdir -p /app/logs && chmod 777 /app/logs
# 复制所有后端源码
COPY . .

@ -37,6 +37,8 @@ services:
- backend
ports:
- "${PORT:-8080}:80"
volumes:
- ./images:/usr/share/nginx/html/images
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/"]
interval: 30s

@ -14,6 +14,12 @@ RUN npm ci --quiet
# 复制所有前端源码
COPY . .
# 确保images目录存在于public目录中
RUN if [ ! -d "public/images" ] && [ -d "../images" ]; then \
mkdir -p public/images && \
cp -r ../images/* public/images/; \
fi
# 设置生产环境构建
ENV NODE_ENV=production
@ -26,9 +32,16 @@ RUN ls -la dist || exit 1
# 第二阶段使用nginx提供静态文件
FROM nginx:stable-alpine AS production-stage
# 安装curl用于健康检查
RUN apk add --no-cache curl
# 从构建阶段复制构建结果到nginx默认目录
COPY --from=build-stage /app/dist /usr/share/nginx/html
# 创建images目录并确保权限正确
RUN mkdir -p /usr/share/nginx/html/images && \
chmod -R 755 /usr/share/nginx/html
# 复制自定义nginx配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

@ -8,6 +8,11 @@ server {
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 允许跨域访问
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
root /usr/share/nginx/html;
index index.html;
@ -18,6 +23,15 @@ server {
add_header Cache-Control "public, max-age=31536000";
access_log off;
}
# 特别处理images目录
location /images/ {
alias /usr/share/nginx/html/images/;
autoindex off;
expires max;
add_header Cache-Control "public, max-age=31536000";
try_files $uri $uri/ =404;
}
# 静态资源请求直接访问
location / {

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@ -1,115 +1,3 @@
<template>
<div class="admin-container">
<h1>管理控制台</h1>
@ -179,9 +67,6 @@
:disabled="currentUser && currentUser.id === user.id">
删除
</button>
<button @click="resetUserScore(user.id)" class="reset-btn">
重置分数
</button>
</td>
</tr>
</tbody>
@ -222,44 +107,6 @@
</div>
</div>
<!-- 排行榜管理 -->
<div v-if="activeTab === 'leaderboard'" class="tab-content">
<h2>排行榜管理</h2>
<div class="leaderboard-actions">
<button @click="confirmResetAllScores" class="danger-btn">
重置所有分数
</button>
</div>
<div class="table-wrapper">
<table class="leaderboard-table">
<thead>
<tr>
<th>排名</th>
<th>用户名</th>
<th>最高分</th>
<th>最后游戏</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, index) in leaderboard" :key="user.id">
<td>{{ index + 1 }}</td>
<td>{{ user.username }}</td>
<td>{{ user.high_score }}</td>
<td>{{ formatDate(user.last_login) }}</td>
<td class="actions">
<button @click="editUser(user)" class="edit-btn">编辑</button>
<button @click="resetUserScore(user.id)" class="reset-btn">
重置分数
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 游戏历史管理 -->
<div v-if="activeTab === 'history'" class="tab-content">
<h2>游戏历史管理</h2>
@ -334,7 +181,6 @@ export default {
activeTab: 'users',
tabs: [
{ id: 'users', name: '用户管理' },
{ id: 'leaderboard', name: '排行榜管理' },
{ id: 'history', name: '游戏历史' }
],
@ -343,9 +189,6 @@ export default {
filteredUsers: [],
userSearchTerm: '',
//
leaderboard: [],
//
gameHistory: [],
filteredGameHistory: [],
@ -441,7 +284,6 @@ export default {
await Promise.all([
this.loadUsers(),
this.loadLeaderboard(),
this.loadGameHistory()
])
},
@ -472,59 +314,6 @@ export default {
this.loadUsers()
},
//
async loadLeaderboard() {
try {
const response = await axios.get('/api/leaderboard')
this.leaderboard = response.data.leaderboard
} catch (error) {
console.error('加载排行榜失败:', error)
}
},
async confirmResetAllScores() {
this.showConfirmDialog = true
this.confirmDialogTitle = '重置所有分数'
this.confirmDialogMessage = '确定要重置所有用户的分数吗?此操作不可撤销!'
this.confirmDialogAction = this.resetAllScores
},
async resetAllScores() {
try {
await axios.post('/api/admin/leaderboard/reset')
this.showConfirmDialog = false
//
await this.loadUsers()
await this.loadLeaderboard()
await this.loadGameHistory()
alert('所有分数已重置')
} catch (error) {
console.error('重置分数失败:', error)
alert('重置分数失败: ' + (error.response?.data?.error || '未知错误'))
}
},
async resetUserScore(userId) {
this.showConfirmDialog = true
this.confirmDialogTitle = '重置用户分数'
this.confirmDialogMessage = '确定要重置此用户的分数吗?此操作不可撤销!'
this.confirmDialogAction = async () => {
try {
await axios.post('/api/admin/leaderboard/reset', { user_id: userId })
this.showConfirmDialog = false
//
await this.loadUsers()
await this.loadLeaderboard()
await this.loadGameHistory()
alert('用户分数已重置')
} catch (error) {
console.error('重置分数失败:', error)
alert('重置分数失败: ' + (error.response?.data?.error || '未知错误'))
}
}
},
//
async loadGameHistory() {
try {
@ -595,7 +384,6 @@ export default {
//
await this.loadUsers()
await this.loadLeaderboard()
// localStorage
const userData = JSON.parse(localStorage.getItem('user'))
@ -656,7 +444,6 @@ export default {
//
await this.loadUsers()
await this.loadLeaderboard()
await this.loadGameHistory()
alert('用户已删除')
@ -784,7 +571,7 @@ tr:hover {
gap: 5px;
}
.edit-btn, .delete-btn, .reset-btn, .refresh-btn {
.edit-btn, .delete-btn, .refresh-btn {
padding: 5px 8px;
border: none;
border-radius: 3px;
@ -802,11 +589,6 @@ tr:hover {
color: white;
}
.reset-btn {
background-color: #ff9800;
color: white;
}
.refresh-btn {
background-color: #2196F3;
color: white;

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@ -1,81 +1,142 @@
@echo off
setlocal enabledelayedexpansion
title Gold Miner Game Launcher
echo ==== 黄金矿工游戏系统部署脚本 ====
echo 正在检查环境...
REM Process command line arguments
if "%1"=="1" goto backend_direct
if "%1"=="2" goto frontend_direct
:: 检查Docker是否安装
docker --version > nul 2>&1
if %errorlevel% neq 0 (
echo 错误: 未检测到Docker. 请安装Docker后再运行此脚本.
pause
exit /b
)
:menu
cls
echo ===================================
echo Gold Miner Game Launcher
echo ===================================
echo.
echo Current computer IP address:
ipconfig | find "IPv4"
echo.
echo Please note the IP address shown above. Other computers can access the game using this address.
echo Other computers should use http://[your-IP-address]:8080 to access the game.
echo.
echo Please select an option:
echo [1] Start Backend Server
echo [2] Start Frontend Server
echo [3] Start Both Frontend and Backend (Two Windows)
echo [4] Exit
echo.
set /p choice=Enter your choice (1-4):
:: 检查Docker Compose是否安装
docker compose version > nul 2>&1
if %errorlevel% neq 0 (
echo 错误: 未检测到Docker Compose. 请安装Docker Compose后再运行此脚本.
pause
exit /b
)
if "%choice%"=="1" goto backend
if "%choice%"=="2" goto frontend
if "%choice%"=="3" goto both
if "%choice%"=="4" goto end
echo Invalid option, please try again.
timeout /t 2 >nul
goto menu
:backend_direct
REM Start backend directly from command line
title Gold Miner - Backend Server
goto backend_start
:backend
cls
echo ===================================
echo Starting Backend Server
echo ===================================
echo.
:backend_start
cd /d %~dp0
echo Docker环境检查通过!
:: 检查.env文件是否存在不存在则从示例文件创建
if not exist ".env" (
echo 未发现.env文件, 从示例创建...
if exist ".env.example" (
copy .env.example .env
echo 已创建.env文件. 请检查并根据需要修改配置.
) else (
echo 错误: 未找到.env.example文件. 正在创建基本配置...
echo # 应用配置> .env
echo FLASK_ENV=production>> .env
echo PORT=8080>> .env
echo.>> .env
echo # 数据库配置>> .env
echo DB_HOST=mysql2.sqlpub.com>> .env
echo DB_PORT=3307>> .env
echo DB_USER=goldminer>> .env
echo DB_PASSWORD=nBAWq9DDwJ14Fugq>> .env
echo DB_NAME=goldminer>> .env
echo.>> .env
echo # 安全配置>> .env
echo SECRET_KEY=dev_key_for_goldminer>> .env
echo ADMIN_SETUP_KEY=goldminer_admin_setup_key>> .env
echo.>> .env
echo # 时区>> .env
echo TZ=Asia/Shanghai>> .env
)
REM Activate virtual environment if it exists
if exist "..\..\.venv\Scripts\activate.bat" (
call "..\..\.venv\Scripts\activate.bat"
echo Virtual environment activated
)
:: 构建并启动容器
echo 正在构建并启动容器...
docker compose down
docker compose build --no-cache
docker compose up -d
:: 检查容器是否成功启动
timeout /t 5 /nobreak > nul
docker compose ps | find "goldminer-backend" > nul
if %errorlevel% neq 0 (
echo 错误: 容器未能成功启动. 请查看日志排查问题:
docker compose logs
REM Check backend dependencies
echo Installing backend dependencies...
cd backend
python -m pip install -r requirements.txt
REM Run the backend server with host=0.0.0.0
echo ===================================
echo Starting Backend Server...
echo Backend will listen on all network interfaces (0.0.0.0:5000)
echo Connecting to cloud database: mysql2.sqlpub.com:3307
echo ===================================
python app.py
pause
if "%1"=="" goto menu
exit /b
:frontend_direct
REM Start frontend directly from command line
title Gold Miner - Frontend Server
goto frontend_start
:frontend
cls
echo ===================================
echo Starting Frontend Server
echo ===================================
echo.
:frontend_start
cd /d %~dp0
REM Switch to frontend directory
cd frontend
echo Current directory: %cd%
REM Check if npm is installed
where npm >nul 2>nul
if %ERRORLEVEL% NEQ 0 (
echo Error: npm not found. Please install Node.js
pause
exit /b
goto menu
)
:: 获取端口号
set PORT=8080
for /f "tokens=1,2 delims==" %%a in (.env) do (
if "%%a"=="PORT" set PORT=%%b
)
REM Install dependencies
echo Installing frontend dependencies...
call npm install
call npm install vue-router@4 axios --save
echo ==== 黄金矿工游戏系统已成功部署! ====
echo 前端访问地址: http://localhost:%PORT%
echo 管理员初始账号: admin
echo 管理员初始密码: admin
REM Run the frontend server with host=0.0.0.0
echo ===================================
echo Starting Frontend Server...
echo Frontend will listen on all network interfaces (0.0.0.0:8080)
echo ===================================
echo Local access URL: http://localhost:8080
echo LAN access URL: http://[your-IP-address]:8080
echo ===================================
call npm run serve -- --host 0.0.0.0
pause
if "%1"=="" goto menu
exit /b
:both
cls
echo ===================================
echo Starting Both Frontend and Backend Servers
echo ===================================
echo.
echo Two windows will open to run frontend and backend servers separately.
echo Do not close either window until you want to stop the game.
echo.
echo 提示: 按任意键退出,系统将继续在后台运行
pause
echo Press any key to continue...
pause >nul
REM Start backend in a new window
start cmd /k "%~f0" 1
REM Start frontend in a new window
start cmd /k "%~f0" 2
goto menu
:end
echo Thank you for using Gold Miner Game Launcher!
timeout /t 2 >nul
exit /b 0

@ -1,55 +0,0 @@
#!/bin/bash
# 设置颜色变量
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}==== 黄金矿工游戏系统部署脚本 ====${NC}"
echo -e "${YELLOW}正在检查环境...${NC}"
# 检查Docker是否安装
if ! [ -x "$(command -v docker)" ]; then
echo -e "${RED}错误: 未检测到Docker. 请安装Docker后再运行此脚本.${NC}" >&2
exit 1
fi
# 检查Docker Compose是否安装
if ! [ -x "$(command -v docker compose)" ]; then
echo -e "${RED}错误: 未检测到Docker Compose. 请安装Docker Compose后再运行此脚本.${NC}" >&2
exit 1
fi
echo -e "${GREEN}Docker环境检查通过!${NC}"
# 检查.env文件是否存在不存在则从示例文件创建
if [ ! -f ".env" ]; then
echo -e "${YELLOW}未发现.env文件, 从示例创建...${NC}"
if [ -f ".env.example" ]; then
cp .env.example .env
echo -e "${BLUE}已创建.env文件. 请检查并根据需要修改配置.${NC}"
else
echo -e "${RED}错误: 未找到.env.example文件. 无法创建配置.${NC}" >&2
exit 1
fi
fi
# 构建并启动容器
echo -e "${GREEN}正在构建并启动容器...${NC}"
docker compose down
docker compose build --no-cache
docker compose up -d
# 检查容器是否成功启动
sleep 5
if [ "$(docker compose ps -q | wc -l)" -eq 2 ]; then
echo -e "${GREEN}==== 黄金矿工游戏系统已成功部署! ====${NC}"
echo -e "${BLUE}前端访问地址: http://localhost:$(grep PORT .env | cut -d= -f2 || echo 8080)${NC}"
echo -e "${BLUE}管理员初始账号: admin${NC}"
echo -e "${BLUE}管理员初始密码: admin${NC}"
else
echo -e "${RED}错误: 容器未能成功启动. 请查看日志排查问题:${NC}"
docker compose logs
fi
Loading…
Cancel
Save