feat(review): 实现复习内容滚动展示与交互
- Welcome.vue 新增复习内容水平滚动条,展示报告/残片摘要 - 新增 ReviewDetail.vue 复习详情页,展示完整内容及会话上下文 - 新增 review.ts API 模块,路由注册 /review/detail/:type/:id
This commit is contained in:
@@ -1,5 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import router from "@/router";
|
||||
import { getReviewFeed, type ReviewFeedItem } from "@/api/review";
|
||||
|
||||
const reviewItems = ref<ReviewFeedItem[]>([]);
|
||||
const isHovering = ref(false);
|
||||
|
||||
const truncatedItems = computed(() =>
|
||||
reviewItems.value.map((item) => ({
|
||||
...item,
|
||||
display:
|
||||
item.content.length > 50
|
||||
? item.content.substring(0, 50) + "..."
|
||||
: item.content,
|
||||
}))
|
||||
);
|
||||
|
||||
// 复制一份实现无缝循环
|
||||
const duplicatedItems = computed(() => [...truncatedItems.value, ...truncatedItems.value]);
|
||||
|
||||
const loadReviewFeed = async () => {
|
||||
try {
|
||||
const res = await getReviewFeed(30);
|
||||
reviewItems.value = res?.data || [];
|
||||
} catch {
|
||||
// feed 加载失败不影响页面主体功能
|
||||
}
|
||||
};
|
||||
|
||||
const goToReviewDetail = (item: ReviewFeedItem) => {
|
||||
const type = item.sourceType === "REPORT" ? "report" : "fragment";
|
||||
router.push(`/review/detail/${type}/${item.id}`);
|
||||
};
|
||||
|
||||
const startStudy = () => {
|
||||
router.push("/study");
|
||||
@@ -8,6 +40,10 @@ const startStudy = () => {
|
||||
const startReview = () => {
|
||||
router.push("/review");
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadReviewFeed();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -36,6 +72,36 @@ const startReview = () => {
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="review-scroll-section surface-card" v-if="reviewItems.length > 0">
|
||||
<h3>复习滚动条</h3>
|
||||
<div class="review-scroll-track">
|
||||
<div
|
||||
class="review-scroll-content"
|
||||
:class="{ paused: isHovering }"
|
||||
@mouseenter="isHovering = true"
|
||||
@mouseleave="isHovering = false"
|
||||
>
|
||||
<span
|
||||
v-for="(item, index) in duplicatedItems"
|
||||
:key="index"
|
||||
class="review-chip"
|
||||
@click="goToReviewDetail(item)"
|
||||
>
|
||||
<el-tag
|
||||
size="small"
|
||||
:type="item.sourceType === 'REPORT' ? 'success' : 'warning'"
|
||||
effect="plain"
|
||||
disable-transitions
|
||||
>
|
||||
{{ item.sourceType === 'REPORT' ? '报告' : '残片' }}
|
||||
</el-tag>
|
||||
<strong>{{ item.taskName }}</strong>
|
||||
<span>{{ item.display }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tips-board surface-card">
|
||||
<h3>建议流程</h3>
|
||||
<ol>
|
||||
@@ -90,6 +156,76 @@ const startReview = () => {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 复习滚动条区域 */
|
||||
.review-scroll-section {
|
||||
padding: 20px 22px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.review-scroll-section h3 {
|
||||
margin: 0 0 12px;
|
||||
color: var(--green-900);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.review-scroll-track {
|
||||
overflow: hidden;
|
||||
mask-image: linear-gradient(to right, transparent, black 3%, black 97%, transparent);
|
||||
-webkit-mask-image: linear-gradient(to right, transparent, black 3%, black 97%, transparent);
|
||||
}
|
||||
|
||||
.review-scroll-content {
|
||||
display: inline-flex;
|
||||
gap: 14px;
|
||||
white-space: nowrap;
|
||||
animation: review-ticker 80s linear infinite;
|
||||
}
|
||||
|
||||
.review-scroll-content.paused {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
@keyframes review-ticker {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.review-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 14px;
|
||||
background: var(--surface-strong);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 24px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s, box-shadow 0.2s;
|
||||
flex-shrink: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.review-chip:hover {
|
||||
background: #e8f5e9;
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.review-chip strong {
|
||||
color: var(--green-700);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.review-chip span {
|
||||
color: var(--text-secondary);
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 220px;
|
||||
}
|
||||
|
||||
.tips-board {
|
||||
padding: 20px 22px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user