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.
300 lines
10 KiB
300 lines
10 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\api\apiService;
|
|
|
|
use core\base\BaseApiService;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 学员服务层
|
|
* Class StudentService
|
|
* @package app\service\api\apiService
|
|
*/
|
|
class StudentService extends BaseApiService
|
|
{
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
}
|
|
|
|
/**
|
|
* 添加学员
|
|
* @param array $data
|
|
* @return array
|
|
*/
|
|
public function add(array $data)
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
|
|
try {
|
|
// 准备插入数据
|
|
$insertData = [
|
|
'name' => $data['name'],
|
|
'gender' => $data['gender'],
|
|
'age' => $data['age'],
|
|
'birthday' => $data['birthday'],
|
|
'user_id' => $data['user_id'],
|
|
'campus_id' => $data['campus_id'],
|
|
'class_id' => $data['class_id'],
|
|
'note' => $data['note'],
|
|
'status' => $data['status'],
|
|
'emergency_contact' => $data['emergency_contact'],
|
|
'contact_phone' => $data['contact_phone'],
|
|
'member_label' => $data['member_label'],
|
|
'consultant_id' => $data['consultant_id'],
|
|
'coach_id' => $data['coach_id'],
|
|
'trial_class_count' => $data['trial_class_count'],
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
'updated_at' => date('Y-m-d H:i:s'),
|
|
'deleted_at' => 0
|
|
];
|
|
|
|
// 插入数据库
|
|
$id = Db::table('school_student')->insertGetId($insertData);
|
|
|
|
if ($id) {
|
|
$res['code'] = 1;
|
|
$res['msg'] = '添加成功';
|
|
$res['data'] = ['id' => $id];
|
|
} else {
|
|
$res['msg'] = '添加失败';
|
|
}
|
|
} catch (\Exception $e) {
|
|
$res['msg'] = '添加失败:' . $e->getMessage();
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* 获取学员列表(教练端专用)
|
|
* @param array $data
|
|
* @return array
|
|
*/
|
|
public function getList(array $data)
|
|
{
|
|
$res = [
|
|
'code' => 0,
|
|
'msg' => '操作失败',
|
|
'data' => []
|
|
];
|
|
|
|
try {
|
|
// 获取当前登录人员的ID
|
|
$currentUserId = $this->getUserId();
|
|
if (empty($currentUserId)) {
|
|
// 用户未登录或不是有效用户,返回空数据
|
|
$res['code'] = 1;
|
|
$res['data'] = [];
|
|
$res['msg'] = '获取成功';
|
|
return $res;
|
|
}
|
|
|
|
// 查询符合条件的学生ID集合
|
|
$studentIds = $this->getCoachStudentIds($currentUserId, $data);
|
|
|
|
if (empty($studentIds)) {
|
|
// 当前教练没有负责的学员,返回空数据
|
|
$res['code'] = 1;
|
|
$res['data'] = [];
|
|
$res['msg'] = '获取成功';
|
|
return $res;
|
|
}
|
|
|
|
// 构建学员基础查询条件
|
|
$where = [];
|
|
$where[] = ['s.deleted_at', '=', 0];
|
|
$where[] = ['s.id', 'in', $studentIds];
|
|
|
|
// 支持搜索参数
|
|
if (!empty($data['name'])) {
|
|
$where[] = ['s.name', 'like', '%' . $data['name'] . '%'];
|
|
}
|
|
|
|
if (!empty($data['phone'])) {
|
|
$where[] = ['s.contact_phone', 'like', '%' . $data['phone'] . '%'];
|
|
}
|
|
|
|
if (!empty($data['campus_id'])) {
|
|
$where[] = ['s.campus_id', '=', $data['campus_id']];
|
|
}
|
|
|
|
if (!empty($data['status'])) {
|
|
$where[] = ['s.status', '=', $data['status']];
|
|
}
|
|
|
|
// 查询学员基础信息
|
|
$list = Db::table('school_student s')
|
|
->leftJoin('school_campus c', 's.campus_id = c.id')
|
|
->where($where)
|
|
->field('s.*, c.campus_name as campus')
|
|
->order('s.created_at', 'desc')
|
|
->select()
|
|
->toArray();
|
|
|
|
// 为每个学员添加课程信息和到访情况
|
|
foreach ($list as &$student) {
|
|
// 获取学员最新有效的课程信息
|
|
$courseInfo = $this->getStudentLatestCourse($student['id']);
|
|
$student = array_merge($student, $courseInfo);
|
|
|
|
// 查询该学员的课程安排记录,按日期排序获取一访和二访信息
|
|
$visitRecords = Db::table('school_person_course_schedule')
|
|
->where([
|
|
['person_id', '=', $student['id']],
|
|
['person_type', '=', 'student']
|
|
])
|
|
->order('course_date', 'asc')
|
|
->select()
|
|
->toArray();
|
|
|
|
// 初始化到访信息
|
|
$student['first_visit_time'] = '';
|
|
$student['second_visit_time'] = '';
|
|
$student['first_visit_status'] = '未到访';
|
|
$student['second_visit_status'] = '未到访';
|
|
|
|
// 设置一访和二访信息
|
|
if (!empty($visitRecords)) {
|
|
if (isset($visitRecords[0])) {
|
|
$student['first_visit_time'] = $visitRecords[0]['course_date'];
|
|
$student['first_visit_status'] = '已到访';
|
|
}
|
|
if (isset($visitRecords[1])) {
|
|
$student['second_visit_time'] = $visitRecords[1]['course_date'];
|
|
$student['second_visit_status'] = '已到访';
|
|
}
|
|
}
|
|
|
|
// 保留原始访问记录数据供前端使用
|
|
$student['visit_records'] = $visitRecords;
|
|
}
|
|
|
|
$res['code'] = 1;
|
|
$res['data'] = $list;
|
|
} catch (\Exception $e) {
|
|
$res['msg'] = '获取失败:' . $e->getMessage();
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* 获取教练负责的学生ID集合
|
|
* @param int $coachId 教练ID
|
|
* @param array $data 查询条件
|
|
* @return array
|
|
*/
|
|
private function getCoachStudentIds($coachId, $data = [])
|
|
{
|
|
// 1. 从 school_student_courses 表中查询 main_coach_id 或 education_id 是当前教练的学生
|
|
$courseStudentIds = Db::table('school_student_courses')
|
|
->where(function($query) use ($coachId) {
|
|
$query->where('main_coach_id', $coachId)
|
|
->whereOr('education_id', $coachId);
|
|
})
|
|
->column('student_id');
|
|
|
|
// 调试日志
|
|
error_log("Coach ID: " . $coachId);
|
|
error_log("Course Student IDs: " . json_encode($courseStudentIds));
|
|
|
|
// 2. 从 school_person_course_schedule 和 school_course_schedule 表联查,获取教练负责的学生
|
|
$scheduleStudentIds = Db::table('school_person_course_schedule pcs')
|
|
->leftJoin('school_course_schedule cs', 'pcs.schedule_id = cs.id')
|
|
->where(function($query) use ($coachId) {
|
|
$query->where('cs.education_id', $coachId)
|
|
->whereOr('cs.coach_id', $coachId);
|
|
})
|
|
->where('pcs.person_type', 'student')
|
|
->where('pcs.deleted_at', 0)
|
|
->where('cs.deleted_at', 0)
|
|
->column('pcs.student_id');
|
|
|
|
error_log("Schedule Student IDs: " . json_encode($scheduleStudentIds));
|
|
|
|
// 3. 合并并去重学生ID
|
|
$allStudentIds = array_merge($courseStudentIds, $scheduleStudentIds);
|
|
$uniqueStudentIds = array_unique($allStudentIds);
|
|
|
|
error_log("Final Student IDs: " . json_encode($uniqueStudentIds));
|
|
|
|
return array_values($uniqueStudentIds);
|
|
}
|
|
|
|
/**
|
|
* 获取学员最新有效的课程信息
|
|
* @param int $studentId 学员ID
|
|
* @return array
|
|
*/
|
|
private function getStudentLatestCourse($studentId)
|
|
{
|
|
$courseInfo = Db::table('school_student_courses sc')
|
|
->leftJoin('school_course c', 'sc.course_id = c.id')
|
|
->leftJoin('school_customer_resources cr', 'sc.resource_id = cr.id')
|
|
->where([
|
|
['sc.student_id', '=', $studentId]
|
|
])
|
|
->field('sc.total_hours, sc.gift_hours, sc.use_total_hours, sc.use_gift_hours, sc.end_date, sc.resource_id as resource_sharing_id, c.course_name')
|
|
->order('sc.created_at', 'desc')
|
|
->find();
|
|
|
|
if (empty($courseInfo)) {
|
|
return [
|
|
'total_hours' => 0,
|
|
'gift_hours' => 0,
|
|
'use_total_hours' => 0,
|
|
'use_gift_hours' => 0,
|
|
'end_date' => '',
|
|
'resource_sharing_id' => 0,
|
|
'course_name' => ''
|
|
];
|
|
}
|
|
|
|
return $courseInfo;
|
|
}
|
|
|
|
/**
|
|
* 获取当前登录用户ID
|
|
* @return int
|
|
*/
|
|
private function getUserId()
|
|
{
|
|
// 员工端通过JWT token获取用户信息,支持token和Authorization两种header
|
|
$token = request()->header('token') ?: request()->header('Authorization');
|
|
if (empty($token)) {
|
|
return 0; // 返回0而不是抛异常,让上层处理
|
|
}
|
|
|
|
// 去掉Bearer前缀
|
|
$token = str_replace('Bearer ', '', $token);
|
|
|
|
try {
|
|
// 解析JWT token
|
|
$decoded = \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key(config('app.app_key'), 'HS256'));
|
|
|
|
// 检查token是否过期
|
|
if ($decoded->exp < time()) {
|
|
return 0; // token过期返回0
|
|
}
|
|
|
|
// 返回用户ID
|
|
return $decoded->user_id ?? 0;
|
|
} catch (\Exception $e) {
|
|
return 0; // token解析失败返回0
|
|
}
|
|
}
|
|
}
|