智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

782 lines
27 KiB

/**
* UniApp Mock数据服务
* 支持环境变量控制,默认开启Mock数据
* 提供与API响应结构一致的数据格式
*/
import { isMockEnabled, isDebug } from '@/common/config.js'
// Mock数据规则 - 基于MockJS规则
const mockRules = {
// 用户数据规则
user: {
'id|+1': 1,
'username': '@cname',
'phone': /^1[3-9]\d{9}$/,
'avatar': '@image("100x100", "#50B347", "#FFF", "Avatar")',
'email': '@email',
'status|1': ['active', 'inactive'],
'created_at': '@datetime',
'updated_at': '@datetime'
},
// 学生数据规则
student: {
'id|+1': 1,
'name': '@cname',
'student_no': '@string("number", 10)',
'phone': /^1[3-9]\d{9}$/,
'avatar': '@image("100x100", "#50B347", "#FFF", "Student")',
'class_id|1-20': 1,
'status|1': ['active', 'inactive', 'graduated'],
'created_at': '@datetime'
},
// 课程数据规则
course: {
'id|+1': 1,
'name': '@ctitle(5, 15)',
'description': '@cparagraph(1, 3)',
'teacher_id|1-10': 1,
'price|100-1000.2': 1,
'duration|30-120': 1,
'status|1': ['active', 'inactive'],
'created_at': '@datetime'
},
// 课程表数据规则
schedule: {
'id|+1': 1,
'course_id|1-20': 1,
'teacher_id|1-10': 1,
'classroom': '@ctitle(3, 8)',
'date': '@date',
'start_time': '@time',
'end_time': '@time',
'status|1': ['scheduled', 'completed', 'cancelled']
}
}
// 生成Mock数据的函数
function generateMockData(rule, count = 1) {
const result = []
for (let i = 0; i < count; i++) {
const item = {}
for (const key in rule) {
if (key.includes('|')) {
const [field, mockRule] = key.split('|')
if (mockRule.includes('+')) {
item[field] = i + 1
} else if (mockRule.includes('-')) {
const [min, max] = mockRule.split('-')
item[field] = Math.floor(Math.random() * (max - min + 1)) + parseInt(min)
} else if (mockRule === '1') {
const options = rule[key]
item[field] = Array.isArray(options) ?
options[Math.floor(Math.random() * options.length)] :
options
}
} else {
item[key] = rule[key]
}
}
result.push(item)
}
return count === 1 ? result[0] : result
}
// Mock数据存储
const mockData = {
// 用户相关数据
users: generateMockData(mockRules.user, 50),
students: generateMockData(mockRules.student, 100),
courses: generateMockData(mockRules.course, 30),
schedules: generateMockData(mockRules.schedule, 200),
// 登录用户信息
currentUser: {
id: 1,
username: '张三',
phone: '13800138000',
avatar: 'https://via.placeholder.com/100x100?text=User',
email: 'zhangsan@example.com',
status: 'active',
role: 'student',
created_at: '2024-01-01 10:00:00',
updated_at: '2024-01-01 10:00:00'
},
// 家长信息 (school_customer_resources)
parentInfo: {
id: 1001,
name: '张家长',
phone_number: '13800138000',
gender: 'male',
age: 35,
created_at: '2024-01-01 10:00:00',
updated_at: '2024-01-01 10:00:00'
},
// 孩子列表 (school_student)
childrenList: [
{
id: 2001,
name: '张小明',
gender: 1, // 1男 2女
age: 8.5, // 8岁5个月
birthday: '2015-06-15',
user_id: 1001, // 关联家长ID
campus_id: 1,
campus_name: '总部校区',
class_id: 101,
class_name: '少儿篮球初级班',
note: '性格活泼,运动能力强',
status: 1, // 1有效
emergency_contact: '张家长',
contact_phone: '13800138000',
member_label: '优秀学员',
consultant_id: '1',
coach_id: '1',
coach_name: '王教练',
created_at: '2024-01-01 10:00:00',
updated_at: '2024-01-01 10:00:00',
avatar: 'https://via.placeholder.com/100x100?text=张小明',
// 统计数据
total_courses: 12,
completed_courses: 8,
remaining_courses: 4,
attendance_rate: 85.5
},
{
id: 2002,
name: '张小丽',
gender: 2, // 2女
age: 6.2, // 6岁2个月
birthday: '2017-10-20',
user_id: 1001, // 关联家长ID
campus_id: 2,
campus_name: '南山校区',
class_id: 102,
class_name: '少儿舞蹈基础班',
note: '喜欢舞蹈,有艺术天赋',
status: 1, // 1有效
emergency_contact: '张家长',
contact_phone: '13800138000',
member_label: '新学员',
consultant_id: '2',
coach_id: '2',
coach_name: '李教练',
created_at: '2024-01-15 10:00:00',
updated_at: '2024-01-15 10:00:00',
avatar: 'https://via.placeholder.com/100x100?text=张小丽',
// 统计数据
total_courses: 8,
completed_courses: 3,
remaining_courses: 5,
attendance_rate: 95.0
},
{
id: 2003,
name: '张小华',
gender: 1, // 1男
age: 10.8, // 10岁8个月
birthday: '2013-04-10',
user_id: 1001, // 关联家长ID
campus_id: null, // 未分配校区
campus_name: '未分配',
class_id: null, // 未分配班级
class_name: '未分配',
note: '刚报名,待安排班级',
status: 1, // 1有效
emergency_contact: '张家长',
contact_phone: '13800138000',
member_label: '待分班',
consultant_id: '3',
coach_id: null,
coach_name: '未分配',
created_at: '2024-01-20 10:00:00',
updated_at: '2024-01-20 10:00:00',
avatar: 'https://via.placeholder.com/100x100?text=张小华',
// 统计数据
total_courses: 0,
completed_courses: 0,
remaining_courses: 0,
attendance_rate: 0
}
],
// 学员信息 (xy_memberInfo)
memberInfo: {
id: 1001,
name: '李小明',
student_no: 'ST202401001',
phone: '13800138001',
age: 15,
gender: 1, // 1男 2女
classes_count: 8, // 我的课程数
sign_count: 15, // 已上课时
stay_sign_count: 5, // 待上课时
created_at: '2024-01-01 08:00:00',
memberHasOne: {
headimg: 'https://via.placeholder.com/144x144?text=Student',
id: 1001
},
customerResources: {
member: {
headimg: 'https://via.placeholder.com/144x144?text=Student'
}
}
},
// 体测数据 (xy_physicalTest)
physicalTestData: {
data: [
{
id: 1,
resource_id: 1001,
height: 165,
weight: 55,
calculateChildHealthScore: 85,
created_at: '2024-01-10 14:30:00',
bmi: 20.2,
test_items: {
flexibility: 78,
strength: 85,
endurance: 82
}
}
],
total: 1,
page: 1,
pages: 1
},
// 课程安排数据 (xy_personCourseSchedule)
personCourseSchedule: {
data: [
{
id: 2001,
resources_id: 1001,
course_date: '2024-01-16',
time_slot: '09:00-10:30',
status: '0', // 0待上课 1已上课 2请假
courseScheduleHasOne: {
venue: {
venue_name: '篮球馆A'
},
course: {
course_name: '青少年篮球训练'
}
},
created_at: '2024-01-15 10:00:00'
},
{
id: 2002,
resources_id: 1001,
course_date: '2024-01-18',
time_slot: '14:00-15:30',
status: '0',
courseScheduleHasOne: {
venue: {
venue_name: '足球场B'
},
course: {
course_name: '足球基础课'
}
},
created_at: '2024-01-15 10:00:00'
}
],
total: 2,
page: 1,
pages: 1
},
// 作业数据 (xy_assignment)
assignmentData: {
data: [
{
id: 3001,
resources_id: 1001,
description: '完成本周的体能训练视频拍摄,展示标准动作',
content_type: 2, // 1图片 2视频 3文本
content_text: 'https://example.com/video.mp4',
status: '2', // 1待批改 2未提交 3已提交
created_at: '2024-01-14 16:00:00',
student: {
name: '李小明',
customerResources: {
member: {
headimg: 'https://via.placeholder.com/50x50?text=Student'
}
}
}
},
{
id: 3002,
resources_id: 1001,
description: '上传训练心得体会,字数不少于200字',
content_type: 3,
content_text: '今天的训练很充实,学到了很多新的技巧...',
status: '3',
created_at: '2024-01-12 10:00:00',
student: {
name: '李小明',
customerResources: {
member: {
headimg: 'https://via.placeholder.com/50x50?text=Student'
}
}
}
}
],
total: 2,
page: 1,
pages: 1
},
// 日历数据 (xy_personCourseScheduleGetCalendar)
calendarData: {
'2024-01-15': [
{
id: 2001,
course_name: '篮球训练',
time_slot: '09:00-10:30',
status: 'scheduled'
}
],
'2024-01-16': [
{
id: 2002,
course_name: '足球基础',
time_slot: '14:00-15:30',
status: 'scheduled'
}
]
},
// 教练信息 (xy_personCourseScheduleGetMyCoach)
coachData: {
data: [
{
id: 5001,
name: '王教练',
phone: '13800135001',
specialty: '篮球',
experience: '5年教学经验',
avatar: 'https://via.placeholder.com/100x100?text=Coach',
introduction: '专业篮球教练,擅长青少年基础训练和技能提升',
courses: ['青少年篮球', '篮球进阶训练']
}
],
total: 1
},
// 学生课程表
studentSchedules: [
{
id: 1,
course_name: '数学基础',
teacher_name: '王老师',
classroom: '101教室',
date: '2024-01-15',
start_time: '09:00',
end_time: '10:30',
status: 'scheduled'
},
{
id: 2,
course_name: '英语口语',
teacher_name: '李老师',
classroom: '202教室',
date: '2024-01-15',
start_time: '14:00',
end_time: '15:30',
status: 'scheduled'
}
],
// 考试成绩
examResults: [
{
id: 1,
exam_name: '期中考试',
course_name: '数学',
score: 85,
total_score: 100,
rank: 5,
exam_date: '2024-01-10',
status: 'published'
},
{
id: 2,
exam_name: '期末考试',
course_name: '英语',
score: 92,
total_score: 100,
rank: 2,
exam_date: '2024-01-12',
status: 'published'
}
]
}
// Mock服务类
class MockService {
constructor() {
this.enabled = isMockEnabled
this.debug = isDebug
this.init()
}
init() {
if (this.debug) {
console.log('Mock服务状态:', this.enabled ? '已启用' : '已禁用')
}
}
// 统一的响应格式
createResponse(data, code = 200, message = 'success') {
return {
code,
message,
data,
timestamp: Date.now()
}
}
// 分页响应格式
createPaginatedResponse(list, page = 1, size = 10, total = null) {
const actualTotal = total || list.length
const start = (page - 1) * size
const end = start + size
const paginatedList = list.slice(start, end)
return this.createResponse({
list: paginatedList,
total: actualTotal,
page: parseInt(page),
size: parseInt(size),
pages: Math.ceil(actualTotal / size)
})
}
// 模拟网络延迟
async delay(ms = 500) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// 获取Mock数据
async getMockData(endpoint, params = {}) {
if (!this.enabled) {
return null
}
await this.delay()
// 根据端点返回相应的Mock数据 - 支持完整URL和方法名匹配
const checkEndpoint = (patterns) => {
return patterns.some(pattern => endpoint.includes(pattern))
}
// 家长端API接口
if (checkEndpoint(['/parent/children', 'parent_getChildrenList'])) {
return this.createResponse({
data: mockData.childrenList,
total: mockData.childrenList.length,
parent_info: mockData.parentInfo
}, 1, 'success')
}
// 获取指定孩子信息
if (checkEndpoint(['/parent/child/info', 'parent_getChildInfo'])) {
const childId = params.child_id || params.id
const child = mockData.childrenList.find(item => item.id == childId)
return this.createResponse(child || {}, child ? 1 : 0, child ? 'success' : '孩子信息不存在')
}
// 获取指定孩子的课程信息
if (checkEndpoint(['/parent/child/courses', 'parent_getChildCourses'])) {
const childId = params.child_id || params.id
const child = mockData.childrenList.find(item => item.id == childId)
if (!child) {
return this.createResponse([], 0, '孩子信息不存在')
}
// 模拟该孩子的课程数据
const childCourses = [
{
id: 1,
course_name: child.class_name || '未分配班级',
teacher_name: child.coach_name || '未分配',
campus_name: child.campus_name || '未分配',
schedule_time: '周六 09:00-10:30',
progress: `${child.completed_courses}/${child.total_courses}`,
status: child.class_id ? 'active' : 'inactive',
next_class: child.class_id ? '2024-01-20 09:00' : null
}
]
return this.createResponse({
data: childCourses,
total: childCourses.length,
child_info: child
}, 1, 'success')
}
// 获取指定孩子的订单信息
if (checkEndpoint(['/parent/child/orders', 'parent_getChildOrders'])) {
const childId = params.child_id || params.id
const child = mockData.childrenList.find(item => item.id == childId)
if (!child) {
return this.createResponse([], 0, '孩子信息不存在')
}
// 模拟该孩子的订单数据
const childOrders = [
{
id: 1001,
order_no: 'ORD202401001',
course_name: child.class_name || '课程包',
amount: 2880.00,
status: 'paid',
status_text: '已支付',
created_at: '2024-01-01 10:00:00',
pay_time: '2024-01-01 10:05:00'
}
]
return this.createResponse({
data: childOrders,
total: childOrders.length,
child_info: child
}, 1, 'success')
}
// 获取学员课程信息
if (checkEndpoint(['/getStudentCourseInfo', 'getStudentCourseInfo'])) {
const resourceId = params.resource_id || params.id
// 模拟课程信息数据
const courseInfoData = [
{
id: 1,
course_name: '少儿篮球初级班',
total_count: 24, // 总课时
used_count: 8, // 已使用课时
remaining_count: 16, // 剩余课时
formal_hours: 20, // 正式课时
gift_hours: 4, // 赠送课时
used_formal_hours: 6, // 已使用正式课时
used_gift_hours: 2, // 已使用赠送课时
leave_count: 1, // 请假次数
start_date: '2024-01-01', // 开始日期
expiry_date: '2024-06-30', // 结束日期
status: 'active', // 课程状态
course_type: '正式课',
teacher_name: '王教练',
course_price: 2880.00,
class_duration: 90, // 单节时长(分钟)
create_time: '2024-01-01 10:00:00'
},
{
id: 2,
course_name: '体能训练课',
total_count: 12,
used_count: 3,
remaining_count: 9,
formal_hours: 10,
gift_hours: 2,
used_formal_hours: 2,
used_gift_hours: 1,
leave_count: 0,
start_date: '2024-01-15',
expiry_date: '2024-04-15',
status: 'active',
course_type: '正式课',
teacher_name: '李教练',
course_price: 1680.00,
class_duration: 60,
create_time: '2024-01-15 14:00:00'
}
]
return this.createResponse(courseInfoData, 1, 'success')
}
// 其他家长端API的Mock数据处理
if (checkEndpoint(['/parent/child/materials', 'parent_getChildMaterials'])) {
return this.createResponse({ data: [], total: 0 }, 1, 'success')
}
if (checkEndpoint(['/parent/child/services', 'parent_getChildServices'])) {
return this.createResponse({ data: [], total: 0 }, 1, 'success')
}
if (checkEndpoint(['/parent/child/messages', 'parent_getChildMessages'])) {
return this.createResponse({ data: [], total: 0 }, 1, 'success')
}
if (checkEndpoint(['/parent/child/contracts', 'parent_getChildContracts'])) {
return this.createResponse({ data: [], total: 0 }, 1, 'success')
}
// 学员信息
if (checkEndpoint(['/customerResourcesAuth/info', 'xy_memberInfo'])) {
return this.createResponse(mockData.memberInfo, 1, 'success')
}
// 体测数据
if (checkEndpoint(['/xy/physicalTest', 'xy_physicalTest'])) {
return this.createResponse(mockData.physicalTestData, 1, 'success')
}
// 课程安排
if (checkEndpoint(['/xy/personCourseSchedule', 'xy_personCourseSchedule']) && !endpoint.includes('getCalendar') && !endpoint.includes('getMyCoach')) {
// 根据status参数过滤数据
let scheduleData = mockData.personCourseSchedule.data
if (params.status !== undefined) {
scheduleData = scheduleData.filter(item => item.status === params.status)
}
return this.createResponse({
data: scheduleData,
total: scheduleData.length,
page: params.page || 1,
pages: Math.ceil(scheduleData.length / (params.limit || 10))
}, 1, 'success')
}
// 日历数据
if (checkEndpoint(['/xy/personCourseSchedule/getCalendar', 'xy_personCourseScheduleGetCalendar'])) {
return this.createResponse(mockData.calendarData, 1, 'success')
}
// 教练信息
if (checkEndpoint(['/xy/personCourseSchedule/getMyCoach', 'xy_personCourseScheduleGetMyCoach'])) {
return this.createResponse(mockData.coachData, 1, 'success')
}
// 作业列表
if (checkEndpoint(['/xy/assignment', 'xy_assignment']) && !endpoint.includes('/info') && !endpoint.includes('submitObj')) {
// 根据status参数过滤作业数据
let assignmentData = mockData.assignmentData.data
if (params.status !== undefined) {
assignmentData = assignmentData.filter(item => item.status === params.status)
}
return this.createResponse({
data: assignmentData,
total: assignmentData.length,
page: params.page || 1,
pages: Math.ceil(assignmentData.length / (params.limit || 10))
}, 1, 'success')
}
// 作业详情
if (checkEndpoint(['/xy/assignment/info', 'xy_assignmentsInfo'])) {
const assignmentId = params.id || params.assignment_id
const assignment = mockData.assignmentData.data.find(item => item.id == assignmentId)
return this.createResponse(assignment || {}, assignment ? 1 : 0, assignment ? 'success' : '作业不存在')
}
// 作业提交
if (checkEndpoint(['/xy/assignment/submitObj', 'xy_assignmentSubmitObj'])) {
return this.createResponse({}, 1, '作业提交成功')
}
// 学生登录
if (checkEndpoint(['/xy/login', 'xy_login'])) {
return this.createResponse({
token: 'mock_token_' + Date.now(),
user: mockData.memberInfo,
expires_in: 7200
}, 1, '登录成功')
}
// 原有的通用接口
switch (endpoint) {
case '/user/info':
return this.createResponse(mockData.currentUser)
case '/student/schedule':
return this.createResponse(mockData.studentSchedules)
case '/student/exam/results':
return this.createResponse(mockData.examResults)
case '/courses':
return this.createPaginatedResponse(
mockData.courses,
params.page || 1,
params.size || 10
)
case '/students':
return this.createPaginatedResponse(
mockData.students,
params.page || 1,
params.size || 10
)
default:
return this.createResponse(null, 404, '接口未找到')
}
}
// 检查是否应该使用Mock数据
shouldUseMock(url) {
if (!this.enabled) return false
// 定义需要Mock的接口列表
const mockableEndpoints = [
'/user/info',
'/student/schedule',
'/student/exam/results',
'/courses',
'/students',
// 学员端专用API - URL匹配
'/customerResourcesAuth/info', // xy_memberInfo
'/xy/physicalTest', // xy_physicalTest
'/xy/personCourseSchedule', // xy_personCourseSchedule相关
'/xy/assignment', // xy_assignment相关
'/xy/login', // xy_login
'/getStudentCourseInfo', // 获取学员课程信息
// 家长端专用API - URL匹配
'/parent/children', // parent_getChildrenList
'/parent/child/info', // parent_getChildInfo
'/parent/child/courses', // parent_getChildCourses
'/parent/child/orders', // parent_getChildOrders
'/parent/child/materials', // parent_getChildMaterials
'/parent/child/services', // parent_getChildServices
'/parent/child/messages', // parent_getChildMessages
'/parent/child/contracts', // parent_getChildContracts
'/parent/child/update', // parent_updateChildInfo
// 学员端专用API - 方法名匹配(用于开发调试)
'xy_memberInfo',
'xy_physicalTest',
'xy_personCourseSchedule',
'xy_assignment',
'xy_assignmentsInfo',
'xy_assignmentSubmitObj',
'xy_personCourseScheduleGetCalendar',
'xy_personCourseScheduleGetMyCoach',
'xy_login',
'getStudentCourseInfo',
// 家长端专用API - 方法名匹配(用于开发调试)
'parent_getChildrenList',
'parent_getChildInfo',
'parent_getChildCourses',
'parent_getChildOrders',
'parent_getChildMaterials',
'parent_getChildServices',
'parent_getChildMessages',
'parent_getChildContracts',
'parent_updateChildInfo'
]
return mockableEndpoints.some(endpoint => url.includes(endpoint))
}
}
// 创建全局Mock服务实例
const mockService = new MockService()
export default mockService