Ver código fonte

Merge branch 'master' into 商品挂网统计

tangyuanwang 2 meses atrás
pai
commit
82328fd493

+ 2 - 1
.gitignore

@@ -13,4 +13,5 @@ npm-debug.log
 yarn-error.log
 /.idea
 /.vscode
-/public/.user.ini
+/public/.user.ini
+/public/uploads/exports

+ 5 - 3
app/Http/Controllers/Manager/Personnel/Department.php

@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
 use App\Http\Requests\Manager\Personnel\Department as Request;
 use App\Models\Manager\Personnel\Department as DepartmentModel;
 use App\Models\Manager\Personnel\Employee as EmployeeModel;
+use App\Models\Manager\Personnel\EmployeeDepartment as EmployeeDepartmentModel;
 
 
 /**
@@ -148,6 +149,7 @@ class Department extends Controller
         $where = ['id' => $id];
         $Department = $DepartmentModel->where($where)->first();
         if (!$Department) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $Department->toArray();
         //查询是否存在
         $map = ['name' => $all_data['name']];
         $data = $DepartmentModel->where($map)->where('id', '!=', $id)->first();
@@ -160,7 +162,7 @@ class Department extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $DepartmentModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('人员信息管理-部门管理', $admin_id, $table_name, $notes_type, $Department->toArray(), $all_data, '修改了部门' . $Department->name . '信息');
+        $this->addAdminHistory('人员信息管理-部门管理', $admin_id, $table_name, $notes_type,$oldData, $all_data, '修改了部门' . $oldData['name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }
@@ -172,7 +174,7 @@ class Department extends Controller
      * @date      2025-12-04
      * 
      */
-    public function set_status(Request $request, DepartmentModel $DepartmentModel, EmployeeModel $EmployeeModel)
+    public function set_status(Request $request, DepartmentModel $DepartmentModel, EmployeeDepartmentModel $EmployeeDepartmentModel)
     {
         // 验证参数
         $request->scene('set_status')->validate();
@@ -182,7 +184,7 @@ class Department extends Controller
         if ($status == 1) {
             // 查询部门下是否有员工
             $map = ['department_id' => $id];
-            $data = $EmployeeModel->where($map)->first();
+            $data = $EmployeeDepartmentModel->where($map)->first();
             if ($data)     return json_send(['code' => 'error', 'msg' => '该部门下存在员工,不能禁用']);
         }
         // 查询用户

+ 5 - 4
app/Http/Controllers/Manager/Personnel/Employee.php

@@ -44,7 +44,7 @@ class Employee extends Controller
         $role_ids = [];
         $city_id = request('city_id', '');
         $city_ids = request('city_ids', '');
-        $department_ids = request('city_ids', '');
+        $department_ids = request('department_ids', '');
         // 时间条件
         if ($start_time) $map[] = ['insert_time', '>=', strtotime($start_time)];
         if ($end_time) $map[]   = ['insert_time', '<=', strtotime($end_time)];
@@ -100,7 +100,7 @@ class Employee extends Controller
                 if (count($city_ids) > 0) {
                     $city_info = $CitysModel->whereIn('id', $city_ids)->pluck('name');
                 }
-                $result['data'][$key]['department_ids'] = substr($value['department_ids'], 1, strlen($value['department_ids']) -2);
+                $result['data'][$key]['department_ids'] = $value['department_ids'] != '' ? substr($value['department_ids'], 1, strlen($value['department_ids']) -2):'';
                 $result['data'][$key]['department_name'] = $department_name;
                 $result['data'][$key]['role_name'] = isset($role_info['name']) ? $role_info['name'] : '';
                 $result['data'][$key]['city_info'] = $city_info;
@@ -209,7 +209,7 @@ class Employee extends Controller
             $city_info = $CitysModel->whereIn('id', $city_ids)->pluck('name');
         }
         //截取字符串
-        $data['department_ids'] = substr($data['department_ids'], 1, strlen($data['department_ids']) -2);
+        $data['department_ids'] = $data['department_ids'] !='' ? substr($data['department_ids'], 1, strlen($data['department_ids']) -2) : '';
         $data['department_name'] = isset($department_info) ? array_column($department_info, 'name') : '';
         $data['role_name'] = isset($role_info['name']) ? $role_info['name'] : '';
         $data['city_info'] = $city_info;
@@ -275,6 +275,7 @@ class Employee extends Controller
         $where = ['id' => $id];
         $Employee = $EmployeeModel->where($where)->first();
         if (!$Employee) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $Employee->toArray();
         //查询是否存在
         $map = ['name' => $all_data['name']];
         $data = $EmployeeModel->where($map)->where('id', '!=', $id)->first();
