51 Commits

Author SHA1 Message Date
f9400a76ca Merge branch 'server' of http://git.aigc-quickapp.com/WeWork/vs100 into server 2025-11-29 09:06:49 +08:00
9ed6935707 Merge pull request 'chore:在Desktop(touch)上鼠标可以拖动奖金' (#2) from tmp1 into server
Reviewed-on: #2
Reviewed-by: ZF Sun <admin@noreply.localhost>
2025-11-29 01:05:55 +00:00
7fb210599f chore:在Desktop(touch)上鼠标可以拖动奖金 2025-11-29 08:59:42 +08:00
2eea1fb213 chore:在Desktop(touch)上鼠标可以拖动奖金 2025-11-29 08:36:57 +08:00
6cbcce505a chore:在Desktop(touch)中鼠标可以拖动奖金 2025-11-28 13:56:30 +08:00
e33f227aa0 Merge branch 'server' of http://git.aigc-quickapp.com/WeWork/vs100 into server 2025-11-28 11:49:15 +08:00
d9e88f757f chore:在Desktop(touch)上鼠标可以拖动奖品 2025-11-28 09:45:04 +08:00
b6f20fd76d Merge branch 'server' of http://git.aigc-quickapp.com/WeWork/vs100 into server 2025-11-28 09:15:57 +08:00
7e90289fdd chore(footer): 修改footer文字 2025-11-25 14:43:54 +08:00
2a9153217b chore: 调整虎狼之师、英雄榜图片 2025-11-25 13:47:36 +08:00
d5a74e3ec9 Merge branch 'server' of http://192.168.2.64:3208/WeWork/vs100 into server 2025-11-25 11:42:09 +08:00
ab43bd5abf chore: .gitignore 文件中加入vs100.zip, 要过滤掉 2025-11-25 10:43:39 +08:00
a8ff32f77d chore: 根据新的需求,加入虎狼之师,英雄榜条幅 2025-11-25 10:30:18 +08:00
ede3e0d850 chore: 动态计算英雄排名表格高度 2025-11-25 09:32:07 +08:00
cb7a91d245 chore: 奖品替换及字体放大 2025-11-24 17:50:45 +08:00
0dc7d32710 Merge branch 'server' of http://192.168.2.64:3208/WeWork/vs100 into server 2025-11-24 15:18:26 +08:00
5a48653be0 合并远程server分支的代码 2025-11-24 15:10:17 +08:00
156ce493f0 改变了移动端王冠大小 2025-11-24 14:34:49 +08:00
885f0a51dd chore: 支持战区冠军添加图片,增加英雄榜字体及特效 2025-11-24 14:32:58 +08:00
593dad093e chore: 排名明细,表名称居中显示 2025-11-24 09:43:47 +08:00
7fcaa1af1a 把战区排名和英雄排名的框本调整对齐了 2025-11-22 18:08:00 +08:00
7f5c746be6 chore: 修改移动端英雄排名列表样式,确保表头固定不动,只有表格内容可以滚动。 2025-11-22 08:55:35 +08:00
c81516fff1 chore: 优化移动端的加载背景图 2025-11-22 08:49:16 +08:00
03fb2344b4 chore: 实现排名列表及冠军头像圆角化 2025-11-22 08:33:29 +08:00
1d4cb8c184 chore: 调整样式 2025-11-22 08:23:16 +08:00
7c70a7847a chore: 皇冠动画效果实现 2025-11-21 17:20:39 +08:00
94cb525301 chore: 支持过滤0业绩的数据 2025-11-21 16:47:28 +08:00
59c09546a9 chore: 支持配置列显示位置 2025-11-21 16:27:03 +08:00
91e8af324d chore: 移动端战区排名全显示 2025-11-21 14:43:43 +08:00
2fe453955e chore: 变更package.json文件,增加 2025-11-14 14:47:54 +08:00
8d9c91beb4 chore: 调整样式适配 2025-11-14 08:57:30 +08:00
37dfecfe6a chore: 优化奖金模块的显示,去掉不需要的代码 2025-11-13 17:26:22 +08:00
ab60d253de chore: 实现支持定制战区冠军及英雄关键Logo的大小 2025-11-13 16:03:56 +08:00
4164ea36ee chore: 调整管理员排名列表 2025-11-13 15:48:26 +08:00
6f842ef328 chore: 支持上传图片及sass语法 2025-11-13 14:55:45 +08:00
d8275a2781 chore: 调整样式 2025-11-13 14:23:52 +08:00
af14a2ee00 chore: 调整logo的大小为宽度360px 2025-11-13 13:59:26 +08:00
c8e02f2392 chore: 奖金设置部分已经调整到偏左上角位置 2025-11-13 13:56:44 +08:00
f1f423eceb fix: 修复了奖金设置模块的拖动功能 2025-11-13 11:50:22 +08:00
20fe7c5202 chore: 调整针对1080高度的分辨率设置 2025-11-13 11:35:30 +08:00
a378479782 chore: 部分功能优化 2025-11-13 10:44:07 +08:00
6f278c2330 chore: 移动端增加左右标题语的放置 2025-11-13 10:29:57 +08:00
056cdc7d1c chore: 移动端基本适配完成 2025-11-13 10:08:35 +08:00
b35289e021 chore: 调整图片及优化前端页面 2025-11-13 08:56:52 +08:00
7c4fcc1273 chore: update config.json 2025-11-13 08:28:15 +08:00
e5010b6ea3 chore: PC 端基本页面完成 2025-11-13 08:21:46 +08:00
d6ee43e48b chore: 代码保存,除了冠军模块,其他显示正常 2025-11-12 20:01:21 +08:00
391c489fb5 ui: 资源保存 2025-11-12 15:54:21 +08:00
c68c41638f chore: 加速npm包下载安装 2025-11-12 13:45:52 +08:00
1e221550cf ui: 调整到符合游戏风格 2025-11-12 09:37:10 +08:00
58ad47d124 chore: 基本服务器版本完成 2025-11-12 08:23:41 +08:00
42 changed files with 7401 additions and 1162 deletions

1
.gitignore vendored
View File

@@ -22,3 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
vs100.zip

160
.npmrc Normal file
View File

@@ -0,0 +1,160 @@
# =========================================
# .npmrc - 完整镜像配置
# 适用于 Node.js 项目,包含所有常见二进制包镜像
# =========================================
# ====================
# 基础镜像配置
# ====================
registry=https://registry.npmmirror.com/
# Node.js 相关镜像
disturl=https://npmmirror.com/mirrors/node
nodedir=https://npmmirror.com/mirrors/node
node_src_dir=https://npmmirror.com/mirrors/node
nodelibcxxdir=https://npmmirror.com/mirrors/node_libcxx
# ====================
# 原生模块二进制镜像
# ====================
# node-sass 相关
sass_binary_site=https://npmmirror.com/mirrors/node-sass
sass_binary_host=https://npmmirror.com/mirrors/node-sass
# Electron 相关
electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/
# Python 相关
python_mirror=https://npmmirror.com/mirrors/python
# ====================
# 浏览器驱动镜像
# ====================
# Chrome 相关
chromedriver_cdnurl=https://npmmirror.com/mirrors/chromedriver
CHROMEDRIVER_CDNURL=https://npmmirror.com/mirrors/chromedriver
# Firefox 相关
geckodriver_cdnurl=https://npmmirror.com/mirrors/geckodriver
GECKODRIVER_CDNURL=https://npmmirror.com/mirrors/geckodriver
# Opera 相关
operadriver_cdnurl=https://npmmirror.com/mirrors/operadriver
OPERADRIVER_CDNURL=https://npmmirror.com/mirrors/operadriver
# Edge 相关
edgedriver_cdnurl=https://npmmirror.com/mirrors/edgedriver
EDGEDRIVER_CDNURL=https://npmmirror.com/mirrors/edgedriver
# ====================
# 测试工具镜像
# ====================
# PhantomJS
phantomjs_cdnurl=https://npmmirror.com/mirrors/phantomjs
PHANTOMJS_CDNURL=https://npmmirror.com/mirrors/phantomjs
# Selenium
selenium_cdnurl=https://npmmirror.com/mirrors/selenium
SELENIUM_CDNURL=https://npmmirror.com/mirrors/selenium
# ====================
# 数据库相关镜像
# ====================
# SQLite
sqlite3_binary_host=https://npmmirror.com/mirrors/sqlite3
sqlite3_binary_host_mirror=https://npmmirror.com/mirrors/sqlite3
# PostgreSQL (pg)
pg_binary_host=https://npmmirror.com/mirrors/pg
# ====================
# 图像处理相关镜像
# ====================
# Canvas
canvas_binary_host=https://npmmirror.com/mirrors/canvas
canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas
# Sharp
sharp_binary_host=https://npmmirror.com/mirrors/sharp
sharp_libvips_binary_host=https://npmmirror.com/mirrors/sharp
# ====================
# 加密和压缩相关
# ====================
# bcrypt
bcrypt_binary_host=https://npmmirror.com/mirrors/bcrypt
# node-zopfli
zopfli_binary_host=https://npmmirror.com/mirrors/node-zopfli
# ====================
# 其他常见二进制包
# ====================
# fsevents (macOS)
fsevents_binary_host_mirror=https://npmmirror.com/mirrors/fsevents
# grpc
grpc_binary_host_mirror=https://npmmirror.com/mirrors/grpc
# leveldown
leveldown_binary_host=https://npmmirror.com/mirrors/leveldown
# snappy
snappy_binary_host=https://npmmirror.com/mirrors/snappy
# hiredis
hiredis_binary_host=https://npmmirror.com/mirrors/hiredis
# utf-8-validate
utf-8-validate_binary_host=https://npmmirror.com/mirrors/utf-8-validate
# bufferutil
bufferutil_binary_host=https://npmmirror.com/mirrors/bufferutil
# ====================
# node-gyp 构建配置
# ====================
# Python 配置
python=python3
# 构建工具配置
msvs_version=2019
# 缓存和日志配置
loglevel=verbose
progress=true
# ====================
# 网络和超时配置
# ====================
# 重试配置
fetch-retries=5
fetch-timeout=300000
socket-timeout=300000
# SSL 配置
strict-ssl=false
# ====================
# 开发工具配置
# ====================
# TypeScript
typescript_registry=https://registry.npmmirror.com/
# Webpack
webpack_cli_registry=https://registry.npmmirror.com/
# Babel
babel_registry=https://registry.npmmirror.com/

985
data/config.json Normal file
View File

@@ -0,0 +1,985 @@
{
"individualRankings": [
{
"id": 8,
"name": "杨鑫鹏",
"score": 208600,
"level": "SSS",
"avatar": "/uploads/1763972044872.jpg",
"department": "销售部",
"completedTasks": 32,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763600399414,
"name": "王松根",
"score": 149000,
"level": "A",
"avatar": "👑",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763702198797,
"name": "岳杨",
"score": 149000,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763703428082,
"name": "刘博",
"score": 149000,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 1763606483656,
"name": "陈梦蝶",
"score": 149000,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1,
"name": "刘贵博",
"score": 149000,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 48,
"bonus": 0,
"team": "一战区"
},
{
"id": 3,
"name": "赵政行",
"score": 149000,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 42,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763703454998,
"name": "汪思柔",
"score": 119200,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 1763703551860,
"name": "刘正艺",
"score": 89400,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 1763703442159,
"name": "刘莉",
"score": 89400,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 2,
"name": "张政",
"score": 89400,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 45,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763702288912,
"name": "仝维茜",
"score": 89400,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702407090,
"name": "李明娣",
"score": 89400,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702548562,
"name": "高博祎",
"score": 89400,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763606463583,
"name": "刘天乐",
"score": 69600,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 4,
"name": "秦婧婧",
"score": 59600,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 40,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763606343912,
"name": "李胜豪",
"score": 59600,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606422126,
"name": "贾景杰",
"score": 59600,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763702177212,
"name": "东知",
"score": 59600,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702567245,
"name": "吕璐",
"score": 59600,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 7,
"name": "姜浩然",
"score": 39800,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 34,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763702217482,
"name": "何盘珍",
"score": 29800,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 12,
"name": "孙珊珊",
"score": 26820,
"level": "SSS",
"avatar": "🥇",
"department": "刘奔腾",
"completedTasks": 24,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763703508858,
"name": "毕艺超",
"score": 0,
"level": "SSS",
"avatar": "/uploads/1763860106271.jpg",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 5,
"name": "李先锐",
"score": 0,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 38,
"bonus": 0,
"team": "一战区"
},
{
"id": 6,
"name": "孙悦",
"score": 0,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 36,
"bonus": 0,
"team": "一战区"
},
{
"id": 9,
"name": "曾焱平",
"score": 0,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 30,
"bonus": 0,
"team": "一战区"
},
{
"id": 10,
"name": "贺鸿飞",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 28,
"bonus": 0,
"team": "二战区"
},
{
"id": 11,
"name": "齐文涛",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 26,
"bonus": 0,
"team": "二战区"
},
{
"id": 13,
"name": "刘奔腾",
"score": 0,
"level": "B",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 22,
"bonus": 0,
"team": "二战区"
},
{
"id": 14,
"name": "刘硕",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 20,
"bonus": 0,
"team": "二战区"
},
{
"id": 15,
"name": "王蓉",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 18,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606252253,
"name": "朱宝林",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606266583,
"name": "宋鹏博",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606282323,
"name": "蔡令斐",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606298308,
"name": "李奉颖",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606312478,
"name": "张如意",
"score": 0,
"level": "SSS",
"avatar": "🥇",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "二战区"
},
{
"id": 1763606387926,
"name": "李杰",
"score": 0,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763606403982,
"name": "刘丽",
"score": 0,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763606503187,
"name": "贾振颖",
"score": 0,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763606519461,
"name": "王雨晴",
"score": 0,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763606538022,
"name": "高俊圳",
"score": 0,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763606552741,
"name": "毕洁雨",
"score": 0,
"level": "SSS",
"avatar": "🥈",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "三战区"
},
{
"id": 1763606570669,
"name": "熊春杰",
"score": 0,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763606588683,
"name": "张频",
"score": 0,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702274156,
"name": "杨李佳",
"score": 0,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702306246,
"name": "吴玉洁",
"score": 0,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702325175,
"name": "谢寒雪",
"score": 0,
"level": "SSS",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702340664,
"name": "袁如萍",
"score": 0,
"level": "A",
"avatar": "🥉",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "四战区"
},
{
"id": 1763702392030,
"name": "周顺凡",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702423195,
"name": "陈亚军",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702436351,
"name": "刘红珍",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702447900,
"name": "符引娣",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702460269,
"name": "郭天浩",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702472630,
"name": "申婷",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702487455,
"name": "胡飞宇",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702504527,
"name": "乌甜丽",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763702516929,
"name": "蒋雪柔",
"score": 0,
"level": "SSS",
"avatar": "⭐",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "五战区"
},
{
"id": 1763702537028,
"name": "刘家秀",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763702585045,
"name": "孙丽霞",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763702598899,
"name": "金芳林",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763702614259,
"name": "班悦",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763702630093,
"name": "吴玮良",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763702726441,
"name": "彭颖",
"score": 0,
"level": "SSS",
"avatar": "👑",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "一战区"
},
{
"id": 1763703383063,
"name": "李子豪",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763703395440,
"name": "崔凤鸣",
"score": 0,
"level": "SSS",
"avatar": "🔥",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "六战区"
},
{
"id": 1763703414516,
"name": "曹恒",
"score": 0,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 1763703472947,
"name": "刘孜一",
"score": 0,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
},
{
"id": 1763703487798,
"name": "王灿佳",
"score": 0,
"level": "SSS",
"avatar": "🎯",
"department": "销售部",
"completedTasks": 0,
"bonus": 0,
"team": "七战区"
}
],
"teamRankings": [
{
"id": 1,
"name": "一战区",
"totalScore": 844400,
"memberCount": 11,
"level": "SSS",
"leader": "王将军",
"completedTasks": 210,
"bonus": 0
},
{
"id": 7,
"name": "七战区",
"totalScore": 447000,
"memberCount": 8,
"level": "A",
"leader": "曹将军",
"completedTasks": 148,
"bonus": 0
},
{
"id": 4,
"name": "四战区",
"totalScore": 327800,
"memberCount": 10,
"level": "S",
"leader": "熊将军",
"completedTasks": 172,
"bonus": 0
},
{
"id": 3,
"name": "三战区",
"totalScore": 278200,
"memberCount": 9,
"level": "SS",
"leader": "李将军",
"completedTasks": 185,
"bonus": 0
},
{
"id": 6,
"name": "六战区",
"totalScore": 149000,
"memberCount": 10,
"level": "A",
"leader": "刘将军",
"completedTasks": 155,
"bonus": 0
},
{
"id": 5,
"name": "五战区",
"totalScore": 89400,
"memberCount": 9,
"level": "S",
"leader": "周将军",
"completedTasks": 165,
"bonus": 0
},
{
"id": 2,
"name": "二战区",
"totalScore": 86420,
"memberCount": 12,
"level": "SS",
"leader": "贺将军",
"completedTasks": 198,
"bonus": 0
}
],
"bonusRules": [
{
"rank": "1-3",
"individualBonus": "5000元, 3000元, 2000元",
"teamBonus": "15000元, 10000元, 8000元",
"description": "顶尖表现,高额奖励"
},
{
"rank": "4-6",
"individualBonus": "1500元, 1000元, 1000元",
"teamBonus": "6000元, 6000元",
"description": "优秀表现,丰厚激励"
},
{
"rank": "7-10",
"individualBonus": "800元, 800元, 500元, 500元",
"teamBonus": "无",
"description": "良好表现,基础奖励"
}
],
"systemUsers": [
{
"username": "admin",
"password": "admin123",
"role": "admin"
},
{
"username": "manager",
"password": "manager123",
"role": "manager"
}
],
"displayConfig": {
"showBonusModule": true,
"individual": {
"showLevel": false,
"showDepartment": false,
"scoreColumn": {
"displayName": "业绩",
"displayStyle": "amount"
},
"columnWidths": {
"rank": 48,
"avatar": 48,
"name": 100,
"score": 150,
"level": 80,
"department": 1,
"bonus": 100,
"team": 100
},
"columnAlignments": {
"rank": "center",
"avatar": "left",
"name": "left",
"score": "left",
"level": "left",
"department": "left",
"bonus": "left"
},
"defaultDisplayRows": 0,
"filterZeroScore": true
},
"crown": {
"size": 72,
"animationEnabled": true
},
"crownPosition": {
"top": -80,
"left": null,
"right": null,
"bottom": null
},
"team": {
"showMemberCount": false,
"showLeader": true,
"totalScoreColumn": {
"displayName": "业绩",
"displayStyle": "amount"
},
"columnWidths": {
"rank": 30,
"name": 100,
"score": 100,
"memberCount": 60,
"leader": 100,
"bonus": 80
},
"columnAlignments": {
"rank": "center",
"name": "center",
"score": "left",
"memberCount": "left",
"leader": "left",
"bonus": "left"
},
"defaultDisplayRows": 0,
"filterZeroScore": false
},
"championLogos": {
"teamChampion": "/uploads/1763979489455.png",
"individualChampion": "",
"teamChampionSize": 121,
"individualChampionSize": 120,
"teamChampionType": "photo",
"teamChampionPhotoWidth": 400,
"teamChampionPhotoHeight": 242
},
"subtitleImage": {
"src": "/completed_performance.png",
"width": 200,
"height": 60,
"alt": "总战绩"
}
},
"battleEndTime": {
"date": "2026-02-08",
"time": "00:00:00"
},
"drumConfig": {
"sound": {
"volume": 1,
"frequency1": 150,
"frequency2": 100,
"attackTime": 0.01,
"decayTime": 0.3,
"type1": "sine",
"type2": "triangle",
"enabled": false
},
"animation": {
"beatInterval": 200,
"beatScale": 1.3,
"beatTranslateY": -15,
"beatRotate": 5,
"idlePulseDuration": 2,
"beatDuration": 100,
"enabled": true
},
"pattern": {
"strongBeats": [
1,
4
],
"totalBeats": 4,
"accentMultiplier": 1.5,
"accentFrequencyOffset": 10,
"accentAnimation": 50
}
}
}

1553
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,14 +6,20 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"server": "npm run build && node server.js",
"start": "node server.js"
},
"dependencies": {
"cors": "^2.8.5",
"express": "^5.1.0",
"multer": "^1.4.5-lts.1",
"vue": "^3.5.24",
"vue-router": "^4.6.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"sass": "^1.94.0",
"vite": "^7.2.2"
}
}

