Ver código fonte

药检报告 API 接口

LAPTOP-VT1IP978\suxio 2 semanas atrás
pai
commit
2306108359

+ 55 - 3
app/Http/Controllers/AlihealthController.php

@@ -3,15 +3,67 @@
 namespace App\Http\Controllers;
 
 use App\Services\AlihealthService;
+use Carbon\Carbon;
+use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 
 class AlihealthController extends Controller
 {
+    /**
+     * 查询上游企业的待签收药检报告信息
+     * (?begin_time=2025-11-01 00:00:00&end_time=2025-11-31 23:59:59&page=1&page_size=20)
+     * @param Request $request
+     * @param AlihealthService $service
+     * @return JsonResponse
+     * @throws \Exception
+     */
+    public function queryDrugReport(Request $request, AlihealthService $service)
+    {
+        $beginTime = $request->get("begin_time") ?? Carbon::now()->startOfMonth()->toDateTimeString();
+        $endTime = $request->get("end_time") ?? Carbon::now()->endOfMonth()->toDateTimeString();
+        $page = $request->get("page") ?? 1;
+        $pageSize = $request->get("page_size") ?? 20;
+        $data = $service->queryDrugReport($beginTime, $endTime, $page, $pageSize);
+        dd($data);
+        return response()->json($data);
+    }
+
+    /**
+     * 查询上传报告信息接口
+     * (?begin_time=2025-03-01 00:00:00&end_time=2025-03-31 23:59:59&page=1&page_size=20&is_seal=0)
+     * @param Request $request
+     * @param AlihealthService $service
+     * @return JsonResponse
+     * @throws \Exception
+     */
     public function querySealDrugReport(Request $request, AlihealthService $service)
     {
-        $beginTime = "2025-03-01 00:00:00";
-        $endTime = "2025-03-31 23:59:59";
-        $data = $service->querySealDrugReport($beginTime, $endTime);
+        $beginTime = $request->get("begin_time") ?? Carbon::now()->startOfMonth()->toDateTimeString();
+        $endTime = $request->get("end_time") ?? Carbon::now()->endOfMonth()->toDateTimeString();
+        $page = $request->get("page") ?? 1;
+        $pageSize = $request->get("page_size") ?? 20;
+        $isSeal = $request->get("is_seal") ?? 0;
+        $data = $service->querySealDrugReport($beginTime, $endTime, $page, $pageSize, $isSeal);
+        dd($data);
+        return response()->json($data);
+    }
+
+    /**
+     * 药检报告操作日志
+     * (?begin_date=2025-11-01&end_date=2025-11-31&page=1&page_size=20)
+     * @param Request $request
+     * @param AlihealthService $service
+     * @return JsonResponse
+     * @throws \Exception
+     */
+    public function drugReportOptHistory(Request $request, AlihealthService $service)
+    {
+        $beginDate = $request->get("begin_date") ?? Carbon::now()->startOfMonth()->toDateString();
+        $endDate = $request->get("end_date") ?? Carbon::now()->endOfMonth()->toDateString();
+        $page = $request->get("page") ?? 1;
+        $pageSize = $request->get("page_size") ?? 20;
+        $data = $service->drugReportOptHistory($beginDate, $endDate, $page, $pageSize);
         dd($data);
+        return response()->json($data);
     }
 }

+ 2 - 1
app/Http/Controllers/Controller.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Controllers;
 
+use App\Traits\JsonReturn;
 use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
 use Illuminate\Foundation\Bus\DispatchesJobs;
 use Illuminate\Foundation\Validation\ValidatesRequests;
@@ -9,5 +10,5 @@ use Illuminate\Routing\Controller as BaseController;
 
 class Controller extends BaseController
 {
-    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests, JsonReturn;
 }

