diff --git a/app/Http/Controllers/Admin/ChartController.php b/app/Http/Controllers/Admin/ChartController.php index 759e825..be29179 100644 --- a/app/Http/Controllers/Admin/ChartController.php +++ b/app/Http/Controllers/Admin/ChartController.php @@ -21,6 +21,8 @@ class ChartController extends CommonController * tags={"图表"}, * summary="首页统计", * description="", + * @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string"), required=false, description="开始日期,例如:2022-01-01"), + * @OA\Parameter(name="end_date", in="query", @OA\Schema(type="string"), required=false, description="结束日期,例如:2022-12-31"), * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Response( * response="200", @@ -30,31 +32,51 @@ class ChartController extends CommonController */ public function home() { + $all = request()->all(); + $startDate = $all['start_date'] ?? null; + $endDate = $all['end_date'] ?? null; + + // 构建查询条件 + $buildQuery = function($type) use ($startDate, $endDate) { + $query = Visit::where('type', $type); + if ($startDate && $endDate) { + $query->whereBetween('date', [$startDate, $endDate]); + } elseif ($startDate) { + $query->where('date', '>=', $startDate); + } elseif ($endDate) { + $query->where('date', '<=', $endDate); + } + return $query; + }; + $list = [ 'common_visit' => [ - 'total' => Visit::where('type', 1)->count(), - 'enter_visit' => Visit::where('type', 1)->whereNotNull('accept_admin_sign')->count(), + 'total' => $buildQuery(1)->count(), + 'enter_visit' => $buildQuery(1)->whereNotNull('accept_admin_sign')->count(), 'today_total' => Visit::where('type', 1)->where('date', date('Y-m-d'))->count(), 'today_enter_visit' => Visit::where('type', 1)->where('date', date('Y-m-d'))->whereNotNull('accept_admin_sign')->count(), ], 'work_visit' => [ - 'total' => Visit::where('type', 2)->count(), - 'enter_visit' => Visit::where('type', 2)->whereNotNull('accept_admin_sign')->count(), + 'total' => $buildQuery(2)->count(), + 'enter_visit' => $buildQuery(2)->whereNotNull('accept_admin_sign')->count(), 'today_total' => Visit::where('type', 2)->where('date', date('Y-m-d'))->count(), 'today_enter_visit' => Visit::where('type', 2)->where('date', date('Y-m-d'))->whereNotNull('accept_admin_sign')->count(), ], 'car_visit' => [ - 'total' => Visit::where('type', 3)->count(), - 'enter_visit' => Visit::where('type', 3)->whereNotNull('accept_admin_sign')->count(), + 'total' => $buildQuery(3)->count(), + 'enter_visit' => $buildQuery(3)->whereNotNull('accept_admin_sign')->count(), 'today_total' => Visit::where('type', 3)->where('date', date('Y-m-d'))->count(), 'today_enter_visit' => Visit::where('type', 3)->where('date', date('Y-m-d'))->whereNotNull('accept_admin_sign')->count(), ], ]; - $startDate = date('Y-m-d', strtotime('-30 day', time())); - $dateList = getDateFromRange($startDate, date('Y-m-d')); + + // 图表日期范围:如果有时间筛选参数,使用筛选参数;否则使用最近30天 + $chartStartDate = $startDate ?: date('Y-m-d', strtotime('-30 day', time())); + $chartEndDate = $endDate ?: date('Y-m-d'); + $dateList = getDateFromRange($chartStartDate, $chartEndDate); $all_date_list = []; foreach ($dateList as &$item) { - $allDateList[] = [ + $all_date_list[] = [ 'date' => $item, 'common_visit' => Visit::where('type', 1)->where('date', $item)->count(), 'work_visit' => Visit::where('type', 2)->where('date', $item)->count(), diff --git a/app/Http/Controllers/Mobile/CommonController.php b/app/Http/Controllers/Mobile/CommonController.php index d44f0a9..2b5f9c7 100644 --- a/app/Http/Controllers/Mobile/CommonController.php +++ b/app/Http/Controllers/Mobile/CommonController.php @@ -27,4 +27,116 @@ class CommonController extends Controller return $this->guard()->id(); } + /** + * @OA\Post( + * path="/api/mobile/validate-idcard", + * summary="验证身份证号码", + * description="验证身份证号码是否合法正规", + * tags={"移动端-通用接口"}, + * @OA\RequestBody( + * required=true, + * @OA\JsonContent( + * @OA\Property(property="idcard", type="string", description="身份证号码", example="110101199003071234") + * ) + * ), + * @OA\Response( + * response=200, + * description="验证成功", + * @OA\JsonContent( + * @OA\Property(property="code", type="integer", example=0), + * @OA\Property(property="message", type="string", example="success"), + * @OA\Property(property="data", type="boolean", description="身份证号码是否有效", example=true) + * ) + * ), + * @OA\Response( + * response=422, + * description="参数错误", + * @OA\JsonContent( + * @OA\Property(property="code", type="integer", example=1001), + * @OA\Property(property="message", type="string", example="身份证号码必填") + * ) + * ) + * ) + */ + public function validateIdcard() + { + $all = request()->all(); + $messages = [ + 'idcard.required' => '身份证号码必填' + ]; + $validator = Validator::make($all, [ + 'idcard' => 'required' + ], $messages); + + if ($validator->fails()) { + return response()->json([ + 'code' => ResponseCode::ERROR_PARAMETER, + 'message' => implode(',', $validator->errors()->all()), + 'data' => null + ], 422); + } + + $idcard = $all['idcard']; + $isValid = $this->isValidIdcard($idcard); + + return $this->success($isValid); + } + + /** + * 验证身份证号码是否有效 + */ + private function isValidIdcard($idcard) + { + // 基础格式验证 + if (!preg_match('/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/', $idcard)) { + return false; + } + + // 长度验证 + if (strlen($idcard) != 18) { + return false; + } + + // 转化为大写 + $idcard = strtoupper($idcard); + + // 加权因子 + $wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; + $ai = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; + + // 校验码验证 + $sigma = 0; + for ($i = 0; $i < 17; $i++) { + $b = (int)$idcard[$i]; + $w = $wi[$i]; + $sigma += $b * $w; + } + + $sidcard = $sigma % 11; + $check_idcard = $ai[$sidcard]; + + if ($idcard[17] != $check_idcard) { + return false; + } + + // 日期验证 + $year = substr($idcard, 6, 4); + $month = substr($idcard, 10, 2); + $day = substr($idcard, 12, 2); + + if (!checkdate($month, $day, $year)) { + return false; + } + + // 年龄合理性验证 + $birthDate = $year . '-' . $month . '-' . $day; + $age = \Carbon\Carbon::parse($birthDate)->age; + + if ($age < 0 || $age > 150) { + return false; + } + + return true; + } + } diff --git a/app/Http/Controllers/SwaggerController.php b/app/Http/Controllers/SwaggerController.php index 78c2973..3c34127 100644 --- a/app/Http/Controllers/SwaggerController.php +++ b/app/Http/Controllers/SwaggerController.php @@ -14,7 +14,7 @@ class SwaggerController extends Controller if (config('app.debug')) { $swagger = \OpenApi\Generator::scan([ app_path('Http/Controllers/Admin/'), - app_path('Http/Controllers/GateController.php'), + app_path('Http/Controllers/Mobile/'), app_path('Http/Controllers/Controller.php') ]); return response()->json($swagger, 200); diff --git a/routes/api.php b/routes/api.php index 20e4575..b5c1783 100644 --- a/routes/api.php +++ b/routes/api.php @@ -89,6 +89,9 @@ Route::group(["namespace" => "Admin", "prefix" => "admin", "middleware" => "sanc // 前台 Route::get('mobile/user/login', [\App\Http\Controllers\Mobile\UserController::class, 'login']); Route::get('mobile/user/config', [\App\Http\Controllers\Mobile\UserController::class, 'config']); +// 身份证验证接口(无需认证) +Route::post('mobile/validate-idcard', [\App\Http\Controllers\Mobile\CommonController::class, 'validateIdcard']); + Route::group(["namespace" => "Mobile", "prefix" => "mobile", "middleware" => "sanctum.jwt:mobile"], function () { Route::post('user/save', [\App\Http\Controllers\Mobile\UserController::class, 'save']); Route::get('user/mobile', [\App\Http\Controllers\Mobile\UserController::class, 'mobile']);