feat: #10000 基础完成

This commit is contained in:
赵世界 2023-04-20 20:43:49 +08:00
parent 4e872a2d50
commit 87e1fcec05
21 changed files with 896 additions and 28 deletions

View File

@ -3,18 +3,21 @@
namespace App\Console\Commands;
use App\Events\StockUpdateEvent;
use App\Exports\DiffTodayPriceGoodsExport;
use App\Models\BusinessGoodsSku;
use App\Models\BusinessOrder;
use App\Models\GoodsSku;
use App\Models\GoodsType;
use App\Models\Log;
use App\Models\Shop;
use App\Models\TodayPrice;
use App\Services\Business\BusinessFactory;
use App\Utils\DateTimeUtils;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use App\Jobs\BusinessGoodsSkuIncrQuantity;
use Illuminate\Database\Eloquent\Builder;
use Maatwebsite\Excel\Facades\Excel;
class Test extends Command
{
@ -49,5 +52,104 @@ class Test extends Command
*/
public function handle()
{
$todayPrice = TodayPrice::query()
->with([
'goodsSku:id,goods_id,title,external_sku_id',
'goodsSku.goods:id,title',
])
->where('day', date('Y-m-d'))
->get();
if ($todayPrice->isEmpty()) {
exit('今日价格数据未找到,请先上传');
}
$todayGoodsPrice = [];
foreach ($todayPrice as $item) {
$todayGoodsPrice[$item['external_sku_id']] = [
'today_price' => $item['price'],
'goods_name' => $item['goodsSku']['goods']['title'] . $item['goodsSku']['title'],
'external_sku_id' => $item['external_sku_id'],
];
}
$shops = Shop::query()
->where('plat_id', Shop::$PLAT_KTT)
->where('expires_at', '>', time())
->get();
$data = [];
foreach ($shops as $shop) {
$business = BusinessFactory::init()->make($shop->plat_id);
$business->setShop($shop);
$res = $business->queryGroup();
if (!isset($res['ktt_group_query_list_response'])) {
continue;
}
$activityNos =$activities = [];
foreach ($res['ktt_group_query_list_response']['activity_list'] as $activity) {
if (0 === $activity['is_help_sell'] && '补款勿拍' !== $activity['title']) {
$activityNos[] = $activity['activity_no'];
$activities[$activity['activity_no']] = $activity['title'];
}
}
$businessGoodsSkus = BusinessGoodsSku::query()
->where('shop_id', $shop->id)
->whereIn('activity_no', $activityNos)
->orderBy('activity_no')
->get(['shop_id', 'title', 'activity_no', 'goods_name', 'price_in_fen', 'external_sku_id']);
if ($businessGoodsSkus->isEmpty()) {
continue;
}
$data[$shop->name] = $this->diffTodayPrice($businessGoodsSkus, $todayGoodsPrice,$activities);
}
foreach ($data as $shopName => $activity) {
foreach ($activity as $activityNo => $item) {
foreach ($item as $k => $v) {
foreach ($v as $i) {
if ('diff_price' === $k) {
$s[] = [$shopName, $i['title'], $i['goods_name'], $i['price_in_fen'], $i['today_price'], $i['external_sku_id']];
}
if ('not_in_group' === $k) {
$s[] = [$shopName, $i['title'], $i['goods_name'], '团购无此商品', $i['today_price'], $i['external_sku_id']];
}
}
}
}
}
dd($s);
ob_end_clean();
return Excel::download(new DiffTodayPriceGoodsExport($data), date('Y-m-d') . '今日差价商品.xlsx');
}
private function diffTodayPrice($businessGoodsSkus, $todayPrice,$activities)
{
$data = [];
foreach ($businessGoodsSkus as $item) {
// 记录团购下商品id
$data[$item['activity_no']]['ids'][] = $item['external_sku_id'];
// 团购中有,表格没有
// if (!isset($todayPrice[$item['external_sku_id']])) {
// $data[$item['activity_no']]['in_group'][] = $item->toArray();
// }
// 价格不一样
if (isset($todayPrice[$item['external_sku_id']]) && $item['price_in_fen'] != $todayPrice[$item['external_sku_id']]['today_price']) {
$item['today_price'] = $todayPrice[$item['external_sku_id']]['today_price'];
$data[$item['activity_no']]['diff_price'][] = $item->toArray();
}
}
$todayIds = array_keys($todayPrice);
foreach ($data as $no=> &$arr) {
foreach ($arr as $key => $value) {
if ('ids' === $key) {
$ids = array_unique($value);
$ids = array_diff($todayIds, $ids);
foreach ($ids as $id) {
$todayPrice[$id]['title'] = $activities[$no];
$arr['not_in_group'][] = $todayPrice[$id];
}
}
}
unset($arr['ids']);
}
return $data;
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace App\Exports;
use App\Models\DailyStockRecord;
use App\Models\Log;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use App\Models\GoodsSku;
use Illuminate\Support\Collection;
class DiffTodayPriceGoodsExport implements FromCollection, ShouldAutoSize
{
private $data;
public function __construct($data)
{
$this->data = $this->createData($data);
}
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return new Collection($this->data);
}
private function createData($data)
{
$headTitle = [
'店铺',
'团购标题',
'商品名称',
'快团团价格',
'今日价格',
'编码',
];
$bodyData = [];
foreach ($data as $shopName => $activity) {
foreach ($activity as $activityNo => $item) {
foreach ($item as $k => $v) {
foreach ($v as $i) {
if ('diff_price' === $k) {
$bodyData[] = [$shopName, $i['title'], $i['goods_name'], $i['price_in_fen'], $i['today_price'], $i['external_sku_id']];
}
if ('not_in_group' === $k) {
$bodyData[] = [$shopName, $i['title'], $i['goods_name'], '团购无此商品', $i['today_price'], $i['external_sku_id']];
}
}
}
}
}
return [$headTitle, $bodyData];
}
}

View File

@ -5,14 +5,22 @@ namespace App\Http\Controllers\Business;
use App\Events\BusinessOrdersUpdate;
use App\Http\Controllers\Controller;
use App\Http\Resources\BusinessGoodsSkuResource;
use App\Imports\TodayPriceImport;
use App\Models\BusinessGoodsSku;
use App\Models\BusinessOrderItem;
use App\Models\Goods;
use App\Models\GoodsSku;
use App\Models\Log as LogModel;
use App\Models\Shop;
use App\Models\TodayPrice;
use App\Services\Business\BusinessFactory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\DiffTodayPriceGoodsExport;
class BusinessGoodsSkusController extends Controller
{
@ -90,4 +98,112 @@ class BusinessGoodsSkusController extends Controller
}
return response($this->res, $this->res['httpCode']);
}
public function todayPriceImport(Request $request)
{
if (!$request->hasFile('today_price')) {
$this->res = [
'httpCode' => 404,
'errorCode' => 404404,
'errorMessage' => 'not found file',
];
}
try {
$import = new TodayPriceImport();
$path = $request->file('today_price');
Excel::import($import, $path);
} catch (ValidationException $exception) {
$this->setValidatorFailResponse($exception->validator->getMessageBag()->getMessages());
}
return response($this->res, $this->res['httpCode']);
}
public function exportTodayPrice(Request $request)
{
$todayPrice = TodayPrice::query()
->with([
'goodsSku:id,goods_id,title,external_sku_id',
'goodsSku.goods:id,title',
])
->where('day', date('Y-m-d'))
->get();
if ($todayPrice->isEmpty()) {
exit('今日价格数据未找到,请先上传');
}
$todayGoodsPrice = [];
foreach ($todayPrice as $item) {
$todayGoodsPrice[$item['external_sku_id']] = [
'today_price' => $item['price'],
'goods_name' => $item['goodsSku']['goods']['title'] . $item['goodsSku']['title'],
'external_sku_id' => $item['external_sku_id'],
];
}
$shops = Shop::query()
->where('plat_id', Shop::$PLAT_KTT)
->where('expires_at', '>', time())
->get();
$data = [];
foreach ($shops as $shop) {
$business = BusinessFactory::init()->make($shop->plat_id);
$business->setShop($shop);
$res = $business->queryGroup();
if (!isset($res['ktt_group_query_list_response'])) {
continue;
}
$activityNos = $activities = [];
foreach ($res['ktt_group_query_list_response']['activity_list'] as $activity) {
if (0 === $activity['is_help_sell'] && '补款勿拍' !== $activity['title']) {
$activityNos[] = $activity['activity_no'];
$activities[$activity['activity_no']] = $activity['title'];
}
}
$businessGoodsSkus = BusinessGoodsSku::query()
->where('shop_id', $shop->id)
->whereIn('activity_no', $activityNos)
->orderBy('activity_no')
->get(['shop_id', 'title', 'activity_no', 'goods_name', 'price_in_fen', 'external_sku_id']);
if ($businessGoodsSkus->isEmpty()) {
continue;
}
$data[$shop->name] = $this->diffTodayPrice($businessGoodsSkus, $todayGoodsPrice, $activities);
}
ob_end_clean();
return Excel::download(new DiffTodayPriceGoodsExport($data), date('Y-m-d') . '今日差价商品.xlsx');
}
private function diffTodayPrice($businessGoodsSkus, $todayPrice, $activities)
{
$data = [];
foreach ($businessGoodsSkus as $item) {
// 记录团购下商品id
$data[$item['activity_no']]['ids'][] = $item['external_sku_id'];
// 团购中有,表格没有
// if (!isset($todayPrice[$item['external_sku_id']])) {
// $data[$item['activity_no']]['in_group'][] = $item->toArray();
// }
// 价格不一样
if (isset($todayPrice[$item['external_sku_id']]) && $item['price_in_fen'] != $todayPrice[$item['external_sku_id']]['today_price']) {
$item['today_price'] = $todayPrice[$item['external_sku_id']]['today_price'];
$data[$item['activity_no']]['diff_price'][] = $item->toArray();
}
}
$todayIds = array_keys($todayPrice);
foreach ($data as $no => &$arr) {
foreach ($arr as $key => $value) {
if ('ids' === $key) {
$ids = array_unique($value);
$ids = array_diff($todayIds, $ids);
foreach ($ids as $id) {
$todayPrice[$id]['title'] = $activities[$no];
$arr['not_in_group'][] = $todayPrice[$id];
}
}
}
unset($arr['ids']);
}
return $data;
}
}

