feat: 成果详情未完成计算得分时展示引导并隐藏列表
Made-with: Cursor
This commit is contained in:
parent
4ba2af18f6
commit
aca472aa54
@ -20,24 +20,36 @@
|
|||||||
<!-- 统计摘要 -->
|
<!-- 统计摘要 -->
|
||||||
<div class="stats-row">
|
<div class="stats-row">
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
<div class="stat-icon" style="background: rgba(99,102,241,0.1)"><file-text-outlined style="color: #6366f1" /></div>
|
<div class="stat-icon" style="background: rgba(99,102,241,0.1)"><file-text-outlined style="color: #6366f1" />
|
||||||
<div class="stat-info"><span class="stat-count">{{ summary.totalWorks }}</span><span class="stat-label">总作品</span></div>
|
</div>
|
||||||
|
<div class="stat-info"><span class="stat-count">{{ summary.totalWorks }}</span><span
|
||||||
|
class="stat-label">总作品</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
<div class="stat-icon" style="background: rgba(59,130,246,0.1)"><check-circle-outlined style="color: #3b82f6" /></div>
|
<div class="stat-icon" style="background: rgba(59,130,246,0.1)"><check-circle-outlined style="color: #3b82f6" />
|
||||||
<div class="stat-info"><span class="stat-count">{{ summary.scoredWorks }}</span><span class="stat-label">已评分</span></div>
|
</div>
|
||||||
|
<div class="stat-info"><span class="stat-count">{{ summary.scoredWorks }}</span><span
|
||||||
|
class="stat-label">已评分</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
<div class="stat-icon" style="background: rgba(16,185,129,0.1)"><ordered-list-outlined style="color: #10b981" /></div>
|
<div class="stat-icon" style="background: rgba(16,185,129,0.1)"><ordered-list-outlined style="color: #10b981" />
|
||||||
<div class="stat-info"><span class="stat-count">{{ summary.rankedWorks }}</span><span class="stat-label">已排名</span></div>
|
</div>
|
||||||
|
<div class="stat-info"><span class="stat-count">{{ summary.rankedWorks }}</span><span
|
||||||
|
class="stat-label">已排名</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
<div class="stat-icon" style="background: rgba(245,158,11,0.1)"><trophy-outlined style="color: #f59e0b" /></div>
|
<div class="stat-icon" style="background: rgba(245,158,11,0.1)"><trophy-outlined style="color: #f59e0b" /></div>
|
||||||
<div class="stat-info"><span class="stat-count">{{ summary.awardedWorks }}</span><span class="stat-label">已设奖</span></div>
|
<div class="stat-info"><span class="stat-count">{{ summary.awardedWorks }}</span><span
|
||||||
|
class="stat-label">已设奖</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-card" v-if="summary.avgScore">
|
<div class="stat-card" v-if="summary.avgScore">
|
||||||
<div class="stat-icon" style="background: rgba(139,92,246,0.1)"><fund-outlined style="color: #8b5cf6" /></div>
|
<div class="stat-icon" style="background: rgba(139,92,246,0.1)"><fund-outlined style="color: #8b5cf6" /></div>
|
||||||
<div class="stat-info"><span class="stat-count">{{ summary.avgScore }}</span><span class="stat-label">平均分</span></div>
|
<div class="stat-info"><span class="stat-count">{{ summary.avgScore }}</span><span class="stat-label">平均分</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -59,68 +71,93 @@
|
|||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 搜索 -->
|
<!-- 未完成第一步计算得分:操作引导(不展示列表) -->
|
||||||
<div class="filter-bar">
|
<div v-if="!showResultsList" class="step-guide-card">
|
||||||
<a-form :model="searchParams" layout="inline" @finish="handleSearch">
|
<div class="step-guide-icon">
|
||||||
<a-form-item label="作品编号">
|
<calculator-outlined />
|
||||||
<a-input v-model:value="searchParams.workNo" placeholder="请输入作品编号" allow-clear style="width: 150px" />
|
</div>
|
||||||
</a-form-item>
|
<h3 class="step-guide-title">请先完成第一步:计算得分</h3>
|
||||||
<a-form-item label="报名账号">
|
<p class="step-guide-desc">
|
||||||
<a-input v-model:value="searchParams.accountNo" placeholder="请输入报名账号" allow-clear style="width: 150px" />
|
成果列表依赖各作品的最终得分。请先点击下方按钮,系统将根据评审规则汇总评分并写入最终得分;完成后再进行排名、设奖与发布。
|
||||||
</a-form-item>
|
</p>
|
||||||
<a-form-item label="奖项">
|
<ol class="step-guide-steps">
|
||||||
<a-select v-model:value="searchParams.awardLevel" placeholder="全部" allow-clear style="width: 120px" @change="handleSearch">
|
<li>点击「第一步:计算得分」或下方按钮,汇总评委评分为最终得分</li>
|
||||||
<a-select-option v-for="opt in awardFilterOptions" :key="opt" :value="opt">{{ opt }}</a-select-option>
|
<li>再依次完成第二步排名、第三步设奖(见上方操作区)</li>
|
||||||
<a-select-option value="_none">无奖项</a-select-option>
|
</ol>
|
||||||
</a-select>
|
<a-button type="primary" size="large" :loading="calcScoreLoading" @click="handleCalculateScores">
|
||||||
</a-form-item>
|
<template #icon><calculator-outlined /></template>
|
||||||
<a-form-item>
|
开始计算得分
|
||||||
<a-button type="primary" html-type="submit"><template #icon><search-outlined /></template> 搜索</a-button>
|
</a-button>
|
||||||
<a-button style="margin-left: 8px" @click="handleReset"><template #icon><reload-outlined /></template> 重置</a-button>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
<template v-else>
|
||||||
<a-table :columns="columns" :data-source="dataSource" :loading="loading" :pagination="pagination" row-key="id" @change="handleTableChange" class="data-table">
|
<!-- 搜索 -->
|
||||||
<template #bodyCell="{ column, record, index }">
|
<div class="filter-bar">
|
||||||
<template v-if="column.key === 'index'">
|
<a-form :model="searchParams" layout="inline" @finish="handleSearch">
|
||||||
{{ (pagination.current - 1) * pagination.pageSize + index + 1 }}
|
<a-form-item label="作品编号">
|
||||||
</template>
|
<a-input v-model:value="searchParams.workNo" placeholder="请输入作品编号" allow-clear style="width: 150px" />
|
||||||
<template v-else-if="column.key === 'rank'">
|
</a-form-item>
|
||||||
<span v-if="record.rank" class="rank-badge" :class="getRankClass(record.rank)">{{ record.rank }}</span>
|
<a-form-item label="报名账号">
|
||||||
<span v-else class="text-muted">-</span>
|
<a-input v-model:value="searchParams.accountNo" placeholder="请输入报名账号" allow-clear style="width: 150px" />
|
||||||
</template>
|
</a-form-item>
|
||||||
<template v-else-if="column.key === 'workNo'">
|
<a-form-item label="奖项">
|
||||||
<a @click="handleViewWorkDetail(record)">{{ record.workNo || '-' }}</a>
|
<a-select v-model:value="searchParams.awardLevel" placeholder="全部" allow-clear style="width: 120px"
|
||||||
</template>
|
@change="handleSearch">
|
||||||
<template v-else-if="column.key === 'finalScore'">
|
<a-select-option v-for="opt in awardFilterOptions" :key="opt" :value="opt">{{ opt }}</a-select-option>
|
||||||
<span v-if="record.finalScore != null" class="score">{{ Number(record.finalScore).toFixed(2) }}</span>
|
<a-select-option value="_none">无奖项</a-select-option>
|
||||||
<span v-else class="text-muted">-</span>
|
</a-select>
|
||||||
</template>
|
</a-form-item>
|
||||||
<template v-else-if="column.key === 'awardLevel'">
|
<a-form-item>
|
||||||
<a-tag v-if="record.awardName" :color="getAwardColor(record.awardName)">
|
<a-button type="primary" html-type="submit"><template #icon><search-outlined /></template> 搜索</a-button>
|
||||||
{{ record.awardName }}
|
<a-button style="margin-left: 8px" @click="handleReset"><template #icon><reload-outlined /></template>
|
||||||
</a-tag>
|
重置</a-button>
|
||||||
<span v-else class="text-muted">-</span>
|
</a-form-item>
|
||||||
</template>
|
</a-form>
|
||||||
<template v-else-if="column.key === 'nickname'">
|
</div>
|
||||||
<template v-if="contestInfo?.contestType === 'team'">
|
|
||||||
{{ record.registration?.team?.teamName || record.registration?.user?.nickname || '-' }}
|
<!-- 数据表格 -->
|
||||||
|
<a-table :columns="columns" :data-source="dataSource" :loading="loading" :pagination="pagination" row-key="id"
|
||||||
|
@change="handleTableChange" class="data-table">
|
||||||
|
<template #bodyCell="{ column, record, index }">
|
||||||
|
<template v-if="column.key === 'index'">
|
||||||
|
{{ (pagination.current - 1) * pagination.pageSize + index + 1 }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="column.key === 'rank'">
|
||||||
{{ record.registration?.user?.nickname || record.registration?.team?.teamName || '-' }}
|
<span v-if="record.rank" class="rank-badge" :class="getRankClass(record.rank)">{{ record.rank }}</span>
|
||||||
|
<span v-else class="text-muted">-</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'workNo'">
|
||||||
|
<a @click="handleViewWorkDetail(record)">{{ record.workNo || '-' }}</a>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'finalScore'">
|
||||||
|
<span v-if="record.finalScore != null" class="score">{{ Number(record.finalScore).toFixed(2) }}</span>
|
||||||
|
<span v-else class="text-muted">-</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'awardLevel'">
|
||||||
|
<a-tag v-if="record.awardName" :color="getAwardColor(record.awardName)">
|
||||||
|
{{ record.awardName }}
|
||||||
|
</a-tag>
|
||||||
|
<span v-else class="text-muted">-</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'nickname'">
|
||||||
|
<template v-if="contestInfo?.contestType === 'team'">
|
||||||
|
{{ record.registration?.team?.teamName || record.registration?.user?.nickname || '-' }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ record.registration?.user?.nickname || record.registration?.team?.teamName || '-' }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'username'">
|
||||||
|
{{ record.submitterAccountNo || record.registration?.user?.username || '-' }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'action'">
|
||||||
|
<a-button v-if="!isSuperAdmin && contestInfo?.resultState !== 'published'" type="link" size="small"
|
||||||
|
@click="openSetAward(record)">设奖</a-button>
|
||||||
|
<a-button type="link" size="small" @click="handleViewWorkDetail(record)">查看</a-button>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'username'">
|
</a-table>
|
||||||
{{ record.submitterAccountNo || record.registration?.user?.username || '-' }}
|
</template>
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'action'">
|
|
||||||
<a-button v-if="!isSuperAdmin && contestInfo?.resultState !== 'published'" type="link" size="small" @click="openSetAward(record)">设奖</a-button>
|
|
||||||
<a-button type="link" size="small" @click="handleViewWorkDetail(record)">查看</a-button>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
|
|
||||||
<!-- 作品详情弹框 -->
|
<!-- 作品详情弹框 -->
|
||||||
<WorkDetailModal v-model:open="workDetailModalVisible" :work-id="currentWorkId" />
|
<WorkDetailModal v-model:open="workDetailModalVisible" :work-id="currentWorkId" />
|
||||||
@ -129,16 +166,19 @@
|
|||||||
<a-modal v-model:open="setAwardVisible" title="设置奖项" @ok="handleSetAward" :confirm-loading="setAwardLoading">
|
<a-modal v-model:open="setAwardVisible" title="设置奖项" @ok="handleSetAward" :confirm-loading="setAwardLoading">
|
||||||
<a-form layout="vertical" style="margin-top: 16px">
|
<a-form layout="vertical" style="margin-top: 16px">
|
||||||
<a-form-item label="作品">
|
<a-form-item label="作品">
|
||||||
<span>{{ currentAwardWork?.workNo }} — {{ currentAwardWork?.registration?.user?.nickname || currentAwardWork?.registration?.team?.teamName }}</span>
|
<span>{{ currentAwardWork?.workNo }} — {{ currentAwardWork?.registration?.user?.nickname ||
|
||||||
|
currentAwardWork?.registration?.team?.teamName }}</span>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="奖项名称" required>
|
<a-form-item label="奖项名称" required>
|
||||||
<a-select v-model:value="awardForm.awardName" placeholder="选择或输入奖项名称" mode="combobox" :options="existingAwardOptions" />
|
<a-select v-model:value="awardForm.awardName" placeholder="选择或输入奖项名称" mode="combobox"
|
||||||
|
:options="existingAwardOptions" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
<!-- 自动设置奖项弹窗 -->
|
<!-- 自动设置奖项弹窗 -->
|
||||||
<a-modal v-model:open="autoAwardVisible" title="按排名自动设置奖项" @ok="handleAutoSetAwards" :confirm-loading="autoAwardLoading" width="520px">
|
<a-modal v-model:open="autoAwardVisible" title="按排名自动设置奖项" @ok="handleAutoSetAwards"
|
||||||
|
:confirm-loading="autoAwardLoading" width="520px">
|
||||||
<p style="color: #6b7280; font-size: 13px; margin-bottom: 16px">
|
<p style="color: #6b7280; font-size: 13px; margin-bottom: 16px">
|
||||||
自定义奖项名称和获奖人数,系统将按排名从高到低依次分配。
|
自定义奖项名称和获奖人数,系统将按排名从高到低依次分配。
|
||||||
</p>
|
</p>
|
||||||
@ -204,6 +244,13 @@ const contestInfo = ref<any>(null)
|
|||||||
const summary = ref({ totalWorks: 0, scoredWorks: 0, rankedWorks: 0, awardedWorks: 0, unscoredWorks: 0, avgScore: null as string | null })
|
const summary = ref({ totalWorks: 0, scoredWorks: 0, rankedWorks: 0, awardedWorks: 0, unscoredWorks: 0, avgScore: null as string | null })
|
||||||
const canPublish = computed(() => summary.value.rankedWorks > 0)
|
const canPublish = computed(() => summary.value.rankedWorks > 0)
|
||||||
|
|
||||||
|
/** 机构端且未发布时,需先完成「第一步:计算得分」后再展示作品列表与筛选 */
|
||||||
|
const showResultsList = computed(() => {
|
||||||
|
if (isSuperAdmin.value) return true
|
||||||
|
if (contestInfo.value?.resultState === 'published') return true
|
||||||
|
return summary.value.scoredWorks > 0
|
||||||
|
})
|
||||||
|
|
||||||
// 奖项筛选选项(从已有数据中动态提取)
|
// 奖项筛选选项(从已有数据中动态提取)
|
||||||
const awardFilterOptions = computed(() => {
|
const awardFilterOptions = computed(() => {
|
||||||
const names = new Set<string>()
|
const names = new Set<string>()
|
||||||
@ -311,7 +358,7 @@ const handleCalculateScores = async () => {
|
|||||||
calcScoreLoading.value = true
|
calcScoreLoading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await resultsApi.calculateScores(contestId)
|
const res = await resultsApi.calculateScores(contestId)
|
||||||
message.success(res.message)
|
message.success(res.message || '计算成功')
|
||||||
fetchList()
|
fetchList()
|
||||||
fetchSummary()
|
fetchSummary()
|
||||||
} catch (e: any) { message.error(e?.response?.data?.message || '计算失败') }
|
} catch (e: any) { message.error(e?.response?.data?.message || '计算失败') }
|
||||||
@ -323,7 +370,7 @@ const handleCalculateRankings = async () => {
|
|||||||
calcRankLoading.value = true
|
calcRankLoading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await resultsApi.calculateRankings(contestId)
|
const res = await resultsApi.calculateRankings(contestId)
|
||||||
message.success(res.message)
|
message.success(res.message || '计算成功')
|
||||||
fetchList()
|
fetchList()
|
||||||
fetchSummary()
|
fetchSummary()
|
||||||
} catch (e: any) { message.error(e?.response?.data?.message || '计算失败') }
|
} catch (e: any) { message.error(e?.response?.data?.message || '计算失败') }
|
||||||
@ -394,58 +441,215 @@ const handlePublish = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => { fetchSummary(); fetchList() })
|
onMounted(async () => {
|
||||||
|
await fetchSummary()
|
||||||
|
if (showResultsList.value) {
|
||||||
|
await fetchList()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
$primary: #6366f1;
|
$primary: #6366f1;
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
display: flex; justify-content: space-between; align-items: center;
|
display: flex;
|
||||||
padding: 16px 24px; background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); margin-bottom: 16px;
|
justify-content: space-between;
|
||||||
.header-left { display: flex; align-items: center; gap: 8px; }
|
align-items: center;
|
||||||
.page-title { font-size: 18px; font-weight: 600; color: #1e1b4b; }
|
padding: 16px 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1e1b4b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-row { display: flex; gap: 12px; margin-bottom: 16px; }
|
|
||||||
.stat-card {
|
.stat-card {
|
||||||
flex: 1; display: flex; align-items: center; gap: 12px; padding: 14px 16px; background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06);
|
flex: 1;
|
||||||
.stat-icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; }
|
display: flex;
|
||||||
.stat-info { display: flex; flex-direction: column;
|
align-items: center;
|
||||||
.stat-count { font-size: 18px; font-weight: 700; color: #1e1b4b; line-height: 1.2; }
|
gap: 12px;
|
||||||
.stat-label { font-size: 12px; color: #9ca3af; }
|
padding: 14px 16px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.stat-count {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1e1b4b;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #9ca3af;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-bar {
|
.action-bar {
|
||||||
padding: 16px 20px; background: rgba($primary, 0.03); border: 1px dashed rgba($primary, 0.15);
|
padding: 16px 20px;
|
||||||
border-radius: 12px; margin-bottom: 16px;
|
background: rgba($primary, 0.03);
|
||||||
|
border: 1px dashed rgba($primary, 0.15);
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-bar { padding: 20px 24px; background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); margin-bottom: 16px; }
|
.step-guide-card {
|
||||||
|
padding: 40px 32px 48px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border: 1px solid rgba($primary, 0.12);
|
||||||
|
|
||||||
|
.step-guide-icon {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
margin: 0 auto 20px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: rgba($primary, 0.1);
|
||||||
|
color: $primary;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-guide-title {
|
||||||
|
margin: 0 0 12px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1e1b4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-guide-desc {
|
||||||
|
margin: 0 auto 20px;
|
||||||
|
max-width: 520px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.65;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-guide-steps {
|
||||||
|
margin: 0 auto 28px;
|
||||||
|
max-width: 480px;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 20px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #4b5563;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar {
|
||||||
|
padding: 20px 24px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.data-table {
|
.data-table {
|
||||||
:deep(.ant-table-wrapper) { background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); overflow: hidden;
|
:deep(.ant-table-wrapper) {
|
||||||
.ant-table-thead > tr > th { background: #fafafa; font-weight: 600; }
|
background: #fff;
|
||||||
.ant-table-tbody > tr:hover > td { background: rgba($primary, 0.03); }
|
border-radius: 12px;
|
||||||
.ant-table-pagination { padding: 16px; margin: 0; }
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-table-thead>tr>th {
|
||||||
|
background: #fafafa;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-tbody>tr:hover>td {
|
||||||
|
background: rgba($primary, 0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-pagination {
|
||||||
|
padding: 16px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rank-badge {
|
.rank-badge {
|
||||||
display: inline-flex; align-items: center; justify-content: center;
|
display: inline-flex;
|
||||||
width: 28px; height: 28px; border-radius: 50%; font-size: 13px; font-weight: 700; background: #f3f4f6; color: #374151;
|
align-items: center;
|
||||||
&.gold { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #fff; }
|
justify-content: center;
|
||||||
&.silver { background: linear-gradient(135deg, #d1d5db, #9ca3af); color: #fff; }
|
width: 28px;
|
||||||
&.bronze { background: linear-gradient(135deg, #f59e0b, #d97706); color: #fff; }
|
height: 28px;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #374151;
|
||||||
|
|
||||||
|
&.gold {
|
||||||
|
background: linear-gradient(135deg, #fbbf24, #f59e0b);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.silver {
|
||||||
|
background: linear-gradient(135deg, #d1d5db, #9ca3af);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bronze {
|
||||||
|
background: linear-gradient(135deg, #f59e0b, #d97706);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.score { font-weight: 700; color: #10b981; }
|
.score {
|
||||||
.text-muted { color: #d1d5db; }
|
font-weight: 700;
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-muted {
|
||||||
|
color: #d1d5db;
|
||||||
|
}
|
||||||
|
|
||||||
.award-tiers {
|
.award-tiers {
|
||||||
.award-tier-row {
|
.award-tier-row {
|
||||||
display: flex; gap: 8px; align-items: center; margin-bottom: 8px;
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user