diff --git a/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php b/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php index a106a6c2..aa34dfc0 100644 --- a/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php +++ b/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php @@ -165,8 +165,8 @@ class CourseSchedule extends BaseAdminController ["schedule_id",''], ["course_date",''], ["time_slot",''], - ["schedule_type", 1], // 1=正式位, 2=等待位 - ["course_type", 1], // 1=正式课, 2=体验课, 3=补课, 4=试听课 + ["schedule_type", 1], // 1=临时, 2=固定 + ["course_type", 1], // 1=加课, 2=体验课, 3=补课, 4=试听课 ["position", ''] // 位置信息 ]); return (new CourseScheduleService())->addSchedule($data); diff --git a/niucloud/app/api/controller/apiController/StudentManager.php b/niucloud/app/api/controller/apiController/StudentManager.php index 98669514..fc983a89 100644 --- a/niucloud/app/api/controller/apiController/StudentManager.php +++ b/niucloud/app/api/controller/apiController/StudentManager.php @@ -103,4 +103,48 @@ class StudentManager extends BaseApiService return fail('获取学员列表失败:' . $e->getMessage()); } } + + public function edit() + { + try { + $data = $this->request->params([ + ["id", ""], + ["name", ""], + ["gender", 0], + ["age", 0.00], + ["birthday", ""], + ["user_id", 0], + ["campus_id", 0], + ["class_id", 0], + ["note", ""], + ["status", 1], + ["emergency_contact", ""], + ["contact_phone", ""], + ["member_label", ""], + ["consultant_id", ""], + ["coach_id", ""], + ["trial_class_count", 2] + ]); + + // 表单验证 + if (empty($data['name'])) { + return fail('学员姓名不能为空'); + } + if ($data['gender'] == 0) { + return fail('请选择学员性别'); + } + if (empty($data['birthday'])) { + return fail('请选择学员出生日期'); + } + + $result = (new StudentService())->edit($data); + if ($result['code'] === 1) { + return success('修改成功', $result['data']); + } else { + return fail($result['msg']); + } + } catch (\Exception $e) { + return fail('添加学员失败:' . $e->getMessage()); + } + } } \ No newline at end of file diff --git a/niucloud/app/api/route/route.php b/niucloud/app/api/route/route.php index d5473d90..272ca56f 100644 --- a/niucloud/app/api/route/route.php +++ b/niucloud/app/api/route/route.php @@ -258,6 +258,7 @@ Route::group(function () { Route::post('resourceSharing/assign', 'apiController.ResourceSharing/assign'); //销售端-学员-新增 Route::post('student/add', 'apiController.StudentManager/add'); + Route::post('student/edit', 'apiController.StudentManager/edit'); //销售端-学员-列表 Route::get('student/list', 'apiController.StudentManager/list'); diff --git a/niucloud/app/common.php b/niucloud/app/common.php index bea5dcf2..c453928d 100644 --- a/niucloud/app/common.php +++ b/niucloud/app/common.php @@ -1467,3 +1467,26 @@ function sendMessage($touser,$template_id,$value) { curl_close($ch); } + +/** + * 通过 id 获取员工姓名 + */ +function getStaffNameById($id) +{ + //获取全部员工的 id 和 name + $staffs = Personnel::column('id,name'); + $staffs = array_column($staffs, 'name', 'id'); + return $staffs[$id] ?? ''; +} + +/** + * 获取学员有效的课程 + */ +function getValidCourseByStudentId($studentId) +{ + $course = \app\model\student_courses\StudentCourses::where('student_id', $studentId) + ->where('status', 1) + ->order('id', 'desc') + ->find(); + return $course ?? []; +} \ No newline at end of file diff --git a/niucloud/app/service/api/apiService/CustomerResourcesService.php b/niucloud/app/service/api/apiService/CustomerResourcesService.php index f4465124..9af672f7 100644 --- a/niucloud/app/service/api/apiService/CustomerResourcesService.php +++ b/niucloud/app/service/api/apiService/CustomerResourcesService.php @@ -1114,21 +1114,8 @@ class CustomerResourcesService extends BaseApiService ->alias('s') ->leftJoin('school_student_courses sc', 's.id = sc.student_id') ->leftJoin('school_customer_resources cr', 's.user_id = cr.id') - ->where('s.deleted_at', 0); - - // 根据传入的参数查询 - 优先使用student_id,如果都提供则使用OR条件 - if ($studentId && $resourceId) { - // 如果同时提供student_id和resource_id,使用OR条件 - $query->where(function($query) use ($studentId, $resourceId) { - $query->where('s.id', $studentId)->whereOr('s.user_id', $resourceId); - }); - } elseif ($studentId) { - // 仅提供student_id - $query->where('s.id', $studentId); - } elseif ($resourceId) { - // 仅提供resource_id - $query->where('s.user_id', $resourceId); - } + ->where('s.deleted_at', 0) + ->where('s.id', $studentId); // 获取学员基本信息和课程信息 $student = $query @@ -1164,7 +1151,7 @@ class CustomerResourcesService extends BaseApiService $res['msg'] = '学员不存在'; return $res; } - + // 计算课程进度和状态 $totalHours = intval($student['total_hours'] ?: 0) + intval($student['gift_hours'] ?: 0); $usedHours = intval($student['use_total_hours'] ?: 0) + intval($student['use_gift_hours'] ?: 0); diff --git a/niucloud/app/service/api/apiService/StudentService.php b/niucloud/app/service/api/apiService/StudentService.php index 2b54ed61..8efa76a8 100644 --- a/niucloud/app/service/api/apiService/StudentService.php +++ b/niucloud/app/service/api/apiService/StudentService.php @@ -158,6 +158,8 @@ class StudentService extends BaseApiService $student['second_visit_time'] = ''; $student['first_visit_status'] = '未到访'; $student['second_visit_status'] = '未到访'; + $student['academic_affairs'] = getStaffNameById($student['consultant_id']); + $student['class_teacher'] = getStaffNameById($student['coach_id']); // 设置一访和二访信息 if (!empty($visitRecords)) { @@ -265,10 +267,12 @@ class StudentService extends BaseApiService $courseInfo = Db::table('school_student_courses sc') ->leftJoin('school_course c', 'sc.course_id = c.id') ->leftJoin('school_customer_resources cr', 'sc.resource_id = cr.id') + ->leftJoin('school_resource_sharing rs', 'rs.resource_id = cr.id') ->where([ ['sc.student_id', '=', $studentId] ]) - ->field('sc.total_hours, sc.gift_hours, sc.use_total_hours, sc.use_gift_hours, sc.end_date, sc.resource_id as resource_sharing_id, c.course_name') + ->field('sc.total_hours, sc.gift_hours, sc.use_total_hours, + sc.use_gift_hours, sc.end_date, rs.id as resource_sharing_id, c.course_name') ->order('sc.created_at', 'desc') ->find(); @@ -280,7 +284,9 @@ class StudentService extends BaseApiService 'use_gift_hours' => 0, 'end_date' => '', 'resource_sharing_id' => 0, - 'course_name' => '' + 'course_name' => '', + 'class_teacher'=>'', + 'academic_affairs'=>'' ]; } @@ -322,4 +328,39 @@ class StudentService extends BaseApiService return 0; } } + + public function edit(array $data) + { + $res = [ + 'code' => 0, + 'msg' => '操作失败', + 'data' => [] + ]; + $course = getValidCourseByStudentId($data['id']); + $consultant_id = $course['education_id'] ?? 0; + $coach_id = $course['main_coach_id'] ?? 0; + $data['updated_at'] = date('Y-m-d H:i:s'); + if ($consultant_id || $coach_id){ + $data['consultant_id'] = $consultant_id; + $data['coach_id'] = $coach_id; + } + try { + // 插入数据库 + $id = Db::table('school_student') + ->where('id', $data['id']) + ->update($data); + + if ($id) { + $res['code'] = 1; + $res['msg'] = '修改成功'; + $res['data'] = ['id' => $id]; + } else { + $res['msg'] = '添加失败'; + } + } catch (\Exception $e) { + $res['msg'] = '添加失败:' . $e->getMessage(); + } + + return $res; + } } \ No newline at end of file diff --git a/uniapp/api/apiRoute.js b/uniapp/api/apiRoute.js index 6438edb2..4b695489 100644 --- a/uniapp/api/apiRoute.js +++ b/uniapp/api/apiRoute.js @@ -491,6 +491,10 @@ export default { async xs_addStudent(data = {}) { return await http.post('/student/add', data); }, + //销售端-学员-编辑 + async xs_editStudent(data = {}) { + return await http.post('/student/edit', data); + }, //销售端-学员-列表 async xs_getStudentList(data = {}) { return await http.get('/student/list', data); diff --git a/uniapp/components/student-info-card/student-info-card.vue b/uniapp/components/student-info-card/student-info-card.vue index dafb3147..6808048f 100644 --- a/uniapp/components/student-info-card/student-info-card.vue +++ b/uniapp/components/student-info-card/student-info-card.vue @@ -1,8 +1,8 @@ @@ -90,14 +78,9 @@ export default { } }, methods: { - toggleActions() { - this.$emit('toggle-actions', this.student) + handleStudentClick(){ + this.$emit('action',{ action: 'edit', student: this.student}) }, - - handleAction(action) { - this.$emit('action', { action, student: this.student }) - }, - // 计算年龄(x岁x月) calculateAge(birthday) { if (!birthday) return '' diff --git a/uniapp/pages-market/clue/clue_info.vue b/uniapp/pages-market/clue/clue_info.vue index c34f6dd2..8cdd0d09 100644 --- a/uniapp/pages-market/clue/clue_info.vue +++ b/uniapp/pages-market/clue/clue_info.vue @@ -45,7 +45,6 @@ @@ -654,23 +653,30 @@ export default { }) if (tabId === 8) await this.getGiftRecords() }, - + handleStudentAction({ action, student }) { - this.setCurrentStudent(student) + // this.setCurrentStudent(student) + console.log('学生操作:', action, student) - switch (action.key) { - case 'course_info': - this.switch_tags_type = 2 + // 处理不同的学员操作 + switch (action) { + case 'edit': + // 编辑学员信息 - 打开编辑弹窗并回显数据 + this.openEditStudentDialog(student) break - case 'fitness_record': - this.switch_tags_type = 4 + case 'view': + // 查看学员详情 + this.viewStudentDetail(student) break - case 'study_plan': - this.switch_tags_type = 5 + case 'delete': + // 删除学员 + this.confirmDeleteStudent(student) break + default: + console.log('未处理的学员操作:', action) } }, - + setCurrentStudent(student) { const index = this.studentList.findIndex(s => s.id === student.id) if (index !== -1) this.currentStudentIndex = index @@ -1011,15 +1017,100 @@ export default { }) }, + // 打开编辑学员信息弹窗 + openEditStudentDialog(student) { + // 确保组件已经挂载后再调用 + this.$nextTick(() => { + if (this.$refs.studentEditPopup) { + console.log('打开编辑学员弹窗,学员信息:', student) + // 调用组件的 openEdit 方法并传入学员数据进行回显 + this.$refs.studentEditPopup.openEdit(student) + } else { + console.error('studentEditPopup 组件引用不存在') + uni.showToast({ + title: '组件加载中,请稍后再试', + icon: 'none' + }) + } + }) + }, + + // 查看学员详情 + viewStudentDetail(student) { + console.log('查看学员详情:', student) + // 可以显示一个详情弹窗或跳转到详情页面 + const detailInfo = ` +姓名:${student.name} +性别:${student.gender === 1 ? '男' : student.gender === 2 ? '女' : '未知'} +年龄:${student.age || '未知'} +生日:${student.birthday || '未知'} +联系电话:${student.contact_phone || '未填写'} +紧急联系人:${student.emergency_contact || '未填写'} +备注:${student.note || '无'} +状态:${student.status === 1 ? '有效' : '无效'} + `.trim() + + uni.showModal({ + title: '学员详情', + content: detailInfo, + showCancel: false, + confirmText: '知道了' + }) + }, + + // 确认删除学员 + confirmDeleteStudent(student) { + uni.showModal({ + title: '确认删除', + content: `确定要删除学员"${student.name}"吗?此操作无法撤销。`, + success: (res) => { + if (res.confirm) { + this.deleteStudent(student) + } + } + }) + }, + + // 删除学员 + async deleteStudent(student) { + try { + // 这里需要调用删除学员的API + // const res = await apiRoute.deleteStudent({ student_id: student.id }) + // if (res.code === 1) { + uni.showToast({ title: '删除成功', icon: 'success' }) + // 刷新学员列表 + await this.getStudentList() + // } else { + // uni.showToast({ title: res.msg || '删除失败', icon: 'none' }) + // } + } catch (error) { + console.error('删除学员失败:', error) + uni.showToast({ title: '删除失败', icon: 'none' }) + } + }, + async handleStudentEditConfirm(result) { try { - // 调用学生添加API接口 - const res = await apiRoute.xs_addStudent(result.studentData) + console.log('学员编辑确认结果:', result) + + let res + if (result.isEditing) { + // 编辑模式 - 调用学员信息更新API + console.log('编辑学员信息:', result.studentData) + res = await apiRoute.xs_editStudent(result.studentData) + } else { + // 新增模式 - 调用学员添加API + console.log('新增学员信息:', result.studentData) + res = await apiRoute.xs_addStudent(result.studentData) + } if (res.code === 1) { this.$refs.studentEditPopup.close() - uni.showToast({ title: '保存成功', icon: 'success' }) + uni.showToast({ + title: result.isEditing ? '编辑成功' : '添加成功', + icon: 'success' + }) // 保存成功后刷新学生列表 await this.getStudentList() } else { diff --git a/uniapp/pages-student/schedule/index.vue b/uniapp/pages-student/schedule/index.vue index f48dffab..98639633 100644 --- a/uniapp/pages-student/schedule/index.vue +++ b/uniapp/pages-student/schedule/index.vue @@ -238,14 +238,45 @@ async loadStudentInfo() { try { - // 模拟获取学员信息 - const mockStudentInfo = { - id: this.studentId, - name: '小明' + console.log('加载学员信息:', this.studentId) + + // 调用真实API获取学员基本信息 + const response = await apiRoute.getStudentBasicInfo({ + student_id: this.studentId + }) + + console.log('学员信息API响应:', response) + + if (response.code === 1) { + // 处理API返回的数据格式 + this.studentInfo = { + id: this.studentId, + name: response.data.name || response.data.student_name || '学员', + phone: response.data.phone || response.data.mobile || '', + avatar: response.data.avatar || '/static/icon-img/avatar.png' + } + + console.log('学员信息加载成功:', this.studentInfo) + } else { + console.warn('API返回错误,使用默认信息:', response.msg) + // 如果API失败,使用默认信息 + this.studentInfo = { + id: this.studentId, + name: '学员', + phone: '', + avatar: '/static/icon-img/avatar.png' + } } - this.studentInfo = mockStudentInfo } catch (error) { console.error('获取学员信息失败:', error) + console.warn('API调用失败,使用默认信息') + // 如果API调用失败,使用默认信息 + this.studentInfo = { + id: this.studentId, + name: '学员', + phone: '', + avatar: '/static/icon-img/avatar.png' + } } }, @@ -398,16 +429,53 @@ async loadWeeklyStats() { try { - // 模拟获取本周统计数据 - const mockStats = { - total_courses: 8, - completed_courses: 3, - scheduled_courses: 4, - cancelled_courses: 1 + console.log('加载本周统计数据:', this.studentId, this.currentWeekStart) + + // 计算本周的开始和结束日期 + const weekStart = this.formatDateString(this.currentWeekStart) + const weekEnd = new Date(this.currentWeekStart) + weekEnd.setDate(this.currentWeekStart.getDate() + 6) + const weekEndStr = this.formatDateString(weekEnd) + + // 调用真实API获取课程统计 + const response = await apiRoute.getCourseScheduleStatistics({ + student_id: this.studentId, + start_date: weekStart, + end_date: weekEndStr + }) + + console.log('周统计API响应:', response) + + if (response.code === 1) { + // 处理API返回的数据格式 + this.weeklyStats = { + total_courses: response.data.total_courses || 0, + completed_courses: response.data.completed_courses || 0, + scheduled_courses: response.data.scheduled_courses || 0, + cancelled_courses: response.data.cancelled_courses || 0 + } + + console.log('周统计数据加载成功:', this.weeklyStats) + } else { + console.warn('统计API返回错误,使用默认数据:', response.msg) + // 如果API失败,使用默认统计数据 + this.weeklyStats = { + total_courses: 0, + completed_courses: 0, + scheduled_courses: 0, + cancelled_courses: 0 + } } - this.weeklyStats = mockStats } catch (error) { console.error('获取周统计失败:', error) + console.warn('统计API调用失败,使用默认数据') + // 如果API调用失败,使用默认统计数据 + this.weeklyStats = { + total_courses: 0, + completed_courses: 0, + scheduled_courses: 0, + cancelled_courses: 0 + } } },