Files
orico-official-website/app/admin/controller/v1/Product.php

466 lines
16 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
declare (strict_types = 1);
namespace app\admin\controller\v1;
use app\admin\model\v1\ProductCompatRelModel;
use app\admin\model\v1\ProductModel;
use app\admin\model\v1\ProductParamsModel;
use app\admin\model\v1\ProductRelatedModel;
use app\admin\model\v1\ProductSkuAttrModel;
use app\admin\model\v1\ProductSkuModel;
use app\admin\validate\v1\ProductValidate;
/**
* 产品管理控制器
*/
class Product
{
// 分页列表
public function index()
{
$param = request()->get([
'name',
'spu',
'category_id',
'created_at',
'is_show',
'page/d' => 1,
'size/d' => 10
]);
$validate = new ProductValidate();
if (!$validate->scene('index')->check($param)) {
return error($validate->getError());
}
$products = ProductModel::field([
'id',
'name',
'cover_image',
'spu',
'category_id',
'sort',
'is_new',
'is_hot',
'is_sale',
'is_show',
'stock_qty',
'status',
'created_at'
])
->with('category')
->language(request()->lang_id)
->withSearch(['name_nullable', 'spu_nullable', 'created_at_nullable'], [
'name_nullable' => $param['name']??null,
'spu_nullable' => $param['spu']??null,
'created_at_nullable' => !empty($param['created_at']) ? explode(',', $param['created_at']) : null,
])
->categoryNullable($param['category_id']??null)
->isShowNullable(isset($param['is_show']) ? (bool)$param['is_show'] : null)
->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
->paginate([
'list_rows' => $param['size'],
'page' => $param['page'],
])
->bindAttr('category', ['category_name' => 'name'])
->hidden(['category_id', 'category'])
?->each(fn($item) => $item->cover_image = thumb($item->cover_image));
return success('获取成功', $products);
}
// 产品详情
public function read()
{
$product = ProductModel::with(['category' => function($query) {
$query->field(['id', 'name' => 'category_name']);
}])
->withoutField([
'language_id',
'created_at',
'updated_at',
'deleted_at'
])
->bypk(request()->param('id'))
->find()
?->bindAttr('category', ['category_name'])
->hidden(['category']);
if (empty($product)) {
return error('产品不存在');
}
// 获取产品参数
$params = [];
$product_params = ProductParamsModel::productId($product->id)->select();
foreach ($product_params as $val) {
$params[] = implode(":", [$val->name, $val->value]);
}
$product->params = implode(PHP_EOL, $params);
// 获取sku数据
$product->skus = ProductSkuModel::withoutField(['created_at', 'updated_at'])
->with(['attrs' => function($query) {
$query->hidden(['sku_id']);
}])
->productId($product->id)
->select()
->hidden(['id', 'product_id']);
// 获取关联产品
$product->related = ProductRelatedModel::field([
'related_product_id',
'sort'
])
->with(['product' => function($query) {
$query->field(['id', 'spu']);
}])
->productId($product->id)
->select()
->bindAttr('product', ['spu'])
->hidden(['product']);
return success('获取成功', $product);
}
// 更新
public function update()
{
$id = request()->param('id');
$put = request()->put([
'category_id',
'spu',
'name',
'short_name',
'cover_image',
'desc',
'video_img',
'video_url',
'is_sale',
'is_new',
'is_hot',
'is_show',
'sort',
'detail',
'params' => '',
'skus' => '',
'related' => '',
'compat' => '',
'seo_title',
'seo_keywords',
'seo_desc'
]);
$put = array_merge(
$put,
['skus' => json_decode($put['skus'], true)],
['related' => json_decode($put['related'], true)],
);
$validate = new ProductValidate();
$check_data = array_merge($put, ['id' => $id, 'language_id' => request()->lang_id]);
if (!$validate->scene('update')->check($check_data)) {
return error($validate->getError());
}
$product = ProductModel::bypk($id)->find();
if (is_null($product)) {
return error('请确认操作对象是否存在');
}
if (!$product->save($put)) {
return error('操作失败');
}
// 更新产品参数
if ($put['params'] != "") {
ProductParamsModel::productId($id)->delete();
if (preg_match_all('/(.+):(.+)/', $put['params'], $match_result)) {
$params = [];
for ($i = 0; $i < count($match_result[0]); $i++) {
$params[] = [
'product_id' => $id,
'name' => $match_result[1][$i],
'value' => $match_result[2][$i]
];
}
if (!empty($params)) {
ProductParamsModel::insertAll($params);
}
}
}
// 更新SKU
if (!empty($put['skus'])) {
$skus = [];
$attrs_group = [];
foreach ($put['skus'] as $val) {
$skus[] = [
'product_id' => $id,
'sku' => $val['sku'],
'main_image' => $val['main_image'],
'photo_album' => $val['photo_album'],
'sort' => $val['sort']??0
];
foreach ($val['attrs'] as $v) {
$attrs_group[$val['sku']][] = [
'attr_id' => $v['attr_id'],
'attr_value' => $v['attr_value']
];
}
}
if (!empty($skus)) {
$sku_model = new ProductSkuModel;
// 删除原有SKU
$sku_model->productId($id)->delete();
// 添加SKU
$save_ret = $sku_model->saveAll($skus);
if (!$save_ret->isEmpty()) {
$sku_map = [];
foreach ($save_ret as $val) {
$sku_map[$val->sku] = $val->id;
}
$attrs = [];
foreach ($attrs_group as $sku => $sku_attrs) {
if (empty($sku_map[$sku])) {
unset($attrs_group[$sku]);
continue;
}
foreach ($sku_attrs as $k => $v) {
$attrs[] = array_merge($v, ['sku_id' => $sku_map[$sku]]);
}
}
(new ProductSkuAttrModel)->saveAll($attrs);
}
}
}
// 更新关联产品
if (!empty($put['related'])) {
// 删除原有关联产品
ProductRelatedModel::productId($id)->delete();
// 添加关联产品
$related = [];
foreach ($put['related'] as $val) {
$related[] = [
'product_id' => $id,
'related_product_id' => $val['related_product_id'],
'sort' => $val['sort']
];
}
if (!empty($related)) {
ProductRelatedModel::insertAll($related);
}
}
// 更新兼容性信息
if (!empty($put['compat'])) {
$compat = $put['compat'];
$compat['product_id'] = $id;
$compat['compat_id'] = explode(',', str_replace('', ',', $compat['compat_id']));
$rel_id = ProductCompatRelModel::productId($id)->value('id');
if (!empty($rel_id)) {
$compat['id'] = $rel_id;
}
(new ProductCompatRelModel)->save($compat);
}
return success('操作成功');
}
// 设置排序值
public function sort()
{
$id = request()->param('id');
$sort = request()->post('sort');
$product = ProductModel::bypk($id)->find();
if (empty($product)) {
return error('请确认操作对象是否存在');
}
if ($sort != $product->sort) {
$product->sort = $sort;
if (!$product->save()) {
return error('操作失败');
}
}
return success('操作成功');
}
// 上下架操作
public function updownShelves()
{
$id = request()->param('id');
$product = ProductModel::bypk($id)->find();
if (empty($product)) {
return error('请确认操作对象是否存在');
}
$product->is_show = (int)!$product->is_show;
if (!$product->save()) {
return error('操作失败');
}
return success('操作成功');
}
// 删除
public function delete()
{
$product = ProductModel::bypk(request()->param('id'))->find();
if (empty($product)) {
return error('请确认操作对象是否存在');
}
// 软删除
if (!$product->delete()) {
return error('操作失败');
}
return success('操作成功');
}
// 导出
public function export()
{
$schema = [
'id' => 'ID',
'category_name' => '分类名称',
'spu' => '规格型号',
'name' => '产品名称',
'short_name' => '简称(产品副标题)',
'cover_image' => '产品封面图片',
'desc' => '描述',
'video_img' => '视频封面图片',
'video_url' => '视频地址',
'is_sale' => '是否在售',
'is_new' => '是否新品',
'is_hot' => '是否热销',
'is_show' => '上下架状态',
'stock_qty' => '库存数量',
'sort' => '排序值',
'detail' => '产品详情',
'params' => '产品参数',
'related' => '关联产品',
'status' => '状态',
'seo_title' => 'seo标题',
'seo_keywords' => 'seo关键词',
'seo_desc' => 'seo描述',
'created_at' => '添加时间',
'updated_at' => '最后更新时间'
];
// 获取导出数据
$data = $this->getExportProductData();
// 导出
return xlsx_writer($data, $schema, '产品列表' . date('YmdHis'));
}
// 获取产品导出数据
private function getExportProductData()
{
$server = request()->server();
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . '/';
$param = request()->param([
'name',
'spu',
'category_id',
'created_at',
'is_show',
]);
$products = ProductModel::field([
'id',
'category_id',
'spu',
'name',
'short_name',
'cover_image',
'desc',
'video_img',
'video_url',
'CASE WHEN is_new = 1 THEN "是" ELSE "否" END' => 'is_new',
'CASE WHEN is_hot = 1 THEN "是" ELSE "否" END' => 'is_hot',
'CASE WHEN is_sale = 1 THEN "是" ELSE "否" END' => 'is_sale',
'CASE WHEN is_show = 1 THEN "上架" ELSE "下架" END' => 'is_show',
'stock_qty',
'sort',
'detail',
'CASE WHEN status = 1 THEN "启用" WHEN status = -1 THEN "禁用" END' => 'status',
'seo_title',
'seo_keywords',
'seo_desc',
'created_at',
'updated_at',
])
->with('category')
->language(request()->lang_id)
->withSearch(['name_nullable', 'spu_nullable', 'created_at_nullable'], [
'name_nullable' => $param['name']??null,
'spu_nullable' => $param['spu']??null,
'created_at_nullable' => !empty($param['created_at']) ? explode(',', $param['created_at']) : null,
])
->categoryNullable($param['category_id']??null)
->isShowNullable(isset($param['is_show']) ? (bool)$param['is_show'] : null)
->order(['id' => 'asc'])
->select()
->bindAttr('category', ['category_name' => 'name'])
->hidden(['category_id', 'category'])
->each(function($item) use($image_host) {
if (!empty($item["cover_image"])) {
$item["cover_image"] = url_join($image_host, $item["cover_image"]);
}
if (!empty($item["video_img"])) {
$item["video_img"] = url_join($image_host, $item["video_img"]);
}
if (!empty($item["video_url"])) {
$item["video_url"] = url_join($image_host, $item["video_url"]);
}
});
if (!$products->isEmpty()) {
// 产品参数
$product_params = ProductParamsModel::withoutField(['id', 'created_at', 'updated_at'])
->productId($products->column('id'))
->select();
if (!$product_params->isEmpty()) {
$params = [];
foreach ($product_params as $item) {
$params[$item['product_id']][] = $item->name . ':' . $item->value;
}
$products->each(function($product) use($params) {
if (empty($params[$product->id])) {
return;
}
$product->params = implode(PHP_EOL, $params[$product->id]);
});
}
// 关联产品
$product_related = ProductRelatedModel::withoutField(['id', 'created_at', 'updated_at'])
->with(['product' => function($query) {
$query->field(['id', 'spu']);
}])
->productId($products->column('id'))
->order(['sort' => 'asc'])
->select();
if (!$product_related->isEmpty()) {
$related = [];
foreach ($product_related as $item) {
if (!empty($item->product)) {
$related[$item['product_id']][] = $item->product->spu;
}
}
$products->each(function($product) use($related) {
if (empty($related[$product->id])) {
return;
}
$product->related = implode(',', $related[$product->id]);
});
}
}
return $products->toArray();
}
}