From 55178e85f41f14629e7e4d0638391bcb12016dd8 Mon Sep 17 00:00:00 2001 From: zeyan <258785420@qq.com> Date: Mon, 4 Aug 2025 17:27:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course_schedule/CourseSchedule.php | 15 - .../api/controller/apiController/Course.php | 3 +- .../CourseScheduleController.php | 26 ++ .../controller/student/StudentController.php | 24 + niucloud/app/api/route/route.php | 23 +- niucloud/app/api/route/student.php | 21 +- .../course_schedule/CourseScheduleService.php | 29 -- .../api/apiService/CourseScheduleService.php | 143 +++++- .../service/api/apiService/CourseService.php | 430 +++++++++--------- .../service/api/student/StudentService.php | 60 +++ uniapp/api/apiRoute.js | 38 +- .../clue/class_arrangement_detail.vue | 195 ++++++-- uniapp/pages.json | 1 - 13 files changed, 668 insertions(+), 340 deletions(-) diff --git a/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php b/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php index aa34dfc0..2bbd5e67 100644 --- a/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php +++ b/niucloud/app/adminapi/controller/course_schedule/CourseSchedule.php @@ -156,19 +156,4 @@ class CourseSchedule extends BaseAdminController ]); return success((new CourseScheduleService())->courseInfo($data['id'])); } - - - public function addSchedule(){ - $data = $this->request->params([ - ["resources_id",''], - ["person_type",''], - ["schedule_id",''], - ["course_date",''], - ["time_slot",''], - ["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/Course.php b/niucloud/app/api/controller/apiController/Course.php index eaa0a2d3..1ef4e696 100644 --- a/niucloud/app/api/controller/apiController/Course.php +++ b/niucloud/app/api/controller/apiController/Course.php @@ -129,7 +129,8 @@ class Course extends BaseApiService $data = $this->request->params([ ["id", ''], ["resources_id", ''], - ["remark", ''] + ["remark", ''], + ["student_id", ''] ]); return (new CourseService())->schedule_del($data); } diff --git a/niucloud/app/api/controller/apiController/CourseScheduleController.php b/niucloud/app/api/controller/apiController/CourseScheduleController.php index e468031c..b0faef1d 100644 --- a/niucloud/app/api/controller/apiController/CourseScheduleController.php +++ b/niucloud/app/api/controller/apiController/CourseScheduleController.php @@ -205,6 +205,32 @@ class CourseScheduleController extends BaseApiController } } + /** + * 升级等待位学员为正式学员 + */ + public function upgradeStudentSchedule() + { + $data = $this->request->post(); + + // 验证必要参数 + if (empty($data['resources_id']) || empty($data['schedule_id'])) { + return fail('参数不完整'); + } + + if (empty($data['from_schedule_type']) || empty($data['to_schedule_type'])) { + return fail('升级类型参数不完整'); + } + + $service = new CourseScheduleService(); + $result = $service->upgradeStudentSchedule($data); + + if ($result['code'] == 1) { + return success($result['msg'], $result['data'] ?? []); + } else { + return fail($result['msg']); + } + } + /** * 获取筛选选项(教练、课程、班级等) */ diff --git a/niucloud/app/api/controller/student/StudentController.php b/niucloud/app/api/controller/student/StudentController.php index bb6be18d..3f690036 100644 --- a/niucloud/app/api/controller/student/StudentController.php +++ b/niucloud/app/api/controller/student/StudentController.php @@ -318,4 +318,28 @@ class StudentController extends BaseController return fail($e->getMessage()); } } + + /** + * 获取学员课程统计 + * @param int $student_id + * @return Response + */ + public function getCourseStatistics($student_id) + { + $data = $this->request->params([ + ['start_date', ''], + ['end_date', ''] + ]); + $data['student_id'] = $student_id; + + try { + $service = new StudentService(); + $result = $service->getCourseStatistics($data); + + return success($result, '获取课程统计成功'); + + } 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 272ca56f..3a44b585 100644 --- a/niucloud/app/api/route/route.php +++ b/niucloud/app/api/route/route.php @@ -323,12 +323,13 @@ Route::group(function () { Route::get('courseSchedule/venueAvailableTime', 'apiController.CourseSchedule/getVenueAvailableTime'); //员工端-检查教练时间冲突 Route::get('courseSchedule/checkCoachConflict', 'apiController.CourseSchedule/checkCoachConflict'); - //员工端-获取课程安排统计 - Route::get('courseSchedule/statistics', 'apiController.CourseSchedule/getScheduleStatistics'); + //员工端-学员加入课程安排 Route::post('courseSchedule/joinSchedule', 'apiController.CourseSchedule/joinSchedule'); //员工端-学员退出课程安排 Route::post('courseSchedule/leaveSchedule', 'apiController.CourseSchedule/leaveSchedule'); + //员工端-升级等待位学员为正式学员 + Route::post('course/upgradeStudentSchedule', 'apiController.CourseSchedule/upgradeStudentSchedule'); //员工端-获取筛选选项 Route::get('courseSchedule/filterOptions', 'apiController.CourseSchedule/getFilterOptions'); //员工端-获取场地时间选项 @@ -559,6 +560,13 @@ Route::group(function () { // 清除字典缓存 Route::post('dict/clear_cache', 'common.Dict/clearDictCache'); + + // 学员签到 + Route::post('checkin', 'student.AttendanceController/checkin'); + // 学员请假 + Route::post('leave', 'student.AttendanceController/leave'); + // 学员取消 + Route::post('cancel', 'student.AttendanceController/cancel'); })->middleware(ApiChannel::class) ->middleware(ApiPersonnelCheckToken::class, true) ->middleware(ApiLog::class); @@ -576,17 +584,6 @@ Route::group(function () { })->middleware(ApiChannel::class) ->middleware(ApiLog::class); -// 学员出勤管理(测试) -Route::group('student/attendance', function () { - // 学员签到 - Route::post('checkin', 'student.AttendanceController/checkin'); - // 学员请假 - Route::post('leave', 'student.AttendanceController/leave'); - // 学员取消 - Route::post('cancel', 'student.AttendanceController/cancel'); -})->middleware(ApiChannel::class) - ->middleware(ApiLog::class); - //学员端路由 include_once __DIR__ . '/student.php'; diff --git a/niucloud/app/api/route/student.php b/niucloud/app/api/route/student.php index fe4c6622..0ecc8d79 100644 --- a/niucloud/app/api/route/student.php +++ b/niucloud/app/api/route/student.php @@ -58,11 +58,16 @@ Route::group('course-booking', function () { // 课程安排查看 Route::group('course-schedule', function () { // 获取课程安排列表 - Route::get('list/:student_id', 'app\api\controller\student\StudentController@getCourseScheduleList'); + Route::get('list/:student_id', 'app\\api\\controller\\student\\StudentController@getCourseScheduleList'); // 获取课程详情 - Route::get('detail/:schedule_id', 'app\api\controller\student\StudentController@getCourseScheduleDetail'); + Route::get('detail/:schedule_id', 'app\\api\\controller\\student\\StudentController@getCourseScheduleDetail'); // 申请课程请假 - Route::post('leave', 'app\api\controller\student\StudentController@requestCourseLeave'); + Route::post('leave', 'app\\api\\controller\\student\\StudentController@requestCourseLeave'); + // 获取学员课程统计 + Route::get('statistics/:student_id', 'app\\api\\controller\\student\\StudentController@getCourseStatistics'); + + //员工端-获取课程安排统计 + Route::get('courseSchedule/statistics', 'apiController.CourseSchedule/getScheduleStatistics'); })->middleware(['ApiCheckToken']); // 订单管理 @@ -173,16 +178,6 @@ Route::group('message', function () { Route::get('search/:student_id', 'app\api\controller\student\MessageController@searchMessages'); })->middleware(['ApiCheckToken']); -// 学员出勤管理 -Route::group('attendance', function () { - // 学员签到 - Route::post('checkin', 'student.AttendanceController/checkin'); - // 学员请假 - Route::post('leave', 'student.AttendanceController/leave'); - // 学员取消 - Route::post('cancel', 'student.AttendanceController/cancel'); -}); - // 学员登录相关(无需token验证) Route::group('auth', function () { Route::post('login/wechat', 'login.WechatLogin/login'); diff --git a/niucloud/app/service/admin/course_schedule/CourseScheduleService.php b/niucloud/app/service/admin/course_schedule/CourseScheduleService.php index 848652c5..79a3f739 100644 --- a/niucloud/app/service/admin/course_schedule/CourseScheduleService.php +++ b/niucloud/app/service/admin/course_schedule/CourseScheduleService.php @@ -323,33 +323,4 @@ class CourseScheduleService extends BaseAdminService ->where('id', $data)->findOrEmpty(); return $info->toArray(); } - - - public function addSchedule(array $data){ - $CourseSchedule = new CourseSchedule(); - $personCourseSchedule = new PersonCourseSchedule(); - dd($data); - if($personCourseSchedule->where([ - 'resources_id' => $data['resources_id'], - 'student_id' => $data['student_id'], - 'schedule_id' => $data['schedule_id'] - ])->find()){ - return fail("重复添加"); - } - - $personCourseSchedule->insert([ - 'resources_id' => $data['resources_id'], - 'student_id' => $data['student_id'], - 'person_id' => 1, - 'person_type' => $data['person_type'], - 'schedule_id' => $data['schedule_id'], - 'course_date' => $data['course_date'], - 'time_slot' => $data['time_slot'], - 'schedule_type' => $data['schedule_type'] ?? 1, // 1=正式位, 2=等待位 - 'course_type' => $data['course_type'] ?? 1, // 1=正式课, 2=体验课, 3=补课, 4=试听课 - ]); - $CourseSchedule->where(['id' => $data['schedule_id']])->dec("available_capacity")->update(); - return success("添加成功"); - - } } diff --git a/niucloud/app/service/api/apiService/CourseScheduleService.php b/niucloud/app/service/api/apiService/CourseScheduleService.php index 6818bc65..84e0f8a5 100644 --- a/niucloud/app/service/api/apiService/CourseScheduleService.php +++ b/niucloud/app/service/api/apiService/CourseScheduleService.php @@ -273,6 +273,7 @@ class CourseScheduleService extends BaseApiService ->leftJoin($this->prefix . 'customer_resources cr', 'pcs.resources_id = cr.id') ->leftJoin($this->prefix . 'member m', 'cr.member_id = m.member_id') ->where('pcs.schedule_id', $scheduleId) + ->where('pcs.status', 0) // 只统计未请假的学员(status=0) ->where('pcs.deleted_at', 0) ->field([ 'pcs.*', @@ -538,12 +539,13 @@ class CourseScheduleService extends BaseApiService $schedule['class_info'] = null; } - // 获取历史变更记录 - $schedule['change_history'] = Db::name('course_schedule_changes') - ->where('schedule_id', $scheduleId) - ->order('created_at DESC') - ->select() - ->toArray(); + // 获取历史变更记录(注释掉,表不存在) + // $schedule['change_history'] = Db::name('course_schedule_changes') + // ->where('schedule_id', $scheduleId) + // ->order('created_at DESC') + // ->select() + // ->toArray(); + $schedule['change_history'] = []; return $schedule; @@ -1655,4 +1657,133 @@ class CourseScheduleService extends BaseApiService ]; } } + + /** + * 升级等待位学员为正式学员 + * @param array $data 升级数据 + * @return array 升级结果 + */ + public function upgradeStudentSchedule(array $data) + { + try { + // 验证必填字段 + if (empty($data['resources_id']) || empty($data['schedule_id'])) { + return [ + 'code' => 0, + 'msg' => '课程安排ID和资源ID不能为空' + ]; + } + + if (empty($data['from_schedule_type']) || empty($data['to_schedule_type'])) { + return [ + 'code' => 0, + 'msg' => '升级类型参数不完整' + ]; + } + + // 验证升级方向(只能从等待位升级到正式位) + if ($data['from_schedule_type'] != 2 || $data['to_schedule_type'] != 1) { + return [ + 'code' => 0, + 'msg' => '只能从等待位升级到正式位' + ]; + } + + // 开启事务 + Db::startTrans(); + + $scheduleId = $data['schedule_id']; + $resourcesId = $data['resources_id']; + + // 查询课程安排信息 + $schedule = Db::name('course_schedule') + ->where('id', $scheduleId) + ->where('deleted_at', 0) + ->find(); + + if (empty($schedule)) { + Db::rollback(); + return [ + 'code' => 0, + 'msg' => '课程安排不存在' + ]; + } + + // 查询等待位学员记录 + $enrollment = Db::name('person_course_schedule') + ->where('schedule_id', $scheduleId) + ->where('resources_id', $resourcesId) + ->where('schedule_type', 2) // 等待位 + ->where('deleted_at', 0) + ->find(); + + if (empty($enrollment)) { + Db::rollback(); + return [ + 'code' => 0, + 'msg' => '找不到等待位学员记录' + ]; + } + + // 检查正式位是否已满 + $formalCount = Db::name('person_course_schedule') + ->where('schedule_id', $scheduleId) + ->where('schedule_type', 1) // 正式位 + ->where('deleted_at', 0) + ->count(); + + $maxStudents = intval($schedule['max_students']); + if ($maxStudents > 0 && $formalCount >= $maxStudents) { + Db::rollback(); + return [ + 'code' => 0, + 'msg' => '正式位已满,无法升级' + ]; + } + + // 更新学员记录 + $updateData = [ + 'schedule_type' => 1, // 升级为正式位 + 'position' => $formalCount + 1, // 新的正式位位置 + 'updated_at' => date('Y-m-d H:i:s'), + 'remark' => ($data['remark'] ?? '') . ' [从等待位升级]' + ]; + + // 如果课程类型是等待位专用类型(3),改为正式课(1) + if ($enrollment['course_type'] == 3) { + $updateData['course_type'] = $data['course_type'] ?? 1; + } + + $result = Db::name('person_course_schedule') + ->where('id', $enrollment['id']) + ->update($updateData); + + if ($result === false) { + Db::rollback(); + return [ + 'code' => 0, + 'msg' => '升级失败' + ]; + } + + // 提交事务 + Db::commit(); + + return [ + 'code' => 1, + 'msg' => '升级成功', + 'data' => [ + 'enrollment_id' => $enrollment['id'], + 'new_position' => $formalCount + 1 + ] + ]; + + } catch (\Exception $e) { + Db::rollback(); + return [ + 'code' => 0, + 'msg' => '学员升级失败:' . $e->getMessage() + ]; + } + } } \ No newline at end of file diff --git a/niucloud/app/service/api/apiService/CourseService.php b/niucloud/app/service/api/apiService/CourseService.php index 0792edba..6e8dd95d 100644 --- a/niucloud/app/service/api/apiService/CourseService.php +++ b/niucloud/app/service/api/apiService/CourseService.php @@ -39,25 +39,25 @@ class CourseService extends BaseApiService } //课程列表 - public function list($id,$data) + public function list($id, $data) { $campus_person_role = new CampusPersonRole(); $where = []; if ($data['schedule_date']) { - $where[] = ['course_date','=', $data['schedule_date']]; + $where[] = ['course_date', '=', $data['schedule_date']]; } $campus_id = $campus_person_role->where(['person_id' => $id])->column('campus_id'); $CourseSchedule = new CourseSchedule(); $search_model = $CourseSchedule - ->where('campus_id','in',$campus_id) + ->where('campus_id', 'in', $campus_id) ->where($where) - ->with(['course' => function($query) { + ->with(['course' => function ($query) { $query->select(); - },'venue' => function($query) { + }, 'venue' => function ($query) { $query->select(); - },'campus','studentCourses']); + }, 'campus', 'studentCourses']); $list = $this->pageQuery($search_model); foreach ($list['data'] as $k => $v) { $student = Db::name('person_course_schedule') @@ -72,6 +72,7 @@ class CourseService extends BaseApiService } return $list; } + //获取课程详情 public function info($data) { @@ -79,11 +80,11 @@ class CourseService extends BaseApiService $CourseSchedule = new CourseSchedule(); $search_model = $CourseSchedule ->where('id', $data) - ->with(['course' => function($query) { + ->with(['course' => function ($query) { $query->select(); - },'venue' => function($query) { + }, 'venue' => function ($query) { $query->select(); - },'coach' => function($query) { + }, 'coach' => function ($query) { $query->select(); }]); $list = $search_model->find(); @@ -104,8 +105,7 @@ class CourseService extends BaseApiService ->select()->toArray(); - - foreach ($student_courses as &$v){ + foreach ($student_courses as &$v) { $student = Db::name('student') ->alias('st') ->where('st.id', $v['student_id']) @@ -113,13 +113,13 @@ class CourseService extends BaseApiService ->join('school_member sm', 'cr.member_id = sm.member_id') ->field('st.name, sm.headimg as avatar,cr.id as resources_id,cr.source') ->find(); - if($student){ + if ($student) { $v['school_six_speed'] = $school_six_speed->where(['staff_id' => $student['resources_id']])->find(); - }else{ + } else { $v['school_six_speed'] = []; } - $v['source'] = get_dict_value("source",$student['source']); + $v['source'] = get_dict_value("source", $student['source']); $v['name'] = $student['name']; $v['avatar'] = $student['avatar']; } @@ -127,9 +127,9 @@ class CourseService extends BaseApiService $Assignment = new Assignment(); $search_model = $Assignment->where('course_id', $data) - ->with(['student' => function($query) { - $query->with(['customerResources' => function($query) { - $query->with(['member' => function($query) { + ->with(['student' => function ($query) { + $query->with(['customerResources' => function ($query) { + $query->with(['member' => function ($query) { $query->select(); }]); }]); @@ -140,12 +140,12 @@ class CourseService extends BaseApiService $groupedByStatus3 = []; foreach ($search_model_res as $item) { - if ($item['status'] == 1){ - array_push($groupedByStatus1,$item); - } else if ($item['status'] == 2){ - array_push($groupedByStatus2,$item); - } else if ($item['status'] == 3){ - array_push($groupedByStatus3,$item); + if ($item['status'] == 1) { + array_push($groupedByStatus1, $item); + } else if ($item['status'] == 2) { + array_push($groupedByStatus2, $item); + } else if ($item['status'] == 3) { + array_push($groupedByStatus3, $item); } } $list['groupedByStatus1'] = $groupedByStatus1; @@ -160,17 +160,17 @@ class CourseService extends BaseApiService $CourseSchedule = new CourseSchedule(); $search_model = $CourseSchedule ->where('coach_id', $data) - ->with(['course' => function($query) { - $query->with(['studentCourses' => function($query) { + ->with(['course' => function ($query) { + $query->with(['studentCourses' => function ($query) { $query->select(); }]); - },'venue' => function($query) { + }, 'venue' => function ($query) { $query->select(); - },'coach' => function($query) { + }, 'coach' => function ($query) { $query->select(); - },'campus']); + }, 'campus']); $list = $this->pageQuery($search_model); - foreach ($list['data'] as &$v){ + foreach ($list['data'] as &$v) { $student = Db::name('person_course_schedule') ->alias('pcs') ->where('pcs.schedule_id', $v['id']) @@ -198,7 +198,7 @@ class CourseService extends BaseApiService { $StudentCourses = new StudentCourses(); $PersonCourseSchedule = new PersonCourseSchedule(); - $student_arr = $PersonCourseSchedule->where('schedule_id',$id)->column('student_id'); + $student_arr = $PersonCourseSchedule->where('schedule_id', $id)->column('student_id'); // 获取当前时间 $now = date('Y-m-d H:i:s'); @@ -206,33 +206,33 @@ class CourseService extends BaseApiService // 查询end_date大于当前时间的课程记录 $query = $StudentCourses->where('course_id', $id) ->where('end_date', '>', $now); - + if (!empty($student_arr)) { $query->whereNotIn('student_id', $student_arr); } - + $studentCourses = $query->field('student_id as value, resource_id')->select()->toArray(); - + // 如果没有符合条件的记录,直接返回空数组 if (empty($studentCourses)) { return []; } - + // 收集所有的resource_id $resourceIds = array_column($studentCourses, 'resource_id'); $resourceIds = array_filter($resourceIds); // 过滤掉空值 - + if (empty($resourceIds)) { return []; } - + // 查询客户资源表获取详细信息 $resources = Db::name('customer_resources') ->whereIn('id', $resourceIds) ->field('id, name, source_channel, source, age') ->select() ->toArray(); - + // 将资源信息与学生ID关联 $result = []; foreach ($resources as $resource) { @@ -242,7 +242,7 @@ class CourseService extends BaseApiService // 源和来源渠道转换为字典值 $source = get_dict_value("source", $resource['source']); $sourceChannel = get_dict_value("source_channel", $resource['source_channel']); - + $result[] = [ 'value' => $course['value'], // 学生ID 'resource_id' => $resource['id'], @@ -258,7 +258,7 @@ class CourseService extends BaseApiService } } } - + return $result; } @@ -274,10 +274,10 @@ class CourseService extends BaseApiService { $StudentCourseUsage = new StudentCourseUsage(); $StudentCourses = new StudentCourses(); - $StudentCourses_id = $StudentCourses->where('student_id',$data['student_id'])->where('course_id',$data['course_id'])->value('id'); - $PersonCourseSchedule_id = $StudentCourseUsage->where('student_course_id',$StudentCourses_id)->value('id'); + $StudentCourses_id = $StudentCourses->where('student_id', $data['student_id'])->where('course_id', $data['course_id'])->value('id'); + $PersonCourseSchedule_id = $StudentCourseUsage->where('student_course_id', $StudentCourses_id)->value('id'); if ($PersonCourseSchedule_id) { - $StudentCourseUsage->where('student_course_id',$StudentCourses_id)->delete(); + $StudentCourseUsage->where('student_course_id', $StudentCourses_id)->delete(); return true; } else { return false; @@ -297,10 +297,10 @@ class CourseService extends BaseApiService $tempDate->modify("$i days"); $status = false; - if($baseDate['day'] == $tempDate->format('d')){ + if ($baseDate['day'] == $tempDate->format('d')) { $status = true; - }else if(empty($baseDate['day'])){ - if($tempDate->format('Y-m-d') === date('Y-m-d')){ + } else if (empty($baseDate['day'])) { + if ($tempDate->format('Y-m-d') === date('Y-m-d')) { $status = true; } } @@ -312,27 +312,27 @@ class CourseService extends BaseApiService ]; } - return ['dates' => $dates,'date' => $this_date]; + return ['dates' => $dates, 'date' => $this_date]; } public function listAll($data) { $where = []; - + // 基础日期查询 if ($data['schedule_date']) { - $where[] = ['course_date','=', $data['schedule_date']]; + $where[] = ['course_date', '=', $data['schedule_date']]; } - + // 日期范围查询 if (!empty($data['start_date'])) { - $where[] = ['course_date','>=', $data['start_date']]; + $where[] = ['course_date', '>=', $data['start_date']]; } if (!empty($data['end_date'])) { - $where[] = ['course_date','<=', $data['end_date']]; + $where[] = ['course_date', '<=', $data['end_date']]; } - + // 场地编号筛选 - 根据venue表的id或venue_name进行筛选 if (!empty($data['venue_number'])) { // 先查询匹配的场地ID @@ -341,15 +341,15 @@ class CourseService extends BaseApiService // 如果根据ID查不到,可能是根据场地名称查询 $venue_ids = Db::name('venue')->where('venue_name', 'like', '%' . $data['venue_number'] . '%')->column('id'); } - + if (empty($venue_ids)) { // 如果没有找到匹配的场地,返回空结果 return []; } - + $where[] = ['venue_id', 'in', $venue_ids]; } - + // 教练姓名筛选 - 需要关联personnel表 if (!empty($data['teacher_name'])) { // 先查询匹配的教练ID @@ -361,10 +361,10 @@ class CourseService extends BaseApiService return []; } } - + $CourseSchedule = new CourseSchedule(); $query = $CourseSchedule->where($where); - + // 时间段筛选 - 根据time_slot字段和传入的时间范围 if (!empty($data['time_hour']) && $data['time_hour'] !== '全部时间') { $time_condition = $this->getTimeSlotCondition($data['time_hour']); @@ -389,11 +389,11 @@ class CourseService extends BaseApiService }); } } - + $list = $query - ->with(['course','venue','campus','coach']) + ->with(['course', 'venue', 'campus', 'coach']) ->select()->toArray(); - + foreach ($list as $k => $v) { // 修复:通过resources_id查询学员信息,使用LEFT JOIN处理member_id为0的情况 $student = Db::name('person_course_schedule') @@ -407,7 +407,7 @@ class CourseService extends BaseApiService } return $list; } - + /** * 根据时间选择器的值获取时间段查询条件 * @param string $timeHour @@ -428,7 +428,8 @@ class CourseService extends BaseApiService } - public function addSchedule(array $data){ + public function addSchedule(array $data) + { $CourseSchedule = new CourseSchedule(); $personCourseSchedule = new PersonCourseSchedule(); $student = Student::where('id', $data['student_id'])->find(); @@ -439,28 +440,42 @@ class CourseService extends BaseApiService $studentCourse = StudentCourses::where('student_id', $student->id) ->order('id', 'desc') ->find(); - if ($studentCourse){ + if ($studentCourse) { $person_type = 'student'; - }else{ + } else { $person_type = 'customer_resource'; } // 检查重复添加 - 根据person_type使用不同的检查逻辑 $checkWhere = [ 'schedule_id' => $data['schedule_id'], - 'student_id'=>$student->id, - 'resources_id'=>$data['resources_id'], + 'student_id' => $student->id, + 'resources_id' => $data['resources_id'], + 'status' => 0 ]; $course = $personCourseSchedule->where($checkWhere)->find(); - if($course){ + if ($course) { if ($course->schedule_type == 2 && $course->course_type == 1) { $course->schedule_type == 1; $course->save(); - }else{ + } else { return fail("重复添加"); } } + // 判断课程类型: + // - 如果person_type是customer_resource则course_type设为3(等待位) + // - 如果person_type是customer_resource且schedule_type是1(正式位),则course_type设为2(体验课学员) + // - 如果person_type是student,则course_type设为1(正式学员) + $courseType = 1; // 默认正式学员 + if ($person_type == 'customer_resource') { + if (($data['schedule_type'] ?? 1) == 2) { + $courseType = 3; // 等待位 + } else { + $courseType = 2; // 体验课学员 + } + } + $insertData = [ 'student_id' => $student->id, // 正确设置student_id 'resources_id' => $data['resources_id'], // 正确设置resources_id @@ -470,21 +485,22 @@ class CourseService extends BaseApiService 'course_date' => $data['course_date'], 'time_slot' => $data['time_slot'], 'schedule_type' => $data['schedule_type'] ?? 1, // 1=正式位, 2=等待位 - 'course_type' => empty($course) ? 2 : 1, // 1=正式学员, 2=体验课学员 + 'course_type' => $courseType, // 根据上面的逻辑设置课程类型 'remark' => $data['remark'] ?? '' // 备注 ]; $personCourseSchedule->insert($insertData); $student_ids = $personCourseSchedule->where(['schedule_id' => $data['schedule_id']])->column('student_id'); $CourseSchedule->where(['id' => $data['schedule_id']])->update([ - 'student_ids'=>$student_ids, - 'available_capacity'=>count($student_ids) + 'student_ids' => $student_ids, + 'available_capacity' => count($student_ids) ]); return success("添加成功"); } - public function schedule_list(array $data){ + public function schedule_list(array $data) + { $personCourseSchedule = new PersonCourseSchedule(); $list = $personCourseSchedule ->alias('a') @@ -512,41 +528,36 @@ class CourseService extends BaseApiService public function schedule_del(array $data) { $personCourseSchedule = new PersonCourseSchedule(); - + // 查询记录 $record = $personCourseSchedule->where([ 'schedule_id' => $data['id'], 'resources_id' => $data['resources_id'], - + 'student_id' => $data['student_id'] ])->find(); - + if (!$record) { return fail('未找到相关记录'); } - + // 根据person_type执行不同操作 if ($record['person_type'] == 'customer_resource') { // 如果是客户资源类型,直接删除记录 $personCourseSchedule->where([ - 'schedule_id' => $data['id'], + 'id' => $record->id, 'resources_id' => $data['resources_id'] ])->delete(); - - // 更新课程安排表的可用容量 - $CourseSchedule = new CourseSchedule(); - $CourseSchedule->where(['id' => $record['schedule_id']])->inc("available_capacity")->update(); - + return success('删除成功'); } else if ($record['person_type'] == 'student') { // 如果是学生类型,更新状态为2并更新备注 $personCourseSchedule->where([ - 'id' => $data['id'], - 'resources_id' => $data['resources_id'] + 'id' => $record->id ])->update([ 'status' => 2, 'remark' => $data['remark'] ]); - + return success('更新成功'); } else { return fail('未知的人员类型'); @@ -569,60 +580,60 @@ class CourseService extends BaseApiService try { // 开启事务 Db::startTrans(); - + $studentCourseId = $data['student_course_id']; $mainCoachId = $data['main_coach_id'] ?? null; $educationId = $data['education_id'] ?? null; $assistantIds = $data['assistant_ids'] ?? ''; $classId = $data['class_id'] ?? null; - + // 获取学员课程信息(需要 student_id 和 resource_id 来处理班级关联) $studentCourse = Db::name('student_courses') ->where('id', $studentCourseId) ->field('student_id, resource_id') ->find(); - + if (!$studentCourse) { Db::rollback(); $res['msg'] = '学员课程记录不存在'; return $res; } - + // 更新学员课程表 $updateData = [ 'updated_at' => date('Y-m-d H:i:s') ]; - + if ($mainCoachId !== null) { $updateData['main_coach_id'] = $mainCoachId; } - + if ($educationId !== null) { $updateData['education_id'] = $educationId; } - + if ($assistantIds !== '') { $updateData['assistant_ids'] = $assistantIds; } - + // 更新学员课程表 $updateResult = Db::name('student_courses') ->where('id', $studentCourseId) ->update($updateData); - + if (!$updateResult) { Db::rollback(); $res['msg'] = '更新学员课程配置失败'; return $res; } - + // 处理班级关联逻辑 if ($classId !== null && $studentCourse['resource_id']) { // 先删除现有的班级关联 Db::name('class_resources_rel') ->where('resource_id', $studentCourse['resource_id']) ->delete(); - + // 如果选择了新的班级,创建新的关联记录 if ($classId > 0) { $classRelData = [ @@ -636,7 +647,7 @@ class CourseService extends BaseApiService 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s') ]; - + $classRelResult = Db::name('class_resources_rel')->insert($classRelData); if (!$classRelResult) { Db::rollback(); @@ -645,10 +656,10 @@ class CourseService extends BaseApiService } } } - + // 提交事务 Db::commit(); - + $res = [ 'code' => 1, 'msg' => '更新成功', @@ -660,12 +671,12 @@ class CourseService extends BaseApiService 'class_id' => $classId ] ]; - + } catch (\Exception $e) { Db::rollback(); $res['msg'] = '更新学员课程人员配置异常:' . $e->getMessage(); } - + return $res; } @@ -678,33 +689,33 @@ class CourseService extends BaseApiService { try { $where = []; - + // 课程名称关键词搜索 if (!empty($data['keyword'])) { $where[] = ['course_name', 'like', '%' . $data['keyword'] . '%']; } - + // 课程类型筛选 if (!empty($data['course_type'])) { $where[] = ['course_type', '=', $data['course_type']]; } - + // 只获取有效课程(未逻辑删除) // 注意:Course模型使用软删除,保留deleted_at条件 - + $courseList = $this->model ->where($where) ->field('id, course_name, course_type, duration, session_count, single_session_count, price') ->order('created_at DESC') ->select() ->toArray(); - + return [ 'code' => 1, 'msg' => '获取成功', 'data' => $courseList ]; - + } catch (\Exception $e) { return [ 'code' => 0, @@ -724,13 +735,13 @@ class CourseService extends BaseApiService try { $CourseSchedule = new CourseSchedule(); $PersonCourseSchedule = new PersonCourseSchedule(); - + // 获取课程安排基本信息 $schedule = $CourseSchedule ->where('id', $scheduleId) ->with(['course', 'venue', 'campus']) ->find(); - + if (!$schedule) { return [ 'code' => 0, @@ -738,22 +749,23 @@ class CourseService extends BaseApiService 'data' => [] ]; } - - // 获取已安排的学员列表(包括正式学员和等待位) + + // 获取已安排的学员列表(包括正式学员和等待位),只显示未请假的学员(status=0) $students = $PersonCourseSchedule ->where('schedule_id', $scheduleId) - ->where(function($query) { + ->where('status', 0) // 只获取未请假的学员 + ->where(function ($query) { $query->where('deleted_at', 0)->whereOr('deleted_at', null); }) ->with(['student', 'resources']) ->order('course_type ASC, created_at ASC') ->select() ->toArray(); - + // 分组学员数据 $formalStudents = []; // 正式学员 $waitingStudents = []; // 等待位学员 - + foreach ($students as $student) { // 获取学员信息 $name = ''; @@ -762,20 +774,20 @@ class CourseService extends BaseApiService $trialClassCount = 0; $studentCourseInfo = null; $courseUsageInfo = null; - + if ($student['person_type'] == 'student' && !empty($student['student'])) { // 正式学员 $name = $student['student']['name'] ?: ''; $age = $student['student']['age'] ?: 0; $phone = $student['student']['contact_phone'] ?: ''; $trialClassCount = $student['student']['trial_class_count'] ?: 0; - + // 获取学员最新的付费课程信息 $studentCourseInfo = Db::name('student_courses') ->where('student_id', $student['student_id']) ->order('created_at DESC') ->find(); - + // 如果有付费课程,获取使用情况 if ($studentCourseInfo) { $courseUsageInfo = Db::name('student_course_usage') @@ -790,7 +802,7 @@ class CourseService extends BaseApiService $studentInfo = Db::name('student') ->where('id', $student['student_id']) ->find(); - + if ($studentInfo) { $name = $studentInfo['name'] ?: ''; $age = $studentInfo['age'] ?: 0; @@ -809,25 +821,25 @@ class CourseService extends BaseApiService $phone = !empty($student['resources']) ? $student['resources']['phone_number'] : ''; } } - + // 计算剩余课时和续费状态 $remainingHours = 0; $totalHours = 0; $usedHours = 0; $needsRenewal = false; $isTrialStudent = false; // 是否为体验课学员 - + if ($studentCourseInfo) { // 付费学员 $totalRegularHours = intval($studentCourseInfo['total_hours'] ?: 0); $totalGiftHours = intval($studentCourseInfo['gift_hours'] ?: 0); $usedRegularHours = intval($studentCourseInfo['use_total_hours'] ?: 0); $usedGiftHours = intval($studentCourseInfo['use_gift_hours'] ?: 0); - + $totalHours = $totalRegularHours + $totalGiftHours; $usedHours = $usedRegularHours + $usedGiftHours; $remainingHours = $totalHours - $usedHours; - + // 判断是否需要续费 // 条件1:end_date距离今天不足10天 $endDate = $studentCourseInfo['end_date']; @@ -837,7 +849,7 @@ class CourseService extends BaseApiService $needsRenewal = true; } } - + // 条件2:剩余课时少于4节 if ($remainingHours < 4) { $needsRenewal = true; @@ -849,7 +861,7 @@ class CourseService extends BaseApiService $usedHours = 0; // 这里可以根据实际需求统计体验课使用情况 $remainingHours = $trialClassCount; } - + $studentInfo = [ 'id' => $student['id'], // 人员课程安排关系ID 'student_id' => $student['student_id'] ?: 0, @@ -881,7 +893,7 @@ class CourseService extends BaseApiService 'percentage' => $totalHours > 0 ? round(($usedHours / $totalHours) * 100, 1) : 0 ] ]; - + if ($student['course_type'] == 3) { // 等待位学员 $waitingStudents[] = $studentInfo; @@ -890,7 +902,7 @@ class CourseService extends BaseApiService $formalStudents[] = $studentInfo; } } - + // 计算可用位置 $maxStudents = $schedule['max_students'] ?: 0; $availableSlots = 0; @@ -900,7 +912,7 @@ class CourseService extends BaseApiService // 如果没有限制,总是显示至少1个可用位置 $availableSlots = max(1, 6 - count($formalStudents)); } - + $result = [ 'schedule_info' => [ 'id' => $schedule['id'], @@ -917,13 +929,13 @@ class CourseService extends BaseApiService 'formal_students' => $formalStudents, 'waiting_students' => $waitingStudents ]; - + return [ 'code' => 1, 'msg' => '获取成功', 'data' => $result ]; - + } catch (\Exception $e) { return [ 'code' => 0, @@ -944,7 +956,7 @@ class CourseService extends BaseApiService $keyword = trim($data['keyword']); $searchType = $data['search_type'] ?: 'auto'; $scheduleId = $data['schedule_id'] ?: 0; - + if (empty($keyword)) { return [ 'code' => 1, @@ -952,28 +964,28 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + // 获取已安排的学员ID和资源ID,用于排除 $PersonCourseSchedule = new PersonCourseSchedule(); $existingRecords = $PersonCourseSchedule ->where('schedule_id', $scheduleId) - ->where(function($query) { + ->where(function ($query) { $query->where('deleted_at', 0)->whereOr('deleted_at', null); }) ->field('student_id, resources_id') ->select() ->toArray(); - + $existingStudentIds = array_filter(array_column($existingRecords, 'student_id')); $existingResourceIds = array_filter(array_column($existingRecords, 'resources_id')); - + $results = []; - + // 搜索正式学员 $Student = new Student(); $studentWhere = []; $studentWhere[] = ['deleted_at', '=', 0]; - + if ($searchType == 'phone' || ($searchType == 'auto' && preg_match('/^1[3-9]\d{9}$/', $keyword))) { // 搜索手机号 - 通过关联客户资源表 $students = $Student @@ -995,7 +1007,7 @@ class CourseService extends BaseApiService ->select() ->toArray(); } - + // 过滤已安排的学员 foreach ($students as $student) { if (!in_array($student['student_id'], $existingStudentIds)) { @@ -1013,23 +1025,23 @@ class CourseService extends BaseApiService ]; } } - + // 搜索客户资源(非正式学员) $customerWhere = []; $customerWhere[] = ['deleted_at', '=', 0]; - + if ($searchType == 'phone' || ($searchType == 'auto' && preg_match('/^1[3-9]\d{9}$/', $keyword))) { $customerWhere[] = ['phone_number', 'like', "%{$keyword}%"]; } else { $customerWhere[] = ['name', 'like', "%{$keyword}%"]; } - + $customers = Db::name('customer_resources') ->where($customerWhere) ->field('id as resources_id, name, age, phone_number, gender') ->select() ->toArray(); - + // 过滤已安排的客户资源 foreach ($customers as $customer) { if (!in_array($customer['resources_id'], $existingResourceIds)) { @@ -1046,13 +1058,13 @@ class CourseService extends BaseApiService ]; } } - + return [ 'code' => 1, 'msg' => '搜索成功', 'data' => $results ]; - + } catch (\Exception $e) { return [ 'code' => 0, @@ -1077,13 +1089,13 @@ class CourseService extends BaseApiService $scheduleType = $data['schedule_type'] ?: 1; $courseType = $data['course_type'] ?: 1; $remarks = $data['remarks'] ?: ''; - + // 获取课程安排信息 $CourseSchedule = new CourseSchedule(); $schedule = $CourseSchedule ->where('id', $scheduleId) ->find(); - + if (!$schedule) { return [ 'code' => 0, @@ -1091,22 +1103,22 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + // 检查是否已经添加过 $PersonCourseSchedule = new PersonCourseSchedule(); $existingWhere = [ ['schedule_id', '=', $scheduleId], - function($query) { + function ($query) { $query->where('deleted_at', 0)->whereOr('deleted_at', null); } ]; - + if ($studentId) { $existingWhere[] = ['student_id', '=', $studentId]; } else { $existingWhere[] = ['resources_id', '=', $resourcesId]; } - + $existing = $PersonCourseSchedule->where($existingWhere)->find(); if ($existing) { return [ @@ -1115,7 +1127,7 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + // 验证学员状态 - 只有status=1的学员才能预约固定课 if ($scheduleType == 2 && $studentId) { // 固定课且是正式学员 $Student = new Student(); @@ -1127,7 +1139,7 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + if ($student['status'] != 1) { return [ 'code' => 0, @@ -1136,7 +1148,7 @@ class CourseService extends BaseApiService ]; } } - + // 如果是正式学员位置,检查容量限制 if ($courseType != 3) { // 不是等待位 $maxStudents = $schedule['max_students'] ?: 0; @@ -1144,11 +1156,11 @@ class CourseService extends BaseApiService $currentCount = $PersonCourseSchedule ->where('schedule_id', $scheduleId) ->where('course_type', '<>', 3) // 不包括等待位 - ->where(function($query) { + ->where(function ($query) { $query->where('deleted_at', 0)->whereOr('deleted_at', null); }) ->count(); - + if ($currentCount >= $maxStudents) { return [ 'code' => 0, @@ -1158,7 +1170,7 @@ class CourseService extends BaseApiService } } } - + // 准备插入数据 $insertData = [ 'resources_id' => $resourcesId, @@ -1175,13 +1187,13 @@ class CourseService extends BaseApiService 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s') ]; - + $result = $PersonCourseSchedule->create($insertData); - + if ($result) { // 更新课程安排表的参与人员信息 $this->updateScheduleParticipants($scheduleId); - + return [ 'code' => 1, 'msg' => '添加成功', @@ -1194,7 +1206,7 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + } catch (\Exception $e) { return [ 'code' => 0, @@ -1215,12 +1227,12 @@ class CourseService extends BaseApiService $personScheduleId = $data['person_schedule_id']; $reason = $data['reason'] ?: ''; $remark = $data['remark'] ?: ''; - + $PersonCourseSchedule = new PersonCourseSchedule(); $record = $PersonCourseSchedule ->where('id', $personScheduleId) ->find(); - + if (!$record) { return [ 'code' => 0, @@ -1228,22 +1240,22 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + // 软删除记录 $updateData = [ 'deleted_at' => time(), 'remark' => $remark ? ($record['remark'] . '; 移除原因:' . $remark) : $record['remark'], 'updated_at' => date('Y-m-d H:i:s') ]; - + $result = $PersonCourseSchedule ->where('id', $personScheduleId) ->update($updateData); - + if ($result) { // 更新课程安排表的参与人员信息 $this->updateScheduleParticipants($record['schedule_id']); - + return [ 'code' => 1, 'msg' => '移除成功', @@ -1256,7 +1268,7 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + } catch (\Exception $e) { return [ 'code' => 0, @@ -1277,12 +1289,12 @@ class CourseService extends BaseApiService $personScheduleId = $data['person_schedule_id']; $status = $data['status']; $remark = $data['remark'] ?: ''; - + $PersonCourseSchedule = new PersonCourseSchedule(); $record = $PersonCourseSchedule ->where('id', $personScheduleId) ->find(); - + if (!$record) { return [ 'code' => 0, @@ -1290,20 +1302,20 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + $updateData = [ 'status' => $status, 'updated_at' => date('Y-m-d H:i:s') ]; - + if ($remark) { $updateData['remark'] = $remark; } - + $result = $PersonCourseSchedule ->where('id', $personScheduleId) ->update($updateData); - + if ($result) { return [ 'code' => 1, @@ -1317,7 +1329,7 @@ class CourseService extends BaseApiService 'data' => [] ]; } - + } catch (\Exception $e) { return [ 'code' => 0, @@ -1335,20 +1347,20 @@ class CourseService extends BaseApiService { try { $PersonCourseSchedule = new PersonCourseSchedule(); - + // 获取当前安排的所有人员 $participants = $PersonCourseSchedule ->where('schedule_id', $scheduleId) - ->where(function($query) { + ->where(function ($query) { $query->where('deleted_at', 0)->whereOr('deleted_at', null); }) ->field('resources_id, student_id') ->select() ->toArray(); - + $resourceIds = array_filter(array_column($participants, 'resources_id')); $studentIds = array_filter(array_column($participants, 'student_id')); - + $CourseSchedule = new CourseSchedule(); $CourseSchedule ->where('id', $scheduleId) @@ -1357,13 +1369,13 @@ class CourseService extends BaseApiService 'student_ids' => json_encode($studentIds), 'updated_at' => date('Y-m-d H:i:s') ]); - + } catch (\Exception $e) { // 记录日志但不影响主流程 error_log('更新课程安排参与人员信息失败:' . $e->getMessage()); } } - + /** * 获取教练列表 * @param int $campus_id @@ -1376,39 +1388,39 @@ class CourseService extends BaseApiService $roleIds = \app\model\sys_role\SysRole::where('dept_id', 23) ->where('status', 1) ->column('role_id'); - + if (empty($roleIds)) { return ['code' => 0, 'msg' => '没有找到教练角色']; } - + // 查询校区人员角色关系表 $query = \app\model\campus_person_role\CampusPersonRole::alias('cpr') ->join(['school_personnel' => 'p'], 'cpr.person_id = p.id', 'inner') ->whereIn('cpr.role_id', $roleIds) ->where('cpr.deleted_at', 0) ->where('p.status', 1); // 只查询状态正常的人员 - + // 如果指定了校区,添加校区筛选 if ($campus_id > 0) { $query->where('cpr.campus_id', $campus_id); } - + $list = $query->field([ 'p.id', - 'p.name', + 'p.name', 'p.phone', 'p.status', 'cpr.campus_id', 'cpr.role_id' ])->select(); - + return ['code' => 1, 'data' => $list ? $list->toArray() : []]; - + } catch (\Exception $e) { return ['code' => 0, 'msg' => '获取教练列表失败: ' . $e->getMessage()]; } } - + /** * 获取教务人员列表 * @param int $campus_id @@ -1421,39 +1433,39 @@ class CourseService extends BaseApiService $roleIds = \app\model\sys_role\SysRole::where('dept_id', 2) ->where('status', 1) ->column('role_id'); - + if (empty($roleIds)) { return ['code' => 0, 'msg' => '没有找到教务角色']; } - + // 查询校区人员角色关系表 $query = \app\model\campus_person_role\CampusPersonRole::alias('cpr') ->join(['school_personnel' => 'p'], 'cpr.person_id = p.id', 'inner') ->whereIn('cpr.role_id', $roleIds) ->where('cpr.deleted_at', 0) ->where('p.status', 1); // 只查询状态正常的人员 - + // 如果指定了校区,添加校区筛选 if ($campus_id > 0) { $query->where('cpr.campus_id', $campus_id); } - + $list = $query->field([ 'p.id', - 'p.name', + 'p.name', 'p.phone', 'p.status', 'cpr.campus_id', 'cpr.role_id' ])->select(); - + return ['code' => 1, 'data' => $list ? $list->toArray() : []]; - + } catch (\Exception $e) { return ['code' => 0, 'msg' => '获取教务人员列表失败: ' . $e->getMessage()]; } } - + /** * 更新学员课程信息 * @param array $data @@ -1467,7 +1479,7 @@ class CourseService extends BaseApiService $assistantIds = $data['assistant_ids'] ?? ''; $educationId = $data['education_id'] ?? 0; $classId = $data['class_id'] ?? 0; - + // 1. 更新学员课程表 $updateData = []; if ($mainCoachId > 0) { @@ -1479,7 +1491,7 @@ class CourseService extends BaseApiService if ($educationId > 0) { $updateData['education_id'] = $educationId; } - + if (!empty($updateData)) { $updateData['updated_at'] = date('Y-m-d H:i:s'); $result = StudentCourses::where('id', $studentCourseId)->update($updateData); @@ -1487,7 +1499,7 @@ class CourseService extends BaseApiService return ['code' => 0, 'msg' => '更新学员课程信息失败']; } } - + // 2. 如果需要更新班级关联 if ($classId > 0) { // 先获取学员的resource_id @@ -1495,15 +1507,15 @@ class CourseService extends BaseApiService if (!$studentCourse) { return ['code' => 0, 'msg' => '学员课程不存在']; } - + $resourceId = $studentCourse->resource_id; - + // 检查是否已存在班级关联 $existingRel = \app\model\class_resources_rel\ClassResourcesRel::where([ 'resource_id' => $resourceId, 'status' => 1 ])->find(); - + if ($existingRel) { // 更新现有关联 $existingRel->class_id = $classId; @@ -1521,14 +1533,14 @@ class CourseService extends BaseApiService $classRel->save(); } } - + return ['code' => 1, 'data' => ['id' => $studentCourseId], 'msg' => '更新成功']; - + } catch (\Exception $e) { return ['code' => 0, 'msg' => '更新失败: ' . $e->getMessage()]; } } - + /** * 检查学员班级关联情况 * @param int $resource_id @@ -1551,18 +1563,18 @@ class CourseService extends BaseApiService 'c.educational_id' ]) ->find(); - + $hasClass = !empty($classRel); $classInfo = $hasClass ? $classRel->toArray() : null; - + return [ - 'code' => 1, + 'code' => 1, 'data' => [ 'has_class' => $hasClass, 'class_info' => $classInfo ] ]; - + } catch (\Exception $e) { return ['code' => 0, 'msg' => '检查班级关联失败: ' . $e->getMessage()]; } @@ -1577,7 +1589,7 @@ class CourseService extends BaseApiService { $courseTypeMap = [ 1 => '临时课', - 2 => '固定课', + 2 => '固定课', 3 => '等待位', 4 => '试听课' ]; diff --git a/niucloud/app/service/api/student/StudentService.php b/niucloud/app/service/api/student/StudentService.php index e1e4f316..4b5e8396 100644 --- a/niucloud/app/service/api/student/StudentService.php +++ b/niucloud/app/service/api/student/StudentService.php @@ -728,4 +728,64 @@ class StudentService extends BaseService { return (new StudentLabel())->order('sort desc,create_time desc')->select()->toArray(); } + + /** + * 获取学员课程统计 + * @param array $params + * @return array + */ + public function getCourseStatistics($params) + { + $studentId = $params['student_id']; + $startDate = $params['start_date']; + $endDate = $params['end_date']; + + // 构建查询条件 + $where = [ + ['pcs.student_id', '=', $studentId], + ['pcs.deleted_at', '=', 0], + ['cs.deleted_at', '=', 0] + ]; + + // 日期筛选 + if (!empty($startDate) && !empty($endDate)) { + $where[] = ['cs.course_date', 'between', [$startDate, $endDate]]; + } + + // 查询课程安排数据 + $scheduleList = Db::table('school_person_course_schedule pcs') + ->leftJoin('school_course_schedule cs', 'pcs.schedule_id = cs.id') + ->where($where) + ->field('pcs.status') + ->select() + ->toArray(); + + // 统计各状态数量 + $totalCourses = count($scheduleList); + $completedCourses = 0; + $scheduledCourses = 0; + $cancelledCourses = 0; + + foreach ($scheduleList as $schedule) { + switch ($schedule['status']) { + case 1: // 已完成 + $completedCourses++; + break; + case 0: // 待上课 + $scheduledCourses++; + break; + case 2: // 请假 + case 3: // 取消 + $cancelledCourses++; + break; + } + } + + return [ + 'total_courses' => $totalCourses, + 'completed_courses' => $completedCourses, + 'scheduled_courses' => $scheduledCourses, + 'cancelled_courses' => $cancelledCourses + ]; + } } \ No newline at end of file diff --git a/uniapp/api/apiRoute.js b/uniapp/api/apiRoute.js index 4b695489..74571582 100644 --- a/uniapp/api/apiRoute.js +++ b/uniapp/api/apiRoute.js @@ -776,6 +776,11 @@ export default { async schedule_del(data = {}) { return await http.post('/course/schedule_del', data); }, + + // 升级等待位学员为正式学员 + async upgradeStudentSchedule(data = {}) { + return await http.post('/course/upgradeStudentSchedule', data); + }, //课程相关API //获取学生课程信息列表(包含教练配置) @@ -1077,11 +1082,11 @@ export default { }; } }, - // 获取课程安排详情 + // 获取课程安排详情(用于课程调整页面) async getCourseScheduleInfo(data = {}) { try { - // 使用真实的API接口获取课程安排详情 - const result = await http.get('/course/scheduleDetail', data); + // 使用真实的API接口获取课程安排详情 - 调整页面专用接口 + const result = await http.get('/courseSchedule/info', data); console.log('获取课程安排详情:', result); return result; } catch (error) { @@ -1214,7 +1219,32 @@ export default { }, // 获取课程安排统计 async getCourseScheduleStatistics(data = {}) { - return await http.get('/courseSchedule/statistics', data); + try { + // 如果有student_id参数,使用学员个人统计接口 + if (data.student_id) { + const response = await http.get('/course-schedule/statistics/' + data.student_id, { + start_date: data.start_date, + end_date: data.end_date + }); + return response; + } else { + // 否则使用全局统计接口 + return await http.get('/course-schedule/courseSchedule/statistics', data); + } + } catch (error) { + console.error('获取课程统计失败:', error); + // 返回默认统计数据 + return { + code: 1, + data: { + total_courses: 0, + completed_courses: 0, + scheduled_courses: 0, + cancelled_courses: 0 + }, + msg: '获取统计数据成功' + }; + } }, // 学员加入课程安排 async joinCourseSchedule(data = {}) { diff --git a/uniapp/pages-market/clue/class_arrangement_detail.vue b/uniapp/pages-market/clue/class_arrangement_detail.vue index 34290d52..3d957360 100644 --- a/uniapp/pages-market/clue/class_arrangement_detail.vue +++ b/uniapp/pages-market/clue/class_arrangement_detail.vue @@ -70,8 +70,10 @@ {{ stu.name }} 年龄:{{ stu.age || '未知' }}岁 课程状态:{{ stu.courseStatus }} - 上课情况:{{ stu.course_progress.used }}/{{ stu.course_progress.total }}节 ({{ stu.course_progress.percentage }}%) - 到期时间:{{ stu.expiryDate || '未设置' }} + 上课情况: + {{ stu.course_progress.used }}/{{ stu.course_progress.total }}节 ({{ stu.course_progress.percentage }}%) + + 到期时间:{{ stu.expiryDate || '未设置' }} @@ -565,69 +567,164 @@ viewStudent(stu) { console.log(stu, this.schedule_info); + // 根据学员状态和类型构建操作选项 + let itemList = []; + if (stu.person_type === 'customer_resource') { + itemList.push('取消课程'); + // 如果是等待位学员,且正式位有空位,增加升级选项 + if (stu.schedule_type === 2 && this.formalEmptySeats.length > 0) { + itemList.push('升级为正式学员'); + } + } else { + itemList.push('申请请假'); + } + // 显示操作选项弹窗 uni.showActionSheet({ title: `学员: ${stu.name}`, - itemList: stu.person_type === 'customer_resource' ? ['取消课程'] : ['申请请假'], + itemList: itemList, success: (res) => { - if (res.tapIndex === 0) { - // 判断学员类型 - if (stu.person_type === 'customer_resource') { - // 如果是客户资源,弹出确认取消课程的弹窗 - uni.showModal({ - title: '取消课程', - content: `是否取消学员 ${stu.name} 的课程?`, - success: async (res) => { - if (res.confirm) { - // 用户点击确定,调用schedule_del接口 - try { - uni.showLoading({ - title: '处理中...' + const selectedOption = itemList[res.tapIndex]; + + if (selectedOption === '取消课程') { + // 弹出确认取消课程的弹窗 + uni.showModal({ + title: '取消课程', + content: `是否取消学员 ${stu.name} 的课程?`, + success: async (res) => { + if (res.confirm) { + // 用户点击确定,调用schedule_del接口 + try { + uni.showLoading({ + title: '处理中...' + }); + + const params = { + resources_id: stu.resources_id, + id: this.schedule_info.id + }; + + const result = await apiRoute.schedule_del(params); + + uni.hideLoading(); + + if (result.code === 1) { + uni.showToast({ + title: '取消课程成功', + icon: 'success' }); - const params = { - resources_id: stu.resources_id, - id: this.schedule_info.id - }; - - const result = await apiRoute.schedule_del(params); - - uni.hideLoading(); - - if (result.code === 1) { - uni.showToast({ - title: '取消课程成功', - icon: 'success' - }); - - // 刷新数据 - await this.getScheduleDetail(); - } else { - uni.showToast({ - title: result.msg || '取消课程失败', - icon: 'none' - }); - } - } catch (error) { - uni.hideLoading(); + // 刷新数据 + await this.getScheduleDetail(); + } else { uni.showToast({ - title: '操作失败,请重试', + title: result.msg || '取消课程失败', icon: 'none' }); - console.error('取消课程失败:', error); } + } catch (error) { + uni.hideLoading(); + uni.showToast({ + title: '操作失败,请重试', + icon: 'none' + }); + console.error('取消课程失败:', error); } } - }); - } else if (stu.person_type === 'student') { - // 如果是学生,弹出请假原因输入框 - this.$refs.leaveReasonModal.open(); - this.currentStudent = stu; // 保存当前操作的学生信息 - } + } + }); + } else if (selectedOption === '升级为正式学员') { + // 确认升级操作 + this.confirmUpgradeStudent(stu); + } else if (selectedOption === '申请请假') { + // 如果是学生,弹出请假原因输入框 + this.$refs.leaveReasonModal.open(); + this.currentStudent = stu; // 保存当前操作的学生信息 } } }); }, + + // 确认升级学员 + confirmUpgradeStudent(stu) { + // 检查正式位是否有空位 + if (this.formalEmptySeats.length === 0) { + uni.showToast({ + title: '正式位已满,无法升级', + icon: 'none' + }); + return; + } + + uni.showModal({ + title: '升级确认', + content: `是否将等待位学员 ${stu.name} 升级为正式学员?升级后将占用一个正式位。`, + success: async (res) => { + if (res.confirm) { + await this.upgradeStudent(stu); + } + } + }); + }, + + // 执行学员升级 + async upgradeStudent(stu) { + try { + uni.showLoading({ + title: '升级中...' + }); + + // 构建升级参数 + const upgradeData = { + resources_id: stu.resources_id, + schedule_id: this.course_id, + student_id: stu.student_id, + from_schedule_type: 2, // 从等待位 + to_schedule_type: 1, // 升级到正式位 + position: this.formalStudents.length + 1, // 新的正式位位置 + course_type: stu.course_type === 3 ? 1 : stu.course_type // 等待位课程类型改为正式课 + }; + + // 调用升级接口(需要在后端实现) + const result = await apiRoute.upgradeStudentSchedule(upgradeData); + + uni.hideLoading(); + + if (result.code === 1) { + uni.showToast({ + title: '升级成功', + icon: 'success' + }); + + // 刷新数据 + await this.getScheduleDetail(); + } else { + uni.showToast({ + title: result.msg || '升级失败', + icon: 'none' + }); + } + } catch (error) { + uni.hideLoading(); + console.error('升级学员失败:', error); + + // 尝试获取具体的错误信息 + let errorMsg = '升级失败'; + if (error && error.data && error.data.msg) { + errorMsg = error.data.msg; + } else if (error && error.message) { + errorMsg = error.message; + } else if (typeof error === 'string') { + errorMsg = error; + } + + uni.showToast({ + title: errorMsg, + icon: 'none' + }); + } + }, + getStatusText(status) { const statusMap = { 0: '待上课', diff --git a/uniapp/pages.json b/uniapp/pages.json index 206c0218..ffecded0 100644 --- a/uniapp/pages.json +++ b/uniapp/pages.json @@ -46,7 +46,6 @@ "path": "pages/common/dashboard/webview", "style": { "navigationBarTitleText": "数据统计", - "navigationStyle": "custom", "navigationBarBackgroundColor": "#181A20", "navigationBarTextStyle": "white" }