| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- <template>
- <div class="grid-4">
- <div
- v-for="student in students"
- :key="student.userId"
- class="student-card"
- :class="'status-' + student.status"
- @click="$emit('click', student)"
- >
- <div class="avatar" :class="'avatar-' + student.status">
- {{ student.name.charAt(0) }}
- </div>
- <!-- 完成态与其余状态同形:只有名字,分数在个人报告弹窗里看(spec §8) -->
- <span class="name">{{ student.name }}</span>
- <span v-if="student.status === 'completed'" class="indicator check">✓</span>
- <span v-else-if="student.status === 'reading'" class="indicator dot pulse"></span>
- <span v-else class="indicator dash">—</span>
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import type { ArticleClassSessionSummary } from '@/types/articleReading'
- defineProps<{ students: ArticleClassSessionSummary[] }>()
- defineEmits<{ click: [student: ArticleClassSessionSummary] }>()
- </script>
- <style lang="scss" scoped>
- .grid-4 {
- display: grid;
- grid-template-columns: repeat(4, minmax(0, 1fr));
- gap: 12px;
- }
- .student-card {
- display: flex;
- align-items: center;
- gap: 10px;
- padding: 8px 12px;
- border-radius: 8px;
- cursor: pointer;
- transition: box-shadow 0.15s ease;
- background: #fff;
- border: 2px solid transparent;
- &:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); }
- &.status-completed { border-color: #facc15; }
- &.status-reading { border-color: #fde68a; }
- &.status-not_started {
- background: #f3f4f6;
- border: 2px dashed #9ca3af;
- }
- }
- .avatar {
- flex-shrink: 0;
- width: 32px;
- height: 32px;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 14px;
- font-weight: 600;
- color: #fff;
- background: #d1d5db;
- &.avatar-completed { background: #f59e0b; }
- &.avatar-reading { background: #fbbf24; }
- }
- .name {
- flex: 1;
- min-width: 0;
- font-size: 13px;
- color: #111827;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .indicator {
- flex-shrink: 0;
- font-size: 12px;
- &.check { color: #16a34a; }
- &.dash { color: #9ca3af; }
- &.dot {
- width: 8px;
- height: 8px;
- border-radius: 50%;
- background: #fbbf24;
- }
- &.pulse { animation: article-class-pulse 1.4s ease-in-out infinite; }
- }
- @keyframes article-class-pulse {
- 0%, 100% { opacity: 1; }
- 50% { opacity: 0.35; }
- }
- </style>
|