View File

@ -4,8 +4,12 @@ namespace App\Http\Controllers\Goods;
use App\Http\Controllers\Controller;
use App\Http\Resources\GoodsSkuResource;
use App\Models\CombinationGood;
use App\Models\Goods;
use App\Models\GoodsSku;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class GoodsCombinationController extends Controller
{
@ -14,27 +18,124 @@ class GoodsCombinationController extends Controller
$skus = GoodsSku::query()
->where('is_combination', 1)
->with([
'combinationItems:goods_sku_id,item_id,item_num',
'combinationItems.goodsSkuItem:id,goods_id,title,stock,external_sku_id',
'combinationItems.goodsSkuItem.goods:id,title',
'combinationGoods:id,goods_sku_id,item_id,item_num',
'combinationGoods.goodsSkuItem:id,goods_id,title,stock,external_sku_id,updated_at,yesterday_num,reference_price,status',
'combinationGoods.goodsSkuItem.goods:id,title,img_url',
])
->paginate($request->get('per_page'));
foreach ($skus as &$item) {
$items = [];
foreach ($item['combinationGoods'] as $combinationItem) {
$items[] = [
'cost' => 0,
'external_sku_id' => $combinationItem['goodsSkuItem']['external_sku_id'],
'goods_id' => $combinationItem['goodsSkuItem']['goods_id'],
'id' => $combinationItem['item_id'],
'is_combination' => 0,
'num' => $combinationItem['item_num'],
'reference_price' => $combinationItem['goodsSkuItem']['reference_price'],
'status' => $combinationItem['goodsSkuItem']['status'],
'stock' => $combinationItem['goodsSkuItem']['stock'],
'thumb_url' => $combinationItem['goodsSkuItem']['goods']['img_url'],
'img_url' => $combinationItem['goodsSkuItem']['goods']['img_url'],
'title' => $combinationItem['goodsSkuItem']['goods']['title'] . $combinationItem['goodsSkuItem']['title'],
'updated_at' => $combinationItem['goodsSkuItem']['updated_at'],
'yesterday_num' => $combinationItem['goodsSkuItem']['yesterday_num'],
];
}
$item['children'] = $items;
unset($item['combinationGoods']);
}
return GoodsSkuResource::collection($skus);
}
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required',
'external_sku_id' => 'required',
'combination_goods.*' => 'required',
'combination_goods.*.item_id' => 'required',
'combination_goods.*.item_num' => 'required|gt:0',
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
DB::beginTransaction();
try {
if ($id = $request->input('id')) {
$sku = GoodsSku::query()->findOrFail($id);
} else {
$sku = new GoodsSku();
$sku->goods_id = 0;
$sku->title = $request->input('title');
$sku->sku_code = $request->input('external_sku_id');
$sku->external_sku_id = $request->input('external_sku_id');
$sku->is_combination = 1;
$sku->save();
}
CombinationGood::query()
->where('goods_sku_id', $sku->id)
->delete();
foreach ($request->input('combination_goods') as $item) {
CombinationGood::query()->create(['goods_sku_id' => $sku->id, 'item_id' => $item['item_id'],'item_num' => $item['item_num']]);
}
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
'httpCode' => 400,
'errorCode' => 400500,
'errorMessage' => $exception->getMessage(),
];
}
return response($this->res, $this->res['httpCode']);
}
public function show(Request $request, $id)
{
$sku = GoodsSku::query()
->with([
'combinationGoods:id,goods_sku_id,item_id,item_num',
'combinationGoods.goodsSkuItem:id,title,goods_id',
'combinationGoods.goodsSkuItem.goods:id,title',
])
->findOrFail($id);
$items = [];
foreach ($sku['combinationGoods'] as $item) {
$items[] = [
'id' => $item['goodsSkuItem']['id'],
'title' => $item['goodsSkuItem']['goods']['title'] . $item['goodsSkuItem']['title'],
];
}
$sku['skus'] = $items;
return new GoodsSkuResource($sku);
}
public function update(Request $request, $id)
public function destroy(Request $request, $id)
{
}
public function goodsSkus(Request $request, $title)
{
$goodsIds = Goods::query()
->where('title', 'like', '%' . $title . '%')
->pluck('id');
$skus = GoodsSku::query()
->whereIn('goods_id', $goodsIds)
->where('is_combination', 0)
->with('goods:id,title')
->get(['id', 'title', 'goods_id']);
foreach ($skus as &$sku) {
$sku['title'] = $sku['goods']['title'] . $sku['title'];
}
return GoodsSkuResource::collection($skus);
}
}

