用户信息、个人名片、加密、水印
This commit is contained in:
@@ -4,6 +4,7 @@ namespace app\common\controller;
|
||||
use app\common\controller\BaseController;
|
||||
use app\common\model\UsedCar;
|
||||
use app\common\model\UsedCarPdfLog;
|
||||
use app\common\model\User;
|
||||
use app\common\service\OssService;
|
||||
use app\common\traits\crud\CrudControllerTrait;
|
||||
use app\common\service\UsedCarService;
|
||||
@@ -138,8 +139,14 @@ class UsedCarController extends BaseController
|
||||
}
|
||||
$data['attachment'] = $attachments;
|
||||
$data['price'] = $price;
|
||||
|
||||
$pdf = (new MpdfDriver())->exportUsedCarPdf($data);
|
||||
$user = User::where('id',$request->user['id'])->first();
|
||||
$contact = $user['email'] ?? $user['phone'] ?? $user['whatsapp'] ?? null;
|
||||
if(!empty($user['social_code'])){
|
||||
$ossService = new OssService();
|
||||
$user['social_code'] = $ossService->generatePrivateUrl($user['social_code']);
|
||||
$user['social_code'] = $this->service->downloadImage($user['social_code']);
|
||||
}
|
||||
$pdf = (new MpdfDriver())->exportUsedCarPdf($data,$user,$contact);
|
||||
UsedCar::where('id', $data['id'])->update(['pdf_src' => $pdf]);
|
||||
|
||||
array_map('unlink', glob(runtime_path('pdf/images/*.jpg')));
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace app\common\controller;
|
||||
use app\common\controller\BaseController;
|
||||
use app\common\traits\crud\CrudControllerTrait;
|
||||
use app\common\service\UserService;
|
||||
use support\Request;
|
||||
|
||||
class UserController extends BaseController
|
||||
{
|
||||
@@ -30,4 +31,60 @@ class UserController extends BaseController
|
||||
// $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
|
||||
// return $data;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*
|
||||
* @param Request $request 请求对象
|
||||
* @return mixed 返回更新成功的数据或信息
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
try {
|
||||
$data = $request->post();
|
||||
$request->setPost('id',$request->user['id']);
|
||||
$res = $this->service->serviceUpdate($request, $data);
|
||||
return $this->success([], '更新成功');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
*
|
||||
* @param Request $request 请求对象
|
||||
* @param int|string $id 资源 ID
|
||||
* @return mixed 返回资源详情数据
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setGet('id',$request->user['id']);
|
||||
$raw = $this->service->serviceShow($request);
|
||||
$data = $this->transformData($raw, method_exists($this, 'showFormat')
|
||||
? [$this, 'showFormat']
|
||||
: null);
|
||||
return $this->success($data);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表页数据格式化
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
protected function showFormat($data)
|
||||
{
|
||||
if (isset($data['created_at']))
|
||||
$data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
|
||||
if (isset($data['updated_at']))
|
||||
$data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
|
||||
unset($data['union_id']);
|
||||
unset($data['app_id']);
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ class User extends Model
|
||||
/**
|
||||
* 允许自动填充模型字段
|
||||
*/
|
||||
protected $fillable = ['id', 'union_id', 'app_id', 'name'];
|
||||
protected $fillable = ['id', 'union_id', 'app_id', 'name', 'phone', 'email', 'whatsapp', 'social', 'social_code'];
|
||||
|
||||
/**
|
||||
* 不允许自动填充模型字段
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace app\common\service;
|
||||
use app\common\validate\UserValidate;
|
||||
use app\common\traits\crud\CrudServiceTrait;
|
||||
use app\common\model\User;
|
||||
use support\Request;
|
||||
|
||||
class UserService
|
||||
{
|
||||
@@ -28,4 +29,12 @@ class UserService
|
||||
{
|
||||
return new $this->validator;
|
||||
}
|
||||
|
||||
public function beforeServiceUpdate($data, Request $request){
|
||||
unset($data['union_id']);
|
||||
unset($data['app_id']);
|
||||
unset($data['name']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ class MpdfDriver
|
||||
return [$css, $html];
|
||||
}
|
||||
|
||||
public function exportUsedCarPdf($car)
|
||||
public function exportUsedCarPdf($car,$user,$contact)
|
||||
{
|
||||
/*$car = [
|
||||
'title' => '奥迪Q3 2013款 35 TFSI 舒适型',
|
||||
@@ -154,12 +154,35 @@ class MpdfDriver
|
||||
'default_font' => 'sun-exta'
|
||||
]);
|
||||
|
||||
$mpdf->SetProtection(//限制篡改或盗用
|
||||
['print'], // 允许的权限 copy:允许复制、print:允许打印
|
||||
'', // 用户密码(可留空)
|
||||
'Admin@2026@!#' // 拥有者密码(一定要设置)
|
||||
);
|
||||
|
||||
//设置水印
|
||||
$mpdf->SetWatermarkText(
|
||||
$user['name'] .' '. $contact,
|
||||
0.08
|
||||
);
|
||||
$mpdf->showWatermarkText = true;
|
||||
|
||||
// 1️⃣ 车辆基本信息 HTML
|
||||
$mpdf->WriteHTML($html);
|
||||
|
||||
// 2️⃣ 追加附件pdf
|
||||
foreach ($car['attachment'] as $attachment) {
|
||||
$this->appendPdf($mpdf,$attachment);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
$cardTpl = base_path('app/common/utils/pdf/template/contactCard.stub');
|
||||
include $cardTpl;
|
||||
$cardHtml = ob_get_clean();
|
||||
// 3️⃣ 新增一页:名片页
|
||||
$mpdf->AddPage();
|
||||
$mpdf->WriteHTML($cardHtml);
|
||||
|
||||
$pdf = $mpdf->Output('车辆详情.pdf', 'S');
|
||||
$dir = runtime_path('pdf');
|
||||
if (!is_dir($dir)) mkdir($dir, 0777, true);
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
<?php
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
use app\common\audit\AuditBuffer;
|
||||
use app\common\model\User;
|
||||
use Webman\RedisQueue\Redis as Queue;
|
||||
use support\Log;
|
||||
|
||||
class Audit implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$start = microtime(true);
|
||||
AuditBuffer::reset();
|
||||
|
||||
$httpCode = 200; $message = null; $status = 1;
|
||||
|
||||
try {
|
||||
$response = $handler($request);
|
||||
$httpCode = $response->getStatusCode();
|
||||
return $response;
|
||||
} catch (\Throwable $e) {
|
||||
$httpCode = $e->getCode() ?: 500;
|
||||
$message = mb_substr($e->getMessage(), 0, 180);
|
||||
$status = 0;
|
||||
throw $e;
|
||||
} finally {
|
||||
$latency = (int)((microtime(true) - $start) * 1000);
|
||||
$this->enqueue($request, $httpCode, $status, $message, $latency);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function enqueue(Request $req, int $httpCode, int $status, ?string $message, int $latencyMs): void
|
||||
{
|
||||
$buf = AuditBuffer::instance();
|
||||
|
||||
$user = $this->currentUser($req->user);
|
||||
$paramsBrief = $this->briefParams($req->all());
|
||||
$ua = (string)($req->header('user-agent') ?? '');
|
||||
if (mb_strlen($ua) > 191) $ua = mb_substr($ua, 0, 191);
|
||||
|
||||
$payload = [
|
||||
'user_id' => $user['id'] ?? null,
|
||||
'user_name' => $user['name'] ?? null,
|
||||
'route' => $req->path(),
|
||||
'method' => $req->method(),
|
||||
'ip' => $req->getRealIp(),
|
||||
'ua' => $ua,
|
||||
'action' => $buf->action ?? $req->action,
|
||||
'status' => $status,
|
||||
'http_code' => $httpCode,
|
||||
'latency_ms' => $latencyMs,
|
||||
'params_brief' => $paramsBrief, // 数组,消费者再编码
|
||||
'changes' => $buf->changes, // 数组,消费者再编码
|
||||
'message' => $message,
|
||||
'ts' => time()
|
||||
];
|
||||
|
||||
try {
|
||||
Queue::send('audit_log', $payload); // 异步
|
||||
} catch (\Throwable $e) {
|
||||
// 遵循“绝不回落同步写”,仅记录错误
|
||||
Log::error('audit enqueue failed: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected function briefParams(array $params): array
|
||||
{
|
||||
// $mask = ['password','pwd','token','secret','access_token','refresh_token','file','content','html'];
|
||||
$mask = [];
|
||||
$out = [];
|
||||
foreach ($params as $k=>$v) {
|
||||
if (in_array($k, $mask, true)) { $out[$k] = '***'; continue; }
|
||||
if (is_array($v)) { $out[$k] = '[array('.count($v).')]'; continue; }
|
||||
$s = (string)$v;
|
||||
$out[$k] = mb_strlen($s) > 120 ? mb_substr($s, 0, 120).'…' : $s;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
protected function inferAction(Request $req): ?string
|
||||
{
|
||||
$m = strtoupper($req->method());
|
||||
if ($m === 'POST') return 'create';
|
||||
if ($m === 'PUT' || $m === 'PATCH') return 'update';
|
||||
if ($m === 'DELETE') return 'delete';
|
||||
return 'view';
|
||||
}
|
||||
|
||||
protected function currentUser($user): array
|
||||
{
|
||||
$user = (array)$user;
|
||||
|
||||
if (!$user) {
|
||||
return [
|
||||
'id' => 0,
|
||||
'name' => 'guest'
|
||||
];
|
||||
} else {
|
||||
if (!isset($user['uname'])) {
|
||||
$user['uname'] = User::where('id', $user['id'])->value('name');
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $user['uid'] ?? 0,
|
||||
'name' => $user['uname'] ?? 'guest'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use support\Db;
|
||||
use support\Log;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class AuditLog implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = 'audit_log';
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
try {
|
||||
$now = (int)($data['ts'] ?? time());
|
||||
|
||||
$row = [
|
||||
// 'trace_id' => $data['trace_id'] ?? null,
|
||||
'user_id' => $data['user_id'] ?? null,
|
||||
'user_name' => $data['user_name'] ?? null,
|
||||
'route' => $data['route'] ?? null,
|
||||
'method' => $data['method'] ?? null,
|
||||
'ip' => $data['ip'] ?? null,
|
||||
'ua' => $data['ua'] ?? null,
|
||||
'action' => $data['action'] ?? null,
|
||||
'status' => (int)($data['status'] ?? 1),
|
||||
'http_code' => (int)($data['http_code'] ?? 200),
|
||||
'latency_ms' => $data['latency_ms'] ?? null,
|
||||
'params_brief' => !empty($data['params_brief']) ? json_encode($data['params_brief'], JSON_UNESCAPED_UNICODE) : null,
|
||||
'changes' => !empty($data['changes']) ? json_encode($data['changes'], JSON_UNESCAPED_UNICODE) : null,
|
||||
'message' => $data['message'] ?? null,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
Db::table('sys_op_log')->insert($row);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('audit_log consume error: '.$e->getMessage());
|
||||
return false; // 允许重试与失败处理
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 消费失败回调
|
||||
/*
|
||||
$package = [
|
||||
'id' => 1357277951, // 消息ID
|
||||
'time' => 1709170510, // 消息时间
|
||||
'delay' => 0, // 延迟时间
|
||||
'attempts' => 2, // 消费次数
|
||||
'queue' => 'send-mail', // 队列名
|
||||
'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
|
||||
'max_attempts' => 5, // 最大重试次数
|
||||
'error' => '错误信息' // 错误信息
|
||||
]
|
||||
*/
|
||||
public function onConsumeFailure(\Throwable $e, $package)
|
||||
{
|
||||
echo "consume failure\n";
|
||||
echo $e->getMessage() . "\n";
|
||||
// 无需反序列化
|
||||
var_export($package);
|
||||
|
||||
Log::error('audit_log message failed after retries: '.json_encode($package, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
@@ -66,4 +66,11 @@ Route::group('/common', function () {
|
||||
Route::any('/destroy', [app\common\controller\UsedCarController::class, 'destroy']);
|
||||
Route::any('/crawl', [app\common\controller\UsedCarController::class, 'crawlKeyword']);
|
||||
});
|
||||
|
||||
Route::group('/user', function () {
|
||||
Route::any('/info', [app\common\controller\UserController::class, 'show']);
|
||||
Route::any('/edit', [app\common\controller\UserController::class, 'edit']);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user