fix: 产品兼容性 - 分页列表及导出bug修复
All checks were successful
Gitea Actions Official-website / deploy-dev (push) Successful in 5s

This commit is contained in:
2026-08-12 10:35:42 +08:00
parent 0234c3d959
commit 20ac0fde15

View File

@@ -9,6 +9,7 @@ use app\admin\model\v1\ProductCompatPartsModel;
use app\admin\model\v1\ProductCompatTypesModel; use app\admin\model\v1\ProductCompatTypesModel;
use app\admin\validate\v1\ProductCompatValidate; use app\admin\validate\v1\ProductCompatValidate;
use Generator; use Generator;
use think\db\Query;
class ProductCompat class ProductCompat
{ {
@@ -20,8 +21,8 @@ class ProductCompat
$params = request()->param([ $params = request()->param([
'compatible_model', 'compatible_model',
'model', 'model',
'type_id', 'type_id/d',
'part_id', 'part_id/d',
'brand_name', 'brand_name',
'page/d' => 1, 'page/d' => 1,
'size/d' => 10 'size/d' => 10
@@ -45,10 +46,10 @@ class ProductCompat
->language(request()->lang_id) ->language(request()->lang_id)
->where(function ($query) use($params) { ->where(function ($query) use($params) {
if (!empty($params['type_id'])) { if (!empty($params['type_id'])) {
$query->typeId($params['type_id']); $query->where('type_id', '=', $params['type_id']);
} }
if (!empty($params['part_id'])) { if (!empty($params['part_id'])) {
$query->partId($params['part_id']); $query->where('part_id', '=', $params['part_id']);
} }
}) })
->withSearch(['model', 'brand_name', 'compatible_model'], [ ->withSearch(['model', 'brand_name', 'compatible_model'], [
@@ -313,7 +314,7 @@ class ProductCompat
'brand_name' 'brand_name'
]); ]);
$list = ProductCompatModel::withoutField([ $query = ProductCompatModel::withoutField([
'language_id', 'language_id',
'deleted_at' 'deleted_at'
]) ])
@@ -323,9 +324,6 @@ class ProductCompat
}, },
'parts' => function ($query) { 'parts' => function ($query) {
$query->field(['id', 'name']); $query->field(['id', 'name']);
},
'compatible_models' => function ($query) {
$query->field(['compat_id', 'compatible_model']);
} }
]) ])
->language(request()->lang_id) ->language(request()->lang_id)
@@ -341,9 +339,7 @@ class ProductCompat
'model' => $params['model'] ?? null, 'model' => $params['model'] ?? null,
'brand_name' => $params['brand_name'] ?? null, 'brand_name' => $params['brand_name'] ?? null,
'compatible_model' => $params['compatible_model'] ?? null, 'compatible_model' => $params['compatible_model'] ?? null,
]) ]);
->order(['updated_at' => 'desc'])
->cursor();
$schema = [ $schema = [
'id' => 'id', 'id' => 'id',
@@ -363,33 +359,58 @@ class ProductCompat
'updated_at' => '更新时间' 'updated_at' => '更新时间'
]; ];
return xlsx_writer($this->xlsxRowGenerator($list), $schema, '产品兼容性' . date('YmdHis')); return xlsx_writer($this->xlsxRowGenerator($query), $schema, '产品兼容性' . date('YmdHis'));
} }
private function xlsxRowGenerator(Generator $list) private function xlsxRowGenerator(Query $query, int $page_size = 500): Generator
{ {
foreach ($list as $item) { // 主键游标分页,避免 offset 深翻页的性能问题
$compatible_models = []; $last_id = 0;
foreach ($item['compatible_models'] as $model) { while (true) {
$compatible_models[] = $model['compatible_model']; $items = (clone $query)
->where('id', '>', $last_id)
->order(['id' => 'asc'])
->limit($page_size)
->select();
if ($items->isEmpty()) {
break;
} }
yield [ // 仅查询当前批次的兼容型号,避免一次性拉取全量 id 及巨型 IN 子句
'id' => $item['id'], $compat_map = [];
'type_name' => $item['types']['type_name'], $compat_ids = $items->column('id');
'brand_name' => $item['brand_name'], if (!empty($compat_ids)) {
'model' => $item['model'], $compat_models = ProductCompatModelsModel::field(['compat_id', 'compatible_model'])
'part_name' => $item['parts']['part_name'], ->where('compat_id', 'in', $compat_ids)
'level_name' => $item['level_name'], ->order(['id' => 'asc'])
'spec_name' => $item['spec_name'], ->select()
'series_name' => $item['series_name'], ->toArray();
'capacity' => $item['capacity'], foreach ($compat_models as $compat_model) {
'frequency' => $item['frequency'], $compat_map[$compat_model['compat_id']][] = $compat_model['compatible_model'];
'compatible_models' => implode(',', $compatible_models), }
'praise_count' => $item['praise_count'], }
'sort' => $item['sort'],
'created_at' => $item['created_at'], foreach ($items as $item) {
'updated_at' => $item['updated_at'] yield [
]; 'id' => $item['id'],
'type_name' => $item['types']['name'] ?? '',
'brand_name' => $item['brand_name'],
'model' => $item['model'],
'part_name' => $item['parts']['name'] ?? '',
'level_name' => $item['level_name'],
'spec_name' => $item['spec_name'],
'series_name' => $item['series_name'],
'capacity' => $item['capacity'],
'frequency' => $item['frequency'],
'compatible_models' => implode(',', $compat_map[$item['id']] ?? []),
'praise_count' => $item['praise_count'],
'sort' => $item['sort'],
'created_at' => $item['created_at'],
'updated_at' => $item['updated_at']
];
}
// 推进游标,按主键继续取下一页
$last_id = $items->last()->id;
} }
} }