+ 22 - 0
app/Http/Controllers/DrugReportInfoController.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\ListRequest;
+use App\Http\Resources\DrugReportInfoListResource;
+use App\Services\DrugReportInfoService;
+
+class DrugReportInfoController extends Controller
+{
+    public function index(ListRequest $request, DrugReportInfoService $service)
+    {
+        $filters = $request->getFilters();
+        $search = $request->getSearch();
+        $sort = $request->getSort();
+        $perPage = $request->getPerPage();
+
+        $list = $service->getList($filters, $search, $sort, $perPage);
+
+        return $this->success(new DrugReportInfoListResource($list));
+    }
+}

+ 57 - 0
app/Http/Requests/ListRequest.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class ListRequest extends FormRequest
+{
+    public function rules(): array
+    {
+        return [
+            'sort_by' => 'sometimes|string',
+            'sort_order' => 'sometimes|in:asc,desc',
+            'page' => 'sometimes|integer|min:1',
+            'per_page' => 'sometimes|integer|min:1|max:100',
+        ];
+    }
+
+    /**
+     * 自定义错误消息
+     * @return string[]
+     */
+    public function messages(): array
+    {
+        return [
+            'search.max' => '搜索关键字不能超过 100 个',
+//            'filters.status.in' => '状态必须是「0:启用」或「1:禁用」',
+//            'sort_by.in' => '排序字段只能是 id、create_time 或 update_time',
+            'sort_order.in' => '排序方向必须是(asc:升序、desc:降序)',
+            'page.min' => '当前页最小数字为 1',
+            'per_page.min' => '每页数量最小数字为 1',
+        ];
+    }
+
+    public function getSearch(): string
+    {
+        return $this->input('search') ?? '';
+    }
+
+    public function getFilters(): array
+    {
+        return $this->input('filters', []);
+    }
+
+    public function getSort(): array
+    {
+        return [
+            'sort_by' => $this->input('sort_by', 'id'),
+            'sort_order' => $this->input('sort_order', 'desc'),
+        ];
+    }
+
+    public function getPerPage(): int
+    {
+        return $this->input('per_page', 20);
+    }
+}

+ 23 - 0
app/Http/Resources/DrugReportInfoListResource.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\ResourceCollection;
+
+class DrugReportInfoListResource extends ResourceCollection
+{
+    public function toArray($request): array
+    {
+        return [
+            'list' => $this->collection->map(function ($item) {
+                return array_merge($item->toArray(), [
+
+                ]);
+            }),
+            'total' => $this->total(),
+            'current_page' => $this->currentPage(),
+            'per_page' => $this->perPage(),
+        ];
+    }
+}

+ 52 - 8
app/Models/DrugReportInfo.php

@@ -2,52 +2,89 @@
 
 namespace App\Models;
 
