diff --git a/app/Http/Controllers/Admin/ChartController.php b/app/Http/Controllers/Admin/ChartController.php new file mode 100644 index 0000000..744b5c9 --- /dev/null +++ b/app/Http/Controllers/Admin/ChartController.php @@ -0,0 +1,178 @@ +all(); + $messages = [ + 'year.required' => '年份必填', + ]; + $validator = Validator::make($all, [ + 'year' => 'required' + ], $messages); + if ($validator->fails()) { + return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); + } + $monthList = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']; + $list = []; + foreach ($monthList as $item) { + $month = $all['year'] . '-' . $item; + $list[] = [ + 'month' => $month, + 'plan_total' => Visit::where('date', 'like', "%{$month}%")->count(), + 'enter_total' => Visit::where('date', 'like', "%{$month}%")->whereNotNull('accept_admin_sign')->count(), + 'cancel_total' => Visit::where('date', 'like', "%{$month}%")->where('audit_status', 5)->count(), + ]; + } + + if (isset($all['is_export']) && !empty($all['is_export'])) { + return (new FastExcel($list))->download('月度统计' . date('YmdHis') . '.csv', function ($info) { + return [ + '月份' => $info['month'], + '预约人数' => $info['plan_total'], + '入场人数' => $info['enter_total'], + '取消人数' => $info['cancel_total'], + '核销比' => $info['enter_total'] / $info['plan_total'] * 100 + ]; + }); + } else { + return $this->success($list); + } + } + + + /** + * @OA\Get( + * path="/api/admin/chart/time", + * tags={"图表"}, + * summary="时段统计", + * description="", + * @OA\Parameter(name="date", in="query", @OA\Schema(type="string"), required=true, description="日期,例如:2022=01=01"), + * @OA\Parameter(name="is_export", in="query", @OA\Schema(type="string"), required=false, description="是否导出0否1是,默认0"), + * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), + * @OA\Response( + * response="200", + * description="暂无" + * ) + * ) + */ + public function time() + { + $all = \request()->all(); + $messages = [ + 'date.required' => '时段必填', + ]; + $validator = Validator::make($all, [ + 'date' => 'required' + ], $messages); + if ($validator->fails()) { + return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); + } + $timeList = VisitTime::orderBy('start_time', 'asc')->get(); + $list = []; + foreach ($timeList as $item) { + $list[] = [ + 'time' => $item->start_time . '-' . $item->end_time, + 'plan_total' => Visit::where('date', $all['date'])->where('visit_time_id', $item->id)->count(), + 'enter_total' => Visit::where('date', $all['date'])->where('visit_time_id', $item->id)->whereNotNull('accept_admin_sign')->count(), + 'cancel_total' => Visit::where('date', $all['date'])->where('visit_time_id', $item->id)->where('audit_status', 5)->count(), + ]; + } + if (isset($all['is_export']) && !empty($all['is_export'])) { + return (new FastExcel($list))->download('车辆统计' . date('YmdHis') . '.csv', function ($info) { + return [ + '时间段' => $info['time'], + '预约人数' => $info['plan_total'], + '入场人数' => $info['enter_total'], + '取消人数' => $info['cancel_total'], + '核销比' => $info['enter_total'] / $info['plan_total'] * 100 + ]; + }); + } else { + return $this->success($list); + } + } + + /** + * @OA\Get( + * path="/api/admin/chart/car", + * tags={"图表"}, + * summary="车辆统计", + * description="", + * @OA\Parameter(name="year", in="query", @OA\Schema(type="string"), required=true, description="年份,例如:2022"), + * @OA\Parameter(name="is_export", in="query", @OA\Schema(type="string"), required=false, description="是否导出0否1是,默认0"), + * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), + * @OA\Response( + * response="200", + * description="暂无" + * ) + * ) + */ + public function car() + { + $all = \request()->all(); + $messages = [ + 'year.required' => '年份必填', + ]; + $validator = Validator::make($all, [ + 'year' => 'required' + ], $messages); + if ($validator->fails()) { + return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); + } + $monthList = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']; + $list = []; + foreach ($monthList as $item) { + $month = $all['year'] . '-' . $item; + $list[] = [ + 'month' => $month, + 'plan_total' => Visit::where('type', 3)->where('date', 'like', "%{$month}%")->count(), + 'enter_total' => Visit::where('type', 3)->where('date', 'like', "%{$month}%")->whereNotNull('accept_admin_sign')->count(), + 'cancel_total' => Visit::where('type', 3)->where('date', 'like', "%{$month}%")->where('audit_status', 5)->count(), + ]; + } + if (isset($all['is_export']) && !empty($all['is_export'])) { + return (new FastExcel($list))->download('车辆统计' . date('YmdHis') . '.csv', function ($info) { + return [ + '月份' => $info['month'], + '预约车辆数' => $info['plan_total'], + '入场车辆数' => $info['enter_total'], + '取消车辆数' => $info['cancel_total'], + '核销比' => $info['enter_total'] / $info['plan_total'] * 100 + ]; + }); + } else { + return $this->success($list); + } + } + +} diff --git a/app/Http/Controllers/Admin/GateController.php b/app/Http/Controllers/Admin/GateController.php index 3386c75..8882e7a 100644 --- a/app/Http/Controllers/Admin/GateController.php +++ b/app/Http/Controllers/Admin/GateController.php @@ -34,7 +34,7 @@ class GateController extends CommonController { $admin = Admin::whereHas('role', function ($query) { $query->where('name', 'like', '%门岗%'); - }); + })->get(); return $this->success($admin); } @@ -63,7 +63,7 @@ class GateController extends CommonController public function visitList() { $all = request()->all(); - $list = Visit::with('visitTime')->where(function ($query) use ($all) { + $list = Visit::with('visitTime', 'admin', 'visitArea', 'acceptAdmin.department', 'acceptAdminSignFile', 'acceptGoodsAdmin.department')->where(function ($query) use ($all) { if (isset($all['keyword'])) { $query->where('name', 'like', '%' . $all['keyword'] . '%'); } @@ -108,6 +108,10 @@ class GateController extends CommonController if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); } + $check = Visit::where('code', $all['code'])->first(); + if (empty($check)) { + return $this->fail([ResponseCode::ERROR_BUSINESS, '拜访记录不存在']); + } $remark = '进厂'; if ($all['type'] == 2) { $remark = '离厂'; diff --git a/app/Http/Controllers/Admin/VisitAuditController.php b/app/Http/Controllers/Admin/VisitAuditController.php index 82d5b25..6a4ded0 100644 --- a/app/Http/Controllers/Admin/VisitAuditController.php +++ b/app/Http/Controllers/Admin/VisitAuditController.php @@ -113,10 +113,10 @@ class VisitAuditController extends CommonController { $all = \request()->all(); $messages = [ - 'name.required' => '名称必填' + 'visit_id.required' => '参观id必填' ]; $validator = Validator::make($all, [ - 'name' => 'required' + 'visit_id' => 'required' ], $messages); if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); diff --git a/app/Http/Controllers/Admin/VisitController.php b/app/Http/Controllers/Admin/VisitController.php index f24d668..46f6f33 100644 --- a/app/Http/Controllers/Admin/VisitController.php +++ b/app/Http/Controllers/Admin/VisitController.php @@ -29,6 +29,9 @@ class VisitController extends CommonController * @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="is_export", in="query", @OA\Schema(type="string"), required=false, description="是否导出0否1是,默认0"), + * @OA\Parameter(name="my_self", in="query", @OA\Schema(type="string"), required=false, description="是否显示自己创建的0否1是,默认0"), + * @OA\Parameter(name="my_audit", in="query", @OA\Schema(type="string"), required=false, description="是否显示我审核的记录0否1是,默认0"), + * @OA\Parameter(name="my_accept_admin", in="query", @OA\Schema(type="string"), required=false, description="是否显示接待人员是自己的0否1是,默认0"), * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Response( * response="200", @@ -39,7 +42,7 @@ class VisitController extends CommonController public function index() { $all = request()->all(); - $list = Visit::with('visitTime', 'admin')->where(function ($query) use ($all) { + $list = Visit::with('visitTime', 'admin', 'visitArea', 'acceptAdmin.department', 'acceptAdminSignFile', 'acceptGoodsAdmin.department','audit.auditAdmin')->where(function ($query) use ($all) { if (isset($all['keyword'])) { $query->where('name', 'like', '%' . $all['keyword'] . '%'); } @@ -49,6 +52,17 @@ class VisitController extends CommonController if (isset($all['start_date']) && isset($all['end_date'])) { $query->whereBetween('date', [$all['start_date'], $all['end_date']]); } + if (isset($all['my_self']) && !empty($all['my_self'])) { + $query->where('admin_id', $this->getUserId()); + } + if (isset($all['my_accept_admin']) && !empty($all['my_accept_admin'])) { + $query->where('accept_admin_id', $this->getUserId()); + } + if (isset($all['my_audit']) && !empty($all['my_audit'])) { + $query->whereHas('audit', function ($q) { + $q->where('audit_admin_id', $this->getUserId()); + }); + } })->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc'); if (isset($all['is_export']) && !empty($all['is_export'])) { return (new FastExcel($list->limit(5000)->get()->toArray()))->download('访问记录' . date('YmdHis') . '.csv', function ($info) { @@ -100,7 +114,7 @@ class VisitController extends CommonController if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); } - $detail = Visit::find($all['id']); + $detail = Visit::with('audit.auditAdmin', 'visitTime', 'acceptAdmin.department', 'acceptAdminSignFile', 'acceptGoodsAdmin.department', 'visitArea','audit.auditAdmin')->find($all['id']); return $this->success($detail); } diff --git a/app/Http/Controllers/Mobile/UserController.php b/app/Http/Controllers/Mobile/UserController.php index 127d052..8d06daa 100644 --- a/app/Http/Controllers/Mobile/UserController.php +++ b/app/Http/Controllers/Mobile/UserController.php @@ -161,7 +161,7 @@ class UserController extends CommonController public function myVisit() { $all = request()->all(); - $list = Visit::where('user_id', $this->getUserId()) + $list = Visit::with('visitTime', 'admin', 'visitArea', 'acceptAdmin.department', 'acceptAdminSignFile', 'acceptGoodsAdmin.department')->where('user_id', $this->getUserId()) ->where(function ($query) use ($all) { if (isset($all['type'])) { $query->where('type', $all['type']); @@ -197,7 +197,7 @@ class UserController extends CommonController if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); } - $detail = Visit::with('visitTime')->find($all['id']); + $detail = Visit::with('visitTime', 'admin', 'visitArea', 'acceptAdmin.department', 'acceptAdminSignFile', 'acceptGoodsAdmin.department')->find($all['id']); return $this->success($detail); } diff --git a/app/Http/Controllers/Mobile/VisitController.php b/app/Http/Controllers/Mobile/VisitController.php index 7244627..ad4b95d 100644 --- a/app/Http/Controllers/Mobile/VisitController.php +++ b/app/Http/Controllers/Mobile/VisitController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers\Mobile; use App\Helpers\ResponseCode; +use App\Models\Admin; +use App\Models\Department; use App\Models\Study; use App\Models\Visit; use App\Models\VisitArea; @@ -57,11 +59,13 @@ class VisitController extends CommonController $all = \request()->all(); $messages = [ 'name.required' => '名称必填', - 'visit_area_id.required' => '区域id必填' + 'visit_area_id.required' => '区域id必填', + 'accept_admin_id.required' => '接待人必填' ]; $validator = Validator::make($all, [ 'name' => 'required', - 'visit_area_id' => 'required' + 'visit_area_id' => 'required', + 'accept_admin_id' => 'required' ], $messages); if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); @@ -82,11 +86,23 @@ class VisitController extends CommonController if ($area->audit_admin && !isset($all['id'])) { $audit_admin = collect($area->audit_admin)->sortBy('level'); foreach ($audit_admin as $item) { + if (empty($item['admin_id'])) { + // 上级审核 + $admin = Admin::find($all['accept_admin_id']); + if (empty($admin->department_id)) { + return $this->fail([ResponseCode::ERROR_BUSINESS, '接待人部门不存在']); + } + $department = Department::find($admin->department_id); + if (empty($department->manager_id)) { + return $this->fail([ResponseCode::ERROR_BUSINESS, '接待人部门不存在负责人']); + } + $item['admin_id'] = $department->manager_id; + } VisitAudit::create([ 'visit_id' => $model->id, - 'audit_admin_id' => $item->admin_id, + 'audit_admin_id' => $item['admin_id'], 'status' => 0, - 'level' => $item->level + 'level' => $item['level'] ]); } } diff --git a/app/Models/User.php b/app/Models/User.php index 8996368..7169db3 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -12,33 +12,6 @@ class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; - /** - * The attributes that are mass assignable. - * - * @var array - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; + protected $guarded = ['id']; - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * The attributes that should be cast. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', - ]; } diff --git a/app/Models/Visit.php b/app/Models/Visit.php index 3a8859c..2ccb755 100644 --- a/app/Models/Visit.php +++ b/app/Models/Visit.php @@ -30,8 +30,8 @@ class Visit extends SoftDeletesModel public function getAuditStatusTextAttribute() { - $array = [-1 => '待学习', 0 => '待审核', 1 => '通过', 2 => '驳回', 3 => '已进厂', 4 => '已离厂']; - return $array[$this->type] ?? ''; + $array = ['-1' => '待学习', '0' => '待审核', '1' => '通过', '2' => '驳回', '3' => '已进厂', '4' => '已离厂','5'=>'已取消']; + return $array[$this->audit_status] ?? ''; } public function visitTime() @@ -44,4 +44,27 @@ class Visit extends SoftDeletesModel return $this->hasOne(Admin::class, 'id', 'admin_id'); } + public function acceptAdmin() + { + return $this->hasOne(Admin::class, 'id', 'accept_admin_id'); + } + + public function acceptGoodsAdmin() + { + return $this->hasOne(Admin::class, 'id', 'accept_goods_admin_id'); + } + + public function acceptAdminSignFile() + { + return $this->hasOne(Upload::class, 'id', 'accept_admin_sign'); + } + + public function visitArea(){ + return $this->hasOne(VisitArea::class,'id','visit_area_id'); + } + + public function audit(){ + return $this->hasMany(VisitAudit::class,'visit_id','id'); + } + } diff --git a/app/Models/VisitAudit.php b/app/Models/VisitAudit.php index 725698f..bd4890d 100644 --- a/app/Models/VisitAudit.php +++ b/app/Models/VisitAudit.php @@ -9,4 +9,9 @@ class VisitAudit extends SoftDeletesModel return $this->hasOne(Visit::class,'id','visit_id'); } + public function auditAdmin() + { + return $this->hasOne(Admin::class, 'id', 'audit_admin_id'); + } + } diff --git a/config/app.php b/config/app.php index 06c1ce7..296bcbe 100644 --- a/config/app.php +++ b/config/app.php @@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Facade; return [ - 'wechat_appid' => '', - 'wechat_appsecret' => '', + 'wechat_appid' => 'wx35190cc07e73eda1', + 'wechat_appsecret' => 'aa7c4f7f055c2c95fadd52cab04fb800', /* |-------------------------------------------------------------------------- | Application Name diff --git a/database/migrations/2022_05_09_133612_alert_users_table.php b/database/migrations/2022_05_09_133612_alert_users_table.php new file mode 100644 index 0000000..c1fb031 --- /dev/null +++ b/database/migrations/2022_05_09_133612_alert_users_table.php @@ -0,0 +1,54 @@ +dropColumn('name'); + $table->dropColumn('email'); + $table->dropColumn('email_verified_at'); + $table->dropColumn('password'); + $table->string('openid', 200)->nullable()->default(''); + $table->string('sex', 20)->nullable()->default('未知')->comment('性别 未知 男 女'); + $table->string('nickname', 191)->nullable(); + $table->string('mobile', 100)->nullable()->default('')->comment('手机号'); + $table->string('country', 100)->nullable()->default(''); + $table->string('province', 100)->nullable()->default(''); + $table->string('city', 200)->nullable()->default(''); + $table->string('headimgurl')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->string('name'); + $table->string('email')->unique(); + $table->timestamp('email_verified_at')->nullable(); + $table->string('password'); + $table->dropColumn('openid'); + $table->dropColumn('sex'); + $table->dropColumn('nickname'); + $table->dropColumn('mobile'); + $table->dropColumn('country'); + $table->dropColumn('province'); + $table->dropColumn('city'); + $table->dropColumn('headimgurl'); + }); + } +}; diff --git a/database/migrations/2023_03_08_104541_create_visit_audits_table.php b/database/migrations/2023_03_08_104541_create_visit_audits_table.php index a7b6131..6d917f9 100644 --- a/database/migrations/2023_03_08_104541_create_visit_audits_table.php +++ b/database/migrations/2023_03_08_104541_create_visit_audits_table.php @@ -17,7 +17,7 @@ class CreateVisitAuditsTable extends Migration $table->increments('id'); $table->integer('admin_id')->comment('不用填')->nullable(); $table->integer('department_id')->comment('不用填')->nullable(); - $table->date('visit_id')->comment('参观id'); + $table->integer('visit_id')->comment('参观id'); $table->integer('audit_admin_id')->comment('审核人员id'); $table->integer('status')->comment('状态0待审核1通过2驳回')->nullable(); $table->string('reason')->comment('原因')->nullable(); diff --git a/routes/api.php b/routes/api.php index 1000ad7..ca61677 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,6 +26,12 @@ Route::get("admin/gate/use-code", [\App\Http\Controllers\Admin\GateController::c // 后台 Route::group(["namespace" => "Admin", "prefix" => "admin", "middleware" => "sanctum.jwt:admin,rbac"], function () { + // 统计 + Route::get("chart/month", [\App\Http\Controllers\Admin\ChartController::class, "month"]); + Route::get("chart/time", [\App\Http\Controllers\Admin\ChartController::class, "time"]); + Route::get("chart/car", [\App\Http\Controllers\Admin\ChartController::class, "car"]); + + // 配置管理 Route::get("config/index", [\App\Http\Controllers\Admin\ConfigController::class, "index"]); Route::get("config/show", [\App\Http\Controllers\Admin\ConfigController::class, "show"]); @@ -76,8 +82,8 @@ Route::group(["namespace" => "Admin", "prefix" => "admin", "middleware" => "sanc }); // 前台 -Route::group(["namespace" => "Mobile", "prefix" => "mobile"], function () { - Route::get('user/login', [\App\Http\Controllers\Mobile\UserController::class, 'login']); +Route::get('mobile/user/login', [\App\Http\Controllers\Mobile\UserController::class, 'login']); +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']); Route::get('user/show', [\App\Http\Controllers\Mobile\UserController::class, 'show']);