Browse Source

工资计算优化

unknown 1 tháng trước cách đây
mục cha
commit
dd86a83957
2 tập tin đã thay đổi với 183 bổ sung136 xóa
  1. 121 81
      application/api/controller/StaffSalary.php
  2. 62 55
      application/job/InsertDataJob.php

+ 121 - 81
application/api/controller/StaffSalary.php

@@ -732,6 +732,7 @@ use app\common\controller\Api;
 use think\Request;
 use think\Db;
 use think\Queue;
+use think\Log;
 
 class StaffSalary extends Api
 {
@@ -749,76 +750,106 @@ class StaffSalary extends Api
 
         $params = Request::instance()->param();
 
-        // 参数验证
-        if (empty($params['date']) || empty($params['start_date']) || empty($params['end_date'])) {
-            $this->error('日期参数不能为空');
+        // 基础参数验证
+        $requiredParams = ['date', 'start_date', 'end_date'];
+        foreach ($requiredParams as $param) {
+            if (empty($params[$param])) {
+                $this->error("{$param}参数不能为空");
+            }
         }
 
+        $month = trim($params['date']);
+
         // 检查是否有正在执行的任务
         $runningTask = Db::name('queue_tasks')
             ->where('task_type', 'salary_calculation')
-            ->where('task_data', 'like', '%"date":"' . $params['date'] . '"%')
+            ->where('task_data', 'like', '%"date":"' . $month . '"%')
             ->where('status', 'in', ['pending', 'processing'])
             ->find();
 
         if ($runningTask) {
-            $this->success('该月份的工资计算任务已在执行中,请勿重复提交');
+            $this->success('该月份的工资计算任务已在执行中,请稍后查看结果');
         }
 
-        // 添加用户信息
-        $params['user_id'] = session('user_id') ?? 0;
-        $params['user_name'] = session('user_name') ?? '系统';
-        $params['request_time'] = date('Y-m-d H:i:s');
-
-        // 先创建任务记录
-        $taskId = Db::name('queue_tasks')->insertGetId([
-            'task_type' => 'salary_calculation',
-            'task_data' => json_encode($params, JSON_UNESCAPED_UNICODE),
-            'status' => 'pending',
-            'queue_name' => 'salary_calculation',
-            'create_time' => date('Y-m-d H:i:s')
-        ]);
-
-        // 添加到任务数据中
-        $params['task_id'] = $taskId;
-
-        // 提交到工资计算队列
-        $jobHandlerClassName = 'app\job\InsertDataJob';
-        $queueName = 'salary_calculation';
-
-        $jobId = Queue::push($jobHandlerClassName, $params, $queueName);
-
-        if ($jobId) {
-            // 更新任务记录
-            Db::name('queue_tasks')
-                ->where('id', $taskId)
-                ->update([
-                    'job_id' => $jobId,
-                    'update_time' => date('Y-m-d H:i:s')
-                ]);
+        // 准备队列任务数据(确保是简单数组)
+        $taskData = [
+            'date' => $month,
+            'start_date' => trim($params['start_date']),
+            'end_date' => trim($params['end_date']),
+            'sys_id' => $params['sys_id'] ?? '',
+            'vacation_one_start' => $params['vacation_one_start'] ?? '',
+            'vacation_one_end' => $params['vacation_one_end'] ?? '',
+            'vacation_two_start' => $params['vacation_two_start'] ?? '',
+            'vacation_two_end' => $params['vacation_two_end'] ?? '',
+            'user_id' => session('user_id') ?? 0,
+            'user_name' => session('user_name') ?? '系统',
+            'request_time' => date('Y-m-d H:i:s')
+        ];
 
-            $this->success('工资计算任务已提交到队列,请稍后查看结果', null, [
-                'task_id' => $taskId,
-                'job_id' => $jobId,
-                'month' => $params['date'],
-                'queue_name' => $queueName
+        Log::info('准备提交工资计算任务', $taskData);
+
+        try {
+            // 先创建任务记录
+            $taskId = Db::name('queue_tasks')->insertGetId([
+                'task_type' => 'salary_calculation',
+                'task_data' => json_encode($taskData, JSON_UNESCAPED_UNICODE),
+                'status' => 'pending',
+                'queue_name' => 'salary_calculation',
+                'create_time' => date('Y-m-d H:i:s')
             ]);
-        } else {
-            // 更新任务状态为失败
-            Db::name('queue_tasks')
-                ->where('id', $taskId)
-                ->update([
-                    'status' => 'failed',
-                    'error' => '任务提交到队列失败',
-                    'update_time' => date('Y-m-d H:i:s')
+
+            // 添加到任务数据中
+            $taskData['task_id'] = $taskId;
+
+            // 提交到工资计算队列 - 使用正确的队列调用方式
+            $jobHandlerClassName = 'app\job\InsertDataJob';
+            $queueName = 'salary_calculation';
+
+            // 方法1:直接使用队列push(推荐)
+            $jobId = Queue::push($jobHandlerClassName, $taskData, $queueName);
+
+            Log::info('队列提交结果', ['job_id' => $jobId, 'queue_name' => $queueName]);
+
+            if ($jobId !== false) {
+                // 更新任务记录
+                Db::name('queue_tasks')
+                    ->where('id', $taskId)
+                    ->update([
+                        'job_id' => $jobId,
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+
+                $this->success('工资计算任务已提交,正在后台处理...', null, [
+                    'task_id' => $taskId,
+                    'job_id' => $jobId,
+                    'month' => $month,
+                    'queue_name' => $queueName,
+                    'submit_time' => date('Y-m-d H:i:s')
                 ]);
+            } else {
+                throw new \Exception('队列提交返回false');
+            }
 
-            $this->error('工资计算任务提交失败');
+        } catch (\Exception $e) {
+            Log::error('提交工资计算任务失败: ' . $e->getMessage());
+
+            // 如果创建了任务记录但提交失败,更新状态
+            if (isset($taskId)) {
+                Db::name('queue_tasks')
+                    ->where('id', $taskId)
+                    ->update([
+                        'status' => 'failed',
+                        'error' => '任务提交失败: ' . $e->getMessage(),
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+            }
+
+            $this->error('工资计算任务提交失败: ' . $e->getMessage());
         }
     }
 
     /**
-     * 直接执行工资计算(同步版本,用于测试)
+     * 同步执行工资计算(用于测试和调试)
      */
     public function calculateDirect()
     {
@@ -829,7 +860,7 @@ class StaffSalary extends Api
         $params = Request::instance()->param();
 
         try {
-            $service = new \app\service\SalaryCalculationService();
+            $service = new \app\common\service\SalaryCalculationService();
             $result = $service->calculateSalary($params);
 
             if ($result['success']) {
@@ -854,36 +885,45 @@ class StaffSalary extends Api
             $this->error('月份参数错误');
         }
 
-        $task = Db::name('queue_tasks')
-            ->where('task_type', 'salary_calculation')
-            ->where('task_data', 'like', '%"date":"' . $date . '"%')
-            ->order('id', 'desc')
-            ->find();
+        try {
+            $task = Db::name('queue_tasks')
+                ->where('task_type', 'salary_calculation')
+                ->where('task_data', 'like', '%"date":"' . $date . '"%')
+                ->order('id', 'desc')
+                ->find();
 
-        if ($task) {
-            $taskData = json_decode($task['task_data'] ?? '{}', true);
-            $result = json_decode($task['result'] ?? '{}', true);
-
-            $this->success('查询成功', null, [
-                'exists' => true,
-                'task_id' => $task['id'],
-                'date' => $date,
-                'status' => $task['status'],
-                'queue_name' => $task['queue_name'],
-                'job_id' => $task['job_id'],
-                'start_time' => $task['start_time'],
-                'end_time' => $task['end_time'],
-                'retry_count' => $task['retry_count'],
-                'result' => $result,
-                'error' => $task['error'] ?? '',
-                'create_time' => $task['create_time'],
-                'user_info' => [
-                    'user_id' => $taskData['user_id'] ?? 0,
-                    'user_name' => $taskData['user_name'] ?? ''
-                ]
-            ]);
-        } else {
-            $this->success('查询成功', null, ['exists' => false, 'date' => $date]);
+            if ($task) {
+                $taskData = json_decode($task['task_data'] ?? '{}', true) ?: [];
+                $result = json_decode($task['result'] ?? '{}', true) ?: [];
+
+                $response = [
+                    'exists' => true,
+                    'task_id' => (int)$task['id'],
+                    'date' => $date,
+                    'status' => $task['status'] ?? 'unknown',
+                    'queue_name' => $task['queue_name'] ?? '',
+                    'job_id' => $task['job_id'] ?? '',
+                    'start_time' => $task['start_time'] ?? '',
+                    'end_time' => $task['end_time'] ?? '',
+                    'retry_count' => (int)($task['retry_count'] ?? 0),
+                    'result' => $result,
+                    'error' => $task['error'] ?? '',
+                    'create_time' => $task['create_time'] ?? '',
+                    'user_info' => [
+                        'user_id' => $taskData['user_id'] ?? 0,
+                        'user_name' => $taskData['user_name'] ?? ''
+                    ]
+                ];
+            } else {
+                $response = ['exists' => false, 'date' => $date];
+            }
+
+            $this->success('查询成功', null, $response);
+
+        } catch (\Exception $e) {
+            $this->error('查询任务状态失败: ' . $e->getMessage());
         }
     }
+
+
 }

+ 62 - 55
application/job/InsertDataJob.php

@@ -174,20 +174,29 @@ class InsertDataJob
     /**
      * 任务处理方法
      * @param \think\queue\Job $job 任务对象
-     * @param array $data 任务数据
+     * @param mixed $data 任务数据
      */
     public function fire($job, $data)
     {
-        Log::info('开始执行工资计算队列任务', $data);
+        // 确保数据是数组
+        if (!is_array($data)) {
+            Log::error('队列任务数据格式错误', ['data_type' => gettype($data)]);
+            $job->delete();
+            return;
+        }
+
+        Log::info('开始执行工资计算队列任务', ['data_keys' => array_keys($data)]);
 
         try {
-            $taskId = $data['task_id'] ?? 0;
+            $taskId = isset($data['task_id']) ? (int)$data['task_id'] : 0;
 
             // 更新任务状态为执行中
-            $this->updateTaskStatus($taskId, 'processing', [
-                'start_time' => date('Y-m-d H:i:s'),
-                'retry_count' => $job->attempts()
-            ]);
+            if ($taskId > 0) {
+                $this->updateTaskStatus($taskId, 'processing', [
+                    'start_time' => date('Y-m-d H:i:s'),
+                    'retry_count' => $job->attempts()
+                ]);
+            }
 
             // 调用工资计算服务
             $service = new SalaryCalculationService();
@@ -196,60 +205,55 @@ class InsertDataJob
             if ($result['success']) {
                 // 任务成功
                 $job->delete();
-                $this->updateTaskStatus($taskId, 'success', [
-                    'end_time' => date('Y-m-d H:i:s'),
-                    'result' => json_encode($result, JSON_UNESCAPED_UNICODE)
-                ]);
+                if ($taskId > 0) {
+                    $this->updateTaskStatus($taskId, 'success', [
+                        'end_time' => date('Y-m-d H:i:s'),
+                        'result' => json_encode($result, JSON_UNESCAPED_UNICODE)
+                    ]);
+                }
 
                 Log::info('工资计算任务执行成功', [
-                    'month' => $data['date'],
+                    'month' => $data['date'] ?? 'unknown',
                     'result' => $result
                 ]);
             } else {
                 // 任务失败
-                $this->handleFailure($job, $taskId, $result['message']);
+                if ($job->attempts() >= 3) {
+                    $job->delete();
+                    if ($taskId > 0) {
+                        $this->updateTaskStatus($taskId, 'failed', [
+                            'end_time' => date('Y-m-d H:i:s'),
+                            'error' => $result['message'],
+                            'retry_count' => $job->attempts()
+                        ]);
+                    }
+                    Log::error('工资计算任务重试超过3次失败', ['error' => $result['message']]);
+                } else {
+                    $delay = $this->getRetryDelay($job->attempts());
+                    $job->release($delay);
+                    Log::warning('工资计算任务重试', ['attempts' => $job->attempts(), 'delay' => $delay]);
+                }
             }
 
         } catch (\Exception $e) {
-            Log::error('工资计算队列任务异常: ' . $e->getMessage());
-            $this->handleException($job, $taskId ?? 0, $e->getMessage());
-        }
-    }
-
-    /**
-     * 处理任务失败
-     */
-    protected function handleFailure($job, int $taskId, string $error): void
-    {
-        if ($job->attempts() >= 3) {
-            $job->delete();
-            $this->updateTaskStatus($taskId, 'failed', [
-                'end_time' => date('Y-m-d H:i:s'),
-                'error' => $error,
-                'retry_count' => $job->attempts()
+            Log::error('工资计算队列任务异常: ' . $e->getMessage(), [
+                'exception' => $e->getTraceAsString()
             ]);
-            Log::error('工资计算任务重试超过3次失败', ['error' => $error]);
-        } else {
-            $delay = $this->getRetryDelay($job->attempts());
-            $job->release($delay);
-            Log::warning('工资计算任务重试', ['attempts' => $job->attempts(), 'delay' => $delay]);
-        }
-    }
 
-    /**
-     * 处理异常
-     */
-    protected function handleException($job, int $taskId, string $error): void
-    {
-        if ($job->attempts() >= 3) {
-            $job->delete();
-            $this->updateTaskStatus($taskId, 'error', [
-                'end_time' => date('Y-m-d H:i:s'),
-                'error' => $error,
-                'retry_count' => $job->attempts()
-            ]);
-        } else {
-            $job->release(60); // 延迟60秒重试
+            $taskId = isset($data['task_id']) ? (int)$data['task_id'] : 0;
+
+            if ($job->attempts() >= 3) {
+                $job->delete();
+                if ($taskId > 0) {
+                    $this->updateTaskStatus($taskId, 'error', [
+                        'end_time' => date('Y-m-d H:i:s'),
+                        'error' => $e->getMessage(),
+                        'retry_count' => $job->attempts()
+                    ]);
+                }
+            } else {
+                $job->release(60); // 延迟60秒重试
+            }
         }
     }
 
@@ -258,13 +262,16 @@ class InsertDataJob
      */
     protected function updateTaskStatus(int $taskId, string $status, array $data = []): void
     {
-        if ($taskId <= 0) return;
+        try {
+            $updateData = array_merge(['status' => $status, 'update_time' => date('Y-m-d H:i:s')], $data);
 
-        $updateData = array_merge(['status' => $status, 'update_time' => date('Y-m-d H:i:s')], $data);
+            Db::name('queue_tasks')
+                ->where('id', $taskId)
+                ->update($updateData);
 
-        Db::name('queue_tasks')
-            ->where('id', $taskId)
-            ->update($updateData);
+        } catch (\Exception $e) {
+            Log::error('更新任务状态失败: ' . $e->getMessage());
+        }
     }
 
     /**