+use App\Traits\Filterable;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 
 /**
  * App\Models\DrugReportInfo
  *
  * @property int $id
- * @property string $drug_report_v2_id 药检报告ID
- * @property string $drug_report_name 报告名称
+ * @property string $drug_report_v2_id 药检报告ID(来源于querysealdrugreport)
+ * @property string $drug_report_name 药检报告名称
+ * @property string $drug_report_id 报告ID(来源于querydrugreport)
+ * @property string $report_id 报告ID(来源于querysealdrugreport)
+ * @property string $report_no 报告编号
+ * @property string $report_date 报告日期
+ * @property string $batch_no 批次号
  * @property string $drug_id 药品ID
  * @property string $drug_name 药品名称
  * @property string $prod_code 药品子类编码
  * @property string $pkg_spec 包装规格
  * @property string $prepn_spec 制剂规格
+ * @property string $prepn_type_desc 剂型
  * @property array|null $pkg_ratio_list 包装比例
- * @property string $batch_no 批次号
- * @property string $report_id 报告ID
- * @property string $report_no 报告编号
- * @property string $report_date 报告日期
- * @property int $is_seal 是否盖章(1-未盖章、2-已盖章)
- * @property string $sealed_report_url 盖章报告链接
+ * @property int $bill_type 单据类型
+ * @property string $bill_id 单据ID
+ * @property string $bill_detail_id 单据明细ID
+ * @property string $bill_time 单据时间
+ * @property string $bill_code 单据编码
+ * @property string $produce_date 生产日期
+ * @property string $produce_ent_id 生产企业ID
+ * @property string $produce_ent_name 生产企业
+ * @property string $ass_ref_ent_id 委托企业ID
+ * @property string $from_ref_ent_id 发货企业ID
+ * @property string $from_ent_name 发货企业
+ * @property string $sealed_report_url 盖章报告URL
+ * @property array|null $raw_data 待签收原始数据(来源于querydrugreport)
+ * @property array|null $seal_raw_data 已签收原始数据(来源于querysealdrugreport)
+ * @property int $is_sign 是否签收(1-未签收、2-已签收)——定制
+ * @property int $is_seal 是否盖章(1-未盖章、2-已盖章)——定制
  * @property \Illuminate\Support\Carbon $create_time 创建时间
  * @property \Illuminate\Support\Carbon $update_time 更新时间
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo applyFilters(array $filters = [], array $options = [])
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo newModelQuery()
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo newQuery()
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo query()
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereAssRefEntId($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereBatchNo($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereBillCode($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereBillDetailId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereBillId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereBillTime($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereBillType($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereCreateTime($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereDrugId($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereDrugName($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereDrugReportId($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereDrugReportName($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereDrugReportV2Id($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereFromEntName($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereFromRefEntId($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereId($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereIsSeal($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereIsSign($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo wherePkgRatioList($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo wherePkgSpec($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo wherePrepnSpec($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo wherePrepnTypeDesc($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereProdCode($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereProduceDate($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereProduceEntId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereProduceEntName($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereRawData($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereReportDate($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereReportId($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereReportNo($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereSealRawData($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereSealedReportUrl($value)
  * @method static \Illuminate\Database\Eloquent\Builder|DrugReportInfo whereUpdateTime($value)
  * @mixin \Eloquent
  */
 class DrugReportInfo extends Model
 {
+    use HasFactory, Filterable;
+
     protected $table = 'drug_report_info';
 
     protected $guarded = [];
@@ -58,5 +95,12 @@ class DrugReportInfo extends Model
 
     protected $casts = [
         'pkg_ratio_list' => 'array',
+        'raw_data' => 'array',
+        'seal_raw_data' => 'array',
     ];
+
+    /**
+     * @var array|string[] 定义可搜索字段(可选,可在调用时覆盖)
+     */
+    public static $searchable = ['id'];
 }

+ 75 - 1
app/Services/AlihealthService.php

@@ -2,7 +2,10 @@
 
 namespace App\Services;
 
+use AlibabaAlihealthSynergyYzwDrugreportOptHistoryAllRequest;
+use AlibabaAlihealthSynergyYzwQuerydrugreportRequest;
 use AlibabaAlihealthSynergyYzwQuerysealdrugreportRequest;
+use Page;
 use TopClient;
 
 class AlihealthService
