chore: 调整管理员排名列表

This commit is contained in:
2025-11-13 15:48:26 +08:00
parent 6f842ef328
commit 4164ea36ee
3 changed files with 95 additions and 52 deletions

View File

@@ -42,7 +42,7 @@
"department": "财务部",
"completedTasks": 40,
"bonus": 1500,
"team": "精英战"
"team": "精英战"
},
{
"id": 5,
@@ -64,7 +64,7 @@
"department": "销售部",
"completedTasks": 36,
"bonus": 1000,
"team": "无敌战"
"team": "无敌战"
},
{
"id": 7,
@@ -199,7 +199,7 @@
},
{
"id": 4,
"name": "精英战",
"name": "精英战",
"totalScore": 4280,
"memberCount": 5,
"level": "S",
@@ -219,7 +219,7 @@
},
{
"id": 6,
"name": "无敌战",
"name": "无敌战",
"totalScore": 3980,
"memberCount": 5,
"level": "A",
@@ -378,12 +378,16 @@
},
"columnWidths": {
"rank": 60,
"name": 150,
"name": 200,
"score": 120,
"memberCount": 60,
"leader": 1,
"bonus": 80
}
},
"championLogos": {
"teamChampion": "",
"individualChampion": ""
}
},
"battleEndTime": {

View File

@@ -24,8 +24,10 @@
class="form-input"
/>
</div>
<button @click="login" class="btn-game">登录</button>
<button @click="goToHome" class="btn-game-secondary">返回首页</button>
<div style="display: flex; gap: 15px; margin-top: 25px;">
<button @click="login" type="submit" class="btn-game" style="flex: 1; padding: 12px;">登录</button>
<button @click="goToHome" class="btn-game-secondary" style="flex: 1; padding: 12px;">返回首页</button>
</div>
<div v-if="loginError" class="error-message">{{ loginError }}</div>
</div>
</div>
@@ -169,9 +171,9 @@
</div>
</div>
<!-- 排名显示配置 -->
<!-- 排名显示配置 -->
<div class="config-section">
<h3 class="text-gold">👥 排名显示选项</h3>
<h3 class="text-gold">👥 排名显示选项</h3>
<div class="config-options">
<div class="config-item">
<label class="checkbox-label">
@@ -215,7 +217,7 @@
<input type="number" v-model.number="localDisplayConfig.team.columnWidths.rank" min="40" max="200" class="width-input">
</div>
<div class="column-width-item">
<label class="text-gold">名列</label>
<label class="text-gold">名列</label>
<select v-model.number="localDisplayConfig.team.columnWidths.name" class="width-select">
<option :value="1">自动填充</option>
<option value="150">150px</option>
@@ -258,6 +260,7 @@
<div class="rank-table">
<div class="table-header">
<span class="rank-col">排名</span>
<span class="avatar-col">头像</span>
<span class="name-col">姓名</span>
<span class="score-col">{{ localDisplayConfig.individual.scoreColumn.displayName }}</span>
<span v-if="localDisplayConfig.individual.showLevel" class="level-col">等级</span>
@@ -272,28 +275,32 @@
:class="{ 'highlight': index === 0 }"
>
<span class="rank-col">{{ index + 1 }}</span>
<span class="avatar-col">
<img v-if="item.avatar && item.avatar.startsWith('/')" :src="item.avatar" alt="头像" class="table-avatar">
<span v-else>{{ item.avatar || '👤' }}</span>
</span>
<span class="name-col">{{ item.name }}</span>
<span class="score-col">{{ localDisplayConfig.individual.scoreColumn.displayStyle === 'amount' ? '¥' + item.score : item.score }}</span>
<span v-if="localDisplayConfig.individual.showLevel" class="level-col" :class="`level-${item.level}`">{{ item.level }}</span>
<span v-if="localDisplayConfig.individual.showDepartment" class="dept-col">{{ item.department }}</span>
<span class="bonus-col">¥{{ item.bonus }}</span>
<span class="action-col">
<button @click="editIndividual(item)" class="btn-game-secondary"> 编辑</button>
<button @click="deleteIndividual(item.id)" class="btn-game-secondary">🗑 删除</button>
<button @click="editIndividual(item)" class="btn-game-secondary btn-edit"></button>
<button @click="deleteIndividual(item.id)" class="btn-game-secondary btn-delete">🗑</button>
</span>
</div>
</div>
</div>
<!-- 排名管理 --><div v-if="currentTab === 'team'" class="rank-content">
<!-- 排名管理 --><div v-if="currentTab === 'team'" class="rank-content">
<div class="management-header">
<h2 class="game-subtitle">👥 排名管理</h2>
<button @click="showAddTeam = true" class="btn-game"> 添加战</button>
<h2 class="game-subtitle">👥 排名管理</h2>
<button @click="showAddTeam = true" class="btn-game"> 添加战</button>
</div>
<div class="rank-table">
<div class="table-header">
<span class="rank-col">排名</span>
<span class="name-col">名称</span>
<span class="name-col">名称</span>
<span class="score-col">{{ localDisplayConfig.team.totalScoreColumn.displayName }}</span>
<span v-if="localDisplayConfig.team.showMemberCount" class="member-col">人数</span>
<span v-if="localDisplayConfig.team.showLeader" class="leader-col">队长</span>
@@ -313,8 +320,8 @@
<span v-if="localDisplayConfig.team.showLeader" class="leader-col">{{ item.leader }}</span>
<span class="bonus-col">¥{{ item.bonus }}</span>
<span class="action-col">
<button @click="editTeam(item)" class="btn-game-secondary"> 编辑</button>
<button @click="deleteTeam(item.id)" class="btn-game-secondary">🗑 删除</button>
<button @click="editTeam(item)" class="btn-game-secondary btn-edit"></button>
<button @click="deleteTeam(item.id)" class="btn-game-secondary btn-delete">🗑</button>
</span>
</div>
</div>
@@ -366,16 +373,16 @@
<h3 class="text-gold">🎯 战区冠军Logo</h3>
<div class="logo-upload-section">
<div class="logo-preview">
<div v-if="championLogos.teamChampionLogo" class="logo-image-container">
<img :src="championLogos.teamChampionLogo" alt="战区冠军Logo" class="logo-preview-image">
</div>
<div v-if="championLogos.teamChampion" class="logo-image-container">
<img :src="championLogos.teamChampion" alt="战区冠军Logo" class="logo-preview-image">
</div>
<div v-else class="logo-placeholder">
<span>未上传Logo</span>
</div>
</div>
<div class="upload-controls">
<input type="file" accept="image/*" @change="(e) => handleChampionLogoUpload(e, 'teamChampion')" class="logo-input">
<button v-if="championLogos.teamChampionLogo" @click="clearChampionLogo('teamChampion')" class="btn-clear">
<button v-if="championLogos.teamChampion" @click="clearChampionLogo('teamChampion')" class="btn-clear">
清除Logo
</button>
</div>
@@ -387,16 +394,16 @@
<h3 class="text-gold">👤 英雄冠军Logo</h3>
<div class="logo-upload-section">
<div class="logo-preview">
<div v-if="championLogos.individualChampionLogo" class="logo-image-container">
<img :src="championLogos.individualChampionLogo" alt="英雄冠军Logo" class="logo-preview-image">
</div>
<div v-if="championLogos.individualChampion" class="logo-image-container">
<img :src="championLogos.individualChampion" alt="英雄冠军Logo" class="logo-preview-image">
</div>
<div v-else class="logo-placeholder">
<span>未上传Logo</span>
</div>
</div>
<div class="upload-controls">
<input type="file" accept="image/*" @change="(e) => handleChampionLogoUpload(e, 'individualChampion')" class="logo-input">
<button v-if="championLogos.individualChampionLogo" @click="clearChampionLogo('individualChampion')" class="btn-clear">
<button v-if="championLogos.individualChampion" @click="clearChampionLogo('individualChampion')" class="btn-clear">
清除Logo
</button>
</div>
@@ -736,12 +743,12 @@
</div>
</div>
<!-- 添加/编辑战对话框 --><div v-if="showAddTeam || showEditTeam" class="modal-overlay">
<!-- 添加/编辑战对话框 --><div v-if="showAddTeam || showEditTeam" class="modal-overlay">
<div class="modal">
<h3 class="modal-title">{{ editingTeam ? '编辑战' : '添加战' }}</h3>
<h3 class="modal-title">{{ editingTeam ? '编辑战' : '添加战' }}</h3>
<form @submit.prevent="saveTeam">
<div class="form-group">
<label>名称:</label>
<label>名称:</label>
<input v-model="teamForm.name" type="text" required class="form-input">
</div>
<div class="form-group">
@@ -810,7 +817,7 @@ const currentUser = ref({});
// 标签页相关
const tabs = [
{ key: 'individual', label: '个人排名' },
{ key: 'team', label: '战排名' },
{ key: 'team', label: '战排名' },
{ key: 'bonus', label: '奖金设置' },
{ key: 'config', label: '显示配置' },
{ key: 'champion', label: '冠军Logo配置' },
@@ -820,8 +827,8 @@ const tabs = [
// 冠军Logo配置
const championLogos = ref({
teamChampionLogo: '',
individualChampionLogo: ''
teamChampion: '',
individualChampion: ''
});
// 组件挂载时初始化冠军Logo配置
@@ -868,8 +875,8 @@ const handleChampionLogoUpload = async (event, type) => {
const result = await response.json();
if (result.success) {
// 删除旧的图片
if (championLogos.value[`${type}Logo`] && championLogos.value[`${type}Logo`].startsWith('/uploads/')) {
const oldFilename = championLogos.value[`${type}Logo`].split('/').pop();
if (championLogos.value[type] && championLogos.value[type].startsWith('/uploads/')) {
const oldFilename = championLogos.value[type].split('/').pop();
fetch(`/api/upload/${oldFilename}`, {
method: 'DELETE'
}).catch(error => {
@@ -877,7 +884,7 @@ const handleChampionLogoUpload = async (event, type) => {
});
}
championLogos.value[`${type}Logo`] = result.filePath;
championLogos.value[type] = result.filePath;
} else {
alert('上传失败: ' + result.error);
}
@@ -892,15 +899,15 @@ const handleChampionLogoUpload = async (event, type) => {
// 清除冠军Logo
const clearChampionLogo = (type) => {
if (championLogos.value[`${type}Logo`] && championLogos.value[`${type}Logo`].startsWith('/uploads/')) {
const filename = championLogos.value[`${type}Logo`].split('/').pop();
if (championLogos.value[type] && championLogos.value[type].startsWith('/uploads/')) {
const filename = championLogos.value[type].split('/').pop();
fetch(`/api/upload/${filename}`, {
method: 'DELETE'
}).catch(error => {
console.error('删除文件失败:', error);
});
}
championLogos.value[`${type}Logo`] = '';
championLogos.value[type] = '';
};
// 刷新数据
@@ -1190,7 +1197,7 @@ const deleteIndividual = (id) => {
}
};
// 添加/编辑战
// 添加/编辑战
const editTeam = (item) => {
editingTeam.value = item;
Object.assign(teamForm, item);
@@ -1199,7 +1206,7 @@ const editTeam = (item) => {
const saveTeam = () => {
if (editingTeam.value) {
// 编辑现有战
// 编辑现有战
const index = localTeamRankings.value.findIndex(
i => i.id === teamForm.id
);
@@ -1207,7 +1214,7 @@ const saveTeam = () => {
localTeamRankings.value[index] = { ...teamForm };
}
} else {
// 添加新战
// 添加新战
teamForm.id = Date.now();
localTeamRankings.value.push({ ...teamForm });
}
@@ -1232,9 +1239,9 @@ const resetTeamForm = () => {
teamForm.bonus = 0;
};
// 删除战
// 删除战
const deleteTeam = (id) => {
if (confirm('确定要删除这个战吗?')) {
if (confirm('确定要删除这个战吗?')) {
localTeamRankings.value = localTeamRankings.value.filter(
item => item.id !== id
);
@@ -1259,7 +1266,14 @@ const deleteBonusRule = (index) => {
};
</script>
<style scoped>
<style lang="scss" scoped>
.btn-edit, .btn-delete {
padding: 0;
cursor: pointer;
transition: background-color 0.3s;
}
.admin-panel {
min-height: 70vh;
margin-top: 80px;
@@ -1280,6 +1294,9 @@ const deleteBonusRule = (index) => {
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
min-width: 300px;
display: flex;
flex-direction: column;
gap: 15px;
}
.login-title {
@@ -1302,16 +1319,22 @@ const deleteBonusRule = (index) => {
.form-input {
width: 100%;
padding: 10px;
padding: 12px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.3s;
transition: border-color 0.3s, box-shadow 0.3s;
min-height: 44px; /* 增加最小高度,符合可访问性标准 */
}
.form-input:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); /* 增加聚焦效果 */
}
.form-input:hover {
border-color: #99a5f0; /* 悬停效果 */
}
.login-btn {
@@ -1364,7 +1387,7 @@ const deleteBonusRule = (index) => {
width: 100%;
max-width: 1200px;
margin: 0 auto;
height: 100vh;
height: 90vh;
}
.top-nav {
@@ -1613,18 +1636,22 @@ const deleteBonusRule = (index) => {
background: linear-gradient(45deg, #6c757d, #adb5bd);
color: white;
display: grid;
grid-template-columns: 60px 1fr 80px 80px 100px 80px 120px;
grid-template-columns: 60px 120px 1fr 80px 80px 100px 80px 120px;
padding: 15px 10px;
font-weight: bold;
}
.team-rankings .table-header {
grid-template-columns: 60px 1fr 80px 60px 100px 80px 120px;
grid-template-columns: 60px 2fr 80px 60px 100px 80px 120px;
}
.table-row {
display: grid;
grid-template-columns: 60px 1fr 80px 80px 100px 80px 120px;
grid-template-columns: 60px 120px 1fr 80px 80px 100px 80px 120px;
}
.team-rankings .table-row {
grid-template-columns: 60px 2fr 80px 60px 100px 80px 120px;
padding: 15px 10px;
border-bottom: 1px solid #dee2e6;
transition: background-color 0.3s;
@@ -1643,6 +1670,18 @@ const deleteBonusRule = (index) => {
color: white;
}
.avatar-col {
text-align: center;
font-size: 1.2rem;
}
.table-avatar {
width: 30px;
height: 30px;
object-fit: contain;
vertical-align: middle;
}
/* 等级样式 */
.level-SSS {
color: #ffd700;

View File

@@ -113,8 +113,8 @@
<div class="rank-table">
<div class="table-header" :style="{ 'grid-template-columns': individualGridTemplate }">
<span class="rank-col">排名</span>
<span class="avatar-col">头像</span>
<span class="name-col">姓名</span>
<span class="avatar-col">头像</span>
<span class="name-col">姓名</span>
<span v-if="localDisplayConfig.individual?.showTeam" class="team-col">{{ localDisplayConfig.individual?.teamColumn?.displayName || '战区' }}</span>
<span class="score-col">{{ localDisplayConfig.individual?.scoreColumn?.displayName || '业绩' }}</span>
<span v-if="localDisplayConfig.individual?.showLevel" class="level-col">等级</span>