chore: 代码保存,除了冠军模块,其他显示正常

This commit is contained in:
2025-11-12 20:01:21 +08:00
parent 391c489fb5
commit d6ee43e48b
10 changed files with 1048 additions and 294 deletions

View File

@@ -336,6 +336,7 @@
} }
], ],
"displayConfig": { "displayConfig": {
"showBonusModule": true,
"individual": { "individual": {
"showLevel": false, "showLevel": false,
"showDepartment": false, "showDepartment": false,
@@ -371,8 +372,8 @@
} }
}, },
"battleEndTime": { "battleEndTime": {
"date": "2026-02-01", "date": "2026-02-08",
"time": "23:59:59" "time": "00:00:00"
}, },
"drumConfig": { "drumConfig": {
"sound": { "sound": {

View File

@@ -7,7 +7,7 @@
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"start": "node server.js" "start": "npm run build && node server.js"
}, },
"dependencies": { "dependencies": {
"cors": "^2.8.5", "cors": "^2.8.5",

View File

@@ -3,14 +3,95 @@
</script> </script>
<template> <template>
<div class="app-container"> <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>
<router-view /> <router-view />
</div> </div>
</template> </template>
<style scoped> <style scoped>
.app-container { /* 左侧标题语样式 - 相对于content-container定位 */
min-height: 100vh; .banner-left {
overflow-x: hidden; 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 {
height: auto; /* 保持宽高比 */
border-radius: 8px; /* 添加圆角效果 */
max-width: 100%; /* 确保logo不超出容器 */
/* 不设置固定宽度让logo保持原始尺寸 */
}
/* 移动设备响应式设计 */
@media (max-width: 768px) {
/* 移动设备上隐藏左右标题语,避免遮挡主要内容 */
.banner-left,
.banner-right {
display: none;
}
/* 移动设备上的logo样式 - 保持相对于content-container定位 */
.logo-container {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: auto;
text-align: center;
background-color: rgba(0, 0, 0, 0.7); /* 添加半透明背景确保在任何背景下都清晰可见 */
padding: 5px;
border-radius: 0 0 8px 8px;
}
/* 移动设备上缩小logo尺寸 */
.app-logo {
width: 60px; /* 移动设备上设置固定宽度 */
}
} }
</style> </style>

View File

@@ -38,17 +38,17 @@ export const saveBattleEndTime = async (endTime) => {
return await saveBattleEndTimeToConfig(endTime); return await saveBattleEndTimeToConfig(endTime);
}; };
// 保存个人排名数据 // 保存英雄排名数据
export const saveIndividualRankings = async (data) => { export const saveIndividualRankings = async (data) => {
individualRankings = [...data]; individualRankings = [...data];
console.log('保存个人排名数据:', data); console.log('保存英雄排名数据:', data);
return await saveIndividualRankingsToConfig(data); return await saveIndividualRankingsToConfig(data);
}; };
// 保存战排名数据 // 保存战排名数据
export const saveTeamRankings = async (data) => { export const saveTeamRankings = async (data) => {
teamRankings = [...data]; teamRankings = [...data];
console.log('保存战排名数据:', data); console.log('保存战排名数据:', data);
return await saveTeamRankingsToConfig(data); return await saveTeamRankingsToConfig(data);
}; };
@@ -62,7 +62,25 @@ export const saveDisplayConfig = async (config) => {
// 保存战鼓配置 // 保存战鼓配置
export const saveDrumConfig = async (config) => { export const saveDrumConfig = async (config) => {
console.log('保存战鼓配置:', config); console.log('保存战鼓配置:', config);
drumConfig = { ...drumConfig, ...config };
// 深度合并配置确保嵌套对象如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); return await saveDrumConfigToConfig(drumConfig);
}; };

View File

@@ -2,11 +2,43 @@ import { createApp } from 'vue'
import './style.css' import './style.css'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import { getBackgroundConfig } from './services/configService'
// 设置页面背景
const setupBackground = async () => {
try {
const backgroundConfig = await getBackgroundConfig();
// 如果配置了使用背景图片
if (backgroundConfig.useBackgroundImage && backgroundConfig.backgroundImage) {
document.body.style.backgroundImage = `url(${backgroundConfig.backgroundImage})`;
document.body.style.backgroundSize = backgroundConfig.backgroundSize || 'cover';
document.body.style.backgroundPosition = backgroundConfig.backgroundPosition || 'center';
document.body.style.backgroundRepeat = 'no-repeat';
document.body.style.backgroundAttachment = 'fixed';
} else if (backgroundConfig.backgroundColor) {
// 使用纯色背景
document.body.style.backgroundColor = backgroundConfig.backgroundColor;
document.body.style.backgroundImage = 'none';
}
} catch (error) {
console.error('设置背景失败:', error);
}
};
// 设置默认背景(立即应用)
document.body.style.backgroundImage = 'url(/battle-background.jpg)';
document.body.style.backgroundSize = 'contain';
document.body.style.backgroundPosition = 'center';
document.body.style.backgroundRepeat = 'no-repeat';
document.body.style.backgroundAttachment = 'fixed';
const app = createApp(App) const app = createApp(App)
// 使用路由 // 使用路由
app.use(router) app.use(router)
// 挂载应用 // 挂载应用前设置背景
app.mount('#app') setupBackground().then(() => {
app.mount('#app');
});

View File

@@ -64,6 +64,7 @@ const getDefaultConfig = () => ({
bonusRules: [], bonusRules: [],
systemUsers: [], systemUsers: [],
displayConfig: { displayConfig: {
showBonusModule: true, // 控制奖金设置模块的显示,默认不显示
individual: { individual: {
showLevel: false, showLevel: false,
showDepartment: false, showDepartment: false,
@@ -71,26 +72,46 @@ const getDefaultConfig = () => ({
displayName: '分数', displayName: '分数',
displayStyle: 'number' displayStyle: 'number'
}, },
columnWidths: {} teamColumn: {
displayName: '战区',
displayStyle: 'text'
},
columnWidths: {
rank: '80px',
name: '150px',
dept: '150px',
team: '120px',
score: '100px',
level: '80px',
bonus: '100px'
}
}, },
team: { team: {
showMemberCount: false, showMemberCount: false,
showLeader: false, showLeader: false,
totalScoreColumn: { totalScoreColumn: {
displayName: '总分', displayName: '业绩',
displayStyle: 'number' displayStyle: 'number'
}, },
columnWidths: {} columnWidths: {
rank: '80px',
name: '150px',
score: '100px',
memberCount: '120px',
bonus: '100px'
}
} }
}, },
battleEndTime: { battleEndTime: {
date: new Date().toISOString().split('T')[0], date: new Date().toISOString().split('T')[0],
time: '23:59:59' time: '00:00:00'
}, },
drumConfig: { drumConfig: {
showDrum: false, // 控制战鼓的显示,默认不显示
sound: { sound: {
volume: 1.0, volume: 1.0,
enabled: false enabled: false, // 控制声音播放,默认不播放
soundSrc: '' // 战鼓声音来源文件路径
}, },
animation: { animation: {
enabled: false enabled: false
@@ -99,12 +120,19 @@ const getDefaultConfig = () => ({
strongBeats: [1], strongBeats: [1],
totalBeats: 4 totalBeats: 4
} }
},
backgroundConfig: {
useBackgroundImage: true,
backgroundImage: '/battle-background.jpg', // 默认战旗背景图片
backgroundSize: 'contain',
backgroundPosition: 'center',
backgroundColor: '#1a1a1a' // 备选背景色
} }
}); });
/** /**
* 获取个人排名数据 * 获取英雄排名数据
* @returns {Array} 个人排名数组 * @returns {Array} 英雄排名数组
*/ */
export const getIndividualRankings = async () => { export const getIndividualRankings = async () => {
const config = await readConfig(); const config = await readConfig();
@@ -112,8 +140,8 @@ export const getIndividualRankings = async () => {
}; };
/** /**
* 保存个人排名数据 * 保存英雄排名数据
* @param {Array} rankings 个人排名数组 * @param {Array} rankings 英雄排名数组
* @returns {boolean} 是否保存成功 * @returns {boolean} 是否保存成功
*/ */
export const saveIndividualRankings = async (rankings) => { export const saveIndividualRankings = async (rankings) => {
@@ -123,8 +151,8 @@ export const saveIndividualRankings = async (rankings) => {
}; };
/** /**
* 获取战排名数据 * 获取战排名数据
* @returns {Array} 战排名数组 * @returns {Array} 战排名数组
*/ */
export const getTeamRankings = async () => { export const getTeamRankings = async () => {
const config = await readConfig(); const config = await readConfig();
@@ -132,8 +160,8 @@ export const getTeamRankings = async () => {
}; };
/** /**
* 保存战排名数据 * 保存战排名数据
* @param {Array} rankings 战排名数组 * @param {Array} rankings 战排名数组
* @returns {boolean} 是否保存成功 * @returns {boolean} 是否保存成功
*/ */
export const saveTeamRankings = async (rankings) => { export const saveTeamRankings = async (rankings) => {
@@ -270,7 +298,7 @@ export const updateSystemUser = async (userId, updatedData) => {
*/ */
export const getDisplayConfig = async () => { export const getDisplayConfig = async () => {
const config = await readConfig(); const config = await readConfig();
return config.displayConfig || {}; return config.displayConfig || getDefaultConfig().displayConfig;
}; };
/** /**
@@ -290,7 +318,7 @@ export const saveDisplayConfig = async (displayConfig) => {
*/ */
export const getBattleEndTime = async () => { export const getBattleEndTime = async () => {
const config = await readConfig(); const config = await readConfig();
return config.battleEndTime || {}; return config.battleEndTime || getDefaultConfig().battleEndTime;
}; };
/** /**
@@ -310,7 +338,7 @@ export const saveBattleEndTime = async (endTime) => {
*/ */
export const getDrumConfig = async () => { export const getDrumConfig = async () => {
const config = await readConfig(); const config = await readConfig();
return config.drumConfig || {}; return config.drumConfig || getDefaultConfig().drumConfig;
}; };
/** /**
@@ -323,3 +351,23 @@ export const saveDrumConfig = async (drumConfig) => {
config.drumConfig = drumConfig; config.drumConfig = drumConfig;
return await writeConfig(config); 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

@@ -1,47 +0,0 @@
import { getConfig, writeConfig } from './configService.js';
// 测试配置服务功能
const testConfigService = async () => {
try {
console.log('开始测试配置服务...');
// 读取配置
const config = await getConfig();
console.log('成功读取配置:', {
hasIndividualRankings: config.individualRankings?.length > 0,
hasTeamRankings: config.teamRankings?.length > 0,
hasSystemUsers: config.systemUsers?.length > 0,
hasDisplayConfig: !!config.displayConfig,
hasBattleEndTime: !!config.battleEndTime,
hasDrumConfig: !!config.drumConfig
});
// 写入配置(添加一个小的修改然后恢复)
const testKey = 'test_timestamp';
const originalValue = config[testKey];
config[testKey] = Date.now();
await writeConfig(config);
console.log('成功写入配置修改');
// 验证修改已保存
const updatedConfig = await getConfig();
console.log('修改验证成功:', updatedConfig[testKey] === config[testKey]);
// 恢复原始状态
if (originalValue === undefined) {
delete updatedConfig[testKey];
} else {
updatedConfig[testKey] = originalValue;
}
await writeConfig(updatedConfig);
console.log('成功恢复原始配置');
return { success: true };
} catch (error) {
console.error('配置服务测试失败:', error);
return { success: false, error: error.message };
}
};
export default testConfigService;

View File

@@ -67,6 +67,41 @@ html, body {
#app { #app {
width: 100%; width: 100%;
min-height: 100vh; 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;
}
} }
/* 游戏化标题样式 */ /* 游戏化标题样式 */
@@ -332,12 +367,9 @@ table {
/* 游戏化卡片样式 */ /* 游戏化卡片样式 */
.card-game { .card-game {
background: rgba(255, 255, 255, 0.05); background: transparent;
border: 2px solid var(--gold-primary); border: 0;
border-radius: 15px; /* padding: 20px; */
padding: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), var(--glow-primary);
backdrop-filter: blur(10px);
transition: all 0.3s ease; transition: all 0.3s ease;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@@ -358,8 +390,8 @@ table {
.card-game:hover { .card-game:hover {
transform: translateY(-5px); transform: translateY(-5px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), var(--glow-primary); /* box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), var(--glow-primary); */
border-color: var(--gold-tertiary); /* border-color: var(--gold-tertiary); */
} }
@keyframes shine { @keyframes shine {

View File

@@ -51,7 +51,7 @@
>{{ tab.label }}</button> >{{ tab.label }}</button>
</div> </div>
<!-- 内容区域 --><div class="tab-content"> <!-- 内容区域 --><div class="tab-content" style="max-height: calc(100vh - 200px); overflow-y: auto;">
<!-- 结束时间设置 --><div v-if="currentTab === 'endTime'" class="end-time-content"> <!-- 结束时间设置 --><div v-if="currentTab === 'endTime'" class="end-time-content">
<h2 class="game-subtitle"> 百人大战结束时间设置</h2> <h2 class="game-subtitle"> 百人大战结束时间设置</h2>
<div class="time-setting-section"> <div class="time-setting-section">
@@ -259,9 +259,9 @@
<div class="table-header"> <div class="table-header">
<span class="rank-col">排名</span> <span class="rank-col">排名</span>
<span class="name-col">姓名</span> <span class="name-col">姓名</span>
<span class="score-col">{{ displayConfig.individual.scoreColumn.displayName }}</span> <span class="score-col">{{ localDisplayConfig.individual.scoreColumn.displayName }}</span>
<span v-if="displayConfig.individual.showLevel" class="level-col">等级</span> <span v-if="localDisplayConfig.individual.showLevel" class="level-col">等级</span>
<span v-if="displayConfig.individual.showDepartment" class="dept-col">部门</span> <span v-if="localDisplayConfig.individual.showDepartment" class="dept-col">部门</span>
<span class="bonus-col">奖金</span> <span class="bonus-col">奖金</span>
<span class="action-col">操作</span> <span class="action-col">操作</span>
</div> </div>
@@ -273,9 +273,9 @@
> >
<span class="rank-col">{{ index + 1 }}</span> <span class="rank-col">{{ index + 1 }}</span>
<span class="name-col">{{ item.name }}</span> <span class="name-col">{{ item.name }}</span>
<span class="score-col">{{ displayConfig.individual.scoreColumn.displayStyle === 'amount' ? '¥' + item.score : item.score }}</span> <span class="score-col">{{ localDisplayConfig.individual.scoreColumn.displayStyle === 'amount' ? '¥' + item.score : item.score }}</span>
<span v-if="displayConfig.individual.showLevel" class="level-col" :class="`level-${item.level}`">{{ item.level }}</span> <span v-if="localDisplayConfig.individual.showLevel" class="level-col" :class="`level-${item.level}`">{{ item.level }}</span>
<span v-if="displayConfig.individual.showDepartment" class="dept-col">{{ item.department }}</span> <span v-if="localDisplayConfig.individual.showDepartment" class="dept-col">{{ item.department }}</span>
<span class="bonus-col">¥{{ item.bonus }}</span> <span class="bonus-col">¥{{ item.bonus }}</span>
<span class="action-col"> <span class="action-col">
<button @click="editIndividual(item)" class="btn-game-secondary"> 编辑</button> <button @click="editIndividual(item)" class="btn-game-secondary"> 编辑</button>
@@ -294,9 +294,9 @@
<div class="table-header"> <div class="table-header">
<span class="rank-col">排名</span> <span class="rank-col">排名</span>
<span class="name-col">战队名称</span> <span class="name-col">战队名称</span>
<span class="score-col">{{ displayConfig.team.totalScoreColumn.displayName }}</span> <span class="score-col">{{ localDisplayConfig.team.totalScoreColumn.displayName }}</span>
<span v-if="displayConfig.team.showMemberCount" class="member-col">人数</span> <span v-if="localDisplayConfig.team.showMemberCount" class="member-col">人数</span>
<span v-if="displayConfig.team.showLeader" class="leader-col">队长</span> <span v-if="localDisplayConfig.team.showLeader" class="leader-col">队长</span>
<span class="bonus-col">奖金</span> <span class="bonus-col">奖金</span>
<span class="action-col">操作</span> <span class="action-col">操作</span>
</div> </div>
@@ -308,9 +308,9 @@
> >
<span class="rank-col">{{ index + 1 }}</span> <span class="rank-col">{{ index + 1 }}</span>
<span class="name-col">{{ item.name }}</span> <span class="name-col">{{ item.name }}</span>
<span class="score-col">{{ displayConfig.team.totalScoreColumn.displayStyle === 'amount' ? '¥' + item.totalScore : item.totalScore }}</span> <span class="score-col">{{ localDisplayConfig.team.totalScoreColumn.displayStyle === 'amount' ? '¥' + item.totalScore : item.totalScore }}</span>
<span v-if="displayConfig.team.showMemberCount" class="member-col">{{ item.memberCount }}</span> <span v-if="localDisplayConfig.team.showMemberCount" class="member-col">{{ item.memberCount }}</span>
<span v-if="displayConfig.team.showLeader" class="leader-col">{{ item.leader }}</span> <span v-if="localDisplayConfig.team.showLeader" class="leader-col">{{ item.leader }}</span>
<span class="bonus-col">¥{{ item.bonus }}</span> <span class="bonus-col">¥{{ item.bonus }}</span>
<span class="action-col"> <span class="action-col">
<button @click="editTeam(item)" class="btn-game-secondary"> 编辑</button> <button @click="editTeam(item)" class="btn-game-secondary"> 编辑</button>

File diff suppressed because it is too large Load Diff