<template>
|
<div class="review-container">
|
<el-card>
|
<template #header>
|
<div class="card-header">
|
<h3 class="card-title">项目评审</h3>
|
</div>
|
</template>
|
|
<el-form :inline="true" class="search-form">
|
<el-form-item label="选择比赛">
|
<el-select
|
v-model="selectedActivity"
|
placeholder="请选择比赛"
|
@change="handleActivityChange"
|
style="width: 300px"
|
clearable
|
filterable
|
>
|
<el-option
|
v-for="activity in activities"
|
:key="activity.id"
|
:label="getActivityDisplayName(activity)"
|
:value="activity.id"
|
>
|
<span>{{ getActivityName(activity) }}</span>
|
<span v-if="activity.pid > 0" style="color: #409eff; margin-left: 8px;">
|
{{ activity.name }}
|
</span>
|
</el-option>
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="项目名称">
|
<el-input
|
v-model="searchName"
|
placeholder="请输入项目名称"
|
@keyup.enter="loadProjects"
|
style="width: 200px"
|
/>
|
</el-form-item>
|
|
<el-form-item>
|
<el-button type="primary" @click="loadProjects" :loading="projectsLoading">
|
搜索
|
</el-button>
|
<el-button @click="resetSearch">重置</el-button>
|
</el-form-item>
|
</el-form>
|
|
<el-table
|
:data="projects"
|
style="width: 100%"
|
v-loading="projectsLoading"
|
empty-text="请先选择比赛"
|
>
|
<el-table-column prop="playerName" label="项目名称" min-width="150">
|
<template #default="scope">
|
{{ scope.row.projectName || scope.row.playerName }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="playerName" label="参赛人姓名" min-width="120" />
|
<el-table-column prop="phone" label="联系电话" min-width="120" />
|
<el-table-column prop="ratingCount" label="评审次数" width="100" align="center">
|
<template #default="scope">
|
<el-tag :type="scope.row.ratingCount > 0 ? 'success' : 'info'">
|
{{ scope.row.ratingCount }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="averageScore" label="平均分" width="100" align="center">
|
<template #default="scope">
|
<span v-if="scope.row.averageScore > 0" class="score">
|
{{ scope.row.averageScore.toFixed(1) }}
|
</span>
|
<span v-else class="no-score">未评分</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="applyTime" label="报名时间" width="180">
|
<template #default="scope">
|
{{ formatDate(scope.row.applyTime) }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="state" label="状态" width="100" align="center">
|
<template #default="scope">
|
<el-tag :type="getStateType(scope.row.state)">
|
{{ getStateName(scope.row.state) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="120" fixed="right">
|
<template #default="scope">
|
<el-button type="primary" link @click="viewDetails(scope.row.id)">
|
详情评审
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- 分页 -->
|
<div class="pagination-container" v-if="total > 0">
|
<el-pagination
|
v-model:current-page="currentPage"
|
v-model:page-size="pageSize"
|
:page-sizes="[10, 20, 50, 100]"
|
:total="total"
|
layout="total, sizes, prev, pager, next, jumper"
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
/>
|
</div>
|
</el-card>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, onMounted } from 'vue'
|
import { useRouter } from 'vue-router'
|
import { ElMessage } from 'element-plus'
|
import { getActiveActivities, getCompetitionProjects } from '@/api/projectReview'
|
|
const router = useRouter()
|
|
// 响应式数据
|
const activities = ref([])
|
const selectedActivity = ref(null)
|
const projects = ref([])
|
const searchName = ref('')
|
const activitiesLoading = ref(false)
|
const projectsLoading = ref(false)
|
|
// 分页数据
|
const currentPage = ref(1)
|
const pageSize = ref(10)
|
const total = ref(0)
|
|
// 加载比赛列表
|
const loadActivities = async () => {
|
activitiesLoading.value = true
|
try {
|
const data = await getActiveActivities()
|
activities.value = data
|
} catch (error) {
|
ElMessage.error(error.message)
|
} finally {
|
activitiesLoading.value = false
|
}
|
}
|
|
// 加载项目列表
|
const loadProjects = async () => {
|
if (!selectedActivity.value) {
|
ElMessage.warning('请先选择比赛')
|
return
|
}
|
|
projectsLoading.value = true
|
try {
|
const response = await getCompetitionProjects(
|
selectedActivity.value,
|
currentPage.value - 1, // 后端从0开始
|
pageSize.value,
|
searchName.value
|
)
|
|
projects.value = response.content || []
|
total.value = response.totalElements || 0
|
} catch (error) {
|
console.error('加载项目列表失败:', error)
|
ElMessage.error('加载项目列表失败')
|
// 如果API调用失败,显示空数据
|
projects.value = []
|
total.value = 0
|
} finally {
|
projectsLoading.value = false
|
}
|
}
|
|
// 处理比赛选择变化
|
const handleActivityChange = (activityId) => {
|
currentPage.value = 1
|
loadProjects()
|
}
|
|
// 重置搜索
|
const resetSearch = () => {
|
searchName.value = ''
|
currentPage.value = 1
|
if (selectedActivity.value) {
|
loadProjects()
|
}
|
}
|
|
// 分页处理
|
const handleSizeChange = (size) => {
|
pageSize.value = size
|
currentPage.value = 1
|
loadProjects()
|
}
|
|
const handleCurrentChange = (page) => {
|
currentPage.value = page
|
loadProjects()
|
}
|
|
// 查看详情
|
const viewDetails = (projectId) => {
|
router.push(`/project-review/${projectId}/detail`)
|
}
|
|
// 格式化日期
|
const formatDate = (dateString) => {
|
if (!dateString) return '-'
|
return new Date(dateString).toLocaleString('zh-CN')
|
}
|
|
// 获取状态类型
|
const getStateType = (state) => {
|
const stateMap = {
|
0: 'danger', // 已拒绝
|
1: 'warning', // 待审核
|
2: 'success', // 已通过
|
3: 'info' // 已结束
|
}
|
return stateMap[state] || 'info'
|
}
|
|
// 获取状态名称
|
const getStateName = (state) => {
|
const stateMap = {
|
0: '已拒绝',
|
1: '待评审',
|
2: '已通过',
|
3: '已结束'
|
}
|
return stateMap[state] || '未知'
|
}
|
|
// 获取比赛名称(如果是阶段,返回父比赛名称;如果是比赛,返回自己的名称)
|
const getActivityName = (activity) => {
|
if (activity.pid > 0 && activity.parent) {
|
return activity.parent.name
|
}
|
return activity.name
|
}
|
|
// 获取活动显示名称(用于搜索和选中时显示)
|
const getActivityDisplayName = (activity) => {
|
if (activity.pid > 0 && activity.parent) {
|
return `${activity.parent.name} - ${activity.name}`
|
}
|
return activity.name
|
}
|
|
// 获取阶段名称(如果是阶段,返回阶段名称;如果是比赛,返回比赛名称)
|
const getStageName = (activity) => {
|
return activity.name
|
}
|
|
// 组件挂载时加载数据
|
onMounted(() => {
|
loadActivities()
|
})
|
</script>
|
|
<style scoped>
|
.review-container {
|
padding: 20px;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.card-title {
|
margin: 0;
|
font-size: 18px;
|
font-weight: 500;
|
}
|
|
.search-form {
|
margin-bottom: 20px;
|
padding: 20px;
|
background-color: #f5f7fa;
|
border-radius: 4px;
|
}
|
|
.score {
|
color: #67c23a;
|
font-weight: 600;
|
}
|
|
.no-score {
|
color: #909399;
|
font-style: italic;
|
}
|
|
.pagination-container {
|
margin-top: 20px;
|
display: flex;
|
justify-content: center;
|
}
|
|
:deep(.el-table) {
|
border-radius: 4px;
|
}
|
|
:deep(.el-table th) {
|
background-color: #fafafa;
|
}
|
|
:deep(.el-tag) {
|
border-radius: 12px;
|
}
|
</style>
|