签到记录

master
lion 3 months ago
commit b537949a36

@ -0,0 +1,179 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exports\BaseExport;
use App\Exports\CommonExport;
use App\Helpers\ResponseCode;
use App\Models\AppointmentType;
use App\Models\Book;
use App\Models\Calendar;
use App\Models\Company;
use App\Models\Course;
use App\Models\CourseContentCheck;
use App\Models\CourseContentEvaluationAsk;
use App\Models\CourseContentEvaluationForm;
use App\Models\CourseSign;
use App\Models\CustomForm;
use App\Models\CustomFormField;
use App\Models\EmailTemplate;
use App\Models\SupplyDemand;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use Rap2hpoutre\FastExcel\FastExcel;
class CourseContentCheckController extends BaseController
{
/**
* 构造函数
*/
public function __construct()
{
parent::__construct(new CourseContentCheck());
}
/**
* @OA\Get(
* path="/api/admin/course-content-check/index",
* tags={"签到管理"},
* summary="列表",
* description="",
* @OA\Parameter(name="is_export", in="query", @OA\Schema(type="string"), required=false, description="是否导出0否1是"),
* @OA\Parameter(name="export_fields", in="query", @OA\Schema(type="string"), required=false, description="需要导出的字段数组"),
* @OA\Parameter(name="filter", in="query", @OA\Schema(type="string"), required=false, description="查询条件。数组"),
* @OA\Parameter(name="show_relation", in="query", @OA\Schema(type="string"), required=false, description="需要输出的关联关系数组包括teachercourseSettingscoursePeriods"),
* @OA\Parameter(name="page_size", in="query", @OA\Schema(type="string"), required=false, description="每页显示的条数"),
* @OA\Parameter(name="page", in="query", @OA\Schema(type="string"), required=false, description="页码"),
* @OA\Parameter(name="sort_name", in="query", @OA\Schema(type="string"), required=false, description="排序字段名字"),
* @OA\Parameter(name="sort_type", in="query", @OA\Schema(type="string"), required=false, description="排序类型"),
* @OA\Parameter(name="course_id", in="query", @OA\Schema(type="string"), required=false, description="course_id"),
* @OA\Parameter(name="course_content_id", in="query", @OA\Schema(type="string"), required=false, description="course_content_id"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function index()
{
$all = request()->all();
$list = CourseSign::with(['course.typeDetail', 'user', 'courseContentCheck' => function ($query) use ($all) {
if (isset($all['course_content_id'])) {
$query->where('course_content_id', $all['course_content_id']);
}
}])->where(function ($query) use ($all) {
if (isset($all['course_id'])) {
$query->where('course_id', $all['course_id']);
}
if (isset($all['filter']) && !empty($all['filter'])) {
foreach ($all['filter'] as $condition) {
$key = $condition['key'] ?? null;
$op = $condition['op'] ?? null;
$value = $condition['value'] ?? null;
if (!isset($key) || !isset($op) || !isset($value)) {
continue;
}
// 等于
if ($op == 'eq') {
$query->where($key, $value);
}
// 不等于
if ($op == 'neq') {
$query->where($key, '!=', $value);
}
// 模糊搜索
if ($op == 'like') {
$query->where($key, 'like', '%' . $value . '%');
}
// 否定模糊搜索
if ($op == 'notlike') {
$query->where($key, 'not like', '%' . $value . '%');
}
// 范围搜索
if ($op == 'range') {
list($from, $to) = explode(',', $value);
if (empty($from) || empty($to)) {
continue;
}
$query->whereBetween($key, [$from, $to]);
}
}
}
})->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')
->orderBy('created_at', 'desc');
if (isset($all['is_export']) && !empty($all['is_export'])) {
$list = $list->limit(5000)->get()->toArray();
return Excel::download(new CommonExport($list, $all['export_fields'] ?? ''), $all['file_name'] ?? '' . date('YmdHis') . '.xlsx');
} else {
// 输出
$list = $list->paginate($all['page_size'] ?? 20);
}
return $this->success($list);
}
/**
* @OA\Get(
* path="/api/admin/course-content-check/show",
* tags={"签到管理"},
* summary="详情",
* description="",
* @OA\Parameter(name="id", in="query", @OA\Schema(type="string"), required=true, description="id"),
* @OA\Parameter(name="show_relation", in="query", @OA\Schema(type="string"), required=false, description="需要输出的关联关系数组,填写输出指定数据"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public
function show()
{
return parent::show();
}
/**
* @OA\Post(
* path="/api/admin/course-content-check/save",
* tags={"签到管理"},
* summary="保存",
* description="",
* @OA\Parameter(name="id", in="query", @OA\Schema(type="int"), required=true, description="Id(存在更新,不存在新增)"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="认证token"),
* @OA\Response(
* response="200",
* description="操作成功"
* )
* )
*/
public
function save()
{
return parent::save();
}
/**
* @OA\Get(
* path="/api/admin/course-content-check/destroy",
* tags={"签到管理"},
* summary="删除",
* description="",
* @OA\Parameter(name="id", in="query", @OA\Schema(type="string"), required=true, description="id"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public
function destroy()
{
return parent::destroy();
}
}

@ -553,25 +553,25 @@ class CourseController extends CommonController
{ {
$all = \request()->all(); $all = \request()->all();
$messages = [ $messages = [
'longitude.required' => '经度必填', // 'longitude.required' => '经度必填',
'latitude.required' => '纬度必填', // 'latitude.required' => '纬度必填',
'course_content_id.required' => '课表id必填', 'course_content_id.required' => '课表id必填',
]; ];
$validator = Validator::make($all, [ $validator = Validator::make($all, [
'longitude' => 'required', // 'longitude' => 'required',
'latitude' => 'required', // 'latitude' => 'required',
'course_content_id' => 'required' 'course_content_id' => 'required'
], $messages); ], $messages);
if ($validator->fails()) { if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
} }
// 获取打卡范围,千米 // 获取打卡范围,千米
$content_check_range = Config::getValueByKey('content_check_range'); // $content_check_range = Config::getValueByKey('content_check_range');
$courseContent = CourseContent::find($all['course_content_id']); $courseContent = CourseContent::find($all['course_content_id']);
$distance = getDistance($courseContent->longitude, $courseContent->latitude, $all['longitude'], $all['latitude']); // $distance = getDistance($courseContent->longitude, $courseContent->latitude, $all['longitude'], $all['latitude']);
if ($distance > $content_check_range) { // if ($distance > $content_check_range) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '超出打卡范围']); // return $this->fail([ResponseCode::ERROR_BUSINESS, '超出打卡范围']);
} // }
// 判断当天才能签到 // 判断当天才能签到
$today = date('Y-m-d'); $today = date('Y-m-d');
if ($today != $courseContent->date) { if ($today != $courseContent->date) {
@ -588,8 +588,8 @@ class CourseController extends CommonController
'course_content_id' => $all['course_content_id'], 'course_content_id' => $all['course_content_id'],
'course_id' => $courseContent->course_id, 'course_id' => $courseContent->course_id,
'user_id' => $this->getUserId(), 'user_id' => $this->getUserId(),
'longitude' => $all['longitude'], 'longitude' => $all['longitude']??'',
'latitude' => $all['latitude'], 'latitude' => $all['latitude']??'',
]); ]);
// 同日期课程批量签到 // 同日期课程批量签到
$batch_sign = request('batch_sign', 0); $batch_sign = request('batch_sign', 0);
@ -639,12 +639,12 @@ class CourseController extends CommonController
$all = \request()->all(); $all = \request()->all();
$messages = [ $messages = [
'longitude.required' => '经度必填', 'longitude.required' => '经度必填',
'latitude.required' => '纬度必填', // 'latitude.required' => '纬度必填',
'course_id.required' => '课表id必填', // 'course_id.required' => '课表id必填',
]; ];
$validator = Validator::make($all, [ $validator = Validator::make($all, [
'longitude' => 'required', // 'longitude' => 'required',
'latitude' => 'required', // 'latitude' => 'required',
'course_id' => 'required' 'course_id' => 'required'
], $messages); ], $messages);
if ($validator->fails()) { if ($validator->fails()) {
@ -653,13 +653,13 @@ class CourseController extends CommonController
// 获取打卡范围,千米 // 获取打卡范围,千米
$content_check_range = Config::getValueByKey('content_check_range'); $content_check_range = Config::getValueByKey('content_check_range');
$course = Course::find($all['course_id']); $course = Course::find($all['course_id']);
if (empty($course->longitude) || empty($course->latitude)) { // if (empty($course->longitude) || empty($course->latitude)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '请先设置课程经纬度']); // return $this->fail([ResponseCode::ERROR_BUSINESS, '请先设置课程经纬度']);
} // }
$distance = getDistance($course->longitude, $course->latitude, $all['longitude'], $all['latitude']); // $distance = getDistance($course->longitude, $course->latitude, $all['longitude'], $all['latitude']);
if ($distance > $content_check_range) { // if ($distance > $content_check_range) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '超出打卡范围']); // return $this->fail([ResponseCode::ERROR_BUSINESS, '超出打卡范围']);
} // }
// 判断当天才能签到 // 判断当天才能签到
$today = date('Y-m-d'); $today = date('Y-m-d');
if ($today != $course->start_date) { if ($today != $course->start_date) {
@ -675,8 +675,8 @@ class CourseController extends CommonController
CourseContentCheck::create([ CourseContentCheck::create([
'course_id' => $all['course_id'], 'course_id' => $all['course_id'],
'user_id' => $this->getUserId(), 'user_id' => $this->getUserId(),
'longitude' => $all['longitude'], 'longitude' => $all['longitude']??'',
'latitude' => $all['latitude'], 'latitude' => $all['latitude']??'',
]); ]);
return $this->success('课程签到成功'); return $this->success('课程签到成功');
} }

@ -11,6 +11,7 @@ use App\Jobs\SendAppointCar;
use App\Jobs\SendCourseCar; use App\Jobs\SendCourseCar;
use App\Models\Appointment; use App\Models\Appointment;
use App\Models\Config; use App\Models\Config;
use App\Models\CourseContentCheck;
use App\Models\CourseSign; use App\Models\CourseSign;
use App\Models\RelatedModel; use App\Models\RelatedModel;
use App\Models\ScoreLog; use App\Models\ScoreLog;
@ -521,4 +522,112 @@ class UserController extends CommonController
return $this->success(compact('qrcode')); return $this->success(compact('qrcode'));
} }
/**
* @OA\Get(
* path="/api/mobile/user/mobile-login",
* tags={"小程序-用户管理"},
* summary="手机号登陆",
* @OA\Parameter(name="code", in="query", @OA\Schema(type="string"), required=false, description="code"),
* @OA\Parameter(name="mobile", in="query", @OA\Schema(type="string"), required=false, description="手机号"),
* @OA\Response(
* response=200,
* description="操作成功"
* )
* )
*/
public function mobileLogin()
{
$all = \request()->all();
$messages = [
'code.required' => 'code必填',
'mobile.required' => '手机号必填'
];
$validator = Validator::make($all, [
'code' => 'required',
'mobile' => 'required'
], $messages);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$key = 'sms_login_' . $all['mobile'];
$check = Cache::get($key);
if (empty($check)) return $this->fail([ResponseCode::ERROR_BUSINESS, '请先发送验证码']);
if ($check['code'] != $all['code']) return $this->fail([ResponseCode::ERROR_BUSINESS, '验证码错误']);
$user = User::where('mobile', $all['mobile'])->first();
$token = $user->createToken("mobile-token")->plainTextToken;
return $this->success(compact('token'));
}
/**
* @OA\Get (
* path="/api/mobile/user/mobile-login-code",
* tags={"手机端-用户管理"},
* summary="短信登陆发送验证码",
* description="",
* @OA\Parameter(name="course_id", in="query", @OA\Schema(type="string"), required=true, description="课程id"),
* @OA\Parameter(name="course_content_id", in="query", @OA\Schema(type="string"), required=true, description="课表id"),
* @OA\Parameter(name="mobile", in="query", @OA\Schema(type="string"), required=true, description="手机号"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description=""
* )
* )
*/
public function mobileLoginCode()
{
$all = \request()->all();
$messages = [
'course_id.required' => '课程id必填',
'mobile.required' => '手机号必填',
'mobile.numeric' => '手机号格式错误',
];
$validator = Validator::make($all, [
'course_id' => 'required',
'mobile' => 'required|numeric'
], $messages);
if ($validator->fails()) {
return $this->fail([StarterResponseCode::START_ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
// 监测是否正常报名并通过
$courseSigns = CourseSign::where('course_id', $all['course_id'])
->whereHas('user', function ($query) use ($all) {
$query->where('mobile', $all['mobile']);
})->where('status', 1)
->first();
if (empty($courseSigns)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '未报名课程']);
}
$user = User::where('mobile', $all['mobile'])->first();
if (empty($user)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '用户不存在']);
}
$list = CourseContentCheck::where('course_id', $all['course_id'])
->where(function ($query) use ($all) {
if (isset($all['course_content_id'])) {
$query->where('course_content_id', $all['course_content_id']);
}
})->where('user_id', $user->id)
->orderBy('created_at', 'desc')
->get();
if ($list->isNotEmpty()) {
return $this->success($list);
}
$key = 'sms_login_' . $all['mobile'];
$check = Cache::get($key);
if (isset($check) && time() - $check['time'] <= 60) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '请勿频繁发送']);
}
$code = rand(1000, 9999);
$smsSign = Config::getValueByKey('sms_sign');
$content = "{$smsSign}您的验证码是:{$code},验证码五分钟内有效,如非本人操作,请忽略。";
$result = ymSms($all['mobile'], $content);
if ($result) {
// 缓存
Cache::put($key, ['code' => $code, 'time' => time()], 300);
return $this->success("发送成功");
}
return $this->fail([StarterResponseCode::START_ERROR_PARAMETER, "发送失败"]);
}
} }