View File

@ -45,7 +45,7 @@ class MenusController extends Controller
}
}
$permissionCodes = array_unique($permissionCodes);
$menus = Menu::query()->orderBy('parent_id')->orderBy('seq')->get()->toArray();
$menus = Menu::query()->where('show', 1)->orderBy('parent_id')->orderBy('seq')->get()->toArray();
$hasPermissionMenus = [];
foreach ($menus as $menu) {
if (in_array($menu['code'], $permissionCodes, true)) {

View File

@ -0,0 +1,35 @@
<?php
namespace App\Imports;
use App\Models\TodayPrice;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithStartRow;
class TodayPriceImport implements ToArray, SkipsEmptyRows, WithStartRow
{
public function startRow(): int
{
return 2;
}
public function array(array $array)
{
$data = [];
$day = date('Y-m-d');
foreach ($array as $row) {
$row = array_map(function ($value) {
return trim($value);
}, $row);
$data[] = [
'day' => $day,
'external_sku_id' => $row[0],
'price' => $row[1],
];
}
TodayPrice::query()->delete();
$model = new TodayPrice();
$model->batchInsert($data);
}
}

View File

@ -23,7 +23,6 @@ class BusinessGoodsSku extends Model
'limit_buy',
'market_price',
'update_time',
'price_in_fen',
'quantity',
'goods_purchase_price',
'quantity_type',
@ -66,4 +65,9 @@ class BusinessGoodsSku extends Model
{
return $this->belongsTo(Shop::class, 'shop_id', 'id');
}
public function getPriceInFenAttribute($val)
{
return $val / 100;
}
}

View File

@ -6,8 +6,10 @@ use Illuminate\Database\Eloquent\Model;
class CombinationGood extends Model
{
protected $guarded = [];
public function goodsSkuItem()
{
return $this->belongsTo(GoodsSku::class, 'id', 'item_id');
return $this->belongsTo(GoodsSku::class, 'item_id', 'id');
}
}

View File

@ -78,7 +78,17 @@ class GoodsSku extends Model
}
public function combinationItems()
{
return $this->hasMany(CombinationGood::class, 'item_id', 'id');
}
public function combinationGoods()
{
return $this->hasMany(CombinationGood::class, 'goods_sku_id', 'id');
}
public function todayPrice()
{
return $this->hasOne(TodayPrice::class, 'external_sku_id', 'external_sku_id');
}
}

