fix(mobile-uni): 彻底优化学习中心UI细节,替换长框刷新按钮为精致图标,重构空状态与筛选Chips

This commit is contained in:
2026-07-23 01:50:55 +08:00
parent dd187cf15c
commit 4381dd8f7e
+177 -32
View File
@@ -97,8 +97,8 @@
<view class="section-bar" />
<text>今日任务</text>
</view>
<button class="ghost-button compact-button" :disabled="assignmentLoading" @click="loadAssignments">
{{ assignmentLoading ? '刷新中' : '刷新' }}
<button class="icon-refresh-btn" :disabled="assignmentLoading" @click="loadAssignments" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: assignmentLoading }" />
</button>
</view>
<view v-if="assignments.length" class="task-list">
@@ -128,7 +128,13 @@
</view>
</view>
</view>
<view v-else class="empty">暂无今日任务</view>
<view v-else class="app-empty-state">
<view class="empty-icon-circle">
<uni-icons type="checkmarkempty" size="22" color="#10b981" />
</view>
<text class="empty-title">暂无待完成任务</text>
<text class="empty-desc">今日练习任务已全部搞定,保持优秀!</text>
</view>
</view>
<!-- 错题本 Panel -->
@@ -141,22 +147,27 @@
<text class="panel-caption">低分与违规自动归集</text>
</view>
</view>
<button class="ghost-button compact-button" :disabled="mistakeLoading" @click="loadMistakes">
{{ mistakeLoading ? '加载中' : '刷新' }}
</button>
</view>
<view class="chip-row mistake-filter-row">
<button
v-for="cause in mistakeFilters"
:key="cause"
class="chip"
:class="{ active: cause === activeMistakeCause }"
:disabled="mistakeLoading"
@click="activeMistakeCause = cause"
>
{{ cause }}
<button class="icon-refresh-btn" :disabled="mistakeLoading" @click="loadMistakes" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: mistakeLoading }" />
</button>
</view>
<!-- 横向可滑动错题筛选 Chips -->
<scroll-view class="chip-scroll-view" scroll-x show-scrollbar="false">
<view class="mistake-pill-row">
<button
v-for="cause in mistakeFilters"
:key="cause"
class="mistake-pill"
:class="{ active: cause === activeMistakeCause }"
:disabled="mistakeLoading"
@click="activeMistakeCause = cause"
>
{{ cause }}
</button>
</view>
</scroll-view>
<view v-if="visibleMistakes.length" class="mistake-list">
<view v-for="item in displayedMistakes" :key="item.id" class="app-task-row accent-retry">
<view class="app-task-header">
@@ -185,8 +196,12 @@
{{ showAllMistakes ? '收起 ▲' : `展开全部 ${visibleMistakes.length} 条 ▼` }}
</button>
</view>
<view v-else-if="!mistakeLoading" class="empty">
{{ mistakes.length ? '当前归因筛选暂无错题' : '完成训练后,低分和红线回合会自动出现在这里' }}
<view v-else-if="!mistakeLoading" class="app-empty-state">
<view class="empty-icon-circle circle-amber">
<uni-icons type="flag-filled" size="22" color="#f59e0b" />
</view>
<text class="empty-title">表现优异</text>
<text class="empty-desc">{{ mistakes.length ? '当前归因筛选下暂无错题' : '完成对练后,低分和红线回合将归集于此' }}</text>
</view>
</view>
</view>
@@ -200,8 +215,8 @@
<view class="section-bar" />
<text>岗位 SOP 知识库</text>
</view>
<button class="ghost-button compact-button" :disabled="knowledgeLoading" @click="loadKnowledge(activeTopic)">
{{ knowledgeLoading ? '检索中' : '重查' }}
<button class="icon-refresh-btn" :disabled="knowledgeLoading" @click="loadKnowledge(activeTopic)" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: knowledgeLoading }" />
</button>
</view>
<view v-if="positionSopSummary" class="position-sop-status">
@@ -260,7 +275,13 @@
<text v-if="expandedSnippets[index]" class="snippet-content">{{ snippetExcerpt(snippet.content) }}</text>
</view>
</view>
<view v-else-if="!knowledgeLoading" class="empty">知识库暂未命中可引用内容</view>
<view v-else-if="!knowledgeLoading" class="app-empty-state">
<view class="empty-icon-circle circle-blue">
<uni-icons type="info-filled" size="22" color="#2d80ff" />
</view>
<text class="empty-title">知识空间提示</text>
<text class="empty-desc">知识库暂未命中可引用内容,欢迎咨询师傅!</text>
</view>
</view>
<!-- 训练前预习卡 Panel -->
@@ -270,8 +291,8 @@
<view class="section-bar" />
<text>训练前预习卡</text>
</view>
<button class="ghost-button compact-button" :disabled="prepLoading" @click="loadPrepCard">
{{ prepLoading ? '加载中' : '刷新' }}
<button class="icon-refresh-btn" :disabled="prepLoading" @click="loadPrepCard" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: prepLoading }" />
</button>
</view>
@@ -309,7 +330,13 @@
{{ showPrepDetail ? '收起 ▲' : '展开红线与推荐话术 ▼' }}
</button>
</view>
<view v-else-if="!prepLoading" class="empty">暂无可用预习卡</view>
<view v-else-if="!prepLoading" class="app-empty-state">
<view class="empty-icon-circle circle-blue">
<uni-icons type="paperplane-filled" size="22" color="#2d80ff" />
</view>
<text class="empty-title">预习准备</text>
<text class="empty-desc">暂无可用预习卡,可直接开启实操对练!</text>
</view>
</view>
</view>
@@ -322,8 +349,8 @@
<view class="section-bar" />
<text>上岗资格</text>
</view>
<button class="ghost-button compact-button" :disabled="qualificationLoading" @click="loadQualification">
{{ qualificationLoading ? '加载中' : '刷新' }}
<button class="icon-refresh-btn" :disabled="qualificationLoading" @click="loadQualification" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: qualificationLoading }" />
</button>
</view>
<view class="qualification-status" :class="qualificationTone">
@@ -348,7 +375,9 @@
<text class="panel-caption">岗位考试与自动评分</text>
</view>
</view>
<button class="ghost-button compact-button" :disabled="examLoading" @click="loadExams">{{ examLoading ? '加载中' : '刷新' }}</button>
<button class="icon-refresh-btn" :disabled="examLoading" @click="loadExams" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: examLoading }" />
</button>
</view>
<view v-if="exams.length" class="exam-list">
<view v-for="item in exams" :key="item.id" class="app-task-row accent-daily">
@@ -363,7 +392,13 @@
</view>
</view>
</view>
<view v-else-if="!examLoading" class="empty">暂无考试任务</view>
<view v-else-if="!examLoading" class="app-empty-state">
<view class="empty-icon-circle circle-amber">
<uni-icons type="compose" size="22" color="#f59e0b" />
</view>
<text class="empty-title">暂无考试任务</text>
<text class="empty-desc">经理或主管发布考试后将出现在这里</text>
</view>
</view>
<!-- 岗前/入职任务 Panel -->
@@ -376,8 +411,8 @@
<text class="panel-caption">组织系统已派发的任务</text>
</view>
</view>
<button class="ghost-button compact-button" :disabled="onboardingLoading" @click="loadOnboarding">
{{ onboardingLoading ? '加载中' : '刷新' }}
<button class="icon-refresh-btn" :disabled="onboardingLoading" @click="loadOnboarding" title="刷新">
<uni-icons type="refresh" size="16" color="#64748b" :class="{ spinning: onboardingLoading }" />
</button>
</view>
<view v-if="onboardTasks.length" class="onboarding-list">
@@ -400,7 +435,13 @@
</view>
</view>
</view>
<view v-else-if="!onboardingLoading" class="empty">暂无正式岗前/入职任务</view>
<view v-else-if="!onboardingLoading" class="app-empty-state">
<view class="empty-icon-circle circle-blue">
<uni-icons type="staff" size="22" color="#2d80ff" />
</view>
<text class="empty-title">暂无岗前派发任务</text>
<text class="empty-desc">等待 HR 或组织系统派发正式任务</text>
</view>
</view>
</view>
@@ -1385,6 +1426,110 @@ onUnload(invalidateRequests);
color: #ffffff;
}
.icon-refresh-btn {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 50%;
background: #f1f5f9;
border: none;
padding: 0;
flex: none;
transition: background 0.2s ease, transform 0.15s ease;
}
.icon-refresh-btn:active {
background: #e2e8f0;
transform: scale(0.92);
}
.spinning {
animation: spin 0.8s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.app-empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 24px 16px;
text-align: center;
}
.empty-icon-circle {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
border-radius: 50%;
background: #edf7f0;
margin-bottom: 10px;
}
.empty-icon-circle.circle-amber {
background: #fff8e6;
}
.empty-icon-circle.circle-blue {
background: #eff6ff;
}
.empty-title {
font-size: 14px;
font-weight: 800;
color: #1a1a1a;
}
.empty-desc {
font-size: 12px;
color: #8a8d93;
margin-top: 4px;
line-height: 1.4;
}
/* Horizontal mistake scroll view */
.chip-scroll-view {
width: 100%;
white-space: nowrap;
margin-top: 10px;
margin-bottom: 12px;
}
.mistake-pill-row {
display: inline-flex;
gap: 8px;
padding: 2px 0;
}
.mistake-pill {
display: inline-flex;
align-items: center;
height: 32px;
padding: 0 12px;
border-radius: 999px;
background: #f1f3f7;
color: #64748b;
font-size: 12px;
font-weight: 700;
border: none;
white-space: nowrap;
transition: all 0.2s ease;
}
.mistake-pill.active {
background: #d97706;
color: #ffffff;
}
.fold-toggle {
display: flex;
align-items: center;