feat: KPL v1.5.0 功能迭代
Some checks failed
continuous-integration/drone/push Build is failing

1. 奖章条件优化
- 修复统计查询 SQL 语法
- 添加按类别检查奖章方法

2. 移动端适配
- 登录页、课程中心、课程详情
- 考试页面、成长路径、排行榜

3. 证书系统
- 数据库模型和迁移脚本
- 证书颁发/列表/下载/验证 API
- 前端证书列表页面

4. 数据大屏
- 企业级/团队级数据 API
- ECharts 可视化大屏页面
This commit is contained in:
yuliang_guo
2026-01-29 16:51:17 +08:00
parent 813ba2c295
commit 6f0f2e6363
21 changed files with 4907 additions and 80 deletions

View File

@@ -0,0 +1,149 @@
/**
* 证书系统 API
*/
import request from '@/utils/request'
// 证书类型
export type CertificateType = 'course' | 'exam' | 'achievement'
// 证书模板
export interface CertificateTemplate {
id: number
name: string
type: CertificateType
background_url?: string
is_active: boolean
}
// 证书信息
export interface Certificate {
id: number
certificate_no: string
title: string
description?: string
type: CertificateType
type_name: string
issued_at: string
valid_until?: string
score?: number
completion_rate?: number
pdf_url?: string
image_url?: string
course_id?: number
exam_id?: number
badge_id?: number
meta_data?: Record<string, any>
template?: {
id: number
name: string
background_url?: string
}
user?: {
id: number
username: string
full_name?: string
}
}
// 证书列表响应
export interface CertificateListResponse {
items: Certificate[]
total: number
offset: number
limit: number
}
// 验证结果
export interface VerifyResult {
valid: boolean
certificate_no: string
title?: string
type_name?: string
issued_at?: string
user?: {
id: number
username: string
full_name?: string
}
}
/**
* 获取证书模板列表
*/
export function getCertificateTemplates(type?: CertificateType) {
return request.get<CertificateTemplate[]>('/certificates/templates', {
params: { cert_type: type }
})
}
/**
* 获取我的证书列表
*/
export function getMyCertificates(params?: {
cert_type?: CertificateType
offset?: number
limit?: number
}) {
return request.get<CertificateListResponse>('/certificates/me', { params })
}
/**
* 获取指定用户的证书列表
*/
export function getUserCertificates(userId: number, params?: {
cert_type?: CertificateType
offset?: number
limit?: number
}) {
return request.get<CertificateListResponse>(`/certificates/user/${userId}`, { params })
}
/**
* 获取证书详情
*/
export function getCertificateDetail(certId: number) {
return request.get<Certificate>(`/certificates/${certId}`)
}
/**
* 获取证书分享图片URL
*/
export function getCertificateImageUrl(certId: number): string {
return `/api/v1/certificates/${certId}/image`
}
/**
* 获取证书下载URL
*/
export function getCertificateDownloadUrl(certId: number): string {
return `/api/v1/certificates/${certId}/download`
}
/**
* 验证证书
*/
export function verifyCertificate(certNo: string) {
return request.get<VerifyResult>(`/certificates/verify/${certNo}`)
}
/**
* 颁发课程证书
*/
export function issueCoursCertificate(data: {
course_id: number
course_name: string
completion_rate?: number
}) {
return request.post<Certificate>('/certificates/issue/course', data)
}
/**
* 颁发考试证书
*/
export function issueExamCertificate(data: {
exam_id: number
exam_name: string
score: number
}) {
return request.post<Certificate>('/certificates/issue/exam', data)
}

View File

@@ -1,20 +1,159 @@
/**
* 首页数据API
* 数据大屏 API
*/
import request from './request'
import request from '@/utils/request'
/**
* 获取用户统计数据
*/
export function getUserStatistics() {
return request.get('/api/v1/users/me/statistics')
// 数据概览
export interface DashboardOverview {
overview: {
total_users: number
today_active: number
week_active: number
month_active: number
total_hours: number
checkin_rate: number
}
exam: {
total_count: number
pass_rate: number
avg_score: number
perfect_users: number
}
updated_at: string
}
// 部门对比
export interface DepartmentData {
id: number
name: string
member_count: number
pass_rate: number
avg_hours: number
avg_level: number
}
// 学习趋势
export interface TrendData {
dates: string[]
trend: Array<{
date: string
active_users: number
learning_hours: number
exam_count: number
}>
}
// 等级分布
export interface LevelDistribution {
levels: number[]
counts: number[]
}
// 实时动态
export interface ActivityItem {
id: number
user_id: number
user_name: string
type: string
description: string
exp_amount: number
created_at: string
}
// 课程排行
export interface CourseRanking {
rank: number
id: number
name: string
description: string
learners: number
}
// 团队数据
export interface TeamDashboard {
members: Array<{
id: number
username: string
full_name: string
avatar_url?: string
level: number
total_exp: number
badge_count: number
}>
overview: {
total_members: number
avg_level: number
avg_exp: number
total_badges: number
}
positions: Array<{
id: number
name: string
}>
}
// 完整大屏数据
export interface FullDashboardData {
overview: DashboardOverview
departments: DepartmentData[]
trend: TrendData
level_distribution: LevelDistribution
activities: ActivityItem[]
course_ranking: CourseRanking[]
}
/**
* 获取最近考试列表
* @param limit 返回数量默认5条
* 获取企业级数据概览
*/
export function getRecentExams(limit: number = 5) {
return request.get('/api/v1/users/me/recent-exams', { limit })
export function getEnterpriseOverview() {
return request.get<DashboardOverview>('/dashboard/enterprise/overview')
}
/**
* 获取部门对比数据
*/
export function getDepartmentComparison() {
return request.get<DepartmentData[]>('/dashboard/enterprise/departments')
}
/**
* 获取学习趋势数据
*/
export function getLearningTrend(days = 7) {
return request.get<TrendData>('/dashboard/enterprise/trend', { params: { days } })
}
/**
* 获取等级分布数据
*/
export function getLevelDistribution() {
return request.get<LevelDistribution>('/dashboard/enterprise/level-distribution')
}
/**
* 获取实时动态
*/
export function getRealtimeActivities(limit = 20) {
return request.get<ActivityItem[]>('/dashboard/enterprise/activities', { params: { limit } })
}
/**
* 获取课程热度排行
*/
export function getCourseRanking(limit = 10) {
return request.get<CourseRanking[]>('/dashboard/enterprise/course-ranking', { params: { limit } })
}
/**
* 获取团队数据大屏
*/
export function getTeamDashboard() {
return request.get<TeamDashboard>('/dashboard/team')
}
/**
* 获取完整大屏数据(一次性加载)
*/
export function getFullDashboardData() {
return request.get<FullDashboardData>('/dashboard/all')
}