feat(mobile): learning page fold round 2 — deepen APP-like compression

用户复查后继续压缩(折叠不删减):
- 岗位 SOP:要点默认只显示 2 条,与答案共用「展开全文(含N条要点)」
  开关(原要点全量常显,该面板 1122px 是首因)
- 训练前预习卡:默认只显示「要点」,红线/可说话术收进
  「展开红线与可说话术」(练前场景里预习卡与练页预习视图重复度高)
- 错题本默认 3→2 条(展开全部不变)
- 学习后动作:三个竖排大按钮改为一行三列

高度变化:5452(初始)→3890(第一轮)→3039px(本轮,累计 -44%);
剩余为 8 个功能面板骨架高度,继续压需砍面板,violates 不影响功能原则。
面板分布:错题本 701→544、岗位SOP 1122→738、预习卡 596→361、
学习后动作 234→116。

验证:本地折叠/展开断言全过 + 生产复核 height<3300、双折叠就位。
发布备份 h5-before-$TS。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 13:43:57 +08:00
co-authored by Claude Fable 5
parent 0a7eb38e05
commit c0538ad8c3
+36 -17
View File
@@ -117,7 +117,7 @@
</button> </button>
<text v-else-if="item.retryAssignmentId" class="mistake-completed">已完成</text> <text v-else-if="item.retryAssignmentId" class="mistake-completed">已完成</text>
</view> </view>
<button v-if="visibleMistakes.length > 3" class="fold-toggle" @click="showAllMistakes = !showAllMistakes"> <button v-if="visibleMistakes.length > 2" class="fold-toggle" @click="showAllMistakes = !showAllMistakes">
{{ showAllMistakes ? '收起 ▲' : `展开全部 ${visibleMistakes.length} 条 ▼` }} {{ showAllMistakes ? '收起 ▲' : `展开全部 ${visibleMistakes.length} 条 ▼` }}
</button> </button>
</view> </view>
@@ -228,14 +228,14 @@
</button> </button>
</view> </view>
<text v-if="knowledgeResult?.answer" class="answer-text">{{ displayedAnswer }}</text> <text v-if="knowledgeResult?.answer" class="answer-text">{{ displayedAnswer }}</text>
<button v-if="answerIsLong" class="fold-toggle" @click="showFullAnswer = !showFullAnswer"> <view v-if="displayedKeyPoints.length" class="keypoints">
{{ showFullAnswer ? '收起全文 ▲' : '展开全文 ▼' }} <text v-for="(point, index) in displayedKeyPoints" :key="point" class="keypoint">
</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) }} {{ index + 1 }}. {{ cleanOrderedText(point) }}
</text> </text>
</view> </view>
<button v-if="sopFoldNeeded" class="fold-toggle" @click="showFullAnswer = !showFullAnswer">
{{ showFullAnswer ? '收起全文 ▲' : `展开全文(含 ${knowledgeResult?.keyPoints?.length || 0} 条要点)▼` }}
</button>
<view v-if="knowledgeResult?.snippets?.length" class="snippet-list"> <view v-if="knowledgeResult?.snippets?.length" class="snippet-list">
<view <view
v-for="(snippet, index) in knowledgeResult.snippets?.slice(0, 3)" v-for="(snippet, index) in knowledgeResult.snippets?.slice(0, 3)"
@@ -265,14 +265,19 @@
<text class="prep-label">要点</text> <text class="prep-label">要点</text>
<text v-for="item in prepCard.keyPoints.slice(0, 3)" :key="`point-${item}`" class="prep-line">{{ item }}</text> <text v-for="item in prepCard.keyPoints.slice(0, 3)" :key="`point-${item}`" class="prep-line">{{ item }}</text>
</view> </view>
<view class="prep-block red"> <template v-if="showPrepDetail">
<text class="prep-label">红线</text> <view class="prep-block red">
<text v-for="item in prepCard.redLines.slice(0, 3)" :key="`red-${item}`" class="prep-line">{{ item }}</text> <text class="prep-label">红线</text>
</view> <text v-for="item in prepCard.redLines.slice(0, 3)" :key="`red-${item}`" class="prep-line">{{ item }}</text>
<view class="prep-block script"> </view>
<text class="prep-label">可说话术</text> <view class="prep-block script">
<text v-for="item in prepCard.scripts.slice(0, 3)" :key="`script-${item}`" class="prep-line">{{ item }}</text> <text class="prep-label">可说话术</text>
</view> <text v-for="item in prepCard.scripts.slice(0, 3)" :key="`script-${item}`" class="prep-line">{{ item }}</text>
</view>
</template>
<button class="fold-toggle" @click="showPrepDetail = !showPrepDetail">
{{ showPrepDetail ? '收起 ▲' : '展开红线与可说话术 ▼' }}
</button>
</view> </view>
<view v-else-if="!prepLoading" class="empty">暂无可用预习卡</view> <view v-else-if="!prepLoading" class="empty">暂无可用预习卡</view>
<button class="primary-button full-action" @click="goPractice">练一遍</button> <button class="primary-button full-action" @click="goPractice">练一遍</button>
@@ -366,13 +371,21 @@ const ANSWER_PREVIEW_CHARS = 140;
const showAllMistakes = ref(false); const showAllMistakes = ref(false);
const showFullAnswer = ref(false); const showFullAnswer = ref(false);
const expandedSnippets = ref<Record<number, boolean>>({}); const expandedSnippets = ref<Record<number, boolean>>({});
const displayedMistakes = computed(() => (showAllMistakes.value ? visibleMistakes.value : visibleMistakes.value.slice(0, 3))); const displayedMistakes = computed(() => (showAllMistakes.value ? visibleMistakes.value : visibleMistakes.value.slice(0, 2)));
const answerIsLong = computed(() => (knowledgeResult.value?.answer || '').length > ANSWER_PREVIEW_CHARS); const answerIsLong = computed(() => (knowledgeResult.value?.answer || '').length > ANSWER_PREVIEW_CHARS);
const displayedAnswer = computed(() => { const displayedAnswer = computed(() => {
const answer = knowledgeResult.value?.answer || ''; const answer = knowledgeResult.value?.answer || '';
if (showFullAnswer.value || answer.length <= ANSWER_PREVIEW_CHARS) return answer; if (showFullAnswer.value || answer.length <= ANSWER_PREVIEW_CHARS) return answer;
return `${answer.slice(0, ANSWER_PREVIEW_CHARS)}…`; return `${answer.slice(0, ANSWER_PREVIEW_CHARS)}…`;
}); });
const KEYPOINT_PREVIEW_COUNT = 2;
const displayedKeyPoints = computed(() => {
const points = knowledgeResult.value?.keyPoints || [];
return showFullAnswer.value ? points : points.slice(0, KEYPOINT_PREVIEW_COUNT);
});
const sopFoldNeeded = computed(() =>
answerIsLong.value || (knowledgeResult.value?.keyPoints?.length || 0) > KEYPOINT_PREVIEW_COUNT);
const showPrepDetail = ref(false);
const toggleSnippet = (index: number) => { const toggleSnippet = (index: number) => {
expandedSnippets.value = { ...expandedSnippets.value, [index]: !expandedSnippets.value[index] }; expandedSnippets.value = { ...expandedSnippets.value, [index]: !expandedSnippets.value[index] };
}; };
@@ -1045,11 +1058,17 @@ onUnload(invalidateRequests);
.snippet-list, .snippet-list,
.action-list { .action-list {
display: flex; display: flex;
flex-direction: column; gap: 10px;
gap: 12px;
margin-top: 14px; margin-top: 14px;
} }
.action-list .action-button {
flex: 1;
min-height: 44px;
padding: 0 4px;
font-size: 14px;
}
.task-row { .task-row {
display: flex; display: flex;
gap: 12px; gap: 12px;