@@ -22,7 +25,45 @@ class AlihealthService
     }
 
     /**
-     * 查询上传报告信息接口(@link https://open.taobao.com/api.htm?docId=70145&docType=2&scopeId=30361)
+     * 查询上游企业的待签收药检报告信息
+     * @link https://open.taobao.com/api.htm?docId=70169&docType=2&scopeId=30361
+     * @param string $beginTime
+     * @param string $endTime
+     * @param int $page
+     * @param int $pageSize
+     * @return array
+     */
+    public function queryDrugReport(string $beginTime, string $endTime, int $page = 1, int $pageSize = 20): array
+    {
+        $req = new AlibabaAlihealthSynergyYzwQuerydrugreportRequest;
+        $req->setRefEntId($this->config['enterprise_id']);
+//        $req->setFromRefEntId(""); // 发货企业(可选)
+//        $req->setBillCode(""); // 单据编号(可选)
+        $req->setBeginTime($beginTime);
+        $req->setEndTime($endTime);
+//        $req->setDrugId(""); // 药品ID(可选)
+//        $req->setBatchNo(""); // 批号(可选)
+
+        $pageObj = new Page;
+        $pageObj->page = $page;
+        $pageObj->page_size = $pageSize;
+        $req->setPage(json_encode($pageObj));
+
+        $resp = $this->client->execute($req);
+        if ('SUCCESS' <> $resp->res_result->msg_code) {
+            throw new \Exception($resp->result->msg_info);
+        }
+
+        $data = json_decode(json_encode(
+            $resp->res_result->model->result->onenet_drug_report_top_d_t_o
+        ), true);
+
+        return (array)$resp;
+    }
+
+    /**
+     * 查询上传报告信息接口
+     * @link https://open.taobao.com/api.htm?docId=70145&docType=2&scopeId=30361
      * @param string $beginTime
      * @param string $endTime
      * @param int $page
@@ -56,4 +97,37 @@ class AlihealthService
 
         return (array)$resp;
     }
+
+    /**
+     * 药检报告操作日志
+     * @link https://open.taobao.com/api.htm?docId=71189&docType=2&scopeId=30361
+     * @param string $beginDate
+     * @param string $endDate
+     * @param int $page
+     * @param int $pageSize
+     * @return array
+     * @throws \Exception
+     */
+    public function drugReportOptHistory(string $beginDate, string $endDate, int $page = 1, int $pageSize = 20): array
+    {
+        $req = new AlibabaAlihealthSynergyYzwDrugreportOptHistoryAllRequest;
+        $req->setRefEntId($this->config['enterprise_id']);
+        $req->setBeginTime($beginDate);
+        $req->setEndTime($endDate);
+//        $req->setBatchNo(""); // 批次号(可选)
+//        $req->setDrugId(""); // 药品ID(可选)
+        $req->setPage($page);
+        $req->setPageSize($pageSize);
+
+        $resp = $this->client->execute($req);
+        if ('SUCCESS' <> $resp->result->msg_code) {
+            throw new \Exception($resp->result->msg_info);
+        }
+
+        $data = json_decode(json_encode(
+            $resp->result->model->result_list->top_drug_report_opt_log
+        ), true);
+
+        return (array)$resp;
+    }
 }

+ 20 - 4
app/Services/DrugReportInfoService.php

@@ -35,18 +35,34 @@ class DrugReportInfoService
             return [
                 'drug_report_v2_id' => $item['drug_report_v2_id'] ?? '',
                 'drug_report_name' => $item['drug_report_name'] ?? '',
+                'report_id' => $item['report_id'] ?? '',
+                'report_no' => $item['report_no'] ?? '',
+                'report_date' => $item['report_date'] ?? '',
+                'batch_no' => $item['batch_no'] ?? '',
                 'drug_id' => $item['drug_ent_base_info_id'] ?? '',
                 'drug_name' => $item['drug_name'] ?? '',
                 'prod_code' => $item['prod_code'] ?? '',
                 'pkg_spec' => $item['pkg_spec'] ?? '',
                 'prepn_spec' => $item['prepn_spec'] ?? '',
                 'pkg_ratio_list' => json_encode($item['pkg_ratio_list'] ?? [], JSON_UNESCAPED_UNICODE),
-                'batch_no' => $item['batch_no'] ?? '',
-                'report_id' => $item['report_id'] ?? '',
-                'report_no' => $item['report_no'] ?? '',
-                'report_date' => $item['report_date'] ?? '',
                 'sealed_report_url' => $item['sealed_report_url'] ?? '',
+                'seal_raw_data' => json_encode($data ?? [], JSON_UNESCAPED_UNICODE),
             ];
         }, $data);
     }
+
+    public function getList(array $filters, string $search, array $sort, int $perPage) {
+        $options = array_merge([
+            'search' => $search,
+            'searchable' => DrugReportInfo::$searchable,
+        ], $sort);
+
+        $query = DrugReportInfo::query()
+            ->applyFilters(
+                $filters,
+                $options,
+            );
+
+        return $query->paginate($perPage);
+    }
 }

+ 186 - 0
app/Traits/Filterable.php

