权限控制

This commit is contained in:
2025-06-27 14:10:21 +08:00
parent 75af99c222
commit 8b8b6b980a
7 changed files with 535 additions and 300 deletions

View File

@@ -1,281 +0,0 @@
<template>
<div v-if="visible" class="modal-overlay" @click.self="close">
<div class="modal-content">
<h2>{{ isEditMode ? '编辑参赛记录' : '添加参赛记录' }}</h2>
<form @submit.prevent="submitForm">
<div class="form-group">
<label for="tournament_id">选择赛事:</label>
<select id="tournament_id" v-model="form.tournament_id" @change="updateTournamentName" required :disabled="isEditMode">
<option disabled value="">请选择赛事</option>
<option v-for="t in availableTournaments" :key="t.id" :value="t.id">
{{ t.name }} (ID: {{ t.id }})
</option>
</select>
<input type="hidden" v-model="form.tournament_name">
</div>
<div class="form-group">
<label for="sign_name">报名者/队长名称:</label>
<input type="text" id="sign_name" v-model="form.sign_name" required>
</div>
<div class="form-group">
<label for="team_name">队伍名称 (可选):</label>
<input type="text" id="team_name" v-model="form.team_name">
</div>
<!-- API addSignUp 参数中包含 type, faction, qq, 这里简化处理 -->
<!-- 编辑模式下显示胜负和状态 -->
<template v-if="isEditMode">
<div class="form-group">
<label for="win">胜场数:</label>
<input type="number" id="win" v-model.number="form.win" min="0">
</div>
<div class="form-group">
<label for="lose">负场数:</label>
<input type="number" id="lose" v-model.number="form.lose" min="0">
</div>
<div class="form-group">
<label for="status">状态 (tie, win, lose):</label>
<input type="text" id="status" v-model="form.status">
</div>
<!-- 编辑模式下显示QQ号如果API支持 -->
<div class="form-group">
<label for="qq">QQ号 (可选, 编辑时):</label>
<input type="text" id="qq" v-model="form.qq">
</div>
</template>
<!-- 添加模式下需要QQ号如果addSignUp API需要 -->
<div v-if="!isEditMode" class="form-group">
<label for="qq_add">QQ号 (用于报名):</label>
<input type="text" id="qq_add" v-model="form.qq">
</div>
<div class="form-actions">
<button type="submit" class="submit-button">{{ isEditMode ? '更新记录' : '添加记录' }}</button>
<button type="button" @click="close" class="cancel-button">取消</button>
</div>
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
</form>
</div>
</div>
</template>
<script setup>
import { ref, watch, defineProps, defineEmits } from 'vue';
import { addSignUp, updateSignUpResult, getSignUpResultList } from '../../api/tournament';
const props = defineProps({
visible: Boolean,
playerData: Object, // 用于编辑模式
isEditMode: Boolean,
availableTournaments: Array // 赛事列表,用于选择
});
const emits = defineEmits(['close', 'save']);
const initialFormState = () => ({
tournament_id: null,
tournament_name: '',
sign_name: '',
team_name: '',
qq: '', // 用于添加和编辑
// 编辑模式下的字段
win: '0',
lose: '0',
status: 'tie',
// addSignUp 需要的额外字段 (如果适用)
type: 'individual', // 'teamname' or 'individual'
faction: 'random',
id: null // 在编辑模式下是player id添加模式下是tournament id (API addSignUp 需要 tournament_id as id)
});
const form = ref(initialFormState());
const errorMessage = ref('');
watch(() => props.playerData, (newData) => {
if (newData && props.isEditMode) {
form.value = {
...initialFormState(), // 使用函数确保获取新的初始状态对象
...newData,
id: newData.id // 确保 id 是 player.id
};
} else {
form.value = initialFormState();
}
}, { immediate: true, deep: true });
watch(() => props.visible, (isVisible) => {
if (isVisible && !props.isEditMode) {
form.value = initialFormState(); // 打开添加模态框时重置
}
});
const updateTournamentName = () => {
const selected = props.availableTournaments.find(t => t.id === form.value.tournament_id);
if (selected) {
form.value.tournament_name = selected.name;
}
};
const submitForm = async () => {
errorMessage.value = '';
if (!form.value.tournament_id) {
errorMessage.value = '请选择一个赛事。';
return;
}
updateTournamentName(); // 确保 tournament_name 是最新的
try {
if (props.isEditMode) {
const { id, ...originalFormData } = form.value;
// 为API准备数据确保win和lose是字符串
const dataForApi = {
...originalFormData,
win: String(originalFormData.win || '0'),
lose: String(originalFormData.lose || '0')
};
try {
const response = await getSignUpResultList();
const existingRecord = response.find(item => item.id === id);
if (!existingRecord) {
throw new Error('找不到要更新的报名记录');
}
// 使用处理过的数据调用更新API
await updateSignUpResult(id, dataForApi);
alert('参赛记录更新成功!');
} catch (error) {
console.error('更新参赛记录失败:', error);
errorMessage.value = error.response?.data?.detail || error.message || '更新失败,请重试';
return;
}
} else {
// 添加新记录的逻辑
const dataToAdd = {
...form.value,
id: form.value.tournament_id,
type: form.value.team_name ? 'teamname' : 'individual',
// 注意: form.value.win 和 form.value.lose 在 initialFormState 中默认为字符串 '0'
// 如果 addSignUp API 也严格要求字符串,且这些值可能变为数字,也需在此处 String()
};
await addSignUp(dataToAdd);
alert('参赛记录添加成功!');
}
emits('save');
close();
} catch (error) {
console.error('保存参赛记录失败:', error);
errorMessage.value = error.response?.data?.detail || error.message || '操作失败,请检查数据或联系管理员。';
}
};
const close = () => {
emits('close');
errorMessage.value = '';
// 不在此处重置表单,交由 watch 处理或在打开时处理
};
</script>
<style scoped>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
width: 90%;
max-width: 550px; /* 可以适当增大宽度 */
z-index: 1001;
}
.modal-content h2 {
margin-top: 0;
margin-bottom: 20px;
color: #333;
font-size: 1.5rem;
}
.form-group {
margin-bottom: 18px;
}
.form-group label {
display: block;
margin-bottom: 6px;
font-weight: 500;
color: #555;
font-size: 0.9rem;
}
.form-group input[type="text"],
.form-group input[type="number"],
.form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
font-size: 0.9rem;
}
.form-group input[type="text"]:focus,
.form-group input[type="number"]:focus,
.form-group select:focus {
border-color: #1890ff;
outline: none;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
.form-actions {
margin-top: 25px;
text-align: right;
}
.submit-button, .cancel-button {
padding: 10px 18px;
border-radius: 4px;
border: none;
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
}
.submit-button {
background-color: #1890ff;
color: white;
margin-right: 10px;
}
.submit-button:hover {
background-color: #40a9ff;
}
.cancel-button {
background-color: #f0f0f0;
color: #333;
}
.cancel-button:hover {
background-color: #e0e0e0;
}
.error-message {
color: red;
margin-top: 10px;
font-size: 0.85rem;
}
</style>