You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
874 lines
28 KiB
874 lines
28 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\api\student;
|
|
|
|
use app\model\customer_resources\CustomerResources;
|
|
use app\model\student\Student;
|
|
use app\model\member\Member;
|
|
use app\model\student_label\StudentLabel;
|
|
use app\model\sys\SysUser;
|
|
use think\facade\Cache;
|
|
use think\facade\Db;
|
|
use core\base\BaseService;
|
|
use core\exception\CommonException;
|
|
|
|
/**
|
|
* 学员信息管理服务类
|
|
*/
|
|
class StudentService extends BaseService
|
|
{
|
|
/**
|
|
* 获取当前用户的学员列表
|
|
* @return array
|
|
*/
|
|
public function getStudentList()
|
|
{
|
|
// 获取当前登录用户ID
|
|
$customerId = $this->getUserId();
|
|
|
|
// 通过客户资源表获取user_id
|
|
$customerResource = (new CustomerResources())->where('id', $customerId)->find();
|
|
if (!$customerResource) {
|
|
throw new CommonException('用户信息不存在');
|
|
}
|
|
// 获取该用户的所有学员
|
|
$studentList = (new Student())
|
|
->where('user_id', $customerId)
|
|
->where('deleted_at', 0)
|
|
->field('id,name,gender,birthday,headimg,created_at')
|
|
->order('id desc')
|
|
->select()
|
|
->toArray();
|
|
|
|
// 计算年龄和格式化数据,同时获取课时信息
|
|
foreach ($studentList as &$student) {
|
|
$student['age'] = $this->calculateAge($student['birthday']);
|
|
$student['gender_text'] = $student['gender'] == 1 ? '男' : '女';
|
|
$student['headimg'] = $student['headimg'] ? get_image_url($student['headimg']) : '';
|
|
|
|
// 添加student_id字段,确保前端能正确获取学员ID
|
|
$student['student_id'] = $student['id'];
|
|
|
|
// 获取学员课时统计信息
|
|
$courseStats = $this->getStudentCourseStats($student['id']);
|
|
$student['course_stats'] = $courseStats;
|
|
}
|
|
|
|
return [
|
|
'list' => $studentList,
|
|
'total' => count($studentList)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取学员概览信息(首页用)
|
|
* @param int $studentId
|
|
* @return array
|
|
*/
|
|
public function getStudentSummary($studentId)
|
|
{
|
|
// 验证学员权限
|
|
$this->checkStudentPermission($studentId);
|
|
|
|
$student = (new Student())
|
|
->where('id', $studentId)
|
|
->where('deleted_at', 0)
|
|
->find();
|
|
|
|
if (!$student) {
|
|
throw new CommonException('学员信息不存在');
|
|
}
|
|
|
|
// 获取用户基本信息
|
|
$member = (new CustomerResources())->where('id', $student['user_id'])->find();
|
|
|
|
// 获取课程统计信息
|
|
$courseStats = $this->getStudentCourseStats($studentId);
|
|
|
|
// 获取预约资格信息
|
|
$bookingService = new \app\service\api\student\CourseBookingService();
|
|
$qualification = $bookingService->checkStudentQualification($studentId);
|
|
|
|
return [
|
|
'student_id' => $student['id'],
|
|
'name' => $student['name'],
|
|
'age' => $this->calculateAge($student['birthday']),
|
|
'gender' => $student['gender'],
|
|
'gender_text' => $student['gender'] == 1 ? '男' : '女',
|
|
'headimg' => $student['headimg'] ? get_image_url($student['headimg']) : '',
|
|
'member_name' => $member['name'] ?? '',
|
|
'created_at' => $student['created_at'],
|
|
'create_year_month' => date('Y年m月', strtotime($student['created_at'])),
|
|
'week_day' => '星期' . ['日', '一', '二', '三', '四', '五', '六'][date('w')],
|
|
// 课程统计信息
|
|
'course_stats' => $courseStats,
|
|
// 预约资格信息
|
|
'booking_qualification' => [
|
|
'can_book' => $qualification['can_book'],
|
|
'has_valid_course' => $qualification['has_valid_course'],
|
|
'remaining_courses' => $qualification['total_remaining_hours'] ?? 0,
|
|
'trial_class_count' => $qualification['trial_class_count'] ?? 0,
|
|
'reason' => $qualification['reason']
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取学员详细信息
|
|
* @param int $studentId
|
|
* @return array
|
|
*/
|
|
public function getStudentInfo($studentId)
|
|
{
|
|
// 验证学员权限
|
|
$this->checkStudentPermission($studentId);
|
|
|
|
$student = (new Student())
|
|
->where('id', $studentId)
|
|
->where('deleted_at', 0)
|
|
->find();
|
|
|
|
if (!$student) {
|
|
throw new CommonException('学员信息不存在');
|
|
}
|
|
|
|
$studentData = $student->toArray();
|
|
|
|
// 处理图片URL
|
|
$studentData['headimg'] = $studentData['headimg'] ? get_image_url($studentData['headimg']) : '';
|
|
|
|
// 计算年龄
|
|
$studentData['age'] = $this->calculateAge($studentData['birthday']);
|
|
$studentData['gender_text'] = $studentData['gender'] == 1 ? '男' : '女';
|
|
|
|
return $studentData;
|
|
}
|
|
|
|
/**
|
|
* 获取学员详细信息(包含体测信息)
|
|
* @param int $studentId
|
|
* @return array
|
|
*/
|
|
public function getStudentInfoWithPhysicalTest($studentId)
|
|
{
|
|
// 验证学员权限
|
|
$this->checkStudentPermission($studentId);
|
|
|
|
// 获取学员基本信息
|
|
$student = Db::table('school_student')
|
|
->where('id', $studentId)
|
|
->where('deleted_at', 0)
|
|
->find();
|
|
|
|
if (!$student) {
|
|
throw new CommonException('学员信息不存在');
|
|
}
|
|
|
|
// 获取最新的体测信息
|
|
$physicalTest = Db::table('school_physical_test')
|
|
->where('student_id', $studentId)
|
|
->order('created_at desc')
|
|
->find();
|
|
|
|
// 处理学员信息
|
|
$studentInfo = [
|
|
'id' => $student['id'],
|
|
'name' => $student['name'],
|
|
'gender' => $student['gender'],
|
|
'gender_text' => $student['gender'] == 1 ? '男' : '女',
|
|
'birthday' => $student['birthday'],
|
|
'emergency_contact' => $student['emergency_contact'],
|
|
'contact_phone' => $student['contact_phone'],
|
|
'note' => $student['note'],
|
|
'headimg' => $student['headimg'] ? get_image_url($student['headimg']) : '',
|
|
];
|
|
|
|
// 处理体测信息
|
|
$physicalTestInfo = [];
|
|
if ($physicalTest) {
|
|
$physicalTestInfo = [
|
|
'height' => $physicalTest['height'] ? (string)$physicalTest['height'] : '',
|
|
'weight' => $physicalTest['weight'] ? (string)$physicalTest['weight'] : '',
|
|
'test_date' => date('Y-m-d', strtotime($physicalTest['created_at']))
|
|
];
|
|
}
|
|
|
|
return [
|
|
'student_info' => $studentInfo,
|
|
'physical_test_info' => $physicalTestInfo
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 更新学员信息
|
|
* @param array $data
|
|
* @return bool
|
|
*/
|
|
public function updateStudentInfo($data)
|
|
{
|
|
$studentId = $data['student_id'];
|
|
|
|
// 验证学员权限
|
|
$this->checkStudentPermission($studentId);
|
|
|
|
// 验证学员是否存在
|
|
$student = Db::table('school_student')
|
|
->where('id', $studentId)
|
|
->where('deleted_at', 0)
|
|
->find();
|
|
|
|
if (!$student) {
|
|
throw new CommonException('学员信息不存在');
|
|
}
|
|
|
|
// 允许更新的字段
|
|
$allowedFields = ['name', 'gender', 'birthday', 'emergency_contact', 'contact_phone', 'note', 'headimg'];
|
|
$updateData = [];
|
|
|
|
foreach ($allowedFields as $field) {
|
|
if (isset($data[$field]) && $data[$field] !== '') {
|
|
$updateData[$field] = $data[$field];
|
|
}
|
|
}
|
|
|
|
if (empty($updateData)) {
|
|
throw new CommonException('没有需要更新的数据');
|
|
}
|
|
|
|
// 如果有生日更新,需要重新计算年龄
|
|
if (isset($updateData['birthday'])) {
|
|
$updateData['age'] = $this->calculateAgeFromBirthday($updateData['birthday']);
|
|
}
|
|
|
|
$result = Db::table('school_student')
|
|
->where('id', $studentId)
|
|
->update($updateData);
|
|
|
|
if ($result === false) {
|
|
throw new CommonException('更新学员信息失败');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 上传学员头像
|
|
* @param int $studentId
|
|
* @return array
|
|
*/
|
|
public function uploadAvatar($studentId)
|
|
{
|
|
// 验证学员权限
|
|
$this->checkStudentPermission($studentId);
|
|
|
|
// 处理文件上传
|
|
$uploadService = new \app\service\api\upload\UploadService();
|
|
$result = $uploadService->avatar(request()->file('image'));
|
|
|
|
if (!$result) {
|
|
throw new CommonException('头像上传失败');
|
|
}
|
|
|
|
// 更新学员头像
|
|
$student = (new Student())->where('id', $studentId)->find();
|
|
$student->headimg = $result['url'];
|
|
$student->save();
|
|
|
|
return [
|
|
'url' => get_image_url($result['url']),
|
|
'path' => $result['url']
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 检查学员权限(确保只能操作自己的孩子)
|
|
* @param int $studentId
|
|
* @return bool
|
|
*/
|
|
private function checkStudentPermission($studentId)
|
|
{
|
|
$customerId = $this->getUserId();
|
|
// 获取客户资源信息
|
|
$customerResource = (new CustomerResources())->where('id', $customerId)->find();
|
|
if (!$customerResource) {
|
|
throw new CommonException('用户信息不存在');
|
|
}
|
|
|
|
// 检查学员是否属于当前用户
|
|
$student = (new Student())
|
|
->where('id', $studentId)
|
|
->where('user_id', $customerId)
|
|
->where('deleted_at', 0)
|
|
->find();
|
|
|
|
if (!$student) {
|
|
throw new CommonException('无权限访问该学员信息');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 计算年龄
|
|
* @param string $birthday
|
|
* @return int
|
|
*/
|
|
private function calculateAge($birthday)
|
|
{
|
|
if (!$birthday) return 0;
|
|
|
|
$birthTime = strtotime($birthday);
|
|
if (!$birthTime) return 0;
|
|
|
|
$age = date('Y') - date('Y', $birthTime);
|
|
|
|
// 如果还没过生日,年龄减1
|
|
if (date('md') < date('md', $birthTime)) {
|
|
$age--;
|
|
}
|
|
|
|
return max(0, $age);
|
|
}
|
|
|
|
/**
|
|
* 根据生日精确计算年龄(支持小数表示)
|
|
* @param string $birthday
|
|
* @return float
|
|
*/
|
|
private function calculateAgeFromBirthday($birthday)
|
|
{
|
|
if (!$birthday) return 0;
|
|
|
|
$birthTime = strtotime($birthday);
|
|
if (!$birthTime) return 0;
|
|
|
|
$today = new \DateTime();
|
|
$birthDate = new \DateTime($birthday);
|
|
|
|
$interval = $today->diff($birthDate);
|
|
|
|
$years = $interval->y;
|
|
$months = $interval->m;
|
|
|
|
// 将月份转换为小数,如3岁11个月 = 3.11
|
|
return $years + ($months / 100);
|
|
}
|
|
|
|
/**
|
|
* 添加孩子信息
|
|
* @param array $data
|
|
* @return array
|
|
*/
|
|
public function addChild($data)
|
|
{
|
|
$customerId = $this->getUserId();
|
|
|
|
// 创建学员数据
|
|
$studentData = [
|
|
'user_id' => $customerId,
|
|
'name' => $data['name'],
|
|
'gender' => (int)$data['gender'],
|
|
'birthday' => $data['birthday'],
|
|
'headimg' => $data['headimg'] ?? '',
|
|
'emergency_contact' => $data['emergency_contact'] ?? '',
|
|
'contact_phone' => $data['contact_phone'] ?? '',
|
|
'note' => $data['note'] ?? '',
|
|
'age' => $this->calculateAgeFromBirthday($data['birthday']),
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
'updated_at' => date('Y-m-d H:i:s'),
|
|
'deleted_at' => 0
|
|
];
|
|
|
|
try {
|
|
// 插入学员数据
|
|
$studentId = Db::table('school_student')->insertGetId($studentData);
|
|
|
|
if (!$studentId) {
|
|
throw new CommonException('添加孩子失败');
|
|
}
|
|
|
|
return [
|
|
'student_id' => $studentId,
|
|
'name' => $data['name'],
|
|
'gender_text' => $data['gender'] == 1 ? '男' : '女',
|
|
'age' => $this->calculateAge($data['birthday'])
|
|
];
|
|
|
|
} catch (\Exception $e) {
|
|
throw new CommonException('添加孩子失败:' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取学员课程安排列表
|
|
* @param array $params
|
|
* @return array
|
|
*/
|
|
public function getCourseScheduleList($params)
|
|
{
|
|
$studentId = $params['student_id'];
|
|
// 构建查询条件
|
|
$where = [
|
|
['pcs.student_id', '=', $studentId],
|
|
['pcs.deleted_at', '=', 0],
|
|
['cs.deleted_at', '=', 0]
|
|
];
|
|
|
|
// 日期筛选
|
|
if (!empty($params['date'])) {
|
|
$where[] = ['cs.course_date', '=', $params['date']];
|
|
}
|
|
|
|
// 日期范围筛选
|
|
if (!empty($params['start_date']) && !empty($params['end_date'])) {
|
|
$where[] = ['cs.course_date', 'between', [$params['start_date'], $params['end_date']]];
|
|
}
|
|
|
|
// 状态筛选
|
|
if (isset($params['status']) && $params['status'] !== '') {
|
|
$where[] = ['pcs.status', '=', $params['status']];
|
|
}
|
|
|
|
// 查询课程安排数据,联合两个表
|
|
$scheduleList = Db::table('school_person_course_schedule pcs')
|
|
->leftJoin('school_course_schedule cs', 'pcs.schedule_id = cs.id')
|
|
->leftJoin('school_course c', 'cs.course_id = c.id')
|
|
->leftJoin('school_personnel p', 'cs.coach_id = p.id')
|
|
->leftJoin('school_venue v', 'cs.venue_id = v.id')
|
|
->where($where)
|
|
->field('pcs.id,
|
|
cs.course_date,
|
|
COALESCE(cs.start_time,
|
|
CASE
|
|
WHEN pcs.time_slot REGEXP "^[0-9]{2}:[0-9]{2}-[0-9]{2}:[0-9]{2}$"
|
|
THEN SUBSTRING_INDEX(pcs.time_slot, "-", 1)
|
|
ELSE "09:00"
|
|
END
|
|
) as start_time,
|
|
COALESCE(cs.end_time,
|
|
CASE
|
|
WHEN pcs.time_slot REGEXP "^[0-9]{2}:[0-9]{2}-[0-9]{2}:[0-9]{2}$"
|
|
THEN SUBSTRING_INDEX(pcs.time_slot, "-", -1)
|
|
ELSE "10:00"
|
|
END
|
|
) as end_time,
|
|
cs.time_slot,
|
|
pcs.status,
|
|
pcs.cancel_reason,
|
|
c.course_name,
|
|
c.remarks as course_description,
|
|
p.name as coach_name,
|
|
v.venue_name,
|
|
60 as duration')
|
|
->order('cs.course_date desc, cs.start_time desc')
|
|
->select()
|
|
->toArray();
|
|
|
|
// 处理数据格式
|
|
foreach ($scheduleList as &$schedule) {
|
|
// 状态处理
|
|
$schedule['status_text'] = $this->getScheduleStatusText($schedule['status']);
|
|
|
|
// 时间处理
|
|
if (!$schedule['start_time'] || !$schedule['end_time']) {
|
|
// 如果没有具体时间,从time_slot中解析
|
|
$timeSlot = $schedule['time_slot'] ?? '09:00-10:00';
|
|
$times = explode('-', $timeSlot);
|
|
$schedule['start_time'] = $times[0] ?? '09:00';
|
|
$schedule['end_time'] = $times[1] ?? '10:00';
|
|
}
|
|
|
|
$schedule['time_slot'] = $schedule['start_time'] . '-' . $schedule['end_time'];
|
|
$schedule['duration'] = $schedule['duration'] ?: 60;
|
|
|
|
// 准备事项(模拟数据,实际可从课程信息中获取)
|
|
$schedule['preparation_items'] = $this->getCoursePreparationItems($schedule['course_name']);
|
|
}
|
|
|
|
return [
|
|
'list' => $scheduleList,
|
|
'total' => count($scheduleList)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取课程安排详情
|
|
* @param int $scheduleId
|
|
* @return array
|
|
*/
|
|
public function getCourseScheduleDetail($scheduleId)
|
|
{
|
|
// 查询课程安排详情 - 通过schedule_id关联到course_schedule表获取详细信息
|
|
$schedule = Db::table('school_person_course_schedule pcs')
|
|
->leftJoin('school_course_schedule cs', 'pcs.schedule_id = cs.id')
|
|
->leftJoin('school_course c', 'cs.course_id = c.id')
|
|
->leftJoin('school_personnel p', 'cs.coach_id = p.id')
|
|
->leftJoin('school_venue v', 'cs.venue_id = v.id')
|
|
->leftJoin('school_student s', 'pcs.student_id = s.id')
|
|
->where('pcs.id', $scheduleId)
|
|
->where('pcs.deleted_at', 0)
|
|
->field('
|
|
pcs.id,
|
|
pcs.student_id,
|
|
pcs.course_date,
|
|
COALESCE(cs.start_time,
|
|
CASE
|
|
WHEN pcs.time_slot REGEXP "^[0-9]{2}:[0-9]{2}-[0-9]{2}:[0-9]{2}$"
|
|
THEN SUBSTRING_INDEX(pcs.time_slot, "-", 1)
|
|
ELSE "09:00"
|
|
END
|
|
) as start_time,
|
|
COALESCE(cs.end_time,
|
|
CASE
|
|
WHEN pcs.time_slot REGEXP "^[0-9]{2}:[0-9]{2}-[0-9]{2}:[0-9]{2}$"
|
|
THEN SUBSTRING_INDEX(pcs.time_slot, "-", -1)
|
|
ELSE "10:00"
|
|
END
|
|
) as end_time,
|
|
pcs.status,
|
|
pcs.cancel_reason,
|
|
c.course_name,
|
|
c.remarks as course_description,
|
|
p.name as coach_name,
|
|
v.venue_name,
|
|
s.user_id,
|
|
TIMESTAMPDIFF(MINUTE, cs.start_time, cs.end_time) as duration
|
|
')
|
|
->find();
|
|
|
|
if (!$schedule) {
|
|
throw new CommonException('课程安排不存在');
|
|
}
|
|
|
|
// 验证权限
|
|
$this->checkStudentPermission($schedule['student_id']);
|
|
|
|
// 处理数据格式
|
|
$schedule['status_text'] = $this->getScheduleStatusText($schedule['status']);
|
|
$schedule['time_slot'] = $schedule['start_time'] . '-' . $schedule['end_time'];
|
|
$schedule['duration'] = $schedule['duration'] ?: 60;
|
|
$schedule['preparation_items'] = $this->getCoursePreparationItems($schedule['course_name']);
|
|
|
|
return $schedule;
|
|
}
|
|
|
|
/**
|
|
* 申请课程请假
|
|
* @param array $data
|
|
* @return bool
|
|
*/
|
|
public function requestCourseLeave($data)
|
|
{
|
|
$scheduleId = $data['schedule_id'];
|
|
$reason = $data['reason'] ?? '';
|
|
|
|
// 查询课程安排
|
|
$schedule = Db::table('school_person_course_schedule')
|
|
->where('id', $scheduleId)
|
|
->where('deleted_at', 0)
|
|
->find();
|
|
|
|
if (!$schedule) {
|
|
throw new CommonException('课程安排不存在');
|
|
}
|
|
|
|
// 验证权限
|
|
$this->checkStudentPermission($schedule['student_id']);
|
|
|
|
// 检查课程状态
|
|
if ($schedule['status'] != 0) { // 0-待上课
|
|
throw new CommonException('当前课程状态不允许请假');
|
|
}
|
|
|
|
// 获取对应的课程安排信息来检查时间
|
|
$courseSchedule = Db::table('school_course_schedule')
|
|
->where('id', $schedule['schedule_id'])
|
|
->find();
|
|
|
|
if ($courseSchedule) {
|
|
// 检查请假时间限制(上课前6小时)
|
|
$courseDateTime = $courseSchedule['course_date'] . ' ' . $courseSchedule['start_time'];
|
|
$courseTimestamp = strtotime($courseDateTime);
|
|
$currentTimestamp = time();
|
|
|
|
if ($courseTimestamp - $currentTimestamp < 6 * 3600) {
|
|
throw new CommonException('上课前6小时内不允许请假');
|
|
}
|
|
}
|
|
|
|
// 更新状态为请假
|
|
$result = Db::table('school_person_course_schedule')
|
|
->where('id', $scheduleId)
|
|
->update([
|
|
'status' => 2, // 2-请假
|
|
'cancel_reason' => $reason,
|
|
'updated_at' => date('Y-m-d H:i:s')
|
|
]);
|
|
|
|
if ($result === false) {
|
|
throw new CommonException('请假申请失败');
|
|
}
|
|
|
|
// TODO: 发送消息通知相关人员
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 获取课程状态文本
|
|
* @param int $status
|
|
* @return string
|
|
*/
|
|
private function getScheduleStatusText($status)
|
|
{
|
|
$statusMap = [
|
|
0 => '待上课',
|
|
1 => '已完成',
|
|
2 => '请假',
|
|
3 => '取消'
|
|
];
|
|
|
|
return $statusMap[$status] ?? '未知状态';
|
|
}
|
|
|
|
/**
|
|
* 获取课程准备事项
|
|
* @param string $courseName
|
|
* @return array
|
|
*/
|
|
private function getCoursePreparationItems($courseName)
|
|
{
|
|
// 根据课程名称返回相应的准备事项
|
|
$preparationMap = [
|
|
'基础体能训练' => ['运动服装', '运动鞋', '毛巾', '水杯'],
|
|
'专项技能训练' => ['专项器材', '护具', '运动服装'],
|
|
'体适能评估' => ['轻便服装', '测试表格'],
|
|
'少儿形体课' => ['舞蹈服装', '舞蹈鞋', '毛巾'],
|
|
'成人瑜伽' => ['瑜伽垫', '舒适服装', '毛巾'],
|
|
'私教训练' => ['运动服装', '运动鞋', '水杯'],
|
|
'儿童游泳' => ['泳衣', '泳帽', '游泳镜', '毛巾'],
|
|
'暑季特训营' => ['运动服装', '防晒用品', '充足水分', '能量补充食品']
|
|
];
|
|
|
|
return $preparationMap[$courseName] ?? ['运动服装', '运动鞋', '毛巾', '水杯'];
|
|
}
|
|
|
|
/**
|
|
* 获取学员课时统计信息
|
|
* @param int $studentId
|
|
* @return array
|
|
*/
|
|
private function getStudentCourseStats($studentId)
|
|
{
|
|
// 查询学员的所有课程记录
|
|
$courseStats = Db::table('school_student_courses')
|
|
->where('student_id', $studentId)
|
|
->field('
|
|
SUM(total_hours) as total_hours,
|
|
SUM(gift_hours) as gift_hours,
|
|
SUM(use_total_hours) as use_total_hours,
|
|
SUM(use_gift_hours) as use_gift_hours
|
|
')
|
|
->find();
|
|
|
|
// 如果没有课程记录,返回默认值
|
|
if (!$courseStats || is_null($courseStats['total_hours'])) {
|
|
return [
|
|
'remaining_hours' => 0,
|
|
'total_valid_hours' => 0,
|
|
'used_hours' => 0
|
|
];
|
|
}
|
|
|
|
// 计算课时统计
|
|
$totalHours = (int)$courseStats['total_hours'];
|
|
$giftHours = (int)$courseStats['gift_hours'];
|
|
$useTotalHours = (int)$courseStats['use_total_hours'];
|
|
$useGiftHours = (int)$courseStats['use_gift_hours'];
|
|
|
|
// 有效课程 = total_hours + gift_hours
|
|
$totalValidHours = $totalHours + $giftHours;
|
|
|
|
// 已使用 = use_total_hours + use_gift_hours
|
|
$usedHours = $useTotalHours + $useGiftHours;
|
|
|
|
// 剩余课时数 = total_hours + gift_hours - use_total_hours - use_gift_hours
|
|
$remainingHours = $totalValidHours - $usedHours;
|
|
|
|
return [
|
|
'remaining_hours' => max(0, $remainingHours), // 确保不为负数
|
|
'total_valid_hours' => $totalValidHours,
|
|
'used_hours' => $usedHours
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取当前登录用户ID
|
|
* @return int
|
|
*/
|
|
private function getUserId()
|
|
{
|
|
// 从request中获取memberId(由ApiCheckToken中间件设置)
|
|
$memberId = request()->memberId();
|
|
if ($memberId) {
|
|
return $memberId;
|
|
}
|
|
|
|
// 如果没有中间件设置,尝试解析token
|
|
$token = request()->header('token');
|
|
if ($token) {
|
|
try {
|
|
$loginService = new \app\service\api\login\LoginService();
|
|
$tokenInfo = $loginService->parseToken($token);
|
|
if (!empty($tokenInfo) && isset($tokenInfo['member_id'])) {
|
|
return $tokenInfo['member_id'];
|
|
}
|
|
} catch (\Exception $e) {
|
|
// token解析失败,抛出异常
|
|
throw new CommonException('用户未登录或token无效');
|
|
}
|
|
}
|
|
|
|
// 如果都没有,抛出异常
|
|
throw new CommonException('用户未登录');
|
|
}
|
|
|
|
/**
|
|
* 学员标签
|
|
* @return array
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public function getStudentTagList()
|
|
{
|
|
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
|
|
];
|
|
}
|
|
|
|
public function checkMemberOldPwd(string $old_passowrd)
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
$customerResources = new CustomerResources();
|
|
|
|
$personnel_id = $this->getUserId();
|
|
$member = new Member();
|
|
$phone = $customerResources->where('id', $personnel_id)->value('phone_number');
|
|
|
|
$password = $customerResources->where('id', $personnel_id)->value('password');
|
|
|
|
if (!check_password($old_passowrd, $password)) {
|
|
$res['msg'] = '旧密码错误';
|
|
return $res;
|
|
}
|
|
$res['code'] = 1;
|
|
$res['msg'] = '密码正确';
|
|
$res['data'] = [
|
|
'key_value' => $this->setEditPasswordKey($phone)
|
|
];
|
|
return $res;
|
|
}
|
|
|
|
public function updatePassword($new_password){
|
|
$customerResources = new CustomerResources();
|
|
|
|
$personnel_id = $this->getUserId();
|
|
|
|
$update = $customerResources->where('id', $personnel_id)->update([
|
|
'password' => create_password($new_password)
|
|
]);
|
|
if (!$update) {
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
} else {
|
|
$res = [
|
|
'code' => 1,
|
|
'msg' => '操作成功',
|
|
'data' => []
|
|
];
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
public function setEditPasswordKey(string $phone)
|
|
{
|
|
$key_name = 'edit_password_' . $phone;
|
|
//生成字符串,存入cache中
|
|
//check_password()//验证
|
|
//create_password()//创建
|
|
|
|
$key_value = create_password($key_name);
|
|
// 缓存在3600秒之后过期
|
|
Cache::set($key_name, $key_value, 3600);
|
|
return $key_value;
|
|
}
|
|
}
|
|
|