@@ -0,0 +1,186 @@
+<?php
+
+namespace App\Traits;
+
+use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Support\Str;
+
+trait Filterable
+{
+    /**
+     * 通用筛选方法(支持多场景)
+     *
+     * @param Builder $query
+     * @param array $filters = [
+     *     'field' => value,                       // 直接查询(=)
+     *     'scope:method' => value,                // 调用模型 scope 方法
+     *     'relation.field' => value,              // 关联模型字段查询
+     *     'date_range:field' => [                 // 日期范围
+     *         'start' => value1,
+     *         'end' => value2,
+     *     ],
+     *     'or' => [                               // OR 条件组
+     *         ['field1' => value1],
+     *         ['field2' => value2]
+     *     ]
+     * ]
+     * @param array $options = [
+     *     'search' => value,                // 搜索词
+     *     'searchable' => [                 // 可搜索字段(支持关联字段)
+     *         'field',                      // 当前模型字段搜索
+     *         'relation.field',             // 关联模型字段搜索
+     *     ],
+     *     'sort_by' => 'field',             // 排序字段
+     *     'sort_order' => 'asc/desc'        // 排序方向(asc:升序、desc:降序)
+     * ]
+     * @return Builder
+     */
+    public function scopeApplyFilters(Builder $query, array $filters = [], array $options = []): Builder
+    {
+        // 处理筛选条件
+        foreach ($filters as $field => $value) {
+            // 跳过空值
+            if (is_null($value)) continue;
+
+            // 动态解析筛选类型
+            switch (true) {
+                case Str::startsWith($field, 'scope:'):
+                    $this->applyScopeFilter($query, $field, $value);
+                    break;
+
+                case Str::contains($field, '.'):
+                    $this->applyRelationFilter($query, $field, $value);
+                    break;
+
+                case Str::startsWith($field, 'date_range:'):
+                    $this->applyDateRangeFilter($query, $field, $value);
+                    break;
+
+                case $field === 'or':
+                    $this->applyOrConditions($query, $value);
+                    break;
+
+                default:
+                    $this->applyDefaultFilter($query, $field, $value);
+            }
+        }
+
+        // 处理全局搜索
+        if (!empty($options['search']) && !empty($options['searchable'])) {
+            $this->applyGlobalSearch($query, $options['search'], $options['searchable']);
+        }
+
+        // 处理排序
+        $this->applySorting($query, $options);
+
+        return $query;
+    }
+
+    /**
+     * 应用 Scope 方法筛选
+     */
+    protected function applyScopeFilter(Builder $query, string $field, $value): void
+    {
+        $scopeMethod = Str::after($field, 'scope:');
+
+        if (method_exists($this, 'scope' . Str::studly($scopeMethod))) {
+            $query->{$scopeMethod}($value);
+        } else {
+            // 记录未知 Scope 方法
+            logger()->warning("Undefined scope method: {$scopeMethod}");
+        }
+    }
+
+    /**
+     * 应用关联模型筛选
+     */
+    protected function applyRelationFilter(Builder $query, string $field, $value): void
+    {
+        [$relation, $relationField] = explode('.', $field, 2);
+
+        $query->whereHas($relation, function ($q) use ($relationField, $value) {
+            $q->where($relationField, $value);
+        });
+    }
+
+    /**
+     * 应用日期范围筛选
+     */
+    protected function applyDateRangeFilter(Builder $query, string $field, array $value): void
+    {
+        $dataRangeField = Str::after($field, 'date_range:');
+
+        if (isset($value['start']) && isset($value['end'])) {
+            $start = Carbon::parse($value['start'])->startOfDay();
+            $end = Carbon::parse($value['end'])->endOfDay();
+
+            $query->whereBetween($dataRangeField, [$start, $end]);
+        }
+    }
+
+    /**
+     * 应用 OR 条件组
+     */
+    protected function applyOrConditions(Builder $query, array $conditions): void
+    {
+        $query->where(function ($q) use ($conditions) {
+            foreach ($conditions as $group) {
+                $q->orWhere(function ($subQ) use ($group) {
+                    foreach ($group as $field => $value) {
+                        $subQ->where($field, $value);
+                    }
+                });
+            }
+        });
+    }
+
+    /**
+     * 应用默认筛选(= 条件)
+     */
+    protected function applyDefaultFilter(Builder $query, string $field, $value): void
+    {
+        $query->where($field, $value);
+    }
+
+    /**
+     * 全局模糊搜索
+     */
+    protected function applyGlobalSearch(Builder $query, string $searchTerm, array $searchableFields): void
+    {
+        $query->where(function ($q) use ($searchTerm, $searchableFields) {
+            foreach ($searchableFields as $field) {
+                if (Str::contains($field, '.')) {
+                    $this->applyRelationSearch($q, $field, $searchTerm);
+                } else {
+                    $q->orWhere($field, 'LIKE', "%{$searchTerm}%");
+                }
+            }
+        });
+    }
+
+    /**
+     * 处理关联字段搜索
+     */
+    protected function applyRelationSearch(Builder $query, string $field, string $searchTerm): void
+    {
+        $relations = explode('.', $field);
+        $column = array_pop($relations);
+        $relation = implode('.', $relations);
+
+        $query->orWhereHas($relation, function ($q) use ($column, $searchTerm) {
+            $q->where($column, 'LIKE', "%{$searchTerm}%");
+        });
+    }
+
+    /**
+     * 应用排序逻辑
+     */
+    protected function applySorting(Builder $query, array $options): void
+    {
+        $sortBy = $options['sort_by'] ?? 'id';
+        $sortOrder = $options['sort_order'] ?? 'desc';
+
+        $query->orderBy($sortBy, $sortOrder);
+    }
+}

