340 lines
9.1 KiB
PHP
340 lines
9.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\PrintJob;
|
|
use App\Models\PrintPlugin;
|
|
use App\Models\PrintPluginLog;
|
|
use App\Models\Order;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class PrintJobService
|
|
{
|
|
protected PrintPluginService $pluginService;
|
|
|
|
public function __construct(PrintPluginService $pluginService)
|
|
{
|
|
$this->pluginService = $pluginService;
|
|
}
|
|
|
|
/**
|
|
* 创建打印任务
|
|
*/
|
|
public function createJob(
|
|
int $userId,
|
|
string $platform,
|
|
string $pluginCode,
|
|
array $printData,
|
|
?int $orderId = null,
|
|
?int $templateId = null,
|
|
int $priority = 0
|
|
): array {
|
|
$job = PrintJob::create([
|
|
'user_id' => $userId,
|
|
'job_no' => PrintJob::generateJobNo(),
|
|
'order_id' => $orderId,
|
|
'platform' => $platform,
|
|
'plugin_code' => $pluginCode,
|
|
'template_id' => $templateId,
|
|
'print_data' => $printData,
|
|
'status' => PrintJob::STATUS_PENDING,
|
|
'priority' => $priority,
|
|
]);
|
|
|
|
return [
|
|
'success' => true,
|
|
'job_id' => $job->id,
|
|
'job_no' => $job->job_no,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 批量创建打印任务
|
|
*/
|
|
public function createBatchJobs(
|
|
int $userId,
|
|
string $platform,
|
|
string $pluginCode,
|
|
array $ordersData,
|
|
?int $templateId = null
|
|
): array {
|
|
$jobs = [];
|
|
$failed = [];
|
|
|
|
foreach ($ordersData as $data) {
|
|
try {
|
|
$job = PrintJob::create([
|
|
'user_id' => $userId,
|
|
'job_no' => PrintJob::generateJobNo(),
|
|
'order_id' => $data['order_id'] ?? null,
|
|
'platform' => $platform,
|
|
'plugin_code' => $pluginCode,
|
|
'template_id' => $templateId,
|
|
'print_data' => $data['print_data'] ?? $data,
|
|
'status' => PrintJob::STATUS_PENDING,
|
|
'priority' => $data['priority'] ?? 0,
|
|
]);
|
|
$jobs[] = $job->id;
|
|
} catch (\Exception $e) {
|
|
$failed[] = $data;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'success' => count($failed) === 0,
|
|
'created' => count($jobs),
|
|
'failed' => count($failed),
|
|
'job_ids' => $jobs,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 获取用户打印队列
|
|
*/
|
|
public function getQueue(int $userId, ?string $status = null): array
|
|
{
|
|
$query = PrintJob::where('user_id', $userId);
|
|
|
|
if ($status) {
|
|
$query->where('status', $status);
|
|
} else {
|
|
$query->whereIn('status', [PrintJob::STATUS_PENDING, PrintJob::STATUS_QUEUED, PrintJob::STATUS_PRINTING]);
|
|
}
|
|
|
|
$jobs = $query->orderByDesc('priority')
|
|
->orderBy('created_at')
|
|
->paginate(50);
|
|
|
|
return $jobs->toArray();
|
|
}
|
|
|
|
/**
|
|
* 获取下一个待打印任务(从队列中获取)
|
|
*/
|
|
public function getNextJob(int $userId, string $deviceId): ?PrintJob
|
|
{
|
|
// 确保设备在线
|
|
$deviceStatus = $this->pluginService->getDeviceStatus($userId, $deviceId);
|
|
|
|
// 获取最高优先级的待处理任务
|
|
return PrintJob::where('user_id', $userId)
|
|
->whereIn('status', [PrintJob::STATUS_PENDING, PrintJob::STATUS_QUEUED])
|
|
->orderByDesc('priority')
|
|
->orderBy('created_at')
|
|
->first();
|
|
}
|
|
|
|
/**
|
|
* 认领打印任务(设备开始打印时调用)
|
|
*/
|
|
public function claimJob(int $userId, string $deviceId, int $jobId): bool
|
|
{
|
|
$job = PrintJob::where('id', $jobId)
|
|
->where('user_id', $userId)
|
|
->whereIn('status', [PrintJob::STATUS_PENDING, PrintJob::STATUS_QUEUED])
|
|
->first();
|
|
|
|
if (!$job) {
|
|
return false;
|
|
}
|
|
|
|
$job->markAsPrinting();
|
|
|
|
PrintPluginLog::record(
|
|
$userId,
|
|
PrintPluginLog::TYPE_PRINT,
|
|
"开始打印任务 {$job->job_no}",
|
|
null,
|
|
$job->id,
|
|
['device_id' => $deviceId, 'platform' => $job->platform]
|
|
);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 标记打印完成
|
|
*/
|
|
public function completeJob(int $userId, int $jobId, ?string $deviceId = null): bool
|
|
{
|
|
$job = PrintJob::where('id', $jobId)
|
|
->where('user_id', $userId)
|
|
->where('status', PrintJob::STATUS_PRINTING)
|
|
->first();
|
|
|
|
if (!$job) {
|
|
return false;
|
|
}
|
|
|
|
$job->markAsCompleted();
|
|
|
|
PrintPluginLog::record(
|
|
$userId,
|
|
PrintPluginLog::TYPE_PRINT,
|
|
"打印任务 {$job->job_no} 完成",
|
|
null,
|
|
$job->id,
|
|
['device_id' => $deviceId]
|
|
);
|
|
|
|
// 如果有订单,更新订单状态
|
|
if ($job->order_id) {
|
|
Order::where('id', $job->order_id)->update([
|
|
'print_status' => 'printed',
|
|
'printed_at' => now(),
|
|
]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 标记打印失败
|
|
*/
|
|
public function failJob(int $userId, int $jobId, string $error, ?string $deviceId = null): bool
|
|
{
|
|
$job = PrintJob::where('id', $jobId)
|
|
->where('user_id', $userId)
|
|
->where('status', PrintJob::STATUS_PRINTING)
|
|
->first();
|
|
|
|
if (!$job) {
|
|
return false;
|
|
}
|
|
|
|
$job->markAsFailed($error);
|
|
|
|
PrintPluginLog::record(
|
|
$userId,
|
|
PrintPluginLog::TYPE_ERROR,
|
|
"打印任务 {$job->job_no} 失败: {$error}",
|
|
null,
|
|
$job->id,
|
|
['device_id' => $deviceId, 'error' => $error]
|
|
);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 重试任务
|
|
*/
|
|
public function retryJob(int $userId, int $jobId): array
|
|
{
|
|
$job = PrintJob::where('id', $jobId)
|
|
->where('user_id', $userId)
|
|
->first();
|
|
|
|
if (!$job) {
|
|
return ['success' => false, 'message' => '任务不存在'];
|
|
}
|
|
|
|
if (!$job->canRetry()) {
|
|
return ['success' => false, 'message' => '已达到最大重试次数'];
|
|
}
|
|
|
|
$job->update([
|
|
'status' => PrintJob::STATUS_QUEUED,
|
|
'error_message' => null,
|
|
]);
|
|
|
|
return ['success' => true, 'message' => '任务已重新加入队列'];
|
|
}
|
|
|
|
/**
|
|
* 取消任务
|
|
*/
|
|
public function cancelJob(int $userId, int $jobId): bool
|
|
{
|
|
$job = PrintJob::where('id', $jobId)
|
|
->where('user_id', $userId)
|
|
->whereIn('status', [PrintJob::STATUS_PENDING, PrintJob::STATUS_QUEUED])
|
|
->first();
|
|
|
|
if ($job) {
|
|
$job->cancel();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 获取用户的打印历史
|
|
*/
|
|
public function getHistory(int $userId, int $page = 1, int $perPage = 20): array
|
|
{
|
|
$jobs = PrintJob::where('user_id', $userId)
|
|
->whereIn('status', [PrintJob::STATUS_COMPLETED, PrintJob::STATUS_FAILED, PrintJob::STATUS_CANCELLED])
|
|
->orderByDesc('created_at')
|
|
->paginate($perPage, ['*'], 'page', $page);
|
|
|
|
return $jobs->toArray();
|
|
}
|
|
|
|
/**
|
|
* 获取任务统计
|
|
*/
|
|
public function getStats(int $userId): array
|
|
{
|
|
$pending = PrintJob::where('user_id', $userId)->where('status', PrintJob::STATUS_PENDING)->count();
|
|
$printing = PrintJob::where('user_id', $userId)->where('status', PrintJob::STATUS_PRINTING)->count();
|
|
$queued = PrintJob::where('user_id', $userId)->where('status', PrintJob::STATUS_QUEUED)->count();
|
|
$completedToday = PrintJob::where('user_id', $userId)
|
|
->where('status', PrintJob::STATUS_COMPLETED)
|
|
->whereDate('print_end_time', today())
|
|
->count();
|
|
$failedToday = PrintJob::where('user_id', $userId)
|
|
->where('status', PrintJob::STATUS_FAILED)
|
|
->whereDate('print_end_time', today())
|
|
->count();
|
|
|
|
return [
|
|
'pending' => $pending,
|
|
'printing' => $printing,
|
|
'queued' => $queued,
|
|
'completed_today' => $completedToday,
|
|
'failed_today' => $failedToday,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 批量加入队列
|
|
*/
|
|
public function batchQueue(int $userId, array $jobIds): array
|
|
{
|
|
$queued = 0;
|
|
$failed = 0;
|
|
|
|
foreach ($jobIds as $jobId) {
|
|
$job = PrintJob::where('id', $jobId)
|
|
->where('user_id', $userId)
|
|
->where('status', PrintJob::STATUS_PENDING)
|
|
->first();
|
|
|
|
if ($job) {
|
|
$job->queue();
|
|
$queued++;
|
|
} else {
|
|
$failed++;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'queued' => $queued,
|
|
'failed' => $failed,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 清空已完成任务
|
|
*/
|
|
public function clearCompleted(int $userId): int
|
|
{
|
|
return PrintJob::where('user_id', $userId)
|
|
->whereIn('status', [PrintJob::STATUS_COMPLETED, PrintJob::STATUS_CANCELLED])
|
|
->delete();
|
|
}
|
|
}
|