BIN
public/award1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/award2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

BIN
public/award3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

BIN
public/banner0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

BIN
public/banner1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/banner2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

BIN
public/crown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 KiB

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

26
public/red-background.svg Normal file
View File

@@ -0,0 +1,26 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">
<!-- 渐变定义 -->
<defs>
<linearGradient id="redGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#e74c3c" stop-opacity="0.8"/>
<stop offset="50%" stop-color="#c0392b" stop-opacity="0.9"/>
<stop offset="100%" stop-color="#a93226" stop-opacity="0.8"/>
</linearGradient>
<!-- 纹理图案 -->
<pattern id="pattern" width="100" height="100" patternUnits="userSpaceOnUse">
<rect width="100" height="100" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
<circle cx="50" cy="50" r="2" fill="rgba(255,255,255,0.2)"/>
<path d="M0 50 L100 50 M50 0 L50 100" stroke="rgba(255,255,255,0.05)" stroke-width="1"/>
</pattern>
</defs>
<!-- 主背景 -->
<rect width="1920" height="1080" fill="url(#redGradient)"/>
<!-- 纹理叠加 -->
<rect width="1920" height="1080" fill="url(#pattern)"/>
<!-- 装饰性光效 -->
<circle cx="400" cy="200" r="300" fill="rgba(255,255,255,0.1)" filter="blur(50px)"/>
<circle cx="1500" cy="800" r="400" fill="rgba(255,255,255,0.08)" filter="blur(60px)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/team-propagation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