13
app/Models/TodayPrice.php Normal file
View File

@ -0,0 +1,13 @@
<?php
namespace App\Models;
class TodayPrice extends Model
{
protected $guarded = [];
public function goodsSku()
{
return $this->belongsTo(GoodsSku::class, 'external_sku_id', 'external_sku_id');
}
}

View File

@ -23,6 +23,7 @@ class CreateMenusTable extends Migration
$table->string('name', 32)->comment('菜单名称');
$table->unsignedBigInteger('parent_id')->default(0);
$table->unsignedInteger('seq')->default(0)->comment('排序序号');
$table->tinyInteger('show')->default(1);
// 索引
});
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTodayPricesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (Schema::hasTable('today_prices')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('today_prices', function (Blueprint $table) {
$table->bigIncrements('id');
$table->date('day');
$table->string('external_sku_id');
$table->float('price');
$table->index(['external_sku_id', 'day']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('today_prices');
}
}

View File

@ -51,7 +51,7 @@ class MenusTableSeeder extends Seeder
if (false === strpos($code, '.')) {
DB::table('menus')->updateOrInsert(
['id' => $route['id'], 'parent_id' => $route['parent_id'], 'code' => $code],
['name' => $route['name']]
['name' => $route['name'], 'show' => $route['show']]
);
}
}

View File

@ -132,5 +132,50 @@ export function getStockNum() {
return http({
url: "/api/stock/goods_skus",
method: "get",
})
});
}
export function getGoodsFilter(title) {
return http({
url: "/api/goods/filter/" + title,
method: "get",
});
}
export function addGoodsCombination(data) {
return http({
url: "/api/goods_combination",
method: "post",
data,
});
}
export function getGoodsCombination(params) {
return http({
url: "/api/goods_combination",
method: "get",
params,
});
}
export function showGoodsCombination(id) {
return http({
url: "/api/goods_combination/" + id,
method: "get",
});
}
export function updateGoodsCombination(id, data) {
return http({
url: "/api/goods_combination/" + id,
method: "patch",
data,
});
}
export function delGoodsCombination(id) {
return http({
url: "/api/goods_combination/" + id,
method: "delete",
});
}

