CaiWuXiTong/app/Business/JstOrderLabelOptions.php
qiuxiang daa4c939e7 聚水潭订单标签明细:支持按聚水潭导出的订单 Excel 导入,并放开筛选下拉上限
镜像 ops_jst_orders 只覆盖 2026-04-01 之后,缺的历史区间只能靠财务在聚水潭「导出订单」导文件补。所以:- 新增 JstOrderExportReader:ZipArchive+expat 流式解析聚水潭导出 xlsx。这类文件字符串走 inlineStr、dimension 只写 A1、单文件上万行 ×135 列(解压 78MB),常规读法会读成空表或吃满内存;实测 12286 行 3.5 秒、峰值内存 10MB。
- jst-order-labels:import 新增 --file=:按「线上订单号+标签」去重后拆行写入,可配合 --from/--to 过滤窗口;带 --replace 时先成功读到数据行再清区间,避免文件有问题却先删了线上数据。
- 筛选下拉上限 500 -> 5000:导入 4~7 月后店铺已达 604 个,原来下拉里会缺 104 个店铺;提交筛选值的截断上限同步放开。
- 补两个测试:导出文件去重拆行、窗口过滤+replace。
2026-10-07 16:53:55 +08:00

100 lines
2.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Business;
use App\Models\Business\JstOrderLabel;
use Illuminate\Support\Facades\Cache;
/**
* 聚水潭订单标签明细的筛选下拉选项。
*
* 表里有 200 万行以上,distinct 扫描一次要几秒;这里按公司缓存 24 小时,
* 导入命令结束时会主动预热,避免每次打开页面都慢。
*
* 上限只是防呆(选项过多会拖慢页面),要高于实际店铺数:2026-10 导入 4~7 月后
* 店铺已达 604 个,原来卡在 500 会让一部分店铺选不出来。
*/
class JstOrderLabelOptions
{
private const TTL_HOURS = 24;
private const TOTAL_TTL_MINUTES = 30;
private const LIMIT = 5000;
/** @return list<string> */
public function labels(int $companyId): array
{
return $this->remember($companyId, 'label');
}
/** @return list<string> */
public function shops(int $companyId): array
{
return $this->remember($companyId, 'shop_name');
}
public function warm(int $companyId): void
{
$this->labels($companyId);
$this->shops($companyId);
$this->total($companyId);
}
public function forget(int $companyId): void
{
Cache::forget($this->key($companyId, 'label'));
Cache::forget($this->key($companyId, 'shop_name'));
Cache::forget($this->totalKey($companyId));
}
/** 无筛选时的总行数:233 万行上 COUNT(*) 要 2 秒,缓存后翻页不再重复统计。 */
public function total(int $companyId): int
{
$key = $this->totalKey($companyId);
$cached = Cache::get($key);
if (is_numeric($cached)) {
return (int) $cached;
}
$count = (int) JstOrderLabel::query()->where('company_id', $companyId)->count();
Cache::put($key, $count, now()->addMinutes(self::TOTAL_TTL_MINUTES));
return $count;
}
/** @return list<string> */
private function remember(int $companyId, string $column): array
{
$key = $this->key($companyId, $column);
$cached = Cache::get($key);
if (is_array($cached)) {
return $cached;
}
$values = JstOrderLabel::query()
->where('company_id', $companyId)
->whereNotNull($column)
->where($column, '<>', '')
->distinct()
->orderBy($column)
->limit(self::LIMIT)
->pluck($column)
->all();
Cache::put($key, $values, now()->addHours(self::TTL_HOURS));
return $values;
}
private function key(int $companyId, string $column): string
{
return "jst-order-labels:options:v1:{$companyId}:{$column}";
}
private function totalKey(int $companyId): string
{
return "jst-order-labels:total:v1:{$companyId}";
}
}