Files
lgp-admin-plus-api/app/Service/business/CatalogueService.php
LQ bcf54c2727 初始化
缺陷:主题配色需要优化整体的同风格
2026-08-14 23:21:21 +08:00

194 lines
6.2 KiB
PHP
Raw Permalink 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\Service\business;
use App\BaseApp\BaseService;
use App\Models\business\CatalogueModel;
use App\Models\business\CategoryModel;
use App\Models\business\ImageModel;
use App\Models\business\PriceSheetModel;
use App\Service\common\MediaUrlService;
use Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* 商品图册
*/
class CatalogueService extends BaseService
{
private MediaUrlService $media;
public function __construct()
{
parent::__construct();
$this->model = CatalogueModel::class;
$this->selectField = ['id', 'title', 'category_id', 'cover', 'pdf', 'price', 'alias', 'identifier', 'status', 'created_at', 'updated_at'];
$this->queryField = ['title' => 'like', 'alias' => 'like', 'identifier' => 'like', 'status' => '='];
$this->media = MediaUrlService::getInstance();
}
/**
* 列表
*
* 两处沿用老行为:
* 1. 按分类筛选时连同该分类的子分类一起查,否则选了父分类会一条都搜不到
* 2. 报价单里 6 个历史材质列绝大多数为空只把有值的列名回给前端show_field
* 前端据此决定表格显示哪几列
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function list(): array
{
$this->with = ['category', 'priceSheet'];
$categoryId = (int) request()->get('category_id', 0);
if ($categoryId > 0) {
$ids = CategoryModel::where('pid', $categoryId)->where('deleted_at', 0)->pluck('id')->all();
$ids[] = $categoryId;
$this->whereIn = ['category_id', $ids];
}
$result = $this->getPageList();
foreach ($result['items'] as &$item) {
$item['category_name'] = $item['category']['name'] ?? '';
unset($item['category']);
$item['cover'] = $this->media->toPublic($item['cover'] ?? '');
$item['pdf'] = $this->media->toPublic($item['pdf'] ?? '');
$item['show_field'] = $this->pickUsedMaterialFields($item['price_sheet'] ?? []);
}
unset($item);
return $result;
}
public function option(): mixed
{
$this->optionField = ['id', 'title as name', 'identifier'];
return $this->getOption();
}
/**
* 详情,带规格与两类相册
* @throws Exception
*/
public function detail($id): mixed
{
$info = $this->getDetail($id);
$info->cover = $this->media->toPublic($info->cover);
$info->pdf = $this->media->toPublic($info->pdf);
$priceSheet = PriceSheetModel::where('catalogue_id', $id)
->where('deleted_at', 0)
->orderBy('id')
->get()
->toArray();
$info->show_field = $this->pickUsedMaterialFields($priceSheet);
$info->price_sheet = $priceSheet;
$info->render_images = $this->imagesOf($id, ImageModel::TYPE_RENDER);
$info->physical_images = $this->imagesOf($id, ImageModel::TYPE_PHYSICAL);
return $info;
}
public function create($params): mixed
{
$params = $this->normalize($params);
$this->assertIdentifierUnique((string) ($params['identifier'] ?? ''));
return $this->insert($params);
}
/**
* @throws Exception
*/
public function update($id, $params): mixed
{
$params = $this->normalize($params);
if (array_key_exists('identifier', $params)) {
$this->assertIdentifierUnique((string) $params['identifier'], (int) $id);
}
return $this->save($id, $params);
}
/**
* 删除商品:连带软删它的规格与相册,否则会留下一堆查不到主体的孤儿数据
* @throws Exception
*/
public function delete($id): mixed
{
$ids = array_values(array_filter(array_map('intval', is_array($id) ? $id : [$id])));
if (empty($ids)) {
$this->utils->errorThrow('参数错误');
}
$now = time();
PriceSheetModel::whereIn('catalogue_id', $ids)->where('deleted_at', 0)
->update(['deleted_at' => $now, 'updated_at' => $now]);
ImageModel::whereIn('catalogue_id', $ids)->where('deleted_at', 0)
->update(['deleted_at' => $now, 'updated_at' => $now]);
return $this->del($ids);
}
/**
* @throws Exception
*/
public function status($id, $status): mixed
{
return $this->save($id, ['status' => (int) $status]);
}
/**
* 报价单里真正有值的材质列
*/
private function pickUsedMaterialFields(array $priceSheetRows): array
{
$used = [];
foreach ($priceSheetRows as $row) {
foreach (PriceSheetModel::MATERIAL_FIELDS as $field) {
if (!empty($row[$field] ?? '')) {
$used[$field] = true;
}
}
}
return array_keys($used);
}
private function imagesOf(int|string $catalogueId, int $type): array
{
$rows = ImageModel::where('catalogue_id', $catalogueId)
->where('type', $type)
->where('deleted_at', 0)
->orderBy('id')
->get(['id', 'url', 'type'])
->toArray();
$this->media->publicEach($rows, ['url']);
return $rows;
}
private function normalize(array $params): array
{
foreach (['cover', 'pdf'] as $field) {
if (array_key_exists($field, $params)) {
$params[$field] = $this->media->firstOf($params[$field]);
}
}
return $params;
}
/**
* 商品编号是小程序搜索和线下对单的依据,重复了就没法定位货品
* @throws Exception
*/
private function assertIdentifierUnique(string $identifier, int $exceptId = 0): void
{
$identifier = trim($identifier);
if ($identifier === '') {
return;
}
$exists = CatalogueModel::where('identifier', $identifier)
->where('deleted_at', 0)
->when($exceptId > 0, fn ($q) => $q->where('id', '<>', $exceptId))
->exists();
if ($exists) {
$this->utils->errorThrow('商品编号已存在:' . $identifier);
}
}
}