Some checks failed
continuous-integration/drone/push Build is failing
1. 课程学习进度追踪
- 新增 UserCourseProgress 和 UserMaterialProgress 模型
- 新增 /api/v1/progress/* 进度追踪 API
- 更新 admin.py 使用真实课程完成率数据
2. 路由权限检查完善
- 新增前端 permissionChecker.ts 权限检查工具
- 更新 router/guard.ts 实现团队和课程权限验证
- 新增后端 permission_service.py
3. AI 陪练音频转文本
- 新增 speech_recognition.py 语音识别服务
- 新增 /api/v1/speech/* API
- 更新 ai-practice-coze.vue 支持语音输入
4. 双人对练报告生成
- 更新 practice_room_service.py 添加报告生成功能
- 新增 /rooms/{room_code}/report API
- 更新 duo-practice-report.vue 调用真实 API
5. 学习提醒推送
- 新增 notification_service.py 通知服务
- 新增 scheduler_service.py 定时任务服务
- 支持钉钉、企微、站内消息推送
6. 智能学习推荐
- 新增 recommendation_service.py 推荐服务
- 新增 /api/v1/recommendations/* API
- 支持错题、能力、进度、热门多维度推荐
7. 安全问题修复
- DEBUG 默认值改为 False
- 添加 SECRET_KEY 安全警告
- 新增 check_security_settings() 检查函数
8. 证书 PDF 生成
- 更新 certificate_service.py 添加 PDF 生成
- 添加 weasyprint、Pillow、qrcode 依赖
- 更新下载 API 支持 PDF 和 PNG 格式
86 lines
1.7 KiB
Vue
86 lines
1.7 KiB
Vue
<template>
|
|
<div class="level-badge" :style="{ '--level-color': color }">
|
|
<div class="level-icon">
|
|
<span class="level-number">{{ level }}</span>
|
|
</div>
|
|
<div class="level-info" v-if="showInfo">
|
|
<span class="level-title">{{ title }}</span>
|
|
<span class="level-exp" v-if="showExp">{{ exp }}/{{ nextLevelExp }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
|
|
interface Props {
|
|
level: number
|
|
title?: string
|
|
color?: string
|
|
exp?: number
|
|
nextLevelExp?: number
|
|
showInfo?: boolean
|
|
showExp?: boolean
|
|
size?: 'small' | 'medium' | 'large'
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
title: '初学者',
|
|
color: '#909399',
|
|
exp: 0,
|
|
nextLevelExp: 1000,
|
|
showInfo: true,
|
|
showExp: false,
|
|
size: 'medium'
|
|
})
|
|
|
|
const sizeMap = {
|
|
small: { icon: 24, font: 12 },
|
|
medium: { icon: 32, font: 14 },
|
|
large: { icon: 48, font: 18 }
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.level-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
|
|
.level-icon {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, var(--level-color) 0%, color-mix(in srgb, var(--level-color) 80%, #000) 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
|
.level-number {
|
|
color: #fff;
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
}
|
|
}
|
|
|
|
.level-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
|
|
.level-title {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--level-color);
|
|
}
|
|
|
|
.level-exp {
|
|
font-size: 12px;
|
|
color: #909399;
|
|
}
|
|
}
|
|
}
|
|
</style>
|