+ 50 - 0
app/Traits/JsonReturn.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Traits;
+
+use Illuminate\Http\JsonResponse;
+use Illuminate\Support\Facades\Log;
+
+trait JsonReturn
+{
+    /**
+     * 成功响应
+     * @param $data
+     * @param string $message
+     * @param int $code
+     * @return JsonResponse
+     */
+    public function success($data = null, string $message = 'success', int $code = 0): JsonResponse
+    {
+        return response()->json([
+            'status' => $code,
+            'data' => $data,
+            'message' => $message,
+            'meta' => [
+                'request_id' => request('request_id'),
+                'timestamp' => now()->toDateTimeString(),
+            ],
+        ], 200);
+    }
+
+    /**
+     * 错误响应
+     * @param int $code
+     * @param string $message
+     * @param array $errors
+     * @return JsonResponse
+     */
+    public function error(int $code = 1, string $message = 'error', array $errors = []): JsonResponse
+    {
+        Log::error("响应错误:" . var_export($errors, true));
+        return response()->json([
+            'status' => $code,
+            'message' => $message,
+            'errors' => $errors,
+            'meta' => [
+                'request_id' => request('request_id'),
+                'timestamp' => now()->toDateTimeString(),
+            ],
+        ], 500);
+    }
+}

+ 10 - 1
routes/api.php

@@ -1,6 +1,7 @@
 <?php
 
 use App\Http\Controllers\AlihealthController;
+use App\Http\Controllers\DrugReportInfoController;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Route;
 
@@ -19,4 +20,12 @@ Route::middleware('auth:api')->get('/user', function (Request $request) {
     return $request->user();
 });
 
-Route::get('query-seal-drug-report', [AlihealthController::class, 'querySealDrugReport']);
+Route::prefix('ali-health')->group(function () {
+    Route::get('query-drug-report', [AlihealthController::class, 'queryDrugReport']);
+    Route::get('query-seal-drug-report', [AlihealthController::class, 'querySealDrugReport']);
+    Route::get('drug-report-opt-history', [AlihealthController::class, 'drugReportOptHistory']);
+});
+
+Route::prefix('drug-report-info')->group(function () {
+    Route::get('/', [DrugReportInfoController::class, 'index']);
+});