feat: 添加产品购买链接相关接口
This commit is contained in:
339
app/admin/controller/v1/ProductPurchaseLink.php
Normal file
339
app/admin/controller/v1/ProductPurchaseLink.php
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\v1;
|
||||||
|
|
||||||
|
use app\admin\model\v1\ProductModel;
|
||||||
|
use app\admin\model\v1\ProductPurchaseLinkModel;
|
||||||
|
use app\admin\model\v1\ProductPurchaseLinkPlatformModel;
|
||||||
|
use app\admin\validate\v1\ProductPurchaseLinkValidate;
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
|
class ProductPurchaseLink
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取购买平台
|
||||||
|
*/
|
||||||
|
public function platforms()
|
||||||
|
{
|
||||||
|
$platforms = ProductPurchaseLinkPlatformModel::withoutField([
|
||||||
|
'language_id',
|
||||||
|
'desc',
|
||||||
|
'sort',
|
||||||
|
'created_at'
|
||||||
|
])
|
||||||
|
->language(request()->lang_id)
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
|
->select();
|
||||||
|
|
||||||
|
return success('获取成功', $platforms);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买链接分布数据
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$params = request()->param([
|
||||||
|
'name' => '',
|
||||||
|
'spu' => '',
|
||||||
|
'page/d' => 1,
|
||||||
|
'size/d' => 10
|
||||||
|
]);
|
||||||
|
|
||||||
|
$links = ProductModel::alias('pd')
|
||||||
|
->field([
|
||||||
|
'pd.id',
|
||||||
|
'pd.spu',
|
||||||
|
'pd.name',
|
||||||
|
'CASE WHEN pd.is_show = 0 THEN "已下架" WHEN pd.is_show = 1 THEN "已上架" END' => 'is_show',
|
||||||
|
'pf.id' => 'platform_id',
|
||||||
|
'pf.platform' => 'platform_name',
|
||||||
|
'min(pl.id)' => 'link_id',
|
||||||
|
'pl.link'
|
||||||
|
])
|
||||||
|
->leftJoin('product_purchase_link pl', 'pl.product_id = pd.id')
|
||||||
|
->leftJoin('product_purchase_platform pf', 'pf.id = pl.platform_id')
|
||||||
|
->where(function ($query) use ($params) {
|
||||||
|
$query->where('pd.is_show', '=', 1);
|
||||||
|
if (!empty($params['name'])) {
|
||||||
|
$query->where('pd.name', 'like', '%' . $params['name'] . '%');
|
||||||
|
}
|
||||||
|
if (!empty($params['spu'])) {
|
||||||
|
$query->where('pd.spu', 'like', '%' . $params['spu'] . '%');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->where('pd.language_id', '=', request()->lang_id)
|
||||||
|
->group('pd.id')
|
||||||
|
->order(['pl.sort' => 'asc', 'pl.id' => 'desc', 'pd.id' => 'desc'])
|
||||||
|
->paginate([
|
||||||
|
'list_rows' => $params['size'],
|
||||||
|
'page' => $params['page'],
|
||||||
|
]);
|
||||||
|
if ($links->isEmpty()) {
|
||||||
|
return success('获取成功', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
$others = ProductPurchaseLinkModel::alias('pl')
|
||||||
|
->field([
|
||||||
|
'pl.product_id',
|
||||||
|
'pl.platform_id',
|
||||||
|
'pf.platform' => 'platform_name',
|
||||||
|
'pl.id' => 'link_id',
|
||||||
|
'pl.link'
|
||||||
|
])
|
||||||
|
->join('product_purchase_platform pf', 'pf.id = pl.platform_id')
|
||||||
|
->where('pl.language_id', '=', request()->lang_id)
|
||||||
|
->where('pl.product_id', 'in', array_column($links->items(), 'id'))
|
||||||
|
->where('pl.id', 'not in', array_column($links->items(), 'link_id'))
|
||||||
|
->select();
|
||||||
|
if (!$others->isEmpty()) {
|
||||||
|
$others_map = [];
|
||||||
|
$others_arr = $others->toArray();
|
||||||
|
foreach ($others_arr as $other) {
|
||||||
|
$product_id = $other['product_id'];
|
||||||
|
unset($other['product_id']);
|
||||||
|
$others_map[$product_id][] = $other;
|
||||||
|
}
|
||||||
|
$links->each(function ($item) use ($others_map) {
|
||||||
|
if (!empty($others_map[$item['id']])) {
|
||||||
|
$item['rowspan'] = $others_map[$item['id']];
|
||||||
|
}
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('获取成功', $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入
|
||||||
|
*/
|
||||||
|
public function import()
|
||||||
|
{
|
||||||
|
$file = request()->file('file');
|
||||||
|
if ($file->getSize() > 20 * 1024 * 1024) {
|
||||||
|
return error('上传文件不能超过20M');
|
||||||
|
}
|
||||||
|
|
||||||
|
$reader = IOFactory::createReader('Xlsx');
|
||||||
|
|
||||||
|
// 读取文件
|
||||||
|
$spreadsheet = $reader->load($file->getRealPath());
|
||||||
|
|
||||||
|
// 获取活动sheet
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
// 获取行数
|
||||||
|
$rows = $sheet->getHighestRow();
|
||||||
|
|
||||||
|
// 从表格获取数据
|
||||||
|
$xlsx_data = [];
|
||||||
|
for ($i=2; $i <= $rows; $i++) {
|
||||||
|
$xlsx_data[$i] = [
|
||||||
|
'spu' => $sheet->getCell('A' . $i)->getValue(),
|
||||||
|
'platform' => $sheet->getCell('B' . $i)->getValue(),
|
||||||
|
'link' => $sheet->getCell('C' . $i)->getValue(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$platforms_name = array_unique(array_column($xlsx_data, 'platform'));
|
||||||
|
$platforms_map = ProductPurchaseLinkPlatformModel::language(request()->lang_id)
|
||||||
|
->where('platform', 'in', $platforms_name)
|
||||||
|
->column('id', 'platform');
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
$errors = [];
|
||||||
|
$chunks = array_chunk($xlsx_data, 500, true);
|
||||||
|
// 分组验证每行,并组装数据
|
||||||
|
foreach ($chunks as $chunk) {
|
||||||
|
$spus = array_unique(array_column($chunk, 'spu'));
|
||||||
|
$products_map = ProductModel::language(request()->lang_id)
|
||||||
|
->where('spu', 'in', $spus)
|
||||||
|
->column('id', 'spu');
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
foreach ($chunk as $r => $it) {
|
||||||
|
if (empty($platforms_map[$it['platform']])) {
|
||||||
|
$errors[] = sprintf("第%d行,平台名称错误", $r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (empty($products_map[$it['spu']])) {
|
||||||
|
$errors[] = sprintf("第%d行,型号不存在", $r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$items[] = [
|
||||||
|
'language_id' => request()->lang_id,
|
||||||
|
'product_id' => $products_map[$it['spu']],
|
||||||
|
'platform_id' => $platforms_map[$it['platform']],
|
||||||
|
'link' => $it['link'],
|
||||||
|
'sort' => 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (!empty($items)) {
|
||||||
|
$data[] = $items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装sql,并执行
|
||||||
|
if (!empty($data)) {
|
||||||
|
$link_model = new ProductPurchaseLinkModel();
|
||||||
|
$sql = sprintf(
|
||||||
|
'REPLACE INTO %s (id, language_id, product_id, platform_id, link, sort) VALUES ',
|
||||||
|
$link_model->getTable(),
|
||||||
|
);
|
||||||
|
foreach ($data as $items) {
|
||||||
|
$products_id = array_unique(array_column($items, 'product_id'));
|
||||||
|
$links = $link_model->field([
|
||||||
|
'id',
|
||||||
|
'product_id',
|
||||||
|
'platform_id'
|
||||||
|
])
|
||||||
|
->where('product_id', 'in', $products_id)
|
||||||
|
->select();
|
||||||
|
$links_map = [];
|
||||||
|
if (!$links->isEmpty()) {
|
||||||
|
foreach ($links as $link) {
|
||||||
|
$links_map[$link['product_id'] . '_' . $link['platform_id']] = $link['id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$item['id'] = null;
|
||||||
|
if (!empty($links_map[$item['product_id'] . '_' . $item['platform_id']])) {
|
||||||
|
$item['id'] = $links_map[$item['product_id'] . '_' . $item['platform_id']];
|
||||||
|
}
|
||||||
|
$sql .= sprintf(
|
||||||
|
'(%d, %d, %d, %d, "%s", %d),',
|
||||||
|
$item['id'],
|
||||||
|
$item['language_id'],
|
||||||
|
$item['product_id'],
|
||||||
|
$item['platform_id'],
|
||||||
|
$item['link'],
|
||||||
|
$item['sort']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Db::execute(rtrim($sql, ','));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($errors)) {
|
||||||
|
return error(implode(";\n", $errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('导入成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出
|
||||||
|
*/
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
$schema = [
|
||||||
|
'spu' => '型号',
|
||||||
|
'platform' => '平台',
|
||||||
|
'link' => '链接'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 获取导出数据
|
||||||
|
$data = $this->getExportLinkData();
|
||||||
|
|
||||||
|
// 获取Spreadsheet对象
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
// 写入表头
|
||||||
|
$title = array_values($schema);
|
||||||
|
$title_col = 'A';
|
||||||
|
foreach ($title as $value) {
|
||||||
|
// 单元格内容写入
|
||||||
|
$sheet->setCellValue($title_col . '1', $value);
|
||||||
|
$title_col++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入数据
|
||||||
|
$row = 2;
|
||||||
|
$keys = array_keys($schema);
|
||||||
|
foreach ($data as $item) {
|
||||||
|
$data_col = 'A';
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$sheet->setCellValue($data_col . $row, $item[$key] ?? '');
|
||||||
|
$data_col++;
|
||||||
|
}
|
||||||
|
$row++;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush();
|
||||||
|
ob_flush();
|
||||||
|
$filename = date('YmdHms');
|
||||||
|
header('Access-Control-Expose-Headers: Content-Disposition');
|
||||||
|
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; Charset=UTF-8');
|
||||||
|
header('Content-Disposition: attachment;filename=' . $filename . '.xlsx');
|
||||||
|
header('Cache-Control: max-age=0');
|
||||||
|
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||||
|
$writer->save('php://output');
|
||||||
|
}
|
||||||
|
private function getExportLinkData()
|
||||||
|
{
|
||||||
|
$params = request()->param([
|
||||||
|
'name' => '',
|
||||||
|
'spu' => ''
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ProductModel::alias('pd')
|
||||||
|
->field([
|
||||||
|
'pd.spu',
|
||||||
|
'pf.platform',
|
||||||
|
'pl.link'
|
||||||
|
])
|
||||||
|
->leftJoin('product_purchase_link pl', 'pl.product_id = pd.id')
|
||||||
|
->leftJoin('product_purchase_platform pf', 'pf.id = pl.platform_id')
|
||||||
|
->where(function ($query) use ($params) {
|
||||||
|
$query->where('pd.is_show', '=', 1);
|
||||||
|
if (!empty($params['name'])) {
|
||||||
|
$query->where('pd.name', 'like', '%' . $params['name'] . '%');
|
||||||
|
}
|
||||||
|
if (!empty($params['spu'])) {
|
||||||
|
$query->where('pd.spu', 'like', '%' . $params['spu'] . '%');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->where('pd.language_id', '=', request()->lang_id)
|
||||||
|
->order(['pl.sort' => 'asc', 'pl.id' => 'desc', 'pd.id' => 'desc'])
|
||||||
|
->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新购买链接
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
$id = request()->param('id');
|
||||||
|
$put = request()->put([
|
||||||
|
'link',
|
||||||
|
'platform_id'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'id' => $id,
|
||||||
|
'link' => $put['link'],
|
||||||
|
'platform_id' => $put['platform_id']
|
||||||
|
];
|
||||||
|
$validate = new ProductPurchaseLinkValidate;
|
||||||
|
if (!$validate->scene('update')->check($data)) {
|
||||||
|
return error($validate->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
$link = ProductPurchaseLinkModel::bypk($data['id'])->find();
|
||||||
|
if (empty($link)) {
|
||||||
|
return error('请确认操作对象是否存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$link->save($data)) {
|
||||||
|
return error('操作失败');
|
||||||
|
}
|
||||||
|
return success('操作成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/admin/model/v1/ProductPurchaseLinkModel.php
Normal file
31
app/admin/model/v1/ProductPurchaseLinkModel.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\admin\model\v1;
|
||||||
|
|
||||||
|
use app\common\model\ProductPurchaseLinkBaseModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品 - 购买链接模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class ProductPurchaseLinkModel extends ProductPurchaseLinkBaseModel
|
||||||
|
{
|
||||||
|
// 关联产品
|
||||||
|
public function product()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ProductModel::class, 'product_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关联平台
|
||||||
|
public function platform()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ProductPurchaseLinkPlatformModel::class, 'platform_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据语言查询
|
||||||
|
public function scopeLanguage($query, $value)
|
||||||
|
{
|
||||||
|
$query->where('language_id', '=', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/admin/model/v1/ProductPurchaseLinkPlatformModel.php
Normal file
19
app/admin/model/v1/ProductPurchaseLinkPlatformModel.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\admin\model\v1;
|
||||||
|
|
||||||
|
use app\common\model\ProductPurchasePlatformBaseModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品 - 采购链接平台模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class ProductPurchaseLinkPlatformModel extends ProductPurchasePlatformBaseModel
|
||||||
|
{
|
||||||
|
// 根据语言查询
|
||||||
|
public function scopeLanguage($query, $value)
|
||||||
|
{
|
||||||
|
$query->where('language_id', '=', $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -184,6 +184,24 @@ Route::group('v1', function () {
|
|||||||
Route::delete('delete/:id', 'ProductCategory/delete');
|
Route::delete('delete/:id', 'ProductCategory/delete');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 产品购买链接
|
||||||
|
Route::group('buypass', function () {
|
||||||
|
// 购买链接平台列表
|
||||||
|
Route::get('platforms', 'ProductPurchaseLink/platforms');
|
||||||
|
|
||||||
|
// 购买链接列表
|
||||||
|
Route::get('index', 'ProductPurchaseLink/index');
|
||||||
|
|
||||||
|
// 购买链接导入
|
||||||
|
Route::post('import', 'ProductPurchaseLink/import');
|
||||||
|
|
||||||
|
// 购买链接导出
|
||||||
|
Route::get('export', 'ProductPurchaseLink/export');
|
||||||
|
|
||||||
|
// 购买链接更新
|
||||||
|
Route::put('update/:id', 'ProductPurchaseLink/update');
|
||||||
|
});
|
||||||
|
|
||||||
// 产品回收站
|
// 产品回收站
|
||||||
Route::group('trash', function () {
|
Route::group('trash', function () {
|
||||||
// 产品回收站列表
|
// 产品回收站列表
|
||||||
|
|||||||
45
app/admin/validate/v1/ProductPurchaseLinkValidate.php
Normal file
45
app/admin/validate/v1/ProductPurchaseLinkValidate.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\validate\v1;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
class ProductPurchaseLinkValidate extends Validate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 定义验证规则
|
||||||
|
* 格式:'字段名' => ['规则1','规则2'...]
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $rule = [
|
||||||
|
'id' => 'require|integer',
|
||||||
|
'link' => 'url|max:255',
|
||||||
|
'platform_id' => 'integer'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义错误信息
|
||||||
|
* 格式:'字段名.规则名' => '错误信息'
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $message = [
|
||||||
|
'id.require' => 'id不能为空',
|
||||||
|
'id.integer' => 'id字段类型错误',
|
||||||
|
'link.url' => '链接格式不正确',
|
||||||
|
'link.max' => '链接不能超过255个字符',
|
||||||
|
'platform_id.integer' => '平台id类型错误'
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新场景
|
||||||
|
*/
|
||||||
|
public function sceneUpdate()
|
||||||
|
{
|
||||||
|
return $this->only(['id', 'link', 'platform_id'])->remove('id', 'require');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user