|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Models\Admin;
|
|
|
|
|
|
use App\Models\Visit;
|
|
|
|
|
|
use App\Models\VisitLog;
|
|
|
|
|
|
use App\Models\GateLog;
|
|
|
|
|
|
use App\Models\Upload;
|
|
|
|
|
|
use App\Helpers\ApiResponse;
|
|
|
|
|
|
use App\Helpers\ResponseCode;
|
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
use Carbon\Carbon;
|
|
|
|
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @OA\Tag(
|
|
|
|
|
|
* name="门岗端接口",
|
|
|
|
|
|
* description="门岗端相关接口,无需鉴权"
|
|
|
|
|
|
* )
|
|
|
|
|
|
*/
|
|
|
|
|
|
class GateController extends Controller
|
|
|
|
|
|
{
|
|
|
|
|
|
use ApiResponse;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @OA\Get(
|
|
|
|
|
|
* path="/api/admin/gate/user-list",
|
|
|
|
|
|
* tags={"门岗端接口"},
|
|
|
|
|
|
* summary="门岗用户列表",
|
|
|
|
|
|
* description="",
|
|
|
|
|
|
* @OA\Response(
|
|
|
|
|
|
* response="200",
|
|
|
|
|
|
* description="暂无"
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function uerList()
|
|
|
|
|
|
{
|
|
|
|
|
|
$admin = Admin::whereHas('role', function ($query) {
|
|
|
|
|
|
$query->where('name', 'like', '%门岗%');
|
|
|
|
|
|
})->get();
|
|
|
|
|
|
return $this->success($admin);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @OA\Get(
|
|
|
|
|
|
* path="/api/gate/visits",
|
|
|
|
|
|
* tags={"门岗端接口"},
|
|
|
|
|
|
* summary="拜访信息列表",
|
|
|
|
|
|
* description="获取门岗端拜访信息列表",
|
|
|
|
|
|
* @OA\Parameter(name="date", in="query", @OA\Schema(type="string"), required=false, description="查询日期,格式:Y-m-d,默认今天"),
|
|
|
|
|
|
* @OA\Parameter(name="status", in="query", @OA\Schema(type="string"), required=false, description="状态筛选:1通过(待进厂)3已进厂4已离厂"),
|
|
|
|
|
|
* @OA\Parameter(name="type", in="query", @OA\Schema(type="string"), required=false, description="类型筛选:1访客2访客车辆3物流车辆"),
|
|
|
|
|
|
* @OA\Parameter(name="keyword", in="query", @OA\Schema(type="string"), required=false, description="关键词搜索(人牌,身份证,核销码)"),
|
|
|
|
|
|
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer"), required=false, description="页码,默认1"),
|
|
|
|
|
|
* @OA\Parameter(name="page_size", in="query", @OA\Schema(type="integer"), required=false, description="每页数量,默认20"),
|
|
|
|
|
|
* @OA\Response(
|
|
|
|
|
|
* response="200",
|
|
|
|
|
|
* description="成功获取拜访信息列表",
|
|
|
|
|
|
* @OA\JsonContent(
|
|
|
|
|
|
* @OA\Property(property="code", type="integer", example=200),
|
|
|
|
|
|
* @OA\Property(property="message", type="string", example="success"),
|
|
|
|
|
|
* @OA\Property(property="data", type="object",
|
|
|
|
|
|
* @OA\Property(property="current_page", type="integer"),
|
|
|
|
|
|
* @OA\Property(property="data", type="array", @OA\Items(type="object")),
|
|
|
|
|
|
* @OA\Property(property="total", type="integer")
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function visits(Request $request)
|
|
|
|
|
|
{
|
|
|
|
|
|
try {
|
|
|
|
|
|
$date = $request->input('date', Carbon::today()->format('Y-m-d'));
|
|
|
|
|
|
$status = $request->input('status');
|
|
|
|
|
|
$type = $request->input('type');
|
|
|
|
|
|
$keyword = $request->input('keyword');
|
|
|
|
|
|
$page = $request->input('page', 1);
|
|
|
|
|
|
$pageSize = $request->input('page_size', 20);
|
|
|
|
|
|
|
|
|
|
|
|
$query = Visit::with([
|
|
|
|
|
|
'visitArea',
|
|
|
|
|
|
'visitTime',
|
|
|
|
|
|
'acceptDepartment',
|
|
|
|
|
|
'acceptAdmin',
|
|
|
|
|
|
'visitAudits',
|
|
|
|
|
|
'acceptAdminSign'
|
|
|
|
|
|
])->whereDate('date', $date);
|
|
|
|
|
|
|
|
|
|
|
|
// 状态筛选
|
|
|
|
|
|
if ($status) {
|
|
|
|
|
|
$query->where('audit_status', $status);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 默认显示待进厂和已进厂的记录
|
|
|
|
|
|
$query->whereIn('audit_status', [Visit::AUDIT_STATUS_APPROVED, Visit::AUDIT_STATUS_ENTERED, Visit::AUDIT_STATUS_LEFT]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 类型筛选
|
|
|
|
|
|
if ($type) {
|
|
|
|
|
|
$query->where('type', $type);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 关键词搜索
|
|
|
|
|
|
if ($keyword) {
|
|
|
|
|
|
$query->where(function ($q) use ($keyword) {
|
|
|
|
|
|
$q->where('person_no', "{$keyword}")
|
|
|
|
|
|
->orWhere('idcard', "{$keyword}")
|
|
|
|
|
|
->orWhere('code', "{$keyword}");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visits = $query->orderBy('created_at', 'desc')
|
|
|
|
|
|
->paginate($pageSize, ['*'], 'page', $page);
|
|
|
|
|
|
|
|
|
|
|
|
return $this->success($visits);
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
Log::error('门岗端获取拜访列表失败:' . $e->getMessage());
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_INSIDE, __('gate.get_visit_list_failed')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @OA\Post(
|
|
|
|
|
|
* path="/api/gate/visits/detail",
|
|
|
|
|
|
* tags={"门岗端接口"},
|
|
|
|
|
|
* summary="拜访详情信息",
|
|
|
|
|
|
* description="获取指定拜访的详细信息",
|
|
|
|
|
|
* @OA\RequestBody(
|
|
|
|
|
|
* required=true,
|
|
|
|
|
|
* @OA\JsonContent(
|
|
|
|
|
|
* @OA\Property(property="id", type="integer", description="拜访ID")
|
|
|
|
|
|
* )
|
|
|
|
|
|
* ),
|
|
|
|
|
|
* @OA\Response(
|
|
|
|
|
|
* response="200",
|
|
|
|
|
|
* description="成功获取拜访详情",
|
|
|
|
|
|
* @OA\JsonContent(
|
|
|
|
|
|
* @OA\Property(property="code", type="integer", example=200),
|
|
|
|
|
|
* @OA\Property(property="message", type="string", example="success"),
|
|
|
|
|
|
* @OA\Property(property="data", type="object")
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function visitDetail(Request $request)
|
|
|
|
|
|
{
|
|
|
|
|
|
try {
|
|
|
|
|
|
$id = $request->input('id');
|
|
|
|
|
|
|
|
|
|
|
|
if (!$id) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, __('gate.visit_id_required')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visit = Visit::with([
|
|
|
|
|
|
'visitArea',
|
|
|
|
|
|
'visitTime',
|
|
|
|
|
|
'acceptDepartment',
|
|
|
|
|
|
'acceptAdmin',
|
|
|
|
|
|
'acceptGoodsAdmin',
|
|
|
|
|
|
'accompany',
|
|
|
|
|
|
'visitAudits',
|
|
|
|
|
|
'logs',
|
|
|
|
|
|
'acceptAdminSign'
|
|
|
|
|
|
])->find($id);
|
|
|
|
|
|
|
|
|
|
|
|
if (!$visit) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.visit_not_found')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $this->success($visit);
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
Log::error('门岗端获取拜访详情失败:' . $e->getMessage());
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_INSIDE, __('gate.get_visit_detail_failed')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @OA\Post(
|
|
|
|
|
|
* path="/api/gate/visits/update",
|
|
|
|
|
|
* tags={"门岗端接口"},
|
|
|
|
|
|
* summary="更新拜访信息",
|
|
|
|
|
|
* description="门岗端更新拜访信息(绑定ID卡、修改状态、上传货车图片等)",
|
|
|
|
|
|
* @OA\RequestBody(
|
|
|
|
|
|
* required=true,
|
|
|
|
|
|
* @OA\JsonContent(
|
|
|
|
|
|
* @OA\Property(property="id", type="integer", description="拜访ID"),
|
|
|
|
|
|
* @OA\Property(property="action", type="string", description="操作类型:bind_card绑定ID卡,enter进厂,leave离厂,upload_vehicle上传货车图片"),
|
|
|
|
|
|
* @OA\Property(property="person_no", type="string", description="人牌号(绑定ID卡时必填)"),
|
|
|
|
|
|
* @OA\Property(property="car_no", type="string", description="停车牌号(绑定ID卡时必填)"),
|
|
|
|
|
|
* @OA\Property(property="vehicle_images", type="array", description="货车图片ID数组(上传货车图片时必填)", @OA\Items(type="integer")),
|
|
|
|
|
|
* @OA\Property(property="remark", type="string", description="备注信息")
|
|
|
|
|
|
* )
|
|
|
|
|
|
* ),
|
|
|
|
|
|
* @OA\Response(
|
|
|
|
|
|
* response="200",
|
|
|
|
|
|
* description="更新成功",
|
|
|
|
|
|
* @OA\JsonContent(
|
|
|
|
|
|
* @OA\Property(property="code", type="integer", example=200),
|
|
|
|
|
|
* @OA\Property(property="message", type="string", example="操作成功"),
|
|
|
|
|
|
* @OA\Property(property="data", type="object")
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function updateVisit(Request $request)
|
|
|
|
|
|
{
|
|
|
|
|
|
try {
|
|
|
|
|
|
$id = $request->input('id');
|
|
|
|
|
|
|
|
|
|
|
|
if (!$id) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, __('gate.visit_id_required')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visit = Visit::find($id);
|
|
|
|
|
|
if (!$visit) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.visit_not_found')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$action = $request->input('action');
|
|
|
|
|
|
$remark = $request->input('remark', '');
|
|
|
|
|
|
|
|
|
|
|
|
DB::beginTransaction();
|
|
|
|
|
|
|
|
|
|
|
|
switch ($action) {
|
|
|
|
|
|
case 'bind_card':
|
|
|
|
|
|
// 绑定ID卡
|
|
|
|
|
|
$personNo = $request->input('person_no');
|
|
|
|
|
|
$carNo = $request->input('car_no');
|
|
|
|
|
|
|
|
|
|
|
|
if (!$personNo) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, __('gate.person_no_required')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visit->person_no = $personNo;
|
|
|
|
|
|
if ($carNo) {
|
|
|
|
|
|
$visit->car_no = $carNo;
|
|
|
|
|
|
}
|
|
|
|
|
|
$visit->save();
|
|
|
|
|
|
|
|
|
|
|
|
// 记录日志
|
|
|
|
|
|
$this->createVisitLog($visit, VisitLog::TYPE_ENTER, __('gate.bind_card_log', ['person_no' => $personNo, 'car_no' => $carNo ?: '']));
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'enter':
|
|
|
|
|
|
// 进厂
|
|
|
|
|
|
if ($visit->audit_status != Visit::AUDIT_STATUS_APPROVED) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.only_approved_visits_can_enter')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visit->audit_status = Visit::AUDIT_STATUS_ENTERED;
|
|
|
|
|
|
$visit->save();
|
|
|
|
|
|
|
|
|
|
|
|
// 记录日志
|
|
|
|
|
|
$this->createVisitLog($visit, VisitLog::TYPE_ENTER, __('gate.enter_log') . ($remark ? ':' . $remark : ''));
|
|
|
|
|
|
|
|
|
|
|
|
// 记录门岗日志
|
|
|
|
|
|
$this->createGateLog($visit, 'enter', $remark);
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'leave':
|
|
|
|
|
|
// 离厂
|
|
|
|
|
|
if ($visit->audit_status != Visit::AUDIT_STATUS_ENTERED) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.only_entered_visitors_can_leave')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visit->audit_status = Visit::AUDIT_STATUS_LEFT;
|
|
|
|
|
|
$visit->save();
|
|
|
|
|
|
|
|
|
|
|
|
// 记录日志
|
|
|
|
|
|
$this->createVisitLog($visit, VisitLog::TYPE_LEAVE, __('gate.leave_log') . ($remark ? ':' . $remark : ''));
|
|
|
|
|
|
|
|
|
|
|
|
// 记录门岗日志
|
|
|
|
|
|
$this->createGateLog($visit, 'leave', $remark);
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'upload_vehicle':
|
|
|
|
|
|
// 上传货车图片
|
|
|
|
|
|
if ($visit->type != Visit::TYPE_LOGISTICS_CAR) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.only_logistics_cars_can_upload_images')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$vehicleImages = $request->input('vehicle_images', []);
|
|
|
|
|
|
if (empty($vehicleImages)) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.vehicle_images_required')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证图片ID是否存在于uploads表中
|
|
|
|
|
|
$existingImages = Upload::whereIn('id', $vehicleImages)->pluck('id')->toArray();
|
|
|
|
|
|
if (count($existingImages) !== count($vehicleImages)) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.invalid_vehicle_images')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 存储货车图片ID数组到vehicle_images字段
|
|
|
|
|
|
$visit->vehicle_images = $vehicleImages;
|
|
|
|
|
|
$visit->save();
|
|
|
|
|
|
|
|
|
|
|
|
// 记录日志
|
|
|
|
|
|
$this->createVisitLog($visit, VisitLog::TYPE_ENTER, __('gate.upload_vehicle_images_log', ['count' => count($vehicleImages)]));
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.invalid_action_type')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DB::commit();
|
|
|
|
|
|
return $this->success($visit);
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
DB::rollBack();
|
|
|
|
|
|
Log::error('门岗端更新拜访信息失败:' . $e->getMessage());
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_INSIDE, __('gate.operation_failed') . ':' . $e->getMessage()]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建拜访日志
|
|
|
|
|
|
*/
|
|
|
|
|
|
private function createVisitLog($visit, $type, $remark = '')
|
|
|
|
|
|
{
|
|
|
|
|
|
VisitLog::log($visit->id, $type, $remark);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建门岗日志
|
|
|
|
|
|
*/
|
|
|
|
|
|
private function createGateLog($visit, $action, $remark = '')
|
|
|
|
|
|
{
|
|
|
|
|
|
$personNo = $visit->person_no ? [$visit->person_no] : [];
|
|
|
|
|
|
$carNo = $visit->car_no ? [$visit->car_no] : [];
|
|
|
|
|
|
|
|
|
|
|
|
GateLog::create([
|
|
|
|
|
|
'code' => $visit->code,
|
|
|
|
|
|
'remark' => $remark,
|
|
|
|
|
|
'person_no' => $personNo,
|
|
|
|
|
|
'car_no' => $carNo,
|
|
|
|
|
|
'created_at' => now(),
|
|
|
|
|
|
'updated_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @OA\Get(
|
|
|
|
|
|
* path="/api/gate/visits/use-code",
|
|
|
|
|
|
* tags={"门岗端接口"},
|
|
|
|
|
|
* summary="核销",
|
|
|
|
|
|
* description="",
|
|
|
|
|
|
* @OA\Parameter(name="admin_id", in="query", @OA\Schema(type="string"), required=false, description="管理员id"),
|
|
|
|
|
|
* @OA\Parameter(name="keyword", in="query", @OA\Schema(type="string"), required=false, description="关键词(人牌,身份证,核销码)"),
|
|
|
|
|
|
* @OA\Parameter(name="type", in="query", @OA\Schema(type="string"), required=false, description="1进厂2离厂"),
|
|
|
|
|
|
* @OA\Response(
|
|
|
|
|
|
* response="200",
|
|
|
|
|
|
* description="暂无"
|
|
|
|
|
|
* )
|
|
|
|
|
|
* )
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function useCode()
|
|
|
|
|
|
{
|
|
|
|
|
|
$all = \request()->all();
|
|
|
|
|
|
$messages = [
|
|
|
|
|
|
'keyword.required' => __('gate.validation.keyword_required'),
|
|
|
|
|
|
'type.required' => __('gate.validation.type_required'),
|
|
|
|
|
|
'admin_id.required' => __('gate.validation.admin_id_required')
|
|
|
|
|
|
];
|
|
|
|
|
|
$validator = Validator::make($all, [
|
|
|
|
|
|
'keyword' => 'required',
|
|
|
|
|
|
'type' => 'required',
|
|
|
|
|
|
'admin_id' => 'required'
|
|
|
|
|
|
], $messages);
|
|
|
|
|
|
if ($validator->fails()) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
|
|
|
|
|
|
}
|
|
|
|
|
|
$code = \request('code');
|
|
|
|
|
|
$idcard = \request('idcard');
|
|
|
|
|
|
if (empty($idcard) && empty($code)) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, __('gate.validation.code_or_idcard_required')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
$check = Visit::where(function ($query) use ($all) {
|
|
|
|
|
|
$query->where('person_no', "{$all['keyword']}")
|
|
|
|
|
|
->orWhere('idcard', "{$all['keyword']}")
|
|
|
|
|
|
->orWhere('code', "{$all['keyword']}");
|
|
|
|
|
|
})->first();
|
|
|
|
|
|
if (empty($check)) {
|
|
|
|
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, __('gate.business.visit_not_found')]);
|
|
|
|
|
|
}
|
|
|
|
|
|
$remark = __('gate.operation.enter_factory');
|
|
|
|
|
|
if ($all['type'] == 2) {
|
|
|
|
|
|
$remark = __('gate.operation.leave_factory');
|
|
|
|
|
|
}
|
|
|
|
|
|
$gateLog = GateLog::add($all['admin_id'], $all['code'], $all['person_no'] ?? [], $all['car_no'] ?? [], $remark);
|
|
|
|
|
|
if ($all['type'] == 1) {
|
|
|
|
|
|
// 入场
|
|
|
|
|
|
Visit::where('code', $all['code'])->update(['audit_status' => 3, 'person_no' => $all['person_no'] ?? '', 'car_no' => $all['car_no'] ?? '']);
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($all['type'] == 2) {
|
|
|
|
|
|
Visit::where('code', $all['code'])->update(['audit_status' => 4]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return $this->success($gateLog);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|