feat(mobile): learning page APP-ification (fold long content, batch 2 of app-like)
学习中心页(全站最长,实测 5452px)按「折叠不删减」治理: - 岗位 SOP 长答案默认收起为 140 字预览+「展开全文/收起全文」 (短答案不出现开关;切换主题自动复位) - 学习资料段落(snippet)默认只显示标题行,点标题展开/收起正文; 超长文档标题两行截断 - 错题本默认 3 条,「展开全部 N 条」可切换(随归因筛选联动) 实测页面高度 5452 → 3834(-30%),其余为八个功能面板固有高度, 继续压缩需删减面板,违背不影响功能原则,不做。 本地+生产复核:高度、段落默认收起、点击展开均通过。 发布备份 h5-before-$TS。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,7 +98,7 @@
|
||||
</button>
|
||||
</view>
|
||||
<view v-if="visibleMistakes.length" class="mistake-list">
|
||||
<view v-for="item in visibleMistakes" :key="item.id" class="mistake-row">
|
||||
<view v-for="item in displayedMistakes" :key="item.id" class="mistake-row">
|
||||
<view class="mistake-copy">
|
||||
<view class="mistake-meta">
|
||||
<text class="mistake-cause">{{ item.cause }}</text>
|
||||
@@ -117,6 +117,9 @@
|
||||
</button>
|
||||
<text v-else-if="item.retryAssignmentId" class="mistake-completed">已完成</text>
|
||||
</view>
|
||||
<button v-if="visibleMistakes.length > 3" class="fold-toggle" @click="showAllMistakes = !showAllMistakes">
|
||||
{{ showAllMistakes ? '收起 ▲' : `展开全部 ${visibleMistakes.length} 条 ▼` }}
|
||||
</button>
|
||||
</view>
|
||||
<view v-else-if="!mistakeLoading" class="empty">
|
||||
{{ mistakes.length ? '当前归因筛选暂无错题' : '完成训练后,低分和红线回合会自动出现在这里' }}
|
||||
@@ -224,16 +227,26 @@
|
||||
{{ topic }}
|
||||
</button>
|
||||
</view>
|
||||
<text v-if="knowledgeResult?.answer" class="answer-text">{{ knowledgeResult.answer }}</text>
|
||||
<text v-if="knowledgeResult?.answer" class="answer-text">{{ displayedAnswer }}</text>
|
||||
<button v-if="answerIsLong" class="fold-toggle" @click="showFullAnswer = !showFullAnswer">
|
||||
{{ showFullAnswer ? '收起全文 ▲' : '展开全文 ▼' }}
|
||||
</button>
|
||||
<view v-if="knowledgeResult?.keyPoints?.length" class="keypoints">
|
||||
<text v-for="(point, index) in knowledgeResult.keyPoints" :key="point" class="keypoint">
|
||||
{{ index + 1 }}. {{ cleanOrderedText(point) }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="knowledgeResult?.snippets?.length" class="snippet-list">
|
||||
<view v-for="(snippet, index) in knowledgeResult.snippets?.slice(0, 3)" :key="`${snippet.docTitle}-${index}`" class="snippet-row">
|
||||
<text class="snippet-title">{{ snippet.docTitle || '知识片段' }}</text>
|
||||
<text class="snippet-content">{{ snippetExcerpt(snippet.content) }}</text>
|
||||
<view
|
||||
v-for="(snippet, index) in knowledgeResult.snippets?.slice(0, 3)"
|
||||
:key="`${snippet.docTitle}-${index}`"
|
||||
class="snippet-row"
|
||||
>
|
||||
<button class="snippet-head" @click="toggleSnippet(index)">
|
||||
<text class="snippet-title">{{ snippet.docTitle || '知识片段' }}</text>
|
||||
<text class="snippet-arrow">{{ expandedSnippets[index] ? '▲' : '▼' }}</text>
|
||||
</button>
|
||||
<text v-if="expandedSnippets[index]" class="snippet-content">{{ snippetExcerpt(snippet.content) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else-if="!knowledgeLoading" class="empty">知识库暂未命中可引用内容</view>
|
||||
@@ -348,6 +361,22 @@ const visibleMistakes = computed(() => activeMistakeCause.value === '全部'
|
||||
? mistakes.value
|
||||
: mistakes.value.filter((item) => item.cause === activeMistakeCause.value));
|
||||
|
||||
/* APP-like folding: long content collapsed by default, nothing removed. */
|
||||
const ANSWER_PREVIEW_CHARS = 140;
|
||||
const showAllMistakes = ref(false);
|
||||
const showFullAnswer = ref(false);
|
||||
const expandedSnippets = ref<Record<number, boolean>>({});
|
||||
const displayedMistakes = computed(() => (showAllMistakes.value ? visibleMistakes.value : visibleMistakes.value.slice(0, 3)));
|
||||
const answerIsLong = computed(() => (knowledgeResult.value?.answer || '').length > ANSWER_PREVIEW_CHARS);
|
||||
const displayedAnswer = computed(() => {
|
||||
const answer = knowledgeResult.value?.answer || '';
|
||||
if (showFullAnswer.value || answer.length <= ANSWER_PREVIEW_CHARS) return answer;
|
||||
return `${answer.slice(0, ANSWER_PREVIEW_CHARS)}…`;
|
||||
});
|
||||
const toggleSnippet = (index: number) => {
|
||||
expandedSnippets.value = { ...expandedSnippets.value, [index]: !expandedSnippets.value[index] };
|
||||
};
|
||||
|
||||
const qualificationStatusLabel = computed(() => {
|
||||
switch (qualification.value?.status) {
|
||||
case 'PASSED': return '已通过';
|
||||
@@ -554,6 +583,8 @@ const loadKnowledge = async (topic: string, request: RequestScopeTicket = reques
|
||||
const nextKnowledge = await searchKnowledge(topic);
|
||||
if (!requests.isCurrent(request)) return;
|
||||
knowledgeResult.value = nextKnowledge;
|
||||
showFullAnswer.value = false;
|
||||
expandedSnippets.value = {};
|
||||
} catch (error) {
|
||||
if (!requests.isCurrent(request)) return;
|
||||
knowledgeResult.value = null;
|
||||
@@ -1157,4 +1188,53 @@ onUnload(invalidateRequests);
|
||||
.action-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fold-toggle {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 10px 0 0;
|
||||
padding: 8px 0;
|
||||
border: none;
|
||||
border-top: 1px dashed #eceff2;
|
||||
background: transparent;
|
||||
color: #6b7480;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.fold-toggle::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.snippet-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.snippet-head::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.snippet-arrow {
|
||||
flex-shrink: 0;
|
||||
color: #98a1ad;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.snippet-head .snippet-title {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user