model = new Course(); } //课程列表 public function list($id, $data) { $campus_person_role = new CampusPersonRole(); $where = []; if ($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($where) ->with(['course' => function ($query) { $query->select(); }, 'venue' => function ($query) { $query->select(); }, 'campus', 'studentCourses']); $list = $this->pageQuery($search_model); foreach ($list['data'] as $k => $v) { $student = Db::name('person_course_schedule') ->alias('pcs') ->where('pcs.schedule_id', $v['id']) // 建议加上表别名避免冲突 ->join('school_student st', 'pcs.student_id = st.id') ->join('school_customer_resources cr', 'st.user_id = cr.id') ->join('school_member sm', 'cr.member_id = sm.member_id') ->field('st.name, sm.headimg as avatar') // 👈 正确方式取字段 ->select(); $list['data'][$k]['student'] = $student; } return $list; } //获取课程详情 public function info($data) { $school_six_speed = new SixSpeed(); $CourseSchedule = new CourseSchedule(); $search_model = $CourseSchedule ->where('id', $data) ->with(['course' => function ($query) { $query->select(); }, 'venue' => function ($query) { $query->select(); }, 'coach' => function ($query) { $query->select(); }]); $list = $search_model->find(); $student = Db::name('person_course_schedule') ->alias('pcs') ->where('pcs.schedule_id', $list['id']) ->join('school_student st', 'pcs.student_id = st.id') ->join('school_customer_resources cr', 'st.user_id = cr.id') ->join('school_member sm', 'cr.member_id = sm.member_id') ->field('st.name, sm.headimg as avatar') ->select(); $list['student'] = $student; $student_courses = Db::name('student_courses') ->alias('sc') ->where('sc.course_id', $list['id']) ->join('school_student_course_usage sscu', 'sc.id = sscu.student_course_id') ->field('sc.student_id,sc.end_date,sc.end_date,sc.start_date,sc.course_id') ->select()->toArray(); foreach ($student_courses as &$v) { $student = Db::name('student') ->alias('st') ->where('st.id', $v['student_id']) ->join('school_customer_resources cr', 'st.user_id = cr.id') ->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) { $v['school_six_speed'] = $school_six_speed->where(['staff_id' => $student['resources_id']])->find(); } else { $v['school_six_speed'] = []; } $v['source'] = get_dict_value("source", $student['source']); $v['name'] = $student['name']; $v['avatar'] = $student['avatar']; } $list['student_courses'] = $student_courses; $Assignment = new Assignment(); $search_model = $Assignment->where('course_id', $data) ->with(['student' => function ($query) { $query->with(['customerResources' => function ($query) { $query->with(['member' => function ($query) { $query->select(); }]); }]); }]); $search_model_res = $search_model->select()->toArray(); $groupedByStatus1 = []; $groupedByStatus2 = []; $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); } } $list['groupedByStatus1'] = $groupedByStatus1; $list['groupedByStatus2'] = $groupedByStatus2; $list['groupedByStatus3'] = $groupedByStatus3; return $list; } public function classList($data) { $CourseSchedule = new CourseSchedule(); $search_model = $CourseSchedule ->where('coach_id', $data) ->with(['course' => function ($query) { $query->with(['studentCourses' => function ($query) { $query->select(); }]); }, 'venue' => function ($query) { $query->select(); }, 'coach' => function ($query) { $query->select(); }, 'campus']); $list = $this->pageQuery($search_model); foreach ($list['data'] as &$v) { $student = Db::name('person_course_schedule') ->alias('pcs') ->where('pcs.schedule_id', $v['id']) ->join('school_student st', 'pcs.student_id = st.id') ->join('school_customer_resources cr', 'st.user_id = cr.id') ->join('school_member sm', 'cr.member_id = sm.member_id') ->field('st.name, sm.headimg as avatar') ->select(); $v['student'] = $student; } foreach ($list['data'] as &$v) { $student_courses = Db::name('student_courses') ->alias('sc') ->where('sc.course_id', $v['id']) ->join('school_student_course_usage sscu', 'sc.id = sscu.student_course_id') ->field('sc.student_id,sc.end_date,sc.end_date,sc.start_date,sc.course_id') ->select()->toArray(); $v['student_courses'] = $student_courses; } return $list; } //获取添加学员列表 public function StudentList($id) { $StudentCourses = new StudentCourses(); $PersonCourseSchedule = new PersonCourseSchedule(); $student_arr = $PersonCourseSchedule->where('schedule_id', $id)->column('student_id'); // 获取当前时间 $now = date('Y-m-d H:i:s'); // 查询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) { // 查找对应的学生ID foreach ($studentCourses as $course) { if ($course['resource_id'] == $resource['id']) { // 源和来源渠道转换为字典值 $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'], 'text' => $resource['name'], // 学生姓名 'name' => $resource['name'], 'age' => $resource['age'], 'source' => $source, 'source_channel' => $sourceChannel, 'source_raw' => $resource['source'], 'source_channel_raw' => $resource['source_channel'] ]; break; } } } return $result; } public function addStudent($data) { $PersonCourseSchedule = new PersonCourseSchedule(); $res = $PersonCourseSchedule->create($data); return $res; } public function delStudentCourse($data) { $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'); if ($PersonCourseSchedule_id) { $StudentCourseUsage->where('student_course_id', $StudentCourses_id)->delete(); return true; } else { return false; } } public function getDate(array $baseDate) { $dates = []; $this_date = $baseDate['date'] ?: date('Y-m-d'); $date = new DateTime($this_date); for ($i = -2; $i <= 4; $i++) { $tempDate = clone $date; // 避免修改原始对象 $tempDate->modify("$i days"); $status = false; if ($baseDate['day'] == $tempDate->format('d')) { $status = true; } else if (empty($baseDate['day'])) { if ($tempDate->format('Y-m-d') === date('Y-m-d')) { $status = true; } } $dates[] = [ 'date' => $tempDate->format('Y-m-d'), 'day' => $tempDate->format('d'), 'week' => getChineseWeekday($tempDate), 'status' => $status ]; } return ['dates' => $dates, 'date' => $this_date]; } public function listAll($data) { $where = []; // 基础日期查询 if ($data['schedule_date']) { $where[] = ['course_date', '=', $data['schedule_date']]; } // 日期范围查询 if (!empty($data['start_date'])) { $where[] = ['course_date', '>=', $data['start_date']]; } if (!empty($data['end_date'])) { $where[] = ['course_date', '<=', $data['end_date']]; } // 场地编号筛选 - 根据venue表的id或venue_name进行筛选 if (!empty($data['venue_number'])) { // 先查询匹配的场地ID $venue_ids = Db::name('venue')->where('id', $data['venue_number'])->column('id'); if (empty($venue_ids)) { // 如果根据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 $coach_ids = Db::name('personnel')->where('name', 'like', '%' . $data['teacher_name'] . '%')->column('id'); if (!empty($coach_ids)) { $where[] = ['coach_id', 'in', $coach_ids]; } else { // 如果找不到匹配的教练,返回空结果 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']); if ($time_condition) { [$start_time, $end_time] = $time_condition; // 查询time_slot字段中包含在指定时间范围内的课程 // time_slot格式为"HH:MM-HH:MM",我们需要检查时间段是否有重叠 $query = $query->where(function ($subQuery) use ($start_time, $end_time) { $subQuery->where('time_slot', 'like', $start_time . '%') ->whereOr('time_slot', 'like', '%' . $start_time . '%') ->whereOr('time_slot', 'like', '%' . $end_time . '%') ->whereOr(function ($subQuery2) use ($start_time, $end_time) { // 检查开始时间是否在范围内 $subQuery2->whereRaw("TIME(SUBSTRING_INDEX(time_slot, '-', 1)) >= ?", [$start_time]) ->whereRaw("TIME(SUBSTRING_INDEX(time_slot, '-', 1)) < ?", [$end_time]); }) ->whereOr(function ($subQuery3) use ($start_time, $end_time) { // 检查结束时间是否在范围内 $subQuery3->whereRaw("TIME(SUBSTRING_INDEX(time_slot, '-', -1)) > ?", [$start_time]) ->whereRaw("TIME(SUBSTRING_INDEX(time_slot, '-', -1)) <= ?", [$end_time]); }); }); } } $list = $query ->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') ->alias('pcs') ->where('pcs.schedule_id', $v['id']) ->leftJoin('school_customer_resources cr', 'pcs.resources_id = cr.id') ->leftJoin('school_member sm', 'cr.member_id = sm.member_id AND cr.member_id > 0') ->field('cr.name, COALESCE(sm.headimg, "") as avatar, pcs.schedule_type, pcs.course_type, pcs.status') ->select(); $list[$k]['student'] = $student; } return $list; } /** * 根据时间选择器的值获取时间段查询条件 * @param string $timeHour * @return array|null 返回时间范围数组 [start_hour, end_hour] 或 null */ private function getTimeSlotCondition($timeHour) { switch ($timeHour) { case '上午(8:00-12:00)': return ['08:00', '12:00']; // 上午时间范围 case '下午(12:00-18:00)': return ['12:00', '18:00']; // 下午时间范围 case '晚上(18:00-22:00)': return ['18:00', '22:00']; // 晚上时间范围 default: return null; } } public function addSchedule(array $data) { $CourseSchedule = new CourseSchedule(); $personCourseSchedule = new PersonCourseSchedule(); $student = Student::where('id', $data['student_id'])->find(); if (!$student) { return fail("学员不存在"); } $studentCourse = StudentCourses::where('student_id', $student->id) ->order('id', 'desc') ->find(); $student_status = $studentCourse && $this->handeStudentStatus($studentCourse); if ($student_status) { $person_type = 'student'; } else { $person_type = 'customer_resource'; } // 检查重复添加 - 根据person_type使用不同的检查逻辑 $checkWhere = [ 'schedule_id' => $data['schedule_id'], 'student_id' => $student->id, 'resources_id' => $data['resources_id'], 'status' => 0 ]; $course = $personCourseSchedule->where($checkWhere)->find(); if ($course) { return fail("重复添加"); } $insertData = [ 'student_id' => $student->id, // 正确设置student_id 'resources_id' => $data['resources_id'], // 正确设置resources_id 'person_id' => $this->member_id, 'person_type' => $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'], // 根据上面的逻辑设置课程类型 'remark' => $data['remark'] ?? '', // 备注 'student_course_id' => $studentCourse->id ?? 0 ]; $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) ]); return success("添加成功"); } public function schedule_list(array $data) { $personCourseSchedule = new PersonCourseSchedule(); $list = $personCourseSchedule ->alias('a') ->leftJoin(['school_student' => 'st'], 'a.student_id = st.id AND a.person_type = "student"') ->leftJoin(['school_customer_resources' => 'b'], 'a.resources_id = b.id') ->leftJoin(['school_course_schedule' => 'c'], 'c.id = a.schedule_id') ->where('a.schedule_id', $data['schedule_id']) ->field([ 'COALESCE(st.name, b.name) as name', // 优先显示学员姓名,否则客户资源姓名 'a.status', 'a.person_type', 'c.campus_id', 'a.student_id', 'a.resources_id', 'a.schedule_type', 'a.course_type', 'a.id as person_schedule_id' ]) ->select() ->toArray(); return $list; } 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([ 'id' => $record->id, 'resources_id' => $data['resources_id'] ])->delete(); return success('删除成功'); } else if ($record['person_type'] == 'student') { // 如果是学生类型,更新状态为2并更新备注 $personCourseSchedule->where([ 'id' => $record->id ])->update([ 'status' => 2, 'remark' => $data['remark'] ]); return success('更新成功'); } else { return fail('未知的人员类型'); } } /** * 更新学员课程人员配置 * @param array $data * @return array */ public function updateStudentCoursePersonnel(array $data) { $res = [ 'code' => 0, 'msg' => '更新失败', 'data' => [] ]; 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 = [ 'class_id' => $classId, 'resource_id' => $studentCourse['resource_id'], 'campus_id' => 0, // 可根据实际需求设置 'source_id' => $studentCourse['student_id'], 'source_type' => 'student', 'join_time' => time(), 'status' => 1, '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(); $res['msg'] = '更新班级关联失败'; return $res; } } } // 提交事务 Db::commit(); $res = [ 'code' => 1, 'msg' => '更新成功', 'data' => [ 'student_course_id' => $studentCourseId, 'main_coach_id' => $mainCoachId, 'education_id' => $educationId, 'assistant_ids' => $assistantIds, 'class_id' => $classId ] ]; } catch (\Exception $e) { Db::rollback(); $res['msg'] = '更新学员课程人员配置异常:' . $e->getMessage(); } return $res; } /** * 获取课程列表(用于添加课程安排) * @param array $data * @return array */ public function getCourseListForSchedule(array $data) { 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, 'msg' => '获取课程列表失败:' . $e->getMessage(), 'data' => [] ]; } } /** * 获取课程安排详情 * @param int $scheduleId 课程安排ID * @return array */ public function getScheduleDetail($scheduleId) { try { $CourseSchedule = new CourseSchedule(); $PersonCourseSchedule = new PersonCourseSchedule(); // 获取课程安排基本信息 $schedule = $CourseSchedule ->where('id', $scheduleId) ->with(['course', 'venue', 'campus']) ->find(); if (!$schedule) { return [ 'code' => 0, 'msg' => '课程安排不存在', 'data' => [] ]; } // 获取已安排的学员列表(包括正式学员和等待位),排除请假的学员(status!=2) $students = $PersonCourseSchedule ->where('schedule_id', $scheduleId) ->where('status', '<>', 2) // 排除请假的学员,包含待上课(0)和已上课(1) ->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 = ''; $age = 0; $phone = ''; $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') ->where('student_course_id', $studentCourseInfo['id']) ->select() ->toArray(); } } elseif ($student['person_type'] == 'customer_resource') { // 客户资源 - 现在我们有正确的student_id,应该从学生表获取信息 if ($student['student_id'] > 0) { // 从学生表获取学员信息 $studentInfo = Db::name('student') ->where('id', $student['student_id']) ->find(); if ($studentInfo) { $name = $studentInfo['name'] ?: ''; $age = $studentInfo['age'] ?: 0; $phone = $studentInfo['contact_phone'] ?: ''; $trialClassCount = $studentInfo['trial_class_count'] ?: 0; } else { // 如果学生信息不存在,使用客户资源信息作为后备 $name = !empty($student['resources']) ? $student['resources']['name'] : ''; $age = !empty($student['resources']) ? $student['resources']['age'] : 0; $phone = !empty($student['resources']) ? $student['resources']['phone_number'] : ''; } } else { // 如果没有student_id,使用客户资源信息 $name = !empty($student['resources']) ? $student['resources']['name'] : ''; $age = !empty($student['resources']) ? $student['resources']['age'] : 0; $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']; if ($endDate) { $daysUntilExpiry = (strtotime($endDate) - time()) / (24 * 3600); if ($daysUntilExpiry <= 10) { $needsRenewal = true; } } // 条件2:剩余课时少于4节 if ($remainingHours < 4) { $needsRenewal = true; } } else { // 体验课学员(没有付费课程记录) $isTrialStudent = true; $totalHours = $trialClassCount; $usedHours = 0; // 这里可以根据实际需求统计体验课使用情况 $remainingHours = $trialClassCount; } $studentInfo = [ 'id' => $student['id'], // 人员课程安排关系ID 'student_id' => $student['student_id'] ?: 0, 'resources_id' => $student['resources_id'] ?: 0, 'name' => $name, 'age' => $age, 'phone' => $phone, 'courseStatus' => $this->getCourseTypeText($student['course_type']), 'courseType' => $student['schedule_type'] == 2 ? 'fixed' : 'temporary', 'remainingHours' => $remainingHours, 'totalHours' => $totalHours, 'usedHours' => $usedHours, 'expiryDate' => $studentCourseInfo ? ($studentCourseInfo['end_date'] ?: '') : '', 'needsRenewal' => $needsRenewal, 'isTrialStudent' => $isTrialStudent, 'trialClassCount' => $trialClassCount, 'status' => $student['status'] ?: 0, 'remark' => $student['remark'] ?: '', 'person_type' => $student['person_type'], 'schedule_type' => $student['schedule_type'] ?: 1, 'course_type' => $student['course_type'] ?: 1, // 添加课程购买和使用信息 'student_course_info' => $studentCourseInfo, 'course_usage_info' => $courseUsageInfo, 'course_progress' => [ 'total' => $totalHours, 'used' => $usedHours, 'remaining' => $remainingHours, 'percentage' => $totalHours > 0 ? round(($usedHours / $totalHours) * 100, 1) : 0 ] ]; if ($student['course_type'] == 3) { // 等待位学员 $waitingStudents[] = $studentInfo; } else { // 正式学员 $formalStudents[] = $studentInfo; } } // 计算可用位置 $maxStudents = $schedule['max_students'] ?: 0; $availableSlots = 0; if ($maxStudents > 0) { $availableSlots = max(0, $maxStudents - count($formalStudents)); } else { // 如果没有限制,总是显示至少1个可用位置 $availableSlots = max(1, 6 - count($formalStudents)); } $result = [ 'schedule_info' => [ 'id' => $schedule['id'], 'course_name' => $schedule['course']['course_name'] ?? '', 'course_date' => $schedule['course_date'], 'time_slot' => $schedule['time_slot'], 'venue_name' => $schedule['venue']['venue_name'] ?? '', 'campus_name' => $schedule['campus']['campus_name'] ?? '', 'available_capacity' => $schedule['available_capacity'] ?: 0, 'max_students' => $maxStudents, 'available_slots' => $availableSlots, 'status' => $schedule['status'] ?: 0 ], 'formal_students' => $formalStudents, 'waiting_students' => $waitingStudents ]; return [ 'code' => 1, 'msg' => '获取成功', 'data' => $result ]; } catch (\Exception $e) { return [ 'code' => 0, 'msg' => '获取课程安排详情失败:' . $e->getMessage(), 'data' => [] ]; } } /** * 搜索可添加的学员 * @param array $data * @return array */ public function searchAvailableStudents($data) { try { $keyword = trim($data['keyword']); $searchType = $data['search_type'] ?: 'auto'; $scheduleId = $data['schedule_id'] ?: 0; if (empty($keyword)) { return [ 'code' => 1, 'msg' => '搜索成功', 'data' => [] ]; } // 获取已安排的学员ID和资源ID,用于排除 $PersonCourseSchedule = new PersonCourseSchedule(); $existingRecords = $PersonCourseSchedule ->where('schedule_id', $scheduleId) ->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 ->alias('s') ->leftJoin('customer_resources cr', 's.user_id = cr.id') ->where('cr.phone_number', 'like', "%{$keyword}%") ->where('s.deleted_at', 0) ->field('s.id as student_id, s.name, s.gender, s.status, cr.age, cr.phone_number, s.user_id as resource_id, "student" as person_type') ->select() ->toArray(); } else { // 搜索姓名 $students = $Student ->alias('s') ->leftJoin('customer_resources cr', 's.user_id = cr.id') ->where('s.name', 'like', "%{$keyword}%") ->where('s.deleted_at', 0) ->field('s.id as student_id, s.name, s.gender, s.status, cr.age, cr.phone_number, s.user_id as resource_id, "student" as person_type') ->select() ->toArray(); } // 过滤已安排的学员 foreach ($students as $student) { if (!in_array($student['student_id'], $existingStudentIds)) { $results[] = [ 'id' => $student['student_id'], 'student_id' => $student['student_id'], 'resources_id' => $student['resource_id'], 'name' => $student['name'], 'age' => $student['age'] ?: 0, 'phone' => $student['phone_number'] ?: '', 'gender' => $student['gender'], 'status' => $student['status'], // 添加学员状态 'person_type' => 'student', 'type_label' => '正式学员' ]; } } // 搜索客户资源(非正式学员) $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)) { $results[] = [ 'id' => $customer['resources_id'], 'student_id' => 0, 'resources_id' => $customer['resources_id'], 'name' => $customer['name'], 'age' => $customer['age'] ?: 0, 'phone' => $customer['phone_number'] ?: '', 'gender' => $customer['gender'], 'person_type' => 'customer_resource', 'type_label' => '客户资源' ]; } } return [ 'code' => 1, 'msg' => '搜索成功', 'data' => $results ]; } catch (\Exception $e) { return [ 'code' => 0, 'msg' => '搜索学员失败:' . $e->getMessage(), 'data' => [] ]; } } /** * 添加学员到课程安排 * @param array $data * @return array */ public function addStudentToSchedule($data) { try { $scheduleId = $data['schedule_id']; $studentId = $data['student_id'] ?: null; $resourcesId = $data['resources_id'] ?: null; $personType = $data['person_type']; $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, 'msg' => '课程安排不存在', 'data' => [] ]; } // 检查是否已经添加过 $PersonCourseSchedule = new PersonCourseSchedule(); $existingWhere = [ ['schedule_id', '=', $scheduleId], 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 [ 'code' => 0, 'msg' => '该学员已经在此课程安排中', 'data' => [] ]; } // 验证学员状态 - 只有status=1的学员才能预约固定课 if ($scheduleType == 2 && $studentId) { // 固定课且是正式学员 $Student = new Student(); $student = $Student->where('id', $studentId)->find(); if (!$student) { return [ 'code' => 0, 'msg' => '学员不存在', 'data' => [] ]; } if ($student['status'] != 1) { return [ 'code' => 0, 'msg' => '只有有效状态的学员才能预约固定课,该学员只能预约临时课', 'data' => [] ]; } } // 如果是正式学员位置,检查容量限制 if ($courseType != 3) { // 不是等待位 $maxStudents = $schedule['max_students'] ?: 0; if ($maxStudents > 0) { $currentCount = $PersonCourseSchedule ->where('schedule_id', $scheduleId) ->where('course_type', '<>', 3) // 不包括等待位 ->where(function ($query) { $query->where('deleted_at', 0)->whereOr('deleted_at', null); }) ->count(); if ($currentCount >= $maxStudents) { return [ 'code' => 0, 'msg' => '课程安排已满,请添加到等待位', 'data' => [] ]; } } } // 准备插入数据 $insertData = [ 'resources_id' => $resourcesId, 'person_id' => null, // 这个字段根据实际业务需求设置 'student_id' => $studentId, 'person_type' => $personType, 'schedule_id' => $scheduleId, 'course_date' => $schedule['course_date'], 'schedule_type' => $scheduleType, 'course_type' => $courseType, 'time_slot' => $schedule['time_slot'], 'status' => 0, // 待上课 'remark' => $remarks, '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' => '添加成功', 'data' => $result->toArray() ]; } else { return [ 'code' => 0, 'msg' => '添加失败', 'data' => [] ]; } } catch (\Exception $e) { return [ 'code' => 0, 'msg' => '添加学员失败:' . $e->getMessage(), 'data' => [] ]; } } /** * 从课程安排中移除学员 * @param array $data * @return array */ public function removeStudentFromSchedule($data) { try { $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, 'msg' => '记录不存在', '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' => '移除成功', 'data' => [] ]; } else { return [ 'code' => 0, 'msg' => '移除失败', 'data' => [] ]; } } catch (\Exception $e) { return [ 'code' => 0, 'msg' => '移除学员失败:' . $e->getMessage(), 'data' => [] ]; } } /** * 更新学员课程状态 * @param array $data * @return array */ public function updateStudentStatus($data) { try { $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, 'msg' => '记录不存在', '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, 'msg' => '更新成功', 'data' => [] ]; } else { return [ 'code' => 0, 'msg' => '更新失败', 'data' => [] ]; } } catch (\Exception $e) { return [ 'code' => 0, 'msg' => '更新学员状态失败:' . $e->getMessage(), 'data' => [] ]; } } /** * 更新课程安排的参与人员信息 * @param int $scheduleId */ private function updateScheduleParticipants($scheduleId) { try { $PersonCourseSchedule = new PersonCourseSchedule(); // 获取当前安排的所有人员 $participants = $PersonCourseSchedule ->where('schedule_id', $scheduleId) ->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) ->update([ 'participants' => json_encode($resourceIds), '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 * @return array */ public function getCoachList($campus_id = 0) { try { // 查询dept_id=23的教练角色 $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.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 * @return array */ public function getEducationList($campus_id = 0) { try { // 查询dept_id=2的教务角色 $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.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 * @return array */ public function updateCourseInfo($data) { try { $studentCourseId = $data['student_course_id']; $mainCoachId = $data['main_coach_id'] ?? 0; $assistantIds = $data['assistant_ids'] ?? ''; $educationId = $data['education_id'] ?? 0; $classId = $data['class_id'] ?? 0; // 1. 更新学员课程表 $updateData = []; if ($mainCoachId > 0) { $updateData['main_coach_id'] = $mainCoachId; } if (!empty($assistantIds)) { $updateData['assistant_ids'] = $assistantIds; } 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); if (!$result) { return ['code' => 0, 'msg' => '更新学员课程信息失败']; } } // 2. 如果需要更新班级关联 if ($classId > 0) { // 先获取学员的resource_id $studentCourse = StudentCourses::where('id', $studentCourseId)->find(); 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; $existingRel->update_time = date('Y-m-d H:i:s'); $existingRel->save(); } else { // 创建新的班级关联 $classRel = new \app\model\class_resources_rel\ClassResourcesRel(); $classRel->class_id = $classId; $classRel->resource_id = $resourceId; $classRel->campus_id = $studentCourse->campus_id ?? 1; // 默认校区ID $classRel->source_type = 'student'; $classRel->join_time = time(); $classRel->status = 1; $classRel->save(); } } return ['code' => 1, 'data' => ['id' => $studentCourseId], 'msg' => '更新成功']; } catch (\Exception $e) { return ['code' => 0, 'msg' => '更新失败: ' . $e->getMessage()]; } } /** * 检查学员班级关联情况 * @param int $resource_id * @return array */ public function checkClassRelation($resource_id) { try { $classRel = \app\model\class_resources_rel\ClassResourcesRel::alias('crr') ->join(['school_class' => 'c'], 'crr.class_id = c.id', 'left') ->where([ 'crr.resource_id' => $resource_id, 'crr.status' => 1 ]) ->field([ 'crr.id', 'crr.class_id', 'c.class_name', 'c.head_coach', 'c.educational_id' ]) ->find(); $hasClass = !empty($classRel); $classInfo = $hasClass ? $classRel->toArray() : null; return [ 'code' => 1, 'data' => [ 'has_class' => $hasClass, 'class_info' => $classInfo ] ]; } catch (\Exception $e) { return ['code' => 0, 'msg' => '检查班级关联失败: ' . $e->getMessage()]; } } /** * 获取课程类型文本 * @param int $courseType * @return string */ private function getCourseTypeText($courseType) { $courseTypeMap = [ 1 => '临时课', 2 => '固定课', 3 => '等待位', 4 => '试听课' ]; return $courseTypeMap[$courseType] ?? '未知'; } private function handeStudentStatus($studentCourse) { $now = time(); if (strtotime($studentCourse->end_date) > $now) { $total = $studentCourse->total_hours + $studentCourse->gift_hours - $studentCourse->use_total_hours - $studentCourse->use_gift_hours; if ($total > 0) { return true; } } return false; } }