diff --git a/app/Console/Commands/ResetLongTermVisitsCommand.php b/app/Console/Commands/ResetLongTermVisitsCommand.php index 9d08c3e..a481c72 100644 --- a/app/Console/Commands/ResetLongTermVisitsCommand.php +++ b/app/Console/Commands/ResetLongTermVisitsCommand.php @@ -52,10 +52,17 @@ class ResetLongTermVisitsCommand extends Command foreach ($longTermVisits as $visit) { // 重置审核状态为已通过(1) $visit->audit_status = 1; + $visit->person_no = null; + // 数组follw_people中的follw_people数据置空置 + $list = []; + foreach ($visit->follw_people as $follwPerson) { + unset($follwPerson['follw_people_person_no']); + $list[] = $follwPerson; + } + $visit->follw_people = $list; $visit->save(); - // 记录重置日志 - // VisitLog::log($visit->id, VisitLog::TYPE_UPDATE, "系统自动重置:长期拜访预约审核状态已重置为待审核"); + // VisitLog::log($visit->id, VisitLog::TYPE_UPDATE, "系统自动重置:长期拜访预约审核状态已重置为待审核"); $resetCount++; $this->info("已重置访客:{$visit->name}({$visit->code})"); diff --git a/app/Http/Controllers/Admin/ChartController.php b/app/Http/Controllers/Admin/ChartController.php index 65d9a82..8fc7861 100644 --- a/app/Http/Controllers/Admin/ChartController.php +++ b/app/Http/Controllers/Admin/ChartController.php @@ -36,49 +36,53 @@ class ChartController extends CommonController $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; - }; - + $today = date('Y-m-d'); $list = [ 'common_visit' => [ - '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(), - // 离厂统计 - 'leave_total' => $buildQuery(1)->where('audit_status', Visit::AUDIT_STATUS_LEFT)->count(), + // 总预约数 + 'total' => Visit::visitQuery(1, $startDate, $endDate, [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT])->count(), + // 总入场人数 + 'enter_visit' => Visit::visitHome(1, $startDate, $endDate, [Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]), + // 离厂统计人数 + 'leave_total' => Visit::visitHome(1, $startDate, $endDate, [Visit::AUDIT_STATUS_LEFT]), + + // 今日总人数 + 'today_total' => Visit::visitQuery(1, $today, $today, [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT])->count(), + // 今日入场人数 + 'today_enter_visit' => Visit::visitHome(1, $today, $today, [Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]), // 今日离厂 - 'today_leave_total' => Visit::where('type', 1)->where('date', date('Y-m-d'))->where('audit_status', Visit::AUDIT_STATUS_LEFT)->count(), + 'today_leave_total' => Visit::visitHome(1, $today, $today, [Visit::AUDIT_STATUS_LEFT]), + ], 'work_visit' => [ - '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(), + // 总人数 + 'total' => Visit::visitQuery(2, $startDate, $endDate, [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT])->count(), + // 总入场人数 + 'enter_visit' => Visit::visitHome(2, $startDate, $endDate, [Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]), // 离厂统计 - 'leave_total' => $buildQuery(2)->where('audit_status', Visit::AUDIT_STATUS_LEFT)->count(), + 'leave_total' => Visit::visitHome(2, $startDate, $endDate, [Visit::AUDIT_STATUS_LEFT]), + + // 今日总人数 + 'today_total' => Visit::visitQuery(2, $today, $today, [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT])->count(), + // 今日入场人数 + 'today_enter_visit' => Visit::visitHome(2, $today, $today, [Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]), // 今日离厂 - 'today_leave_total' => Visit::where('type', 2)->where('date', date('Y-m-d'))->where('audit_status', Visit::AUDIT_STATUS_LEFT)->count(), + 'today_leave_total' => Visit::visitHome(2, $today, $today, [Visit::AUDIT_STATUS_LEFT]), ], 'car_visit' => [ - '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(), + // 总人数 + 'total' => Visit::visitQuery(3, $startDate, $endDate, [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT])->count(), + // 总入场人数 + 'enter_visit' => Visit::visitHome(3, $startDate, $endDate, [Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]), // 离厂统计 - 'leave_total' => $buildQuery(3)->where('audit_status', Visit::AUDIT_STATUS_LEFT)->count(), + 'leave_total' => Visit::visitHome(3, $startDate, $endDate, [Visit::AUDIT_STATUS_LEFT]), + + // 今日总人数 + 'today_total' => Visit::visitQuery(3, $today, $today, [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT])->count(), + // 今日入场人数 + 'today_enter_visit' => Visit::visitHome(3, $today, $today, [Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]), // 今日离厂 - 'today_leave_total' => Visit::where('type', 3)->where('date', date('Y-m-d'))->where('audit_status', Visit::AUDIT_STATUS_LEFT)->count(), + 'today_leave_total' => Visit::visitHome(3, $today, $today, [Visit::AUDIT_STATUS_LEFT]), ], ]; diff --git a/app/Http/Controllers/Admin/GateController.php b/app/Http/Controllers/Admin/GateController.php index d627791..f88cda2 100644 --- a/app/Http/Controllers/Admin/GateController.php +++ b/app/Http/Controllers/Admin/GateController.php @@ -83,8 +83,11 @@ class GateController extends CommonController if (isset($all['idcard'])) { $query->where('idcard', $all['idcard']); } - if (isset($all['start_date']) && isset($all['end_date'])) { - $query->whereBetween('date', [$all['start_date'], $all['end_date']]); + if (isset($all['start_date'])) { + $query->where('date', '>=', $all['start_date']); + } + if (isset($all['end_date'])) { + $query->where('date', '<=', $all['end_date']); } })->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')->paginate($all['page_size'] ?? 20);; return $this->success($list); @@ -125,7 +128,7 @@ class GateController extends CommonController $query->where('person_no', "{$all['code']}") ->orWhere('idcard', "{$all['code']}") ->orWhere('code', "{$all['code']}"); - })->first(); + })->first(); if (empty($check)) { return $this->fail([ResponseCode::ERROR_BUSINESS, '拜访记录不存在']); } diff --git a/app/Http/Controllers/Admin/VisitAuditController.php b/app/Http/Controllers/Admin/VisitAuditController.php index 2676d77..6c17ab4 100644 --- a/app/Http/Controllers/Admin/VisitAuditController.php +++ b/app/Http/Controllers/Admin/VisitAuditController.php @@ -164,16 +164,17 @@ class VisitAuditController extends CommonController $auditResult = '通过'; Visit::where('id', $all['visit_id'])->update(['audit_status' => 1]); // 发邮件通知接待人审核通过 - if (!empty($acceptAdmin->email)) { - $visitData = [ - 'date' => $visit->date, - 'name' => $visit->name, - 'visitor_name' => $visit->name, - 'accept_admin_name' => $acceptAdmin->name, - 'company_name' => $visit->company_name ?? '' - ]; - $acceptAdmin->notify(new AuditResultEmailNotify($visitData, '通过')); - } + // todo::这里改成拜访人发短信通知 +// if (!empty($acceptAdmin->email)) { +// $visitData = [ +// 'date' => $visit->date, +// 'name' => $visit->name, +// 'visitor_name' => $visit->name, +// 'accept_admin_name' => $acceptAdmin->name, +// 'company_name' => $visit->company_name ?? '' +// ]; +// $acceptAdmin->notify(new AuditResultEmailNotify($visitData, '通过')); +// } } if ($auditResult) { // 发通知订阅消息 diff --git a/app/Http/Controllers/Admin/VisitController.php b/app/Http/Controllers/Admin/VisitController.php index a98806f..b80c4ae 100644 --- a/app/Http/Controllers/Admin/VisitController.php +++ b/app/Http/Controllers/Admin/VisitController.php @@ -54,8 +54,14 @@ class VisitController extends CommonController if (isset($all['audit_status'])) { $query->where('audit_status', $all['audit_status']); } - if (isset($all['start_date']) && isset($all['end_date'])) { - $query->whereBetween('date', [$all['start_date'], $all['end_date']]); + if (isset($all['type'])) { + $query->where('type', $all['type']); + } + if (isset($all['start_date'])) { + $query->where('date', '>=', $all['start_date']); + } + if (isset($all['end_date'])) { + $query->where('date', '<=', $all['end_date']); } if (isset($all['my_self']) && !empty($all['my_self'])) { $query->where('admin_id', $this->getUserId()); @@ -72,7 +78,7 @@ class VisitController extends CommonController }); } // 权限设置 - if ($is_auth) { + if ($is_auth && $this->getUser()->id != 1) { $user = $this->getUser(); $adminIds = Admin::roleAllowAdminIds($user, $departmentIds); $query->where(function ($qry) use ($adminIds, $departmentIds, $user) { diff --git a/app/Http/Controllers/Mobile/VisitController.php b/app/Http/Controllers/Mobile/VisitController.php index 1437545..b3d4dd0 100644 --- a/app/Http/Controllers/Mobile/VisitController.php +++ b/app/Http/Controllers/Mobile/VisitController.php @@ -82,65 +82,63 @@ class VisitController extends CommonController try { if (isset($all['id'])) { $model = Visit::find($all['id']); + $model->fill($all); + $model->save(); + VisitLog::add('', $this->getUser(), $model->id, isset($all['id']) ? '更新拜访记录' : '新增拜访记录'); + DB::commit(); + // 当状态为取消(status=5)时,给被访人发送取消邮件 + if (isset($all['audit_status']) && $all['audit_status'] == Visit::AUDIT_STATUS_CANCELLED) { + VisitAudit::emailCancelNotify($model); + } } else { + // 新增拜访 $model = new Visit(); $all['user_id'] = $this->getUserId(); $all['code'] = randStr(6, true); - } - $model->fill($all); - $model->save(); - // 创建时候审核流程写入 - // 被访问做第一级审核 - VisitAudit::create([ - 'visit_id' => $model->id, - 'audit_admin_id' => $all['accompany_id'], - 'status' => 0, - 'level' => 0 - ]); - $area = VisitArea::find($all['visit_area_id']); - if ($area->audit_admin && !isset($all['id'])) { - // 其他按设置审核 - $audit_admin = collect($area->audit_admin)->sortBy('level'); - foreach ($audit_admin as $key => $item) { - if (empty($item['admin_id'])) { - // 上级审核 - $admin = Admin::find($all['accept_admin_id']); - if (empty($admin->department_id)) { - return $this->fail([ResponseCode::ERROR_BUSINESS, '接待人部门不存在']); + $model->fill($all); + $model->save(); + // 创建时候审核流程写入 + // 被访问做第一级审核 + VisitAudit::create([ + 'visit_id' => $model->id, + 'audit_admin_id' => $all['accompany_id'], + 'status' => 0, + 'level' => 0 + ]); + $area = VisitArea::find($all['visit_area_id']); + if ($area->audit_admin && !isset($all['id'])) { + // 其他按设置审核,level从0开始的审核人 + $audit_admin = collect($area->audit_admin)->sortBy('level'); + foreach ($audit_admin as $key => $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; } - $department = Department::find($admin->department_id); - if (empty($department->manager_id)) { - return $this->fail([ResponseCode::ERROR_BUSINESS, '接待人部门不存在负责人']); + // 判断不能重复 + if ($item['admin_id'] == $all['accept_admin_id']) { + continue; } - $item['admin_id'] = $department->manager_id; + VisitAudit::create([ + 'visit_id' => $model->id, + 'audit_admin_id' => $item['admin_id'], + 'status' => 0, + 'level' => $item['level'] + 1 + ]); } - // 判断不能重复 - if ($item['admin_id'] == $all['accept_admin_id']) { - continue; - } - VisitAudit::create([ - 'visit_id' => $model->id, - 'audit_admin_id' => $item['admin_id'], - 'status' => 0, - 'level' => $item['level'] + 1 - ]); } + VisitLog::add('', $this->getUser(), $model->id, isset($all['id']) ? '更新拜访记录' : '新增拜访记录'); + DB::commit(); + // 邮件通知第一个审核人 + VisitAudit::emailNextAudit($model, -1); } - VisitLog::add('', $this->getUser(), $model->id, isset($all['id']) ? '更新拜访记录' : '新增拜访记录'); - - // 被访人信息 - $acceptAdmin = Admin::find($all['accept_admin_id']); - // 邮件通知被访人 - $visitData = [ - 'date' => $all['date'], - 'name' => $all['name'], - 'mobile' => $all['mobile'], - 'reason' => $all['reason'] ?? '' - ]; - $acceptAdmin->notify(new VisitEmailNotify($visitData)); - // 邮件通知第一个审核人 - VisitAudit::emailNextAudit($model, -1); - DB::commit(); return $this->success('更新成功'); } catch (\Exception $exception) { DB::rollBack(); diff --git a/app/Models/Visit.php b/app/Models/Visit.php index 48c2be2..9fc2822 100644 --- a/app/Models/Visit.php +++ b/app/Models/Visit.php @@ -32,7 +32,7 @@ class Visit extends SoftDeletesModel protected $guarded = ['id']; - protected $appends = ['type_text', 'audit_status_text', 'file_detail', 'vehicle_images_detail']; + protected $appends = ['type_text', 'audit_status_text', 'file_detail', 'vehicle_images_detail', 'follw_people_total']; protected $casts = [ 'follw_people' => 'json', @@ -51,6 +51,14 @@ class Visit extends SoftDeletesModel return Upload::whereIn('id', $this->file)->get(); } + /** + * 获取随访人数 + */ + public function getFollwPeopleTotalAttribute() + { + return $this->follw_people ? count($this->follw_people) : 0; + } + public function getVehicleImagesDetailAttribute() { if (empty($this->vehicle_images)) { @@ -138,4 +146,38 @@ class Visit extends SoftDeletesModel return $app->subscribe_message->send($data); } + /** + * 首页统计 + */ + public static function visitHome($type, $startDate, $endDate, $auditStatus) + { + $visit = self::visitQuery($type, $startDate, $endDate, $auditStatus); + $visitTotal = $visit->count(); + $follwPeopleTotal = $visit->sum('follw_people_total'); + return $visitTotal + $follwPeopleTotal; + } + + /** + * 首页统计 + */ + public static function visitQuery($type, $startDate, $endDate, $auditStatus) + { + $visit = Visit::where(function ($query) use ($type, $startDate, $endDate, $auditStatus) { + if ($type) { + $query->where('type', $type); + } + if ($auditStatus) { + $query->whereIn('audit_status', $auditStatus); + } + if ($startDate) { + $query->where('date', '>=', $startDate); + } + if ($endDate) { + $query->where('date', '<=', $endDate); + } + })->get(); + return $visit; + } + + } diff --git a/app/Models/VisitAudit.php b/app/Models/VisitAudit.php index b00e1a7..371bb45 100644 --- a/app/Models/VisitAudit.php +++ b/app/Models/VisitAudit.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Notifications\AuditEmailNotify; +use App\Notifications\CancelEmailNotify; class VisitAudit extends SoftDeletesModel { @@ -19,7 +20,7 @@ class VisitAudit extends SoftDeletesModel } /** - * 邮件通知下一个审核人 + * 邮件通知下一个审核人审核 */ public static function emailNextAudit($visit, $nowVisitAuditLevel = -1) { @@ -71,4 +72,36 @@ class VisitAudit extends SoftDeletesModel return true; } + /** + * 邮件通知被访人拜访已取消 + */ + public static function emailCancelNotify($visit) + { + // 获取被访人(第一个审核人,level最小的) + $admin = Admin::where('id', function ($query) use ($visit) { + $query->select('audit_admin_id') + ->from('visit_audits') + ->where('visit_id', $visit->id) + ->orderBy('level', 'asc') + ->limit(1); + })->first(); + + if (empty($admin)) { + return false; + } + + // 准备邮件数据 + $visitData = [ + 'date' => $visit->date, + 'name' => $visit->name, + 'mobile' => $visit->mobile, + 'reason' => $visit->reason ?? '' + ]; + + // 发送取消邮件通知 + $admin->notify(new CancelEmailNotify($visitData)); + + return true; + } + } diff --git a/app/Notifications/CancelEmailNotify.php b/app/Notifications/CancelEmailNotify.php new file mode 100644 index 0000000..03cb2b2 --- /dev/null +++ b/app/Notifications/CancelEmailNotify.php @@ -0,0 +1,56 @@ +visitData = $visitData; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $visitData = $this->visitData; + + return (new MailMessage) + ->subject('拜访预约取消通知 - ' . $visitData['name']) + ->greeting('您好 ' . $notifiable->name . ',') + ->line('访客 ' . $visitData['name'] . ' 原预约于 ' . $visitData['date'] . ' 的拜访已取消。') + ->line('访客联系电话:' . $visitData['mobile']) + ->line('拜访事由:' . ($visitData['reason'] ?? '无')) + ->line('如有疑问,请联系访客确认。'); + } +} + diff --git a/database/migrations/2025_11_26_104139_alert_visits_table.php b/database/migrations/2025_11_26_104139_alert_visits_table.php new file mode 100644 index 0000000..031d2d5 --- /dev/null +++ b/database/migrations/2025_11_26_104139_alert_visits_table.php @@ -0,0 +1,32 @@ +time('time')->nullable()->comment('拜访时间'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('visits', function (Blueprint $table) { + // + }); + } +};