View File

@ -16,6 +16,20 @@ const list = [
keepAlive: true,
},
},
{
path: "ADDGOODS",
name: "新建商品",
component: () => import("../views/goods/addgoods/addgoods.vue"),
},
{
path: "EDIT_GOODS",
name: "修改商品规格",
component: () => import("../views/goods/editgoods.vue"),
},
{
path: "/",
redirect: "GOODS_LIST",
},
{
path: "GOODS_TYPE",
name: "商品种类",
@ -31,6 +45,11 @@ const list = [
name: "商品货架",
component: () => import("../views/goods/location.vue"),
},
{
path: "GOODS_COMBINATION",
name: "组合商品",
component: () => import("../views/goods/combination.vue"),
},
{
path: "SHOP_MANAGE",
name: "店铺管理",
@ -57,29 +76,15 @@ const list = [
component: () => import("../views/logs/record.vue"),
},
{
path: "ADDGOODS",
name: "新建商品",
component: () => import("../views/goods/addgoods/addgoods.vue"),
},
{
path: "EDIT_GOODS",
name: "修改商品规格",
component: () => import("../views/goods/editgoods.vue"),
},
{
path: "/",
redirect: "GOODS_LIST",
path: "PLAT_ORDER_LIST",
name: "订单列表",
component: () => import("../views/plat/orderList.vue"),
},
{
path: "PLAT_GOODS_LIST",
name: "货品列表",
component: () => import("../views/plat/goodsList.vue"),
},
{
path: "PLAT_ORDER_LIST",
name: "订单列表",
component: () => import("../views/plat/orderList.vue"),
},
{
path: "GROUP_MANAGEMENT",
name: "团购管理",

View File

@ -0,0 +1,282 @@
<template>
<div>
<el-card :body-style="{ padding: '20px 20px 0 20px' }">
<div class="goods">
<el-form ref="form" :inline="true" :model="searchForm">
<el-form-item label="商品名称:">
<el-input v-model="searchForm.goods_title" placeholder="商品名称" style="width: 100px"></el-input>
</el-form-item>
<el-form-item label="商品编码:">
<el-input v-model="searchForm.external_sku_id" placeholder="商品编码" style="width: 100px"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleChoose(1)">筛选</el-button>
<el-button plain @click="handleReChoose()">重置筛选</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card style="margin-top: 10px">
<div>
<!-- 表格头部操作 -->
<div class="btn">
<el-button type="primary" plain @click="addGoodsCombination">新增组合商品</el-button>
</div>
<!-- 表格 -->
<el-table v-loading="loading" ref="multipleTable" :data="tableData" class="table" tooltip-effect="dark"
style="width: 100%" row-key="id" :tree-props="{ children: 'children' }">
<el-table-column label="商品信息" width="400">
<template slot-scope="scope">
<div class="commodityimg">
<img :src="scope.row.img_url" class="Img" />
</div>
<div>
<p>{{ scope.row.title }}</p>
<p>{{ scope.row.external_sku_id }}</p>
<p>{{ scope.row.updated_at }}</p>
</div>
</template>
</el-table-column>
<el-table-column prop="num" label="数量"></el-table-column>
<el-table-column prop="reference_price" label="售价"></el-table-column>
<el-table-column prop="stock" label="库存"></el-table-column>
<el-table-column prop="status" label="状态"> </el-table-column>
<el-table-column label="操作" width="130">
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row.id)">编辑</el-button>
<!-- <el-button type="text" @click="handleDelete(scope.row.id)">删除</el-button> -->
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页功能 -->
<div class="page">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="current_page" :page-sizes="[15, 50, 100]" :page-size="per_page"
layout="total, sizes, prev, pager, next, jumper" :total="Paginationdata.total">
</el-pagination>
</div>
</el-card>
<el-dialog title="新增组合商品" :visible.sync="dialogVisible">
<el-form :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic">
<el-form-item label="商品名称" prop="title" :rules="[
{ required: true, message: '请输入商品名称', trigger: 'blur' },
]">
<el-input v-model="dynamicValidateForm.title"></el-input>
</el-form-item>
<el-form-item label="商品编码" prop="external_sku_id" :rules="[
{ required: true, message: '请输入商品编码', trigger: 'blur' },
]">
<el-input v-model="dynamicValidateForm.external_sku_id"></el-input>
</el-form-item>
<el-form-item v-for="(item, index) in dynamicValidateForm.combination_goods" :label="'子商品' + index"
:key="item.item_id" :prop="'combination_goods.' + index + '.item_id'" :rules="{
required: true, message: '子商品不能为空', trigger: 'blur'
}">
<el-col :span="8">
<el-select v-model="item.item_id" filterable remote reserve-keyword placeholder="请选择子商品"
:remote-method="remoteMethod" :loading="remoteLoading">
<el-option v-for="sku in skus" :key="sku.id" :label="sku.title" :value="sku.id"></el-option>
</el-select>
</el-col>
<el-col :span="2">
<el-input v-model="item.item_num" placeholder="数量"></el-input>
</el-col>
<el-button type="danger" @click.prevent="removeItem(index)">删除</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button>
<el-button @click="addItem">添加子商品</el-button>
<el-button @click="resetForm('dynamicValidateForm')">重置</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
import { getGoodsCombination, addGoodsCombination, showGoodsCombination, delGoodsCombination, getGoodsFilter } from "../../api/goods.js";
export default {
data() {
return {
dialogVisible: false,
loading: false,
tableData: [], //
searchForm: {
external_sku_id: "",
goods_title: "", //
},
Paginationdata: {}, //
current_page: 1, //
per_page: 100, //
dynamicValidateForm: {
id: 0,
title: '',
external_sku_id: '',
combination_goods: [{
item_id: '',
item_num: 1,
}],
},
skus: [{
'id': '',
'title': ''
}],
remoteLoading: false
};
},
methods: {
//
handleEdit(id) {
this.dialogVisible = true;
showGoodsCombination(id).then((res) => {
this.dynamicValidateForm = res.data.data;
this.skus = res.data.data.skus;
});
},
//
handleDelete(id) {
},
//
getList(params) {
getGoodsCombination(params).then((res) => {
this.tableData = res.data.data;
this.Paginationdata = res.data.meta;
this.loading = false;
});
},
//
handleChoose() {
this.searchForm = {
...this.searchForm,
page: this.current_page,
per_page: this.per_page,
};
this.getList(this.searchForm);
},
//
handleReChoose() {
this.form = {
external_sku_id: "",
goods_title: "", //
};
},
//
handleSizeChange(val) {
//
this.per_page = val;
this.current_page = 1;
this.handleChoose();
},
handleCurrentChange(val) {
//
this.current_page = val;
this.handleChoose();
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
addGoodsCombination(this.dynamicValidateForm).then((res) => {
this.$message({
message: res.data.message,
type: 'success'
});
this.dialogVisible = false;
})
this.getList();
} else {
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
removeItem(index) {
this.dynamicValidateForm.combination_goods.splice(index, 1)
},
addItem() {
this.dynamicValidateForm.combination_goods.push({
item_id: '',
item_num: 1,
});
},
remoteMethod(query) {
if (query !== '') {
this.remoteLoading = true;
getGoodsFilter(query).then((res) => {
this.skus = res.data.data;
this.remoteLoading = false;
});
} else {
this.skus = [];
}
},
addGoodsCombination() {
this.dialogVisible = true;
this.dynamicValidateForm = {
id: 0,
title: '',
external_sku_id: '',
combination_goods: [{
item_id: '',
item_num: 1,
}],
};
}
},
mounted() {
this.getList();
},
};
</script>
<style lang="css" scoped>
.table {
margin-top: 20px;
position: relative;
}
.btn {
float: right;
}
::v-deep .cell {
display: flex;
align-items: center;
}
.commodityimg {
width: 59px;
height: 59px;
background: rgba(227, 227, 227, 0.39);
opacity: 1;
display: block;
margin-right: 12px;
}
.Img {
width: 100%;
height: 100%;
}
::v-deep .btn11 {
padding: 0;
width: 14px;
height: 14px;
}
::v-deep .btn11 img {
width: 100%;
height: 100%;
}
.page {
margin-top: 20px;
}
</style>

View File

@ -141,7 +141,7 @@ export default {
beforeUpload() {
this.loadingModule = this.$loading({
lock: true,
text: '盘点导入中...',
text: '表格导入中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});

View File

@ -22,6 +22,12 @@
<el-form-item>
<el-button type="primary" @click="handleChoose()">筛选</el-button>
<el-button plain @click="handleReChoose()">重置筛选</el-button>
<el-upload ref="myUpload" action="/api/today/price" :multiple="false" name="today_price"
:show-file-list="false" :on-success="uploadSuccess" :before-upload="beforeUpload"
:on-error="uploadError" style="display:inline-block;margin: 0 10px 0 10px;">
<el-button type="primary" plain>今日商品价格导入</el-button>
</el-upload>
<el-button type="danger" plain @click="handleExport()">价格差异导出</el-button>
</el-form-item>
</el-form>
</el-card>
@ -37,6 +43,7 @@
<el-table-column prop="category_name" label="分类名称"></el-table-column>
<el-table-column prop="goods_name" label="商品名称"></el-table-column>
<el-table-column prop="external_sku_id" label="编码"></el-table-column>
<el-table-column prop="price_in_fen" label="价格"></el-table-column>
<el-table-column prop="created_at" label="下载时间"></el-table-column>
<el-table-column label="同步">
<template slot-scope="scope">
@ -214,6 +221,31 @@ export default {
}
}
});
},
beforeUpload() {
this.loadingModule = this.$loading({
lock: true,
text: '表格导入中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
},
uploadSuccess(response) {
this.$message({
message: response.message,
type: "success",
});
this.loadingModule.close();
},
uploadError(err) {
this.$message({
message: err.errorMessage,
type: "error",
});
this.loadingModule.close();
},
handleExport() {
window.open("/today_price/export");
}
},
};

View File

@ -6,11 +6,13 @@ return [
'id' => 1,
'name' => '商品管理',
'parent_id' => 0,
'show' => 1,
],
'GOODS_LIST' => [
'id' => 2,
'name' => '商品列表',
'parent_id' => 1,
'show' => 1,
],
'goods.index' => [
'id' => 20,
@ -66,6 +68,7 @@ return [
'id' => 3,
'name' => '商品种类',
'parent_id' => 1,
'show' => 1,
],
'goods_types.index' => [
'id' => 30,
@ -96,6 +99,7 @@ return [
'id' => 4,
'name' => '商品品牌',
'parent_id' => 1,
'show' => 1,
],
'goods_brands.index' => [
'id' => 40,
@ -126,6 +130,7 @@ return [
'id' => 15,
'name' => '商品货架',
'parent_id' => 1,
'show' => 1,
],
'goods_sku_location.index' => [
'id' => 150,
@ -151,6 +156,7 @@ return [
'id' => 16,
'name' => '组合商品',
'parent_id' => 1,
'show' => 1,
],
'goods_combination.index' => [
'id' => 160,
@ -182,6 +188,7 @@ return [
'id' => 5,
'name' => '店铺管理',
'parent_id' => 0,
'show' => 1,
],
'shops.index' => [
'id' => 50,
@ -223,6 +230,7 @@ return [
'id' => 6,
'name' => '用户管理',
'parent_id' => 0,
'show' => 1,
],
'users.index' => [
'id' => 60,
@ -254,11 +262,13 @@ return [
'id' => 7,
'name' => '系统管理',
'parent_id' => 0,
'show' => 1,
],
'ROLE_MANAGE' => [
'id' => 8,
'name' => '角色管理',
'parent_id' => 7,
'show' => 1,
],
'roles.index' => [
'id' => 80,
@ -289,6 +299,7 @@ return [
'id' => 9,
'name' => '权限管理',
'parent_id' => 7,
'show' => 0,
],
'permissions.index' => [
'id' => 90,
@ -305,6 +316,7 @@ return [
'id' => 10,
'name' => '系统日志',
'parent_id' => 7,
'show' => 1,
],
'logs.index' => [
'id' => 100,
@ -316,11 +328,13 @@ return [
'id' => 12,
'name' => '平台',
'parent_id' => 0,
'show' => 1,
],
'PLAT_GOODS_LIST' => [
'id' => 120,
'name' => '货品列表',
'parent_id' => 12,
'show' => 1,
],
'plat_goods.index' => [
'id' => 1200,
@ -351,6 +365,7 @@ return [
'id' => 14,
'name' => '订单列表',
'parent_id' => 12,
'show' => 1,
],
'plat.orders.index' => [
'id' => 140,
@ -367,6 +382,7 @@ return [
'id' => 13,
'name' => '团购管理',
'parent_id' => 0,
'show' => 1,
],
'group.index' => [
'id' => 130,

View File

@ -9,6 +9,7 @@ use App\Http\Controllers\Business\BusinessGoodsSkusController;
use App\Http\Controllers\Group\GroupsController;
use App\Http\Controllers\Business\BusinessOrderController;
use App\Http\Controllers\Goods\GoodsSkuLocationController;
use App\Http\Controllers\Goods\GoodsCombinationController;
/*
|--------------------------------------------------------------------------
@ -31,6 +32,7 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::resource('logs', 'Log\LogsController', ['only' => ['index']]);
// 商品
Route::resource('goods', 'Goods\GoodsController', ['only' => ['index', 'store']]);
Route::resource('goods_combination', 'Goods\GoodsCombinationController', ['only' => ['index', 'store', 'show', 'update', 'destroy']]);
// 商品规格
Route::resource('goods_skus', 'Goods\GoodsSkusController', ['only' => ['index', 'show', 'update', 'store']]);
Route::patch('batch/goods_skus', [GoodsSkusController::class, 'batchUpdate'])->name('goods_sku.batch_update');
@ -60,6 +62,7 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::delete('goods_sku_location', [GoodsSkuLocationController::class, 'delete'])->name('goods_sku_location.delete');
});
Route::get('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');
// 登录
Route::post('/auth/login', [LoginController::class, 'login'])->name('auth.login');
@ -84,5 +87,7 @@ Route::post('business', [ShopsController::class, 'business'])->name('shop.put.bu
Route::post('inventory/goods_skus', [GoodsSkusController::class, 'inventoryImport'])->name('goods_sku.inventory');
// 商品货架导入
Route::post('goods_sku_location', [GoodsSkuLocationController::class, 'import'])->name('goods_sku_location.import');
// 今日价格导入
Route::post('today/price', [BusinessGoodsSkusController::class, 'todayPriceImport'])->name('plat.today_price.import');
// 文件上传
Route::post('upload', [UploadController::class, 'store'])->name('upload.file');

View File

@ -4,6 +4,7 @@ use App\Http\Controllers\Goods\GoodsSkusController;
use App\Http\Controllers\Goods\GoodsController;
use App\Http\Controllers\Shop\ShopsController;
use App\Http\Controllers\Business\BusinessOrderController;
use App\Http\Controllers\Business\BusinessGoodsSkusController;
/*
|--------------------------------------------------------------------------
@ -22,6 +23,7 @@ Route::get('/', function () {
Route::get('goods_skus/export', [GoodsSkusController::class, 'export'])->name('goods_skus.export');
Route::get('plat_orders/export', [BusinessOrderController::class, 'exportOrderBlank'])->name('plat.orders.export');
Route::get('today_price/export', [BusinessGoodsSkusController::class, 'exportTodayPrice'])->name('plat.today_price.export');
Route::get('goods/import/template', [GoodsController::class, 'download'])->name('download.goods_import.template');