1. 奖章条件优化 - 修复统计查询 SQL 语法 - 添加按类别检查奖章方法 2. 移动端适配 - 登录页、课程中心、课程详情 - 考试页面、成长路径、排行榜 3. 证书系统 - 数据库模型和迁移脚本 - 证书颁发/列表/下载/验证 API - 前端证书列表页面 4. 数据大屏 - 企业级/团队级数据 API - ECharts 可视化大屏页面
This commit is contained in:
149
frontend/src/api/certificate.ts
Normal file
149
frontend/src/api/certificate.ts
Normal 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)
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user