签到记录

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

@ -11,6 +11,7 @@ use App\Jobs\SendAppointCar;
use App\Jobs\SendCourseCar;
use App\Models\Appointment;
use App\Models\Config;
use App\Models\CourseContentCheck;
use App\Models\CourseSign;
use App\Models\RelatedModel;
use App\Models\ScoreLog;
@ -521,4 +522,112 @@ class UserController extends CommonController
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');
}
public function courseContentCheck()
{
return $this->hasOne(CourseContentCheck::class, 'course_id', 'course_id');
}
public function user()
{
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::post('company/save', [\App\Http\Controllers\Admin\CompanyController::class, "save"]);
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('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-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::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::get('course/course-detail', [\App\Http\Controllers\Mobile\CourseController::class, "courseDetail"]);
Route::get('course/evaluation-detail', [\App\Http\Controllers\Mobile\CourseController::class, "evaluationDetail"]);
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-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::get('course/get-sign', [\App\Http\Controllers\Mobile\CourseController::class, "getSign"]);
Route::post('course/update-sign', [\App\Http\Controllers\Mobile\CourseController::class, "updateSign"]);

Loading…
Cancel
Save