@ -57,6 +57,11 @@ class CourseSign extends SoftDeletesModel
return $this->hasOne(Course::class, 'id', 'course_id'); return $this->hasOne(Course::class, 'id', 'course_id');
} }
public function courseContentCheck()
{
return $this->hasOne(CourseContentCheck::class, 'course_id', 'course_id');
}
public function user() public function user()
{ {
return $this->hasOne(User::class, 'id', 'user_id'); return $this->hasOne(User::class, 'id', 'user_id');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -232,6 +232,12 @@ Route::group(["namespace" => "Admin", "prefix" => "admin"], function () {
Route::get('company/show', [\App\Http\Controllers\Admin\CompanyController::class, "show"]); Route::get('company/show', [\App\Http\Controllers\Admin\CompanyController::class, "show"]);
Route::post('company/save', [\App\Http\Controllers\Admin\CompanyController::class, "save"]); Route::post('company/save', [\App\Http\Controllers\Admin\CompanyController::class, "save"]);
Route::get('company/destroy', [\App\Http\Controllers\Admin\CompanyController::class, "destroy"]); Route::get('company/destroy', [\App\Http\Controllers\Admin\CompanyController::class, "destroy"]);
// 签到管理
Route::get('course-content-check/index', [\App\Http\Controllers\Admin\CourseContentCheckController::class, "index"]);
Route::get('course-content-check/show', [\App\Http\Controllers\Admin\CourseContentCheckController::class, "show"]);
Route::post('course-content-check/save', [\App\Http\Controllers\Admin\CourseContentCheckController::class, "save"]);
Route::get('course-content-check/destroy', [\App\Http\Controllers\Admin\CourseContentCheckController::class, "destroy"]);
}); });
}); });
@ -255,10 +261,16 @@ Route::group(["namespace" => "Mobile", "prefix" => "mobile"], function () {
Route::get('course/course-detail-pc', [\App\Http\Controllers\Mobile\CourseController::class, "courseDetailPc"]); Route::get('course/course-detail-pc', [\App\Http\Controllers\Mobile\CourseController::class, "courseDetailPc"]);
// 小程序登陆 // 小程序登陆
Route::get('user/applet-login', [\App\Http\Controllers\Mobile\UserController::class, "appletLogin"]); Route::get('user/applet-login', [\App\Http\Controllers\Mobile\UserController::class, "appletLogin"]);
// 手机号登陆
Route::get('user/mobile-login', [\App\Http\Controllers\Mobile\UserController::class, "mobileLogin"]);
// 手机号登陆发送验证码
Route::get('user/mobile-login-code', [\App\Http\Controllers\Mobile\UserController::class, "mobileLoginCode"]);
// 新闻列表 // 新闻列表
Route::get('course/news', [\App\Http\Controllers\Mobile\CourseController::class, "news"]); Route::get('course/news', [\App\Http\Controllers\Mobile\CourseController::class, "news"]);
// 新闻详情 // 新闻详情
Route::get('course/news-detail', [\App\Http\Controllers\Mobile\CourseController::class, "newsDetail"]); Route::get('course/news-detail', [\App\Http\Controllers\Mobile\CourseController::class, "newsDetail"]);
Route::get('course/course-detail', [\App\Http\Controllers\Mobile\CourseController::class, "courseDetail"]);
Route::get('course/course-content-detail', [\App\Http\Controllers\Mobile\CourseController::class, "courseContentDetail"]);
// 支付回调 // 支付回调
Route::any('course/pay_callback', [\App\Http\Controllers\Mobile\CourseController::class, "payCallback"]); Route::any('course/pay_callback', [\App\Http\Controllers\Mobile\CourseController::class, "payCallback"]);
Route::group(['middleware' => ['sanctum.jwt:mobile']], function () { Route::group(['middleware' => ['sanctum.jwt:mobile']], function () {
@ -275,13 +287,13 @@ Route::group(["namespace" => "Mobile", "prefix" => "mobile"], function () {
Route::post('user/update-donates', [\App\Http\Controllers\Mobile\UserController::class, "updateDonates"]); Route::post('user/update-donates', [\App\Http\Controllers\Mobile\UserController::class, "updateDonates"]);
// 课程信息 // 课程信息
Route::get('course/course-detail', [\App\Http\Controllers\Mobile\CourseController::class, "courseDetail"]);
Route::get('course/evaluation-detail', [\App\Http\Controllers\Mobile\CourseController::class, "evaluationDetail"]); Route::get('course/evaluation-detail', [\App\Http\Controllers\Mobile\CourseController::class, "evaluationDetail"]);
Route::post('course/sign', [\App\Http\Controllers\Mobile\CourseController::class, "sign"]); Route::post('course/sign', [\App\Http\Controllers\Mobile\CourseController::class, "sign"]);
Route::get('course/my-course', [\App\Http\Controllers\Mobile\CourseController::class, "myCourse"]); Route::get('course/my-course', [\App\Http\Controllers\Mobile\CourseController::class, "myCourse"]);
Route::get('course/my-course-content', [\App\Http\Controllers\Mobile\CourseController::class, "myCourseContent"]); Route::get('course/my-course-content', [\App\Http\Controllers\Mobile\CourseController::class, "myCourseContent"]);
Route::get('course/course-content-detail', [\App\Http\Controllers\Mobile\CourseController::class, "courseContentDetail"]);
Route::post('course/course-form', [\App\Http\Controllers\Mobile\CourseController::class, "courseForm"]); Route::post('course/course-form', [\App\Http\Controllers\Mobile\CourseController::class, "courseForm"]);
Route::get('course/get-sign', [\App\Http\Controllers\Mobile\CourseController::class, "getSign"]); Route::get('course/get-sign', [\App\Http\Controllers\Mobile\CourseController::class, "getSign"]);
Route::post('course/update-sign', [\App\Http\Controllers\Mobile\CourseController::class, "updateSign"]); Route::post('course/update-sign', [\App\Http\Controllers\Mobile\CourseController::class, "updateSign"]);

Loading…
Cancel
Save