model = new CourseSchedule(); } /** * 获取课程安排列表 * @param array $where * @return array */ public function getPage(array $where = []) { $field = 'id,campus_id,venue_id,course_date,time_slot,course_id,coach_id,participants,student_ids,available_capacity,status,created_by,created_at,updated_at,deleted_at,auto_schedule'; $order = 'id desc'; $search_model = $this->model->withSearch(["campus_id", "venue_id", "course_date"], $where) ->with(['venue', 'coach', 'course']) ->field($field) ->order($order); $list = $this->pageQuery($search_model); return $list; } /** * 获取课程安排信息 * @param int $id * @return array */ public function getInfo(int $id) { $field = 'id,campus_id,venue_id,course_date,time_slot,course_id,coach_id,participants,student_ids,available_capacity,status,created_by,created_at,updated_at,deleted_at,auto_schedule'; $info = $this->model->field($field)->where([['id', "=", $id]])->findOrEmpty()->toArray(); return $info; } /** * 添加课程安排 * @param array $data * @return mixed */ public function add(array $data) { // 解析时间段,填充start_time和end_time字段 $timeData = $this->parseTimeSlot($data['time_slot']); $create = [ 'campus_id' => $data['campus_id'], 'venue_id' => $data['venue_id'], 'course_date' => $data['course_date'], 'time_slot' => $data['time_slot'], 'start_time' => $timeData ? $timeData['start_time'] : null, 'end_time' => $timeData ? $timeData['end_time'] : null, 'course_id' => $data['course_id'], 'coach_id' => $data['coach_id'], 'auto_schedule' => $data['auto_schedule'], 'available_capacity' => (new Venue())->where('id', $data['venue_id'])->value('capacity'), 'status' => $this->determineInitialStatus($data['course_date'], $timeData), 'created_by' => 'manual' ]; $status = $this->model->where([ ['course_date', '=', $data['course_date']], ['time_slot', '=', $data['time_slot']], ['campus_id', '=', $data['campus_id']], ['venue_id', '=', $data['venue_id']] ])->find(); if ($status) { throw new \Exception('该时间段已有课程安排'); } $res = $this->model->create($create); return $res->id; } /** * 课程安排编辑 * @param int $id * @param array $data * @return bool */ public function edit(int $id, array $data) { // 解析时间段,填充start_time和end_time字段 $timeData = $this->parseTimeSlot($data['time_slot']); $create = [ 'campus_id' => $data['campus_id'], 'venue_id' => $data['venue_id'], 'course_date' => $data['course_date'], 'time_slot' => $data['time_slot'], 'start_time' => $timeData ? $timeData['start_time'] : null, 'end_time' => $timeData ? $timeData['end_time'] : null, 'course_id' => $data['course_id'], 'coach_id' => $data['coach_id'], 'auto_schedule' => $data['auto_schedule'], 'status' => $this->determineInitialStatus($data['course_date'], $timeData) ]; $status = $this->model->where([ ['course_date', '=', $data['course_date']], ['time_slot', '=', $data['time_slot']], ['campus_id', '=', $data['campus_id']], ['venue_id', '=', $data['venue_id']], ['id', '<>', $id] ])->find(); if ($status) { throw new \Exception('该时间段已有课程安排'); } $this->model->where([['id', '=', $id]])->update($create); return true; } /** * 删除课程安排 * @param int $id * @return bool */ public function del(int $id) { $model = $this->model->where([['id', '=', $id]])->find(); $res = $model->delete(); return $res; } /** * 获取课程表数据 * @param array $where * @return array */ public function getTimetables(array $where = []) { // 获取日期范围,默认为本周 $start_date = $where['start_date'] ?? date('Y-m-d', strtotime('monday this week')); $end_date = $where['end_date'] ?? date('Y-m-d', strtotime('sunday this week')); // 校区ID $campus_id = isset($where['campus_id']) && !empty($where['campus_id']) ? intval($where['campus_id']) : 0; // 查询条件 $query_condition = [ ['course_date', '>=', $start_date], ['course_date', '<=', $end_date] ]; // 如果指定了校区,添加校区筛选条件 if ($campus_id > 0) { $query_condition[] = ['campus_id', '=', $campus_id]; } // 查询指定日期范围内的课程安排 $schedules = $this->model->where($query_condition)->select()->toArray(); // 获取所有相关的人员课程安排关系 $schedule_ids = array_column($schedules, 'id'); $person_schedules = []; if (!empty($schedule_ids)) { $person_schedules = (new PersonCourseSchedule())->with(['resources', 'person', 'student'])->where([ ['schedule_id', 'in', $schedule_ids] ]) ->select() ->toArray(); } // 教师 $coach_ids = array_column($schedules, 'coach_id'); $coaches = (new Personnel())->where('id', 'in', $coach_ids)->select()->toArray(); // 组织数据结构 $days = []; $weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']; // 获取所有时间段和教室 $time_slots = []; $classrooms = (new VenueService())->getVenueAll($campus_id); // 如果没有数据,设置默认的时间段和教室 if (empty($schedules)) { $time_slots = (new VenueService())->getVenueTime($classrooms); } else { foreach ($schedules as $schedule) { if (!in_array($schedule['time_slot'], $time_slots)) { $time_slots[] = $schedule['time_slot']; } } } // 按日期组织数据 $current_date = $start_date; $day_index = (int)date('N', strtotime($current_date)) - 1; // 获取周几(1-7),转为索引(0-6) while (strtotime($current_date) <= strtotime($end_date)) { $day_schedules = array_filter($schedules, function ($schedule) use ($current_date) { return $schedule['course_date'] == $current_date; }); // 构建每个时间段的数据 $day_time_slots = []; foreach ($time_slots as $time_slot) { $slot_data = [ 'timeRange' => $time_slot, 'color' => '#FFFFFF', // 默认白色背景 'textColor' => '#000000', // 默认黑色文字 ]; // 查找该时间段的课程 $slot_schedule = array_filter($day_schedules, function ($schedule) use ($time_slot) { return $schedule['time_slot'] == $time_slot; }); if (!empty($slot_schedule)) { $schedule = reset($slot_schedule); // 查找该课程的学员 $students = array_filter($person_schedules, function ($person) use ($schedule) { return $person['schedule_id'] == $schedule['id']; }); $teacher = array_filter($coaches, function ($coach) use ($schedule) { return $coach['id'] == $schedule['coach_id']; }); $venues = array_filter($classrooms, function ($venue) use ($schedule) { return $venue['id'] == $schedule['venue_id']; }); $available_capacity = $schedule['available_capacity'] - count($students); if ($available_capacity > 0) { $slot_data['backgroundColor'] = '#079307'; // 绿色背景 $slot_data['color'] = '#FFFFFF'; // 白色文字 } elseif ($available_capacity == 0) { $slot_data['backgroundColor'] = '#FF0000'; // 红色背景 $slot_data['color'] = '#FFFFFF'; // 白色文字 } else { $slot_data['backgroundColor'] = '#FFFFFF'; // 白色背景 $slot_data['color'] = '#000000'; // 黑色文字 } $slot_data['course'] = [ 'teacher' => is_array($teacher) ? array_values($teacher) : [], 'students' => is_array($students) ? array_values($students) : [], 'classroom' => is_array($venues) ? array_values($venues) : [], 'hasnumber' => $available_capacity, 'schedule' => $schedule, ]; } $day_time_slots[] = $slot_data; } $days[] = [ 'date' => $weekdays[$day_index % 7] . ' (' . $current_date . ')', 'timeSlots' => $day_time_slots, 'classrooms' => $classrooms, ]; $current_date = date('Y-m-d', strtotime($current_date . ' +1 day')); $day_index = ($day_index + 1) % 7; } return $days; } /** * @param $id * @return CourseSchedule[]|array|\think\Collection * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getCampusVenue($id) { return (new Venue())->where('availability_status', 1)->where('campus_id', $id)->select(); } public function schedule_list(array $data){ $personCourseSchedule = new PersonCourseSchedule(); $list = $personCourseSchedule ->alias('a') ->join(['school_customer_resources' => 'b'],'a.resources_id = b.id','left') ->where('a.schedule_id',$data['schedule_id']) ->field("a.id,a.resources_id,a.person_id,a.student_id,a.person_type,a.schedule_id,a.course_date,a.schedule_type,a.course_type,a.time_slot,a.status,a.remark,b.name") ->select()->toArray(); return $list; } public function resourceList(){ $studentCourse = new StudentCourses(); $data = $studentCourse->alias("a") ->join(['school_customer_resources' => 'b'],'a.resource_id = b.id','left') ->where([ ['a.end_date','<=',date('Y-m-d')] ]) ->field("b.name,b.id")->select(); return $data ? $data->toArray() : []; } public function courseInfo(int $data){ $CourseSchedule = new CourseSchedule(); $info = $CourseSchedule ->where('id', $data)->findOrEmpty(); return $info->toArray(); } /** * 解析time_slot字符串,提取开始和结束时间 * @param string $timeSlot 格式如 "09:00-10:30" * @return array|null */ private function parseTimeSlot($timeSlot) { if (empty($timeSlot)) { return null; } // 支持多种格式:09:00-10:30, 09:00~10:30, 9:00-10:30 if (preg_match('/(\d{1,2}:\d{2})\s*[-~~]\s*(\d{1,2}:\d{2})/', $timeSlot, $matches)) { return [ 'start_time' => $matches[1], 'end_time' => $matches[2] ]; } return null; } /** * 根据课程日期和时间段确定初始状态 * @param string $courseDate 课程日期 * @param array|null $timeData 时间数据 * @return string */ private function determineInitialStatus($courseDate, $timeData) { $currentDate = date('Y-m-d'); $currentTime = date('H:i:s'); // 如果是过去的日期,直接标记为已完成 if ($courseDate < $currentDate) { return 'completed'; } // 如果是未来的日期,标记为待安排 if ($courseDate > $currentDate) { return 'pending'; } // 如果是今天且有时间数据,根据时间判断状态 if ($courseDate === $currentDate && $timeData) { $startTime = $timeData['start_time']; $endTime = $timeData['end_time']; $currentTimestamp = strtotime($currentTime); $startTimestamp = strtotime($startTime); $endTimestamp = strtotime($endTime); // 如果当前时间在课程时间段内,状态为进行中 if ($currentTimestamp >= $startTimestamp && $currentTimestamp <= $endTimestamp) { return 'ongoing'; } // 如果课程已结束,状态为已完成 if ($currentTimestamp > $endTimestamp) { return 'completed'; } // 如果距离开始时间不足6小时,状态为即将开始 $timeDiff = $startTimestamp - $currentTimestamp; if ($timeDiff <= 6 * 3600 && $timeDiff > 0) { return 'upcoming'; } } // 其他情况默认为待安排 return 'pending'; } }