151
server.js Normal file
View File

@@ -0,0 +1,151 @@
import express from 'express';
import cors from 'cors';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import multer from 'multer';
// 获取当前文件的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = 3000;
const CONFIG_FILE_PATH = path.join(__dirname, 'data', 'config.json');
// 创建上传目录
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}
// 配置multer
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, uploadDir);
},
filename: (req, file, cb) => {
const timestamp = Date.now();
const ext = path.extname(file.originalname);
const filename = `${timestamp}${ext}`;
cb(null, filename);
}
});
const upload = multer({
storage,
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB限制
fileFilter: (req, file, cb) => {
const allowedTypes = /jpeg|jpg|png|gif/;
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
cb(new Error('只允许上传图片文件JPEG、JPG、PNG、GIF'));
}
}
});
// 中间件
app.use(cors());
app.use(express.json());
// 静态文件服务Vue应用和上传的图片
app.use(express.static(path.join(__dirname, 'dist')));
app.use('/uploads', express.static(uploadDir));
// API: 获取配置数据
app.get('/api/config', (req, res) => {
try {
const configData = fs.readFileSync(CONFIG_FILE_PATH, 'utf8');
res.json(JSON.parse(configData));
} catch (error) {
console.error('读取配置文件失败:', error);
res.status(500).json({ error: '读取配置文件失败' });
}
});
// API: 保存配置数据
app.post('/api/config', (req, res) => {
try {
fs.writeFileSync(CONFIG_FILE_PATH, JSON.stringify(req.body, null, 2), 'utf8');
res.json({ success: true });
} catch (error) {
console.error('保存配置文件失败:', error);
res.status(500).json({ error: '保存配置文件失败' });
}
});
// API: 上传图片
app.post('/api/upload', upload.single('image'), (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ error: '没有文件上传' });
}
// 返回文件的相对路径
const relativePath = `/uploads/${req.file.filename}`;
res.json({
success: true,
filePath: relativePath,
filename: req.file.filename
});
} catch (error) {
console.error('文件上传失败:', error);
res.status(500).json({ error: error.message || '文件上传失败' });
}
});
// API: 删除图片
app.delete('/api/upload/:filename', (req, res) => {
try {
const filename = req.params.filename;
const filePath = path.join(uploadDir, filename);
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
res.json({ success: true });
} else {
res.status(404).json({ error: '文件不存在' });
}
} catch (error) {
console.error('文件删除失败:', error);
res.status(500).json({ error: '文件删除失败' });
}
});
// 处理Vue Router历史模式 - 使用正则表达式代替通配符
app.get(/^((?!\/api).)*$/, (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});
// 启动服务器并监听错误
const server = app.listen(PORT, '0.0.0.0', () => {
console.log(`服务器运行在 http://localhost:${PORT}`);
console.log('服务器已成功启动,可以访问 http://localhost:3000');
console.log('API端点: GET/POST /api/config');
});
// 监听服务器错误
server.on('error', (error) => {
console.error('服务器错误:', error);
if (error.code === 'EADDRINUSE') {
console.error(`端口 ${PORT} 已被占用,请尝试其他端口。`);
}
});
// 监听SIGINT信号Ctrl+C
process.on('SIGINT', () => {
console.log('正在关闭服务器...');
server.close(() => {
console.log('服务器已关闭');
process.exit(0);
});
});
// 确保服务器持续运行
setInterval(() => {
// 保持服务器活动的空操作
}, 60000); // 每分钟执行一次

View File