@@ -290,7 +291,7 @@ class Employee extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $EmployeeModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('人员信息管理-员工管理', $admin_id, $table_name, $notes_type, $Employee->toarray(), $all_data, '修改了员工' . $Employee->name . '信息');
+        $this->addAdminHistory('人员信息管理-员工管理', $admin_id, $table_name, $notes_type,$oldData, $all_data, '修改了员工' .$oldData['name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 3 - 4
app/Http/Controllers/Manager/Personnel/Roles.php

@@ -152,9 +152,8 @@ class Roles extends Controller
         // 更新数据表
         $where = ['id' => $id];
         $Roles = $RolesModel->where($where)->first();
-        if (!$Roles) {
-            return json_send(['code' => 'error', 'msg' => '记录不存在']);;
-        }
+        if (!$Roles) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $Roles->toArray();
         $result =  $RolesModel->editRoles_content($Roles, $all_data);
         // 如果操作失败
         if (!$result)     return json_send(['code' => 'error', 'msg' => '修改失败']);
@@ -162,7 +161,7 @@ class Roles extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $RolesModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('人员信息管理-角色管理', $admin_id, $table_name, $notes_type, $Roles->toarray(), $all_data, '修改了角色' . $Roles->name . '信息');
+        $this->addAdminHistory('人员信息管理-角色管理', $admin_id, $table_name, $notes_type,$oldData, $all_data, '修改了角色' . $oldData['name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 838 - 32
app/Http/Controllers/Manager/Statistics/OverviewPanel.php

@@ -10,6 +10,10 @@ use Illuminate\Support\Facades\DB;
 use PhpOffice\PhpSpreadsheet\Spreadsheet;
 use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
 use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use Illuminate\Support\Carbon;
+use App\Models\Manager\Process\LowPriceGoodsMember as LowPriceGoodsMemberModel;
+use App\Models\Manager\Process\ViolationProductMember as ViolationProductMemberModel;
+use App\Servers\Aliyun\Oss;
 
 /**
  * 报表统计-概览面板
@@ -63,7 +67,8 @@ class OverviewPanel extends Controller
             ->select(['company_name', DB::raw('count(link_url) as count')])->orderby('count', 'desc')
             ->groupby('company_name')->get()->toarray();
         //执行下载
-        $this->Violation_export_download($result);
+        $oss_url = $this->Violation_export_download($result);
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $oss_url]);
     }
 
 
@@ -99,16 +104,24 @@ class OverviewPanel extends Controller
             $sheet->setCellValue('B' . $row, $item['count']);
             $row++;
         }
+        $file_id = date('YmdHis');
+        // 创建Excel文件
+        $filename = '禁止挂网链接数统计数据' . $file_id . '.xlsx';
+        $path = public_path('uploads/exports/');
+        $fullPath = $path. $filename;
+        if (!is_dir($path))         mkdir($path, 0777, true);
+
         // 生成 Excel 文件
         $writer = new Xlsx($spreadsheet);
+        $writer->save($fullPath);
+        // 清理
+        $spreadsheet->disconnectWorksheets();
+        unset($spreadsheet, $writer);
 
-        // 直接输出到浏览器(下载)
-        $filename = '禁止挂网链接数统计数据' . date('YmdHis') . '.xlsx';
-        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
-        header('Content-Disposition: attachment;filename="' . $filename . '"');
-        header('Cache-Control: max-age=0');
-        $writer->save('php://output');
-        exit;
+        $Oss                = new Oss();
+        $oss_url                = $Oss->uploadFile($filename, $fullPath);
+        if ($oss_url)           @unlink($fullPath);
+        return $oss_url;
     }
 
     /**
@@ -153,7 +166,8 @@ class OverviewPanel extends Controller
             ->select(['company_name', DB::raw('count(company_name) as count')])->orderby('count', 'desc')
             ->groupby('company_name')->get()->toarray();
         //执行下载
-        $this->ViolationCompany_export_download($result);
+        $oss_url = $this->ViolationCompany_export_download($result);
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $oss_url]);
     }
 
     /**
@@ -189,16 +203,24 @@ class OverviewPanel extends Controller
             $sheet->setCellValue('B' . $row, $item['count']);
             $row++;
         }
+        $file_id = date('YmdHis');
+        // 创建Excel文件
+        $filename = '禁止挂网公司月度统计数据' . $file_id . '.xlsx';
+        $path = public_path('uploads/exports/');
+        $fullPath = $path. $filename;
+        if (!is_dir($path))         mkdir($path, 0777, true);
+
         // 生成 Excel 文件
         $writer = new Xlsx($spreadsheet);
+        $writer->save($fullPath);
+        // 清理
+        $spreadsheet->disconnectWorksheets();
+        unset($spreadsheet, $writer);
 
-        // 直接输出到浏览器(下载)
-        $filename = '禁止挂网公司月度统计数据' . date('YmdHis') . '.xlsx';
-        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
-        header('Content-Disposition: attachment;filename="' . $filename . '"');
-        header('Cache-Control: max-age=0');
-        $writer->save('php://output');
-        exit;
+        $Oss                = new Oss();
+        $oss_url                = $Oss->uploadFile($filename, $fullPath);
+        if ($oss_url)           @unlink($fullPath);
+        return $oss_url;
     }
 
 
@@ -244,7 +266,8 @@ class OverviewPanel extends Controller
             ->select(['company_name', DB::raw('count(link_url) as count')])->orderby('count', 'desc')
             ->groupby('company_name')->get()->toarray();
         //执行下载
-        $this->LowPrice_export_download($result);
+        $oss_url = $this->LowPrice_export_download($result);
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $oss_url]);
     }
 
     /**
@@ -280,16 +303,24 @@ class OverviewPanel extends Controller
             $sheet->setCellValue('B' . $row, $item['count']);
             $row++;
         }
+        $file_id = date('YmdHis');
+        // 创建Excel文件
+        $filename = '低价违规挂网链接数统计数据' . $file_id . '.xlsx';
+        $path = public_path('uploads/exports/');
+        $fullPath = $path. $filename;
+        if (!is_dir($path))         mkdir($path, 0777, true);
+
         // 生成 Excel 文件
         $writer = new Xlsx($spreadsheet);
+        $writer->save($fullPath);
+        // 清理
+        $spreadsheet->disconnectWorksheets();
+        unset($spreadsheet, $writer);
 
-        // 直接输出到浏览器(下载)
-        $filename = '低价违规挂网链接数统计数据' . date('YmdHis') . '.xlsx';
-        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
-        header('Content-Disposition: attachment;filename="' . $filename . '"');
-        header('Cache-Control: max-age=0');
-        $writer->save('php://output');
-        exit;
+        $Oss                = new Oss();
+        $oss_url                = $Oss->uploadFile($filename, $fullPath);
+        if ($oss_url)           @unlink($fullPath);
+        return $oss_url;
     }
 
     /*
@@ -334,7 +365,8 @@ class OverviewPanel extends Controller
             ->select(['company_name', DB::raw('count(company_name) as count')])->orderby('count', 'desc')
             ->groupby('company_name')->get()->toarray();
         //执行下载
-        $this->LowPriceCompany_export_download($result);
+        $oss_url = $this->LowPriceCompany_export_download($result);
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $oss_url]);
     }
     /**
      * 低价违规挂网公司月度统计-导出下载
@@ -369,15 +401,789 @@ class OverviewPanel extends Controller
             $sheet->setCellValue('B' . $row, $item['count']);
             $row++;
         }
+        $file_id = date('YmdHis');
+        // 创建Excel文件
+        $filename = '低价违规挂网公司月度统计数据' . $file_id . '.xlsx';
+        $path = public_path('uploads/exports/');
+        $fullPath = $path. $filename;
+        if (!is_dir($path))         mkdir($path, 0777, true);
+
+        // 生成 Excel 文件
+        $writer = new Xlsx($spreadsheet);
+        $writer->save($fullPath);
+        // 清理
+        $spreadsheet->disconnectWorksheets();
+        unset($spreadsheet, $writer);
+
+        $Oss                = new Oss();
+        $oss_url                = $Oss->uploadFile($filename, $fullPath);
+        if ($oss_url)           @unlink($fullPath);
+        return $oss_url;
+    }
+
+    /**
+     * 商品数量趋势
+     * @author 唐远望
+     * @version   1.0
+     * @date      2025-12-29
+     * 
+     */
+    public function get_product_trend(request $request, LowPriceGoodsModel $LowPriceGoodsModel, ViolationProductModel $violationProductModel, LowPriceGoodsMemberModel $LowPriceGoodsMemberModel, ViolationProductMemberModel $ViolationProductMemberModel)
+    {
+        $request->scene('get_product_trend')->validate();
+        // 查询条件
+        $map  = [];
+        $status    = request('status', '');
+        $start_time = request('start_time', '');
+        $end_time = request('end_time', '');
+        $product_name = request('product_name', '');
+        $product_names = request('product_names', '');
+        $first_responsible_person = request('first_responsible_person', '');
+        $responsible_person = request('responsible_person', '');
+        $platform = request('platform', '');
+        $company_name = request('company_name', '');
+        $store_name = request('store_name', '');
+        $store_names = request('store_names', '');
+        $source_responsible_person = request('source_responsible_person', '');
+        $processing_status = request('processing_status', '');
+        $product_specs = request('product_specs', '');
+        $online_posting_cunt = request('online_posting_cunt', '');
+        $category_name = request('category_name', '');
+        // 其他条件
+        if ($product_name) $map[] = ['product_name', 'like', "%$product_name%"];
+        if ($store_name) $map[]   = ['store_name', 'like', "%$store_name%"];
+        if ($category_name) $map[] = ['category_name', 'like', "%$category_name%"];
+
+        //多选平台查询
+        if ($platform && is_string($platform)) {
+            $platform = explode(',', $platform);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('platform', $platform);
+            $violationProductModel = $violationProductModel->whereIn('platform', $platform);
+        }
+        //多选处理状态查询
+        if ($processing_status && is_string($processing_status)) {
+            $processing_status = explode(',', $processing_status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('processing_status', $processing_status);
+            $violationProductModel = $violationProductModel->whereIn('processing_status', $processing_status);
+        }
+        //多选状态查询
+        if ($status && is_string($status)) {
+            $status = explode(',', $status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('status', $status);
+            $violationProductModel = $violationProductModel->whereIn('status', $status);
+        }
+        //多选店铺名称查询
+        if ($store_names && is_string($store_names)) {
+            $store_names = explode(',', $store_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('store_name', $store_names);
+            $violationProductModel = $violationProductModel->whereIn('store_name', $store_names);
+        }
+        //多选违规挂网次数查询
+        if ($online_posting_cunt && is_string($online_posting_cunt)) {
+            $online_posting_cunt = explode(',', $online_posting_cunt);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('online_posting_cunt', $online_posting_cunt);
+            $violationProductModel = $violationProductModel->whereIn('online_posting_cunt', $online_posting_cunt);
+        }
+        //多选规格查询
+        if ($product_specs && is_string($product_specs)) {
+            $product_specs = explode(',', $product_specs);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_specs', $product_specs);
+            $violationProductModel = $violationProductModel->whereIn('product_specs', $product_specs);
+        }
+        //多选商品查询
+        if ($product_names && is_string($product_names)) {
+            $product_names = explode(',', $product_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_name', $product_names);
+            $violationProductModel = $violationProductModel->whereIn('product_name', $product_names);
+        }
+        //多选公司查询
+        if ($company_name && is_string($company_name)) {
+            $company_name = explode(',', $company_name);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('company_name', $company_name);
+            $violationProductModel = $violationProductModel->whereIn('company_name', $company_name);
+        }
+        //多选第一责任人
+        if ($first_responsible_person && is_string($first_responsible_person)) {
+            $first_responsible_person = explode(',', $first_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选责任人
+        if ($responsible_person && is_string($responsible_person)) {
+            $responsible_person = explode(',', $responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选溯源责任人
+        if ($source_responsible_person && is_string($source_responsible_person)) {
+            $source_responsible_person = explode(',', $source_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        if ($start_time == '' || $end_time == '') {
+            $start_time = Carbon::now()->startOfMonth()->getTimestamp(); // 本月开始时间
+            $end_time = Carbon::today()->endOfDay()->getTimestamp(); // 今天结束时间 23:59:59
+        } else {
+            $start_time = strtotime($start_time . ' 00:00:00');
+            $end_time = strtotime($end_time . ' 23:59:59');
+        }
+        $low_price_result = $LowPriceGoodsModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(id) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $violation_product_result = $violationProductModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(id) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $moth_list = [];
+        $key_index = 0;
+        for ($i = $end_time; $i >= $start_time; $i -= 86400) {
+            $key_day = Carbon::createFromTimestamp($i)->format('Y-m-d');
+            $moth_list[$key_index]['date'] = $key_day;
+            $moth_list[$key_index]['low_price_totle'] = 0;
+            $moth_list[$key_index]['violation_product_totle'] = 0;
+            $moth_list[$key_index]['product_totle'] = 0;
+            if (isset($low_price_result[$key_day])) {
+                $moth_list[$key_index]['low_price_totle'] = $low_price_result[$key_day]['daily_total'];
+            }
+            if (isset($violation_product_result[$key_day])) {
+                $moth_list[$key_index]['violation_product_totle'] = $violation_product_result[$key_day]['daily_total'];
+            }
+            $moth_list[$key_index]['product_totle'] = $moth_list[$key_index]['low_price_totle'] + $moth_list[$key_index]['violation_product_totle'];
+            $key_index++;
+        }
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $moth_list]);
+    }
+
+    /**
+     * 商品数量趋势-导出
+     * @author 唐远望
+     * @version   1.0
+     * @date      2025-12-29
+     * 
+     */
+    public function product_trend_export(request $request, LowPriceGoodsModel $LowPriceGoodsModel, ViolationProductModel $violationProductModel, LowPriceGoodsMemberModel $LowPriceGoodsMemberModel, ViolationProductMemberModel $ViolationProductMemberModel)
+    {
+        $request->scene('product_trend_export')->validate();
+        // 查询条件
+        $map  = [];
+        $status    = request('status', '');
+        $start_time = request('start_time', '');
+        $end_time = request('end_time', '');
+        $product_name = request('product_name', '');
+        $product_names = request('product_names', '');
+        $first_responsible_person = request('first_responsible_person', '');
+        $responsible_person = request('responsible_person', '');
+        $platform = request('platform', '');
+        $company_name = request('company_name', '');
+        $store_name = request('store_name', '');
+        $store_names = request('store_names', '');
+        $source_responsible_person = request('source_responsible_person', '');
+        $processing_status = request('processing_status', '');
+        $product_specs = request('product_specs', '');
+        $online_posting_cunt = request('online_posting_cunt', '');
+        $category_name = request('category_name', '');
+        // 其他条件
+        if ($product_name) $map[] = ['product_name', 'like', "%$product_name%"];
+        if ($store_name) $map[]   = ['store_name', 'like', "%$store_name%"];
+        if ($category_name) $map[] = ['category_name', 'like', "%$category_name%"];
+
+        //多选平台查询
+        if ($platform && is_string($platform)) {
+            $platform = explode(',', $platform);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('platform', $platform);
+            $violationProductModel = $violationProductModel->whereIn('platform', $platform);
+        }
+        //多选处理状态查询
+        if ($processing_status && is_string($processing_status)) {
+            $processing_status = explode(',', $processing_status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('processing_status', $processing_status);
+            $violationProductModel = $violationProductModel->whereIn('processing_status', $processing_status);
+        }
+        //多选状态查询
+        if ($status && is_string($status)) {
+            $status = explode(',', $status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('status', $status);
+            $violationProductModel = $violationProductModel->whereIn('status', $status);
+        }
+        //多选店铺名称查询
+        if ($store_names && is_string($store_names)) {
+            $store_names = explode(',', $store_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('store_name', $store_names);
+            $violationProductModel = $violationProductModel->whereIn('store_name', $store_names);
+        }
+        //多选违规挂网次数查询
+        if ($online_posting_cunt && is_string($online_posting_cunt)) {
+            $online_posting_cunt = explode(',', $online_posting_cunt);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('online_posting_cunt', $online_posting_cunt);
+            $violationProductModel = $violationProductModel->whereIn('online_posting_cunt', $online_posting_cunt);
+        }
+        //多选规格查询
+        if ($product_specs && is_string($product_specs)) {
+            $product_specs = explode(',', $product_specs);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_specs', $product_specs);
+            $violationProductModel = $violationProductModel->whereIn('product_specs', $product_specs);
+        }
+        //多选商品查询
+        if ($product_names && is_string($product_names)) {
+            $product_names = explode(',', $product_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_name', $product_names);
+            $violationProductModel = $violationProductModel->whereIn('product_name', $product_names);
+        }
+        //多选公司查询
+        if ($company_name && is_string($company_name)) {
+            $company_name = explode(',', $company_name);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('company_name', $company_name);
+            $violationProductModel = $violationProductModel->whereIn('company_name', $company_name);
+        }
+        //多选第一责任人
+        if ($first_responsible_person && is_string($first_responsible_person)) {
+            $first_responsible_person = explode(',', $first_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选责任人
+        if ($responsible_person && is_string($responsible_person)) {
+            $responsible_person = explode(',', $responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选溯源责任人
+        if ($source_responsible_person && is_string($source_responsible_person)) {
+            $source_responsible_person = explode(',', $source_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        if ($start_time == '' || $end_time == '') {
+            $start_time = Carbon::now()->startOfMonth()->getTimestamp(); // 本月开始时间
+            $end_time = Carbon::today()->endOfDay()->getTimestamp(); // 今天结束时间 23:59:59
+        } else {
+            $start_time = strtotime($start_time . ' 00:00:00');
+            $end_time = strtotime($end_time . ' 23:59:59');
+        }
+        $low_price_result = $LowPriceGoodsModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(id) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $violation_product_result = $violationProductModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(id) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $moth_list = [];
+        $key_index = 0;
+        for ($i = $end_time; $i >= $start_time; $i -= 86400) {
+            $key_day = Carbon::createFromTimestamp($i)->format('Y-m-d');
+            $moth_list[$key_index]['date'] = $key_day;
+            $moth_list[$key_index]['low_price_totle'] = 0;
+            $moth_list[$key_index]['violation_product_totle'] = 0;
+            $moth_list[$key_index]['product_totle'] = 0;
+            if (isset($low_price_result[$key_day])) {
+                $moth_list[$key_index]['low_price_totle'] = $low_price_result[$key_day]['daily_total'];
+            }
+            if (isset($violation_product_result[$key_day])) {
+                $moth_list[$key_index]['violation_product_totle'] = $violation_product_result[$key_day]['daily_total'];
+            }
+            $moth_list[$key_index]['product_totle'] = $moth_list[$key_index]['low_price_totle'] + $moth_list[$key_index]['violation_product_totle'];
+            $key_index++;
+        }
+        //执行下载
+        $oss_url = $this->product_trend_export_download($moth_list);
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $oss_url]);
+    }
+
+    /**
+     * 商品数量趋势-导出下载
+     * @author 唐远望
+     * @version   1.0
+     * @date      2025-12-29
+     * 
+     */
+    public function product_trend_export_download($data)
+    {
+        // 创建一个新的 Spreadsheet 对象
+        $spreadsheet = new Spreadsheet();
+        $sheet = $spreadsheet->getActiveSheet();
+
+        //合并单元格
+        $sheet->mergeCells('A1:D1');
+        $sheet->setCellValue('A1', '商品数量趋势统计数据(导出时间:' . date('Y-m-d H:i:s', time()) . ')'); // 设置合并后的单元格内容
+        // 获取合并后的单元格样式对象
+        $style = $sheet->getStyle('A1');
+        // 设置水平居中和垂直居中
+        $style->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setVertical(Alignment::VERTICAL_CENTER);
+        // 然后设置行高以适应两行文本
+        $sheet->getRowDimension(1)->setRowHeight(40); // 设置行高,单位是磅(point)
+        // 设置表头
+        $sheet->setCellValue('A2', '日期');
+        $sheet->setCellValue('B2', '低价商品数量');
+        $sheet->setCellValue('C2', '禁止商品数量');
+        $sheet->setCellValue('D2', '总商品数量');
+
+        // 填充数据
+        $row = 3; // 从第3行开始
+        foreach ($data as $item) {
+            $sheet->setCellValue('A' . $row, $item['date']);
+            $sheet->setCellValue('B' . $row, $item['low_price_totle']);
+            $sheet->setCellValue('C' . $row, $item['violation_product_totle']);
+            $sheet->setCellValue('D' . $row, $item['product_totle']);
+            $row++;
+        }
+
+        $file_id = date('YmdHis');
+        // 创建Excel文件
+        $filename = '商品数量趋势统计数据' . $file_id . '.xlsx';
+        $path = public_path('uploads/exports/');
+        $fullPath = $path. $filename;
+        if (!is_dir($path))         mkdir($path, 0777, true);
+
+        // 生成 Excel 文件
+        $writer = new Xlsx($spreadsheet);
+        $writer->save($fullPath);
+        // 清理
+        $spreadsheet->disconnectWorksheets();
+        unset($spreadsheet, $writer);
+
+        $Oss                = new Oss();
+        $oss_url                = $Oss->uploadFile($filename, $fullPath);
+        if ($oss_url)           @unlink($fullPath);
+        return $oss_url;
+    }
+
+    /**
+     * 商家数量趋势
+     * @author 唐远望
+     * @version   1.0
+     * @date      2025-12-29
+     * 
+     */
+    public function get_store_trend(Request $request, LowPriceGoodsModel $LowPriceGoodsModel, ViolationProductModel $violationProductModel, LowPriceGoodsMemberModel $LowPriceGoodsMemberModel, ViolationProductMemberModel $ViolationProductMemberModel)
+    {
+        $request->scene('get_store_trend')->validate();
+        // 查询条件
+        $map  = [];
+        $status    = request('status', '');
+        $start_time = request('start_time', '');
+        $end_time = request('end_time', '');
+        $product_name = request('product_name', '');
+        $product_names = request('product_names', '');
+        $first_responsible_person = request('first_responsible_person', '');
+        $responsible_person = request('responsible_person', '');
+        $platform = request('platform', '');
+        $company_name = request('company_name', '');
+        $store_name = request('store_name', '');
+        $store_names = request('store_names', '');
+        $source_responsible_person = request('source_responsible_person', '');
+        $processing_status = request('processing_status', '');
+        $product_specs = request('product_specs', '');
+        $online_posting_cunt = request('online_posting_cunt', '');
+        $category_name = request('category_name', '');
+        // 其他条件
+        if ($product_name) $map[] = ['product_name', 'like', "%$product_name%"];
+        if ($store_name) $map[]   = ['store_name', 'like', "%$store_name%"];
+        if ($category_name) $map[] = ['category_name', 'like', "%$category_name%"];
+
+        //多选平台查询
+        if ($platform && is_string($platform)) {
+            $platform = explode(',', $platform);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('platform', $platform);
+            $violationProductModel = $violationProductModel->whereIn('platform', $platform);
+        }
+        //多选处理状态查询
+        if ($processing_status && is_string($processing_status)) {
+            $processing_status = explode(',', $processing_status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('processing_status', $processing_status);
+            $violationProductModel = $violationProductModel->whereIn('processing_status', $processing_status);
+        }
+        //多选状态查询
+        if ($status && is_string($status)) {
+            $status = explode(',', $status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('status', $status);
+            $violationProductModel = $violationProductModel->whereIn('status', $status);
+        }
+        //多选店铺名称查询
+        if ($store_names && is_string($store_names)) {
+            $store_names = explode(',', $store_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('store_name', $store_names);
+            $violationProductModel = $violationProductModel->whereIn('store_name', $store_names);
+        }
+        //多选违规挂网次数查询
+        if ($online_posting_cunt && is_string($online_posting_cunt)) {
+            $online_posting_cunt = explode(',', $online_posting_cunt);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('online_posting_cunt', $online_posting_cunt);
+            $violationProductModel = $violationProductModel->whereIn('online_posting_cunt', $online_posting_cunt);
+        }
+        //多选规格查询
+        if ($product_specs && is_string($product_specs)) {
+            $product_specs = explode(',', $product_specs);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_specs', $product_specs);
+            $violationProductModel = $violationProductModel->whereIn('product_specs', $product_specs);
+        }
+        //多选商品查询
+        if ($product_names && is_string($product_names)) {
+            $product_names = explode(',', $product_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_name', $product_names);
+            $violationProductModel = $violationProductModel->whereIn('product_name', $product_names);
+        }
+        //多选公司查询
+        if ($company_name && is_string($company_name)) {
+            $company_name = explode(',', $company_name);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('company_name', $company_name);
+            $violationProductModel = $violationProductModel->whereIn('company_name', $company_name);
+        }
+        //多选第一责任人
+        if ($first_responsible_person && is_string($first_responsible_person)) {
+            $first_responsible_person = explode(',', $first_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选责任人
+        if ($responsible_person && is_string($responsible_person)) {
+            $responsible_person = explode(',', $responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选溯源责任人
+        if ($source_responsible_person && is_string($source_responsible_person)) {
+            $source_responsible_person = explode(',', $source_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        if ($start_time == '' || $end_time == '') {
+            $start_time = Carbon::now()->startOfMonth()->getTimestamp(); // 本月开始时间
+            $end_time = Carbon::today()->endOfDay()->getTimestamp(); // 今天结束时间 23:59:59
+        } else {
+            $start_time = strtotime($start_time . ' 00:00:00');
+            $end_time = strtotime($end_time . ' 23:59:59');
+        }
+        $low_price_result = $LowPriceGoodsModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(DISTINCT store_name) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $violation_product_result = $violationProductModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(DISTINCT store_name) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $moth_list = [];
+        $key_index = 0;
+        for ($i = $end_time; $i >= $start_time; $i -= 86400) {
+            $key_day = Carbon::createFromTimestamp($i)->format('Y-m-d');
+            $moth_list[$key_index]['date'] = $key_day;
+            $moth_list[$key_index]['low_price_store_totle'] = 0;
+            $moth_list[$key_index]['violation_product_store_totle'] = 0;
+            $moth_list[$key_index]['product_store_totle'] = 0;
+            if (isset($low_price_result[$key_day])) {
+                $moth_list[$key_index]['low_price_store_totle'] = $low_price_result[$key_day]['daily_total'];
+            }
+            if (isset($violation_product_result[$key_day])) {
+                $moth_list[$key_index]['violation_product_store_totle'] = $violation_product_result[$key_day]['daily_total'];
+            }
+            $moth_list[$key_index]['product_store_totle'] = $moth_list[$key_index]['low_price_store_totle'] + $moth_list[$key_index]['violation_product_store_totle'];
+            $key_index++;
+        }
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $moth_list]);
+    }
+
+    /**
+     * 商家数量趋势-导出
+     * @author 唐远望
+     * @version   1.0
+     * @date      2025-12-29
+     * 
+     */
+    public function store_trend_export(Request $request, LowPriceGoodsModel $LowPriceGoodsModel, ViolationProductModel $violationProductModel, LowPriceGoodsMemberModel $LowPriceGoodsMemberModel, ViolationProductMemberModel $ViolationProductMemberModel)
+    {
+        $request->scene('store_trend_export')->validate();
+        // 查询条件
+        $map  = [];
+        $status    = request('status', '');
+        $start_time = request('start_time', '');
+        $end_time = request('end_time', '');
+        $product_name = request('product_name', '');
+        $product_names = request('product_names', '');
+        $first_responsible_person = request('first_responsible_person', '');
+        $responsible_person = request('responsible_person', '');
+        $platform = request('platform', '');
+        $company_name = request('company_name', '');
+        $store_name = request('store_name', '');
+        $store_names = request('store_names', '');
+        $source_responsible_person = request('source_responsible_person', '');
+        $processing_status = request('processing_status', '');
+        $product_specs = request('product_specs', '');
+        $online_posting_cunt = request('online_posting_cunt', '');
+        $category_name = request('category_name', '');
+        // 其他条件
+        if ($product_name) $map[] = ['product_name', 'like', "%$product_name%"];
+        if ($store_name) $map[]   = ['store_name', 'like', "%$store_name%"];
+        if ($category_name) $map[] = ['category_name', 'like', "%$category_name%"];
+
+        //多选平台查询
+        if ($platform && is_string($platform)) {
+            $platform = explode(',', $platform);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('platform', $platform);
+            $violationProductModel = $violationProductModel->whereIn('platform', $platform);
+        }
+        //多选处理状态查询
+        if ($processing_status && is_string($processing_status)) {
+            $processing_status = explode(',', $processing_status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('processing_status', $processing_status);
+            $violationProductModel = $violationProductModel->whereIn('processing_status', $processing_status);
+        }
+        //多选状态查询
+        if ($status && is_string($status)) {
+            $status = explode(',', $status);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('status', $status);
+            $violationProductModel = $violationProductModel->whereIn('status', $status);
+        }
+        //多选店铺名称查询
+        if ($store_names && is_string($store_names)) {
+            $store_names = explode(',', $store_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('store_name', $store_names);
+            $violationProductModel = $violationProductModel->whereIn('store_name', $store_names);
+        }
+        //多选违规挂网次数查询
+        if ($online_posting_cunt && is_string($online_posting_cunt)) {
+            $online_posting_cunt = explode(',', $online_posting_cunt);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('online_posting_cunt', $online_posting_cunt);
+            $violationProductModel = $violationProductModel->whereIn('online_posting_cunt', $online_posting_cunt);
+        }
+        //多选规格查询
+        if ($product_specs && is_string($product_specs)) {
+            $product_specs = explode(',', $product_specs);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_specs', $product_specs);
+            $violationProductModel = $violationProductModel->whereIn('product_specs', $product_specs);
+        }
+        //多选商品查询
+        if ($product_names && is_string($product_names)) {
+            $product_names = explode(',', $product_names);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_name', $product_names);
+            $violationProductModel = $violationProductModel->whereIn('product_name', $product_names);
+        }
+        //多选公司查询
+        if ($company_name && is_string($company_name)) {
+            $company_name = explode(',', $company_name);
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('company_name', $company_name);
+            $violationProductModel = $violationProductModel->whereIn('company_name', $company_name);
+        }
+        //多选第一责任人
+        if ($first_responsible_person && is_string($first_responsible_person)) {
+            $first_responsible_person = explode(',', $first_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选责任人
+        if ($responsible_person && is_string($responsible_person)) {
+            $responsible_person = explode(',', $responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        //多选溯源责任人
+        if ($source_responsible_person && is_string($source_responsible_person)) {
+            $source_responsible_person = explode(',', $source_responsible_person);
+            $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+            $subQuery = $ViolationProductMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid');
+            $violationProductModel = $violationProductModel->whereIn('id', function ($query1) use ($subQuery) {
+                $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1');
+            });
+        }
+        if ($start_time == '' || $end_time == '') {
+            $start_time = Carbon::now()->startOfMonth()->getTimestamp(); // 本月开始时间
+            $end_time = Carbon::today()->endOfDay()->getTimestamp(); // 今天结束时间 23:59:59
+        } else {
+            $start_time = strtotime($start_time . ' 00:00:00');
+            $end_time = strtotime($end_time . ' 23:59:59');
+        }
+        $low_price_result = $LowPriceGoodsModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(DISTINCT store_name) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $violation_product_result = $violationProductModel->where('insert_time', '>=', $start_time)
+            ->where('insert_time', '<=', $end_time)->where($map)
+            ->select(
+                DB::raw("FROM_UNIXTIME(insert_time, '%Y-%m-%d') AS date"),
+                DB::raw('COUNT(DISTINCT store_name) as daily_total'),
+            )
+            ->groupBy('date')
+            ->orderBy('date')
+            ->get()->keyBy('date')->toarray();
+        $moth_list = [];
+        $key_index = 0;
+        for ($i = $end_time; $i >= $start_time; $i -= 86400) {
+            $key_day = Carbon::createFromTimestamp($i)->format('Y-m-d');
+            $moth_list[$key_index]['date'] = $key_day;
+            $moth_list[$key_index]['low_price_store_totle'] = 0;
+            $moth_list[$key_index]['violation_product_store_totle'] = 0;
+            $moth_list[$key_index]['product_store_totle'] = 0;
+            if (isset($low_price_result[$key_day])) {
+                $moth_list[$key_index]['low_price_store_totle'] = $low_price_result[$key_day]['daily_total'];
+            }
+            if (isset($violation_product_result[$key_day])) {
+                $moth_list[$key_index]['violation_product_store_totle'] = $violation_product_result[$key_day]['daily_total'];
+            }
+            $moth_list[$key_index]['product_store_totle'] = $moth_list[$key_index]['low_price_store_totle'] + $moth_list[$key_index]['violation_product_store_totle'];
+            $key_index++;
+        }
+        // 执行下载
+        $oss_url = $this->store_trend_export_download($moth_list);
+        return  json_send(['code' => 'success', 'msg' => '获取成功', 'data' => $oss_url]);
+    }
+    /**
+     * 商家数量趋势-导出下载
+     * @author 唐远望
+     * @version   1.0
+     * @date      2025-12-29
+     * 
+     */
+    public function store_trend_export_download($data)
+    {
+        // 创建一个新的 Spreadsheet 对象
+        $spreadsheet = new Spreadsheet();
+        $sheet = $spreadsheet->getActiveSheet();
+
+        //合并单元格
+        $sheet->mergeCells('A1:D1');
+        $sheet->setCellValue('A1', '商家数量趋势统计数据(导出时间:' . date('Y-m-d H:i:s', time()) . ')'); // 设置合并后的单元格内容
+        // 获取合并后的单元格样式对象
+        $style = $sheet->getStyle('A1');
+        // 设置水平居中和垂直居中
+        $style->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setVertical(Alignment::VERTICAL_CENTER);
+        // 然后设置行高以适应两行文本
+        $sheet->getRowDimension(1)->setRowHeight(40); // 设置行高,单位是磅(point)
+        // 设置表头
+        $sheet->setCellValue('A2', '日期');
+        $sheet->setCellValue('B2', '低价商品商家数量');
+        $sheet->setCellValue('C2', '禁止商品商家数量');
+        $sheet->setCellValue('D2', '总商品商家数量');
+
+        // 填充数据
+        $row = 3; // 从第3行开始
+        foreach ($data as $item) {
+            $sheet->setCellValue('A' . $row, $item['date']);
+            $sheet->setCellValue('B' . $row, $item['low_price_store_totle']);
+            $sheet->setCellValue('C' . $row, $item['violation_product_store_totle']);
+            $sheet->setCellValue('D' . $row, $item['product_store_totle']);
+            $row++;
+        }
+
+        $file_id = date('YmdHis');
+        // 创建Excel文件
+        $filename = '商家数量趋势统计数据_' . $file_id . '.xlsx';
+        $path = public_path('uploads/exports/');
+        $fullPath = $path. $filename;
+        if (!is_dir($path))         mkdir($path, 0777, true);
         // 生成 Excel 文件
         $writer = new Xlsx($spreadsheet);
+        $writer->save($fullPath);
+        // 清理
+        $spreadsheet->disconnectWorksheets();
+        unset($spreadsheet, $writer);
 
-        // 直接输出到浏览器(下载)
-        $filename = '低价违规挂网公司月度统计数据' . date('YmdHis') . '.xlsx';
-        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
-        header('Content-Disposition: attachment;filename="' . $filename . '"');
-        header('Cache-Control: max-age=0');
-        $writer->save('php://output');
-        exit;
+        $Oss                = new Oss();
+        $oss_url                = $Oss->uploadFile($filename, $fullPath);
+        if ($oss_url)           @unlink($fullPath);
+        return $oss_url;
     }
 }

+ 2 - 1
app/Http/Controllers/Manager/WashConfig/CompanyCategory.php

@@ -153,6 +153,7 @@ class CompanyCategory extends Controller
         $where = ['id' => $id];
         $CompanyCategory = $CompanyCategoryModel->where($where)->first();
         if (!$CompanyCategory) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $CompanyCategory->toArray();
         $result =  $CompanyCategoryModel->editCompanyCategory_content($CompanyCategory, $all_data);
         // 如果操作失败
         if (!$result)     return json_send(['code' => 'error', 'msg' => '修改失败']);
@@ -160,7 +161,7 @@ class CompanyCategory extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $CompanyCategoryModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('清洗配置-公司分类管理', $admin_id, $table_name, $notes_type,$CompanyCategory->toarray(),$all_data, '修改了分类' .$CompanyCategory->name . '信息');
+        $this->addAdminHistory('清洗配置-公司分类管理', $admin_id, $table_name, $notes_type,$oldData,$all_data, '修改了分类' .$oldData['name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 2 - 1
app/Http/Controllers/Manager/WashConfig/LowPriceGoods.php

@@ -214,6 +214,7 @@ class LowPriceGoods extends Controller
         $where = ['id' => $id];
         $LowProduct = $LowPriceGoodsModel->where($where)->first();
         if (!$LowProduct) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $LowProduct->toarray();
         //如果修改采集周期,则校验采集时间是否在明天以后
         if ($sampling_cycle != $LowProduct->sampling_cycle) {
             $allow_sampling_time = Carbon::tomorrow()->startOfDay()->getTimestamp(); // 明天的开始时间(允许开始采集时间校验)
@@ -226,7 +227,7 @@ class LowPriceGoods extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $LowPriceGoodsModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('清洗配置-低价商品管理', $admin_id, $table_name, $notes_type, $LowProduct->toarray(), $all_data, '修改了低价商品' . $LowProduct->product_name . '信息');
+        $this->addAdminHistory('清洗配置-低价商品管理', $admin_id, $table_name, $notes_type,$oldData, $all_data, '修改了低价商品' . $oldData['product_name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 2 - 1
app/Http/Controllers/Manager/WashConfig/ProductCategory.php

@@ -153,6 +153,7 @@ class ProductCategory extends Controller
         $where = ['id' => $id];
         $ProductCategory = $ProductCategoryModel->where($where)->first();
         if (!$ProductCategory) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $ProductCategory->toarray();
         $result =  $ProductCategoryModel->editProductCategory_content($ProductCategory, $all_data);
         // 如果操作失败
         if (!$result)     return json_send(['code' => 'error', 'msg' => '修改失败']);
@@ -160,7 +161,7 @@ class ProductCategory extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $ProductCategoryModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('清洗配置-商品分类管理', $admin_id, $table_name, $notes_type, $ProductCategory->toarray(), $all_data, '修改了商品分类' . $ProductCategory->name . '信息');
+        $this->addAdminHistory('清洗配置-商品分类管理', $admin_id, $table_name, $notes_type,$oldData, $all_data, '修改了商品分类' .$oldData['name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 2 - 1
app/Http/Controllers/Manager/WashConfig/ViolationProduct.php

@@ -214,6 +214,7 @@ class ViolationProduct extends Controller
         $where = ['id' => $id];
         $ViolationProduct = $ViolationProductModel->where($where)->first();
         if (!$ViolationProduct) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $ViolationProduct->toarray();
         //如果修改采集周期,则校验采集时间是否在明天以后
         if ($sampling_cycle != $ViolationProduct->sampling_cycle) {
             $allow_sampling_time = Carbon::tomorrow()->startOfDay()->getTimestamp(); // 明天的开始时间(允许开始采集时间校验)
@@ -226,7 +227,7 @@ class ViolationProduct extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $ViolationProductModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('清洗配置-禁止商品管理', $admin_id, $table_name, $notes_type, $ViolationProduct->toarray(), $all_data, '修改了禁止商品' . $ViolationProduct->product_name . '信息');
+        $this->addAdminHistory('清洗配置-禁止商品管理', $admin_id, $table_name, $notes_type,$oldData, $all_data, '修改了禁止商品' . $oldData['product_name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 2 - 1
app/Http/Controllers/Manager/WashConfig/ViolationStore.php

@@ -210,6 +210,7 @@ class ViolationStore extends Controller
         $where = ['id' => $id];
         $ViolationStore = $ViolationStoreModel->where($where)->first();
         if (!$ViolationStore) return json_send(['code' => 'error', 'msg' => '记录不存在']);
+        $oldData = $ViolationStore->toarray();
         $result =  $ViolationStoreModel->updateViolationStore($ViolationStore, $all_data);
         // 如果操作失败
         if (!$result)     return json_send(['code' => 'error', 'msg' => '修改失败']);
@@ -217,7 +218,7 @@ class ViolationStore extends Controller
         $admin_id   = request('access_token.uid', 0); //用户ID
         $table_name = $ViolationStoreModel->getTable();
         $notes_type = 2; //操作类型,1添加,2修改,3=删除
-        $this->addAdminHistory('清洗配置-公司管理', $admin_id, $table_name, $notes_type, $ViolationStore->toarray(), $all_data, '修改了公司' . $ViolationStore->company_name . '信息');
+        $this->addAdminHistory('清洗配置-公司管理', $admin_id, $table_name, $notes_type, $oldData, $all_data, '修改了公司' . $oldData['company_name'] . '信息');
         // 告知结果
         return json_send(['code' => 'success', 'msg' => '修改成功']);
     }

+ 4 - 0
app/Http/Requests/Manager/Statistics/OverviewPanel.php

@@ -47,6 +47,10 @@ class OverviewPanel extends BaseRequest
         'getViolationLinkCount'   => ['page','limit'],
         'getLowPriceLinkCount'   => ['page','limit'],
         'get_violation_company_count'   => ['page','limit'],
+        'get_product_trend'       => [],
+        'product_trend_export'    => [],
+        'get_store_trend'         => [],
+        'store_trend_export'      => [],
     ];
 
     /**

+ 8 - 0
routes/manager.php

@@ -259,3 +259,11 @@ Route::any('statistics/overview_panel/low_price_export', [App\Http\Controllers\M
 Route::any('statistics/overview_panel/get_low_price_company_count', [App\Http\Controllers\Manager\Statistics\OverviewPanel::class, 'getLowPriceCompanyCount']);
 //报表统计-低价违规挂网公司月度统计-导出
 Route::any('statistics/overview_panel/low_price_company_export', [App\Http\Controllers\Manager\Statistics\OverviewPanel::class, 'low_price_company_export']);
+//报表统计-商品数量趋势
+Route::any('statistics/overview_panel/get_product_trend', [App\Http\Controllers\Manager\Statistics\OverviewPanel::class, 'get_product_trend']);
+//报表统计-商品数量趋势-导出
+Route::any('statistics/overview_panel/product_trend_export', [App\Http\Controllers\Manager\Statistics\OverviewPanel::class, 'product_trend_export']);
+//报表统计-商家数量趋势
+Route::any('statistics/overview_panel/get_store_trend', [App\Http\Controllers\Manager\Statistics\OverviewPanel::class, 'get_store_trend']);
+//报表统计-商家数量趋势-导出
+Route::any('statistics/overview_panel/store_trend_export', [App\Http\Controllers\Manager\Statistics\OverviewPanel::class, 'store_trend_export']);