@@ -3,14 +3,210 @@
</script>
<template>
<div class="app-container">
<router-view />
<div class="content-container">
<!-- 左侧标题语图片 - 相对于content-container定位 -->
<div class="banner-left">
<img src="/banner1.png" alt="左侧标题语" class="banner-image" />
</div>
<!-- Logo图片放置在左上角 - 相对于content-container定位 -->
<div class="logo-container">
<img src="/logo.png" alt="Logo" class="app-logo" />
</div>
<!-- 右侧标题语图片 - 相对于content-container定位 -->
<div class="banner-right">
<img src="/banner2.png" alt="右侧标题语" class="banner-image" />
</div>
<div class="main-content">
<router-view />
<!-- 页脚 -->
<footer class="game-footer">
<div class="footer-content">
<p>&copy; 2025-2026 聚上集团 | 云上企 版权所有.</p>
</div>
</footer>
</div>
</div>
</template>
<style scoped>
.app-container {
/* 左侧标题语样式 - 相对于content-container定位 */
.banner-left {
position: absolute;
left: 10px;
top: 680px;
transform: translateY(-50%);
z-index: 900; /* 低于logo但高于其他内容 */
max-width: 200px; /* 设置最大宽度 */
}
/* 右侧标题语样式 - 相对于content-container定位 */
.banner-right {
position: absolute;
right: 10px;
top: 680px;
transform: translateY(-50%);
z-index: 900; /* 低于logo但高于其他内容 */
max-width: 200px; /* 设置最大宽度 */
}
/* 标题语图片样式 */
.banner-image {
width: 100%;
height: auto;
border-radius: 4px; /* 添加圆角效果 */
}
/* Logo容器样式 - 相对于content-container定位 */
.logo-container {
position: absolute;
top: 10px;
left: 10px;
z-index: 1000; /* 确保logo在最上层 */
max-width: calc(100% - 20px); /* 确保不超出容器边界 */
}
/* Logo图片样式 - 不设置固定宽度 */
.app-logo {
width: 360px; /* 设置固定宽度为360px */
height: auto; /* 保持宽高比 */
border-radius: 8px; /* 添加圆角效果 */
max-width: 100%; /* 确保logo不超出容器 */
/* 不设置固定宽度让logo保持原始尺寸 */
}
/* 主容器 */
.main-content {
min-height: 100vh;
overflow-x: hidden;
position: relative;
}
/* 背景覆盖层,确保文本可读性 */
.main-content::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
z-index: -1;
}
.game-footer {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--dark-bg);
color: var(--gold-secondary);
padding: 20px 0;
text-align: center;
}
.footer-content {
font-size: 14px;
/* 雕刻效果使用多层text-shadow创建凸起感 */
text-shadow:
-1px -1px 0 rgba(255, 255, 255, 0.3), /* 高光 - 左上 */
1px 1px 0 rgba(0, 0, 0, 0.5), /* 阴影 - 右下 */
0 0 5px rgba(17, 17, 17, 0.5); /* 光晕 */
/* 背景和内边距 */
padding: 8px 16px;
border-radius: 4px;
/* 添加轻微的3D效果 */
transform: perspective(1000px) rotateX(0deg);
transition: all 0.3s ease;
}
/* 鼠标悬停时增强3D效果 */
.footer-content:hover {
transform: perspective(1000px) rotateX(2deg) translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
text-shadow:
-1px -1px 0 rgba(255, 255, 255, 0.4),
1px 1px 0 rgba(0, 0, 0, 0.6),
0 0 8px rgba(15, 15, 15, 0.7);
}
/* 针对1920x1080分辨率的banner精确定位 */
@media (width: 1920px) and (height: 1080px) {
.banner-left {
left: 120px !important;
top: 240px !important;
transform: translateY(0) !important;
}
.banner-right {
right: 120px !important;
top: 200px !important;
transform: translateY(0) !important;
}
}
/* 移动设备响应式设计 */
@media (max-width: 768px) {
/* 1. 背景图片全屏显示并固定 */
.main-content {
padding: 0 !important;
margin-top: 50px;
background-image: url('/battle-background.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed;
min-height: 100vh;
}
/* 移动设备上隐藏左右标题语,避免遮挡主要内容 */
.banner-left,
.banner-right {
scale: 0.4;
}
.banner-left {
margin-left: -28px;
top: 60px;
}
.banner-right{
margin-right: -28px;
top: 36px;
}
/* 移动设备上的logo样式 - 保持相对于content-container定位 */
.logo-container {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: auto;
text-align: center;
background: transparent; /* 设置为透明背景 */
padding: 5px;
border-radius: 0 0 8px 8px;
}
/* 移动设备上设置logo尺寸 */
.app-logo {
width: 200px; /* 移动设备上设置固定宽度为200px */
}
/* 移动设备上的页脚雕刻效果适配 */
.footer-content {
font-size: 12px;
padding: 6px 12px;
text-shadow:
-1px -1px 0 rgba(255, 255, 255, 0.2),
1px 1px 0 rgba(0, 0, 0, 0.4),
0 0 3px rgba(255, 215, 0, 0.4);
}
.footer-content:hover {
transform: none; /* 移动设备上禁用悬停效果 */
box-shadow: none;
}
}
</style>

View File

@@ -1,450 +1,172 @@
// 模拟数据 - 个人排名
export const individualRankings = [
{
id: 1,
name: '张三',
score: 985,
level: 'SSS',
avatar: '👑',
department: '销售部',
completedTasks: 48,
bonus: 5000
},
{
id: 2,
name: '李四',
score: 972,
level: 'SSS',
avatar: '🥇',
department: '技术部',
completedTasks: 45,
bonus: 3000
},
{
id: 3,
name: '王五',
score: 958,
level: 'SS',
avatar: '🥈',
department: '市场部',
completedTasks: 42,
bonus: 2000
},
{
id: 4,
name: '赵六',
score: 923,
level: 'SS',
avatar: '🥉',
department: '财务部',
completedTasks: 40,
bonus: 1500
},
{
id: 5,
name: '钱七',
score: 897,
level: 'S',
avatar: '⭐',
department: '人力资源部',
completedTasks: 38,
bonus: 1000
},
{
id: 6,
name: '孙八',
score: 876,
level: 'S',
avatar: '⭐',
department: '销售部',
completedTasks: 36,
bonus: 1000
},
{
id: 7,
name: '周九',
score: 854,
level: 'A',
avatar: '🔥',
department: '技术部',
completedTasks: 34,
bonus: 800
},
{
id: 8,
name: '吴十',
score: 832,
level: 'A',
avatar: '🔥',
department: '市场部',
completedTasks: 32,
bonus: 800
},
{
id: 9,
name: '郑十一',
score: 810,
level: 'B',
avatar: '⚡',
department: '财务部',
completedTasks: 30,
bonus: 500
},
{
id: 10,
name: '王十二',
score: 795,
level: 'B',
avatar: '⚡',
department: '人力资源部',
completedTasks: 28,
bonus: 500
},
{
id: 11,
name: '李十三',
score: 782,
level: 'B',
avatar: '⚡',
department: '销售部',
completedTasks: 26,
bonus: 500
},
{
id: 12,
name: '张十四',
score: 765,
level: 'B',
avatar: '⚡',
department: '技术部',
completedTasks: 24,
bonus: 500
},
{
id: 13,
name: '王十五',
score: 748,
level: 'B',
avatar: '⚡',
department: '市场部',
completedTasks: 22,
bonus: 500
},
{
id: 14,
name: '赵十六',
score: 732,
level: 'C',
avatar: '🎯',
department: '财务部',
completedTasks: 20,
bonus: 300
},
{
id: 15,
name: '钱十七',
score: 715,
level: 'C',
avatar: '🎯',
department: '人力资源部',
completedTasks: 18,
bonus: 300
}
import {
getIndividualRankings,
saveIndividualRankings as saveIndividualRankingsToConfig,
getTeamRankings,
saveTeamRankings as saveTeamRankingsToConfig,
getSystemUsers,
saveSystemUsers as saveSystemUsersToConfig,
addSystemUser as addSystemUserToConfig,
deleteSystemUser as deleteSystemUserToConfig,
updateSystemUser as updateSystemUserToConfig,
getDisplayConfig,
saveDisplayConfig as saveDisplayConfigToConfig,
getBattleEndTime,
saveBattleEndTime as saveBattleEndTimeToConfig,
getDrumConfig,
saveDrumConfig as saveDrumConfigToConfig,
getBonusRules,
saveBonusRules as saveBonusRulesToConfig
} from '../services/configService';
// 初始化空数据占位符将在initializeData中正确加载
export let individualRankings = [];
export let teamRankings = [];
export let bonusRules = [
{ rank: '1-3', description: '前三名', individualBonus: '¥10000, ¥8000, ¥5000', teamBonus: '¥50000, ¥30000, ¥20000' },
{ rank: '4-10', description: '四至十名', individualBonus: '¥3000/人', teamBonus: '¥10000/队' },
{ rank: '11-20', description: '十一至二十名', individualBonus: '¥1000/人', teamBonus: '¥5000/队' }
];
// 模拟数据 - 战队排名
export const teamRankings = [
{
id: 1,
name: '王者之师',
totalScore: 4850,
memberCount: 5,
level: 'SSS',
leader: '张三',
completedTasks: 210,
bonus: 15000
},
{
id: 2,
name: '战无不胜',
totalScore: 4680,
memberCount: 5,
level: 'SS',
leader: '李四',
completedTasks: 198,
bonus: 10000
},
{
id: 3,
name: '超越极限',
totalScore: 4520,
memberCount: 5,
level: 'SS',
leader: '王五',
completedTasks: 185,
bonus: 8000
},
{
id: 4,
name: '精英战队',
totalScore: 4280,
memberCount: 5,
level: 'S',
leader: '赵六',
completedTasks: 172,
bonus: 6000
},
{
id: 5,
name: '梦想之巅',
totalScore: 4150,
memberCount: 5,
level: 'S',
leader: '钱七',
completedTasks: 165,
bonus: 6000
},
{
id: 6,
name: '无敌战队',
totalScore: 3980,
memberCount: 5,
level: 'A',
leader: '孙八',
completedTasks: 155,
bonus: 4000
},
{
id: 7,
name: '冲锋陷阵',
totalScore: 3850,
memberCount: 5,
level: 'A',
leader: '周九',
completedTasks: 148,
bonus: 4000
},
{
id: 8,
name: '锐不可当',
totalScore: 3720,
memberCount: 5,
level: 'A',
leader: '吴十',
completedTasks: 142,
bonus: 4000
},
{
id: 9,
name: '同心协力',
totalScore: 3600,
memberCount: 5,
level: 'B',
leader: '郑十一',
completedTasks: 135,
bonus: 2000
},
{
id: 10,
name: '众志成城',
totalScore: 3480,
memberCount: 5,
level: 'B',
leader: '王十二',
completedTasks: 128,
bonus: 2000
},
{
id: 11,
name: '气势如虹',
totalScore: 3350,
memberCount: 5,
level: 'B',
leader: '李十三',
completedTasks: 122,
bonus: 2000
},
{
id: 12,
name: '披荆斩棘',
totalScore: 3220,
memberCount: 5,
level: 'B',
leader: '张十四',
completedTasks: 115,
bonus: 2000
},
{
id: 13,
name: '勇攀高峰',
totalScore: 3100,
memberCount: 5,
level: 'C',
leader: '王十五',
completedTasks: 108,
bonus: 1000
},
{
id: 14,
name: '力争上游',
totalScore: 2980,
memberCount: 5,
level: 'C',
leader: '赵十六',
completedTasks: 102,
bonus: 1000
},
{
id: 15,
name: '蓄势待发',
totalScore: 2850,
memberCount: 5,
level: 'C',
leader: '钱十七',
completedTasks: 95,
bonus: 1000
}
];
// 奖金设置说明
export const bonusRules = [
{
rank: '1-3',
individualBonus: '5000元, 3000元, 2000元',
teamBonus: '15000元, 10000元, 8000元',
description: '顶尖表现,高额奖励'
},
{
rank: '4-6',
individualBonus: '1500元, 1000元, 1000元',
teamBonus: '6000元, 6000元',
description: '优秀表现,丰厚激励'
},
{
rank: '7-10',
individualBonus: '800元, 800元, 500元, 500元',
teamBonus: '无',
description: '良好表现,基础奖励'
}
];
// 系统用户(用于后台登录)
export const systemUsers = [
{
username: 'admin',
password: 'admin123',
role: 'admin'
},
{
username: 'manager',
password: 'manager123',
role: 'manager'
}
];
// 显示配置
export const displayConfig = {
// 个人排名显示配置
individual: {
showLevel: false, // 显示等级列
showDepartment: false, // 显示部门列
scoreColumn: {
displayName: '签单金额', // 列显示名称
displayStyle: 'amount' // 显示样式: 'amount'(金额) 或 'number'(普通数字)
},
columnWidths: {
rank: 60, // 排名列宽度
avatar: 60, // 头像列宽度
name: 1, // 姓名列宽度1表示自动填充
score: 80, // 分数列宽度
level: 80, // 等级列宽度
department: 1, // 部门列宽度1表示自动填充
bonus: 80 // 奖金列宽度
}
},
// 战队排名显示配置
team: {
showMemberCount: false, // 显示人数列
showLeader: false, // 显示队长列
totalScoreColumn: {
displayName: '签单金额', // 列显示名称
displayStyle: 'amount' // 显示样式: 'amount'(金额) 或 'number'(普通数字)
},
columnWidths: {
rank: 60, // 排名列宽度
name: 1, // 战队名列宽度1表示自动填充
score: 80, // 分数列宽度
memberCount: 60, // 人数列宽度
leader: 1, // 队长列宽度1表示自动填充
bonus: 80 // 奖金列宽度
}
}
};
// 结束时间配置(精确到秒)
export let battleEndTime = {
date: '2026-02-01',
time: '23:59:59'
};
// 战鼓参数配置
export let drumConfig = {
// 音效参数
sound: {
volume: 1.0, // 音量 0-1
frequency1: 150, // 第一个音调频率
frequency2: 100, // 第二个音调频率
attackTime: 0.01, // 起音时间
decayTime: 0.3, // 衰减时间
type1: 'sine', // 第一个振荡器类型
type2: 'triangle' // 第二个振荡器类型
},
// 动画参数
animation: {
beatInterval: 200, // 节拍间隔(毫秒)
beatScale: 1.3, // 跳动缩放比例
beatTranslateY: -15, // 跳动上下位移
beatRotate: 5, // 跳动旋转角度
idlePulseDuration: 2, // 闲置脉动持续时间
beatDuration: 100 // 单次跳动持续时间
},
// 节拍模式
pattern: {
strongBeats: [1, 4], // 强拍位置1-4拍
totalBeats: 4 // 每小节总拍数
}
};
export let systemUsers = [];
export let displayConfig = null;
export let battleEndTime = { date: new Date().toISOString().split('T')[0], time: '00:00:00' };
export let drumConfig = {};
// 保存结束时间
export const saveBattleEndTime = (endTime) => {
battleEndTime = endTime;
export const saveBattleEndTime = async (endTime) => {
battleEndTime = { ...endTime };
console.log('保存结束时间:', battleEndTime);
return await saveBattleEndTimeToConfig(endTime);
};
// 保存数据的方法(模拟本地存储)
export const saveIndividualRankings = (data) => {
// 这里只是模拟实际项目中可以考虑使用localStorage或后端API
console.log('保存个人排名数据:', data);
// 在真实环境中可以调用API保存数据
// 保存英雄排名数据
export const saveIndividualRankings = async (data) => {
individualRankings = [...data];
console.log('保存英雄排名数据:', data);
return await saveIndividualRankingsToConfig(data);
};
export const saveTeamRankings = (data) => {
// 这里只是模拟实际项目中可以考虑使用localStorage或后端API
console.log('保存战队排名数据:', data);
// 在真实环境中可以调用API保存数据
// 保存战区排名数据
export const saveTeamRankings = async (data) => {
teamRankings = [...data];
console.log('保存战区排名数据:', data);
return await saveTeamRankingsToConfig(data);
};
// 保存显示配置
export const saveDisplayConfig = (config) => {
// 这里只是模拟实际项目中可以考虑使用localStorage或后端API
export const saveDisplayConfig = async (config) => {
displayConfig = { ...config };
console.log('保存显示配置:', config);
// 在真实环境中可以调用API保存数据
return await saveDisplayConfigToConfig(config);
};
// 保存战鼓配置
export const saveDrumConfig = (config) => {
// 这里只是模拟实际项目中可以考虑使用localStorage或后端API
export const saveDrumConfig = async (config) => {
console.log('保存战鼓配置:', config);
drumConfig = { ...drumConfig, ...config };
// 在真实环境中可以调用API保存数据
// 深度合并配置确保嵌套对象如sound、animation、pattern的属性不会丢失
drumConfig = {
...drumConfig,
...config,
sound: {
...drumConfig.sound,
...config.sound
},
animation: {
...drumConfig.animation,
...config.animation
},
pattern: {
...drumConfig.pattern,
...config.pattern
}
};
return await saveDrumConfigToConfig(drumConfig);
};
// 保存奖金规则
export const saveBonusRules = async (rules) => {
bonusRules = [...rules];
console.log('保存奖金规则:', rules);
return await saveBonusRulesToConfig(rules);
};
// 验证用户登录
export const validateUser = (username, password) => {
return systemUsers.find(user => user.username === username && user.password === password);
};
// 初始化数据(异步版本,用于应用启动时加载数据)
export const initializeData = async () => {
try {
await refreshData();
} catch (error) {
console.error('数据初始化失败:', error);
}
};
// 刷新数据
export const refreshData = async () => {
try {
individualRankings = await getIndividualRankings();
teamRankings = await getTeamRankings();
bonusRules = await getBonusRules() || [
{ rank: '1-3', description: '前三名', individualBonus: '¥10000, ¥8000, ¥5000', teamBonus: '¥50000, ¥30000, ¥20000' },
{ rank: '4-10', description: '四至十名', individualBonus: '¥3000/人', teamBonus: '¥10000/队' },
{ rank: '11-20', description: '十一至二十名', individualBonus: '¥1000/人', teamBonus: '¥5000/队' }
];
systemUsers = await getSystemUsers();
displayConfig = await getDisplayConfig();
battleEndTime = await getBattleEndTime();
drumConfig = await getDrumConfig();
return true;
} catch (error) {
console.error('刷新数据失败:', error);
return false;
}
};
// 添加系统用户
export const addSystemUser = async (user) => {
try {
const result = await addSystemUserToConfig(user);
if (result) {
// 刷新用户列表
systemUsers = await getSystemUsers();
}
return result;
} catch (error) {
console.error('添加用户失败:', error);
throw error;
}
};
// 删除系统用户
export const deleteSystemUser = async (userId) => {
try {
const result = await deleteSystemUserToConfig(userId);
if (result) {
// 刷新用户列表
systemUsers = await getSystemUsers();
}
return result;
} catch (error) {
console.error('删除用户失败:', error);
throw error;
}
};
// 更新系统用户
export const updateSystemUser = async (userId, updatedData) => {
try {
const result = await updateSystemUserToConfig(userId, updatedData);
if (result) {
// 刷新用户列表
systemUsers = await getSystemUsers();
}
return result;
} catch (error) {
console.error('更新用户失败:', error);
throw error;
}
};

View File

@@ -2,11 +2,13 @@ import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import { getBackgroundConfig } from './services/configService'
// 背景设置已移至样式表 style.css 中定义
const app = createApp(App)
// 使用路由
app.use(router)
// 挂载应用
app.mount('#app')
app.mount('#app');

View File

@@ -7,7 +7,7 @@ const routes = [
path: '/',
name: 'BattleRanking',
component: BattleRanking,
meta: { title: '百大战排行榜' }
meta: { title: '百大战排行榜' }
},
{
path: '/admin',

View File

@@ -0,0 +1,373 @@
// 配置文件API路径
const CONFIG_API_URL = '/api/config';
/**
* 读取配置文件
* @returns {Object} 配置数据
*/
export const readConfig = async () => {
try {
const response = await fetch(CONFIG_API_URL);
if (response.ok) {
return await response.json();
} else if (response.status === 404) {
// 配置文件不存在,使用默认配置
console.log('配置文件不存在,使用默认配置');
return getDefaultConfig();
}
throw new Error(`获取配置失败: ${response.status}`);
} catch (error) {
console.error('读取配置失败:', error);
return getDefaultConfig();
}
};
/**
* 写入配置文件
* @param {Object} config 新的配置数据
* @returns {boolean} 是否写入成功
*/
export const writeConfig = async (config) => {
try {
const response = await fetch(CONFIG_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(config)
});
if (response.ok) {
const result = await response.json();
return result.success;
}
throw new Error(`保存配置失败: ${response.status}`);
} catch (error) {
console.error('写入配置失败:', error);
return false;
}
};
// 同步版本的readConfig用于向后兼容
export const getConfig = async () => {
return await readConfig();
};
/**
* 获取默认配置(用于兜底)
* @returns {Object} 默认配置
*/
const getDefaultConfig = () => ({
individualRankings: [],
teamRankings: [],
bonusRules: [],
systemUsers: [],
displayConfig: {
showBonusModule: true, // 控制奖金设置模块的显示,默认不显示
individual: {
showLevel: false,
showDepartment: false,
scoreColumn: {
displayName: '分数',
displayStyle: 'number'
},
teamColumn: {
displayName: '战区',
displayStyle: 'text'
},
columnWidths: {
rank: '80px',
name: '150px',
dept: '150px',
team: '120px',
score: '100px',
level: '80px',
bonus: '100px'
}
},
team: {
showMemberCount: false,
showLeader: false,
totalScoreColumn: {
displayName: '业绩',
displayStyle: 'number'
},
columnWidths: {
rank: '80px',
name: '150px',
score: '100px',
memberCount: '120px',
bonus: '100px'
}
}
},
battleEndTime: {
date: new Date().toISOString().split('T')[0],
time: '00:00:00'
},
drumConfig: {
showDrum: false, // 控制战鼓的显示,默认不显示
sound: {
volume: 1.0,
enabled: false, // 控制声音播放,默认不播放
soundSrc: '' // 战鼓声音来源文件路径
},
animation: {
enabled: false
},
pattern: {
strongBeats: [1],
totalBeats: 4
}
},
backgroundConfig: {
useBackgroundImage: true,
backgroundImage: '/battle-background.jpg', // 默认战旗背景图片
backgroundSize: 'contain',
backgroundPosition: 'center',
backgroundColor: '#1a1a1a' // 备选背景色
}
});
/**
* 获取英雄排名数据
* @returns {Array} 英雄排名数组
*/
export const getIndividualRankings = async () => {
const config = await readConfig();
return config.individualRankings || [];
};
/**
* 保存英雄排名数据
* @param {Array} rankings 英雄排名数组
* @returns {boolean} 是否保存成功
*/
export const saveIndividualRankings = async (rankings) => {
const config = await readConfig();
config.individualRankings = rankings;
return await writeConfig(config);
};
/**
* 获取战区排名数据
* @returns {Array} 战区排名数组
*/
export const getTeamRankings = async () => {
const config = await readConfig();
return config.teamRankings || [];
};
/**
* 保存战区排名数据
* @param {Array} rankings 战区排名数组
* @returns {boolean} 是否保存成功
*/
export const saveTeamRankings = async (rankings) => {
const config = await readConfig();
config.teamRankings = rankings;
return await writeConfig(config);
};
/**
* 获取奖金规则
* @returns {Array} 奖金规则数组
*/
export const getBonusRules = async () => {
const config = await readConfig();
return config.bonusRules || [];
};
/**
* 保存奖金规则
* @param {Array} rules 奖金规则数组
* @returns {boolean} 是否保存成功
*/
export const saveBonusRules = async (rules) => {
const config = await readConfig();
config.bonusRules = rules;
return await writeConfig(config);
};
/**
* 获取系统用户
* @returns {Array} 系统用户数组
*/
export const getSystemUsers = async () => {
const config = await readConfig();
return config.systemUsers || [];
};
/**
* 保存系统用户
* @param {Array} users 系统用户数组
* @returns {boolean} 是否保存成功
*/
export const saveSystemUsers = async (users) => {
const config = await readConfig();
config.systemUsers = users;
return await writeConfig(config);
};
/**
* 添加用户
* @param {Object} user 用户信息
* @returns {boolean} 是否添加成功
*/
export const addSystemUser = async (user) => {
try {
const users = await getSystemUsers();
// 检查用户名是否已存在
const existingUser = users.find(u => u.username === user.username);
if (existingUser) {
throw new Error('用户名已存在');
}
users.push({
id: Date.now(),
...user
});
return await saveSystemUsers(users);
} catch (error) {
console.error('添加用户失败:', error);
throw error;
}
};
/**
* 删除用户
* @param {number} userId 用户ID
* @returns {boolean} 是否删除成功
*/
export const deleteSystemUser = async (userId) => {
try {
let users = await getSystemUsers();
// 确保至少保留一个管理员用户
if (users.length <= 1) {
throw new Error('系统至少需要保留一个管理员用户');
}
users = users.filter(u => u.id !== userId);
return await saveSystemUsers(users);
} catch (error) {
console.error('删除用户失败:', error);
throw error;
}
};
/**
* 更新用户信息
* @param {number} userId 用户ID
* @param {Object} updatedData 更新的数据
* @returns {boolean} 是否更新成功
*/
export const updateSystemUser = async (userId, updatedData) => {
try {
const users = await getSystemUsers();
const userIndex = users.findIndex(u => u.id === userId);
if (userIndex === -1) {
throw new Error('用户不存在');
}
// 如果要更新用户名,检查是否与其他用户冲突
if (updatedData.username && updatedData.username !== users[userIndex].username) {
const existingUser = users.find(u => u.id !== userId && u.username === updatedData.username);
if (existingUser) {
throw new Error('用户名已存在');
}
}
users[userIndex] = {
...users[userIndex],
...updatedData
};
return await saveSystemUsers(users);
} catch (error) {
console.error('更新用户失败:', error);
throw error;
}
};
/**
* 获取显示配置
* @returns {Object} 显示配置
*/
export const getDisplayConfig = async () => {
const config = await readConfig();
return config.displayConfig || getDefaultConfig().displayConfig;
};
/**
* 保存显示配置
* @param {Object} displayConfig 显示配置
* @returns {boolean} 是否保存成功
*/
export const saveDisplayConfig = async (displayConfig) => {
const config = await readConfig();
config.displayConfig = displayConfig;
return await writeConfig(config);
};
/**
* 获取战斗结束时间
* @returns {Object} 结束时间配置
*/
export const getBattleEndTime = async () => {
const config = await readConfig();
return config.battleEndTime || getDefaultConfig().battleEndTime;
};
/**
* 保存战斗结束时间
* @param {Object} endTime 结束时间配置
* @returns {boolean} 是否保存成功
*/
export const saveBattleEndTime = async (endTime) => {
const config = await readConfig();
config.battleEndTime = endTime;
return await writeConfig(config);
};
/**
* 获取战鼓配置
* @returns {Object} 战鼓配置
*/
export const getDrumConfig = async () => {
const config = await readConfig();
return config.drumConfig || getDefaultConfig().drumConfig;
};
/**
* 保存战鼓配置
* @param {Object} drumConfig 战鼓配置
* @returns {boolean} 是否保存成功
*/
export const saveDrumConfig = async (drumConfig) => {
const config = await readConfig();
config.drumConfig = drumConfig;
return await writeConfig(config);
};
/**
* 获取背景配置
* @returns {Object} 背景配置
*/
export const getBackgroundConfig = async () => {
const config = await readConfig();
return config.backgroundConfig || getDefaultConfig().backgroundConfig;
};
/**
* 保存背景配置
* @param {Object} backgroundConfig 背景配置
* @returns {boolean} 是否保存成功
*/
export const saveBackgroundConfig = async (backgroundConfig) => {
const config = await readConfig();
config.backgroundConfig = backgroundConfig;
return await writeConfig(config);
};

View File

@@ -5,25 +5,53 @@
box-sizing: border-box;
}
/* 图片预加载 - 提升移动端加载性能 */
body::before {
content: "";
display: none;
background-image: url(/battle-background.jpg);
}
/* 根元素样式 */
:root {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
/* 王者荣耀风格字体 - 使用系统默认字体但设置更多样化 */
font-family: 'Microsoft YaHei', 'PingFang SC', 'SimHei', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
line-height: 1.5;
font-weight: 400;
font-weight: 500;
/* 自定义颜色变量 */
--primary-color: #ff6b6b;
--secondary-color: #ee5a24;
--accent-color: #6c5ce7;
--success-color: #28a745;
--warning-color: #ffc107;
--danger-color: #dc3545;
--info-color: #17a2b8;
--dark-color: #343a40;
--light-color: #f8f9fa;
/* 王者荣耀风格配色方案 */
/* 主色调:金色、红色、黑色 */
--primary-color: #ffc107; /* 王者荣耀金色 */
--secondary-color: #e74c3c; /* 王者荣耀红色 */
--accent-color: #f39c12; /* 亮金色 */
--success-color: #27ae60; /* 成功绿色 */
--warning-color: #e67e22; /* 警告橙色 */
--danger-color: #c0392b; /* 危险深红色 */
--info-color: #3498db; /* 信息蓝色 */
--dark-color: #1a1a1a; /* 几乎黑色 */
--light-color: #f5f5f5; /* 浅灰色背景 */
--white-color: #ffffff;
--text-color: #495057;
--text-light: #6c757d;
--text-color: #333333;
--text-light: #666666;
/* 王者荣耀特有颜色 */
--gold-primary: #ffd700; /* 纯金色 */
--gold-secondary: #ffc700; /* 次级金色 */
--gold-tertiary: #ffb700; /* 三级金色 */
--red-primary: #e74c3c; /* 主红色 */
--red-secondary: #c0392b; /* 次级红色 */
--black-primary: #1a1a1a; /* 主黑色 */
--black-secondary: #2c2c2c; /* 次级黑色 */
/* 边框发光效果 */
--glow-primary: 0 0 10px rgba(255, 215, 0, 0.5);
--glow-secondary: 0 0 15px rgba(231, 76, 60, 0.4);
/* 渐变背景 */
--gradient-primary: linear-gradient(135deg, #ffd700, #ffc700, #ffb700);
--gradient-secondary: linear-gradient(135deg, #e74c3c, #c0392b, #a93226);
--gradient-background: linear-gradient(135deg, #1a1a1a, #2c2c2c, #1a1a1a);
--gradient-card: linear-gradient(145deg, #ffffff, #f0f0f0);
font-synthesis: none;
text-rendering: optimizeLegibility;
@@ -38,57 +66,393 @@ html, body {
width: 100%;
height: 100%;
color: var(--text-color);
background-color: var(--light-color);
background-color: var(--dark-color);
background-image: url(/battle-background.jpg);
background-size: auto;
background-position: top center;
background-repeat: revert;
background-attachment: fixed;
}
#app {
width: 100%;
min-height: 100vh;
display: flex;
justify-content: center;
}
/* 标题样式 */
/* 主内容容器 - 适配1920x1080分辨率 */
.content-container {
width: 100%;
max-width: 1920px;
min-height: 100vh;
padding: 0 20px;
position: relative;
box-sizing: border-box;
}
/* 当屏幕宽度超过1920px时保持内容居中且大小不变 */
@media (min-width: 1921px) {
.content-container {
width: 1920px;
margin: 0 auto;
/* box-shadow: 0 0 50px rgba(0, 0, 0, 0.5); */
}
}
/* 当屏幕高度超过1080px时保持内容垂直对齐 */
@media (min-height: 1081px) {
#app {
align-items: flex-start;
}
}
/* 针对1920x1080分辨率的精确调整 */
@media (width: 1920px) and (height: 1080px) {
.content-container {
padding: 0;
}
}
/* 游戏化标题样式 */
h1, h2, h3, h4, h5, h6 {
font-weight: 600;
font-weight: 700;
line-height: 1.2;
color: var(--dark-color);
color: var(--gold-primary);
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
letter-spacing: 0.5px;
}
/* 链接样式 */
/* 游戏化主标题 */
h1.game-title {
color: black;
font-size: 3.5rem;
font-weight: 800;
letter-spacing: 1px;
text-transform: uppercase;
text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
/* 游戏化次级标题 */
h2.game-subtitle {
color: var(--gold-secondary);
font-size: 1.8rem;
font-weight: 700;
letter-spacing: 0.5px;
text-align: center;
}
/* 游戏化链接样式 */
a {
color: var(--accent-color);
color: var(--gold-primary);
text-decoration: none;
transition: color 0.3s ease;
transition: all 0.3s ease;
font-weight: 500;
position: relative;
}
a:hover {
color: var(--primary-color);
text-decoration: underline;
color: var(--gold-tertiary);
text-decoration: none;
}
/* 按钮基础样式重置 */
a::after {
content: '';
position: absolute;
width: 0;
height: 2px;
bottom: -2px;
left: 0;
background-color: var(--gold-primary);
transition: width 0.3s ease;
}
a:hover::after {
width: 100%;
box-shadow: 0 0 5px var(--gold-primary);
}
/* 游戏化按钮样式 */
button {
font-family: inherit;
font-size: inherit;
line-height: inherit;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
button:focus {
outline: none;
}
/* 输入框基础样式 */
/* 游戏化主按钮 */
.btn-game {
background: var(--gradient-primary);
color: var(--black-primary);
border: 2px solid var(--gold-primary);
padding: 10px 20px;
border-radius: 30px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3), var(--glow-primary);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.btn-game:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4), var(--glow-primary);
background: var(--gold-tertiary);
}
.btn-game:active {
transform: translateY(-1px);
box-shadow: 0 2px 10px rgba(255, 215, 0, 0.3), var(--glow-primary);
}
/* 按钮波纹效果 */
.btn-game::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.btn-game:active::before {
width: 300px;
height: 300px;
}
/* 游戏化次要按钮 */
.btn-game-secondary {
background: var(--gradient-secondary);
color: var(--white-color);
border: 2px solid var(--red-primary);
padding: 10px 20px;
border-radius: 30px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
box-shadow: 0 4px 15px rgba(231, 76, 60, 0.3), var(--glow-secondary);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.btn-game-secondary:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(231, 76, 60, 0.4), var(--glow-secondary);
background: var(--red-secondary);
animation: borderGlow 1.5s ease-in-out infinite alternate;
}
.btn-game-secondary:active {
transform: translateY(-1px);
box-shadow: 0 2px 10px rgba(231, 76, 60, 0.3), var(--glow-secondary);
}
/* 次要按钮波纹效果 */
.btn-game-secondary::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.btn-game-secondary:active::before {
width: 300px;
height: 300px;
}
/* 游戏化输入框样式 */
input, select, textarea {
font-family: inherit;
font-size: inherit;
line-height: inherit;
background: rgba(0, 0, 0, 0.8);
border: 2px solid var(--gold-primary);
border-radius: 8px;
padding: 10px 15px;
color: var(--gold-primary);
transition: all 0.3s ease;
box-shadow: 0 0 5px rgba(255, 215, 0, 0.3);
font-weight: 600;
letter-spacing: 0.5px;
}
/* 表格样式重置 */
/* 登录表单输入框增强 */
.form-input {
background: rgba(0, 0, 0, 0.9);
border-color: var(--gold-secondary);
color: var(--gold-primary);
font-size: 1.1rem;
padding: 12px 15px;
width: 100%;
box-shadow: 0 0 10px rgba(255, 215, 0, 0.3), inset 0 0 10px rgba(0, 0, 0, 0.5);
}
.form-input:focus {
border-color: var(--gold-tertiary);
box-shadow: 0 0 15px rgba(255, 215, 0, 0.5), inset 0 0 10px rgba(0, 0, 0, 0.5);
background: rgba(0, 0, 0, 0.85);
}
/* 表单标签增强 */
.form-group label {
color: var(--gold-primary);
font-weight: 700;
font-size: 1.1rem;
margin-bottom: 8px;
display: block;
text-shadow: 0 0 10px rgba(255, 215, 0, 0.3);
}
/* 占位符文本颜色 */
input::placeholder {
color: rgba(255, 215, 0, 0.6);
font-style: italic;
}
/* 登录表单容器增强 */
.login-form {
background: rgba(0, 0, 0, 0.85);
padding: 30px;
border-radius: 15px;
box-shadow: 0 0 30px rgba(255, 215, 0, 0.4);
}
/* 错误信息增强 */
.error-message {
color: var(--red-primary);
font-weight: 600;
text-align: center;
margin-top: 15px;
padding: 10px;
border: 1px solid var(--red-primary);
border-radius: 5px;
background: rgba(231, 76, 60, 0.1);
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: var(--gold-tertiary);
box-shadow: 0 0 15px rgba(255, 215, 0, 0.4), var(--glow-primary);
background: rgba(255, 255, 255, 0.15);
}
/* 游戏化表格样式 */
table {
border-collapse: collapse;
width: 100%;
border: 2px solid var(--gold-primary);
box-shadow: 0 0 20px rgba(255, 215, 0, 0.2);
border-radius: 10px;
overflow: hidden;
animation: tableGlow 2s ease-in-out infinite alternate;
}
/* 表格发光动画 */
@keyframes tableGlow {
from { box-shadow: 0 0 20px rgba(255, 215, 0, 0.2); }
to { box-shadow: 0 0 30px rgba(255, 215, 0, 0.4); }
}
/* 游戏化卡片样式 */
.card-game {
background: transparent;
border: 0;
/* padding: 20px; */
transition: all 0.3s ease;
position: relative;
overflow: hidden;
animation: float 3s ease-in-out infinite;
}
.card-game::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255, 215, 0, 0.1), transparent);
transform: rotate(45deg);
animation: shine 6s infinite;
}
.card-game:hover {
transform: translateY(-5px);
/* box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), var(--glow-primary); */
/* border-color: var(--gold-tertiary); */
}
@keyframes shine {
0% { transform: rotate(45deg) translate(-100%, -100%); }
100% { transform: rotate(45deg) translate(100%, 100%); }
}
/* 卡片浮动动画 */
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
100% { transform: translateY(0px); }
}
/* 游戏化边框发光效果 */
.glow-border {
border: 2px solid var(--gold-primary);
box-shadow: 0 0 15px var(--gold-primary), 0 0 30px var(--gold-secondary), inset 0 0 15px var(--gold-primary);
border-radius: 10px;
transition: all 0.3s ease;
animation: glowPulse 2s ease-in-out infinite alternate;
}
.glow-border:hover {
box-shadow: 0 0 20px var(--gold-primary), 0 0 40px var(--gold-secondary), inset 0 0 20px var(--gold-primary);
border-color: var(--gold-tertiary);
animation: glowPulse 1s ease-in-out infinite alternate;
}
/* 发光脉动动画 */
@keyframes glowPulse {
from {
box-shadow: 0 0 10px var(--gold-primary), 0 0 20px var(--gold-secondary), inset 0 0 10px var(--gold-primary);
}
to {
box-shadow: 0 0 20px var(--gold-primary), 0 0 40px var(--gold-secondary), inset 0 0 20px var(--gold-primary);
}
}
/* 游戏化徽章样式 */
.badge-game {
background: var(--gradient-primary);
color: var(--black-primary);
padding: 5px 12px;
border-radius: 20px;
font-weight: 700;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.5px;
box-shadow: 0 2px 8px rgba(255, 215, 0, 0.3);
}
/* 滚动条样式 */
@@ -136,15 +500,220 @@ table {
.mb-4 { margin-bottom: 1.5rem; }
.mb-5 { margin-bottom: 3rem; }
/* 表格行样式增强 */
.table-row {
/* color: var(--gold-secondary); */
font-weight: 600;
font-size: 1rem;
transition: all 0.3s ease;
}
.table-row:hover {
color: var(--gold-primary);
background: rgba(255, 215, 0, 0.1);
}
.table-header {
color: var(--gold-primary);
font-weight: 700;
font-size: 1.1rem;
}
/* 表格单元格样式增强 */
.rank-col, .score-col, .bonus-col {
/* color: var(--gold-tertiary); */
font-weight: 700;
}
.name-col, .dept-col, .level-col {
/* color: var(--gold-secondary); */
font-weight: 600;
}
/* 响应式断点 */
@media (max-width: 768px) {
:root {
font-size: 14px;
}
/* 移动端背景图片优化:保留图片但优化加载性能 */
html, body {
background-color: var(--dark-color);
background-image: url(/battle-background.jpg);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: scroll;
/* 预加载优化 */
background-attachment: scroll !important;
}
.content-container {
padding: 0;
}
}
@media (max-width: 480px) {
:root {
font-size: 13px;
}
/* 小屏幕手机背景图片优化 */
html, body {
background-color: var(--dark-color);
background-image: url(/battle-background.jpg);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: scroll;
}
.content-container {
padding: 0;
}
}
/* 游戏化标题发光动画 */
.game-title {
animation: titleGlow 3s ease-in-out infinite alternate;
text-stroke: 1px var(--gold-tertiary);
-webkit-text-stroke: 1px var(--gold-tertiary);
}
@keyframes titleGlow {
from {
text-shadow:
0 0 1px rgba(0, 0, 0, 0.9), /* 提高清晰度的细影 */
0 0 10px rgba(255, 215, 0, 0.5);
}
to {
text-shadow:
0 0 1px rgba(0, 0, 0, 0.9), /* 提高清晰度的细影 */
0 0 15px rgba(255, 215, 0, 0.7),
0 0 25px rgba(255, 215, 0, 0.5);
}
}
/* 游戏化副标题发光动画 */
.game-subtitle {
animation: subtitleGlow 2s ease-in-out infinite alternate;
}
@keyframes subtitleGlow {
from {
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8), 0 0 15px rgba(255, 193, 7, 0.4);
}
to {
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8), 0 0 25px rgba(255, 193, 7, 0.6);
}
}
/* 数字滚动动画 */
@keyframes countUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 数字滚动效果类 */
.count-animation {
animation: countUp 0.8s ease-out;
font-weight: bold;
color: var(--gold-primary);
}
/* 鼠标悬停缩放效果 */
.hover-scale {
transition: transform 0.3s ease;
}
.hover-scale:hover {
transform: scale(1.05);
}
/* 游戏化滚动条样式 */
::-webkit-scrollbar {
width: 12px;
height: 12px;
}
::-webkit-scrollbar-track {
background: var(--dark-bg);
border-radius: 6px;
}
::-webkit-scrollbar-thumb {
background: linear-gradient(var(--gold-primary), var(--gold-secondary));
border-radius: 6px;
border: 2px solid var(--dark-bg);
}
::-webkit-scrollbar-thumb:hover {
background: linear-gradient(var(--gold-secondary), var(--gold-tertiary));
box-shadow: 0 0 10px rgba(255, 193, 7, 0.5);
}
/* 渐变背景动画 */
.gradient-bg {
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
/* 内容区域渐入动画 */
.content {
animation: fadeIn 0.8s ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 排名前三名特殊发光动画 */
.rank-1 {
animation: championGlow 2s ease-in-out infinite alternate;
}
.rank-2 {
animation: championGlow 2.5s ease-in-out infinite alternate;
}
.rank-3 {
animation: championGlow 3s ease-in-out infinite alternate;
}
@keyframes championGlow {
from {
transform: scale(1);
}
to {
transform: scale(1.05);
}
}
/* 金色文本悬停效果增强 */
.text-gold {
transition: all 0.3s ease;
}
.text-gold:hover {
color: var(--gold-secondary);
text-shadow: 0 0 10px rgba(255, 193, 7, 0.7);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
ui/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

BIN
ui/bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
ui/手表.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

BIN
ui/效果图.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
ui/未标题-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
ui/组 9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

BIN
uploads/1763860106271.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

BIN
uploads/1763956859312.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

BIN
uploads/1763972044872.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

BIN
uploads/1763979489455.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB