Merge pull request !108 from develop
This commit is contained in:
赵世界 2022-10-24 05:39:48 +00:00 committed by Gitee
commit 8c6cecf48c
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
100 changed files with 2337 additions and 16918 deletions

View File

@ -20,6 +20,9 @@
6. `php artisan key:generate` 6. `php artisan key:generate`
7. `php artisan update:super_admin_permissions` 更新超级管理员角色权限 7. `php artisan update:super_admin_permissions` 更新超级管理员角色权限
#### 更新权限
`php artisan db:seed --class=PermissionsTableSeeder`
#### 使用说明 #### 使用说明
1. 阅读并遵守<<[Laravel项目开发规范](https://learnku.com/docs/laravel-specification/9.x/whats-the-use-of-standards/12720)>> 1. 阅读并遵守<<[Laravel项目开发规范](https://learnku.com/docs/laravel-specification/9.x/whats-the-use-of-standards/12720)>>

View File

@ -38,12 +38,12 @@ class BusinessGoodsSkuToLocal extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return mixed * @return void
*/ */
public function handle() public function handle()
{ {
$num = 0; $num = 0;
BusinessGoodsSku::chunk(100, function ($businessGoodsSkus) use ($num) { BusinessGoodsSku::chunk(100, function ($businessGoodsSkus) use (&$num) {
foreach ($businessGoodsSkus as $businessGoodsSku) { foreach ($businessGoodsSkus as $businessGoodsSku) {
if (empty($businessGoodsSku['goods_name']) || empty($businessGoodsSku['external_sku_id'])) { if (empty($businessGoodsSku['goods_name']) || empty($businessGoodsSku['external_sku_id'])) {
continue; continue;

View File

@ -27,8 +27,8 @@ class Kernel extends ConsoleKernel
*/ */
protected function schedule(Schedule $schedule) protected function schedule(Schedule $schedule)
{ {
// 服务器添加cron入口 // 服务器/etc/crontab添加cron入口
// * * * * * cd /home/wwwroot/erp.staging.chutang66.com && php artisan schedule:run >> /dev/null 2>&1 // * * * * * cd /mnt/wwwroot/erp.chutang66.com && php artisan schedule:run >> /dev/null 2>&1
$schedule->command(Inventory::class)->dailyAt('07:00'); $schedule->command(Inventory::class)->dailyAt('07:00');
$schedule->command(KttOrderQuery::class)->everyMinute(); $schedule->command(KttOrderQuery::class)->everyMinute();
$schedule->command(DeleteKttQuery::class)->daily(); $schedule->command(DeleteKttQuery::class)->daily();

View File

@ -0,0 +1,35 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class GroupSetEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $groupId;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($groupId)
{
$this->groupId = $groupId;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

@ -11,11 +11,15 @@ class GoodsFilter extends Filters
protected function typeId($value) protected function typeId($value)
{ {
return $this->builder->where('type_id', '=', $value); if($value){
return $this->builder->where('type_id', '=', $value);
}
} }
protected function brandId($value) protected function brandId($value)
{ {
return $this->builder->where('brand_id', '=', $value); if($value){
return $this->builder->where('brand_id', '=', $value);
}
} }
} }

View File

@ -13,4 +13,9 @@ class GoodsSkuFilter extends Filters
{ {
return $this->builder->where('status', '=', $value); return $this->builder->where('status', '=', $value);
} }
protected function excludeIds($value)
{
return $this->builder->whereNotIn('id', $value);
}
} }

View File

@ -0,0 +1,21 @@
<?php
namespace App\Filters;
class GroupGoodsFilter extends Filters
{
protected function goodsName($value)
{
return $this->builder->where('goods_name', 'like', "%$value%");
}
protected function groupId($value)
{
return $this->builder->where('group_id', '=', $value);
}
protected function externalSkuId($value)
{
return $this->builder->where('external_sku_id', '=', $value);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Filters;
class GroupsFilter extends Filters
{
protected function title($value)
{
return $this->builder->where('title', 'like', "%$value%");
}
protected function shopId($value)
{
if ($value) {
return $this->builder->where('shop_id', '=', $value);
}
}
protected function status($value)
{
return $this->builder->where('status', '=', $value);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Filters;
class ShopFilter extends Filters
{
protected function platId($value)
{
return $this->builder->where('plat_id', '=', $value)->where('expires_at', '>', time());
}
}

View File

@ -73,15 +73,15 @@ class GoodsSkusController extends Controller
}]) }])
->orderBy('updated_at', 'desc') ->orderBy('updated_at', 'desc')
->paginate($request->get('per_page')); ->paginate($request->get('per_page'));
$fields = implode(',', [
'shop_id',
'external_sku_id',
'sum(goods_number) as number',
'sum(already_cancel_number) as cancel_number',
]);
foreach ($goodsSkus as &$sku) { foreach ($goodsSkus as &$sku) {
$externalSkuId = $sku['goods']['goods_code'] . '_' . $sku['sku_code']; $externalSkuId = $sku['goods']['goods_code'] . '_' . $sku['sku_code'];
$lastInventoryTime = $sku['daily']['inventory_time']; $lastInventoryTime = $sku['daily']['inventory_time'];
$fields = implode(',', [
'shop_id',
'external_sku_id',
'sum(goods_number) as number',
'sum(already_cancel_number) as cancel_number',
]);
$orderDetail = BusinessOrderItem::query() $orderDetail = BusinessOrderItem::query()
->select(DB::raw($fields)) ->select(DB::raw($fields))
->where('external_sku_id', $externalSkuId) ->where('external_sku_id', $externalSkuId)
@ -480,7 +480,6 @@ class GoodsSkusController extends Controller
'errorMessage' => 'not found inventory file', 'errorMessage' => 'not found inventory file',
]; ];
} }
try { try {
$import = new InventoryImport(); $import = new InventoryImport();
$path = $request->file('inventoryFile'); $path = $request->file('inventoryFile');

View File

@ -0,0 +1,330 @@
<?php
namespace App\Http\Controllers\Group;
use App\Events\GroupSetEvent;
use App\Http\Controllers\Controller;
use App\Http\Requests\GroupsRequest;
use App\Http\Resources\GoodsSkuResource;
use App\Models\Goods;
use App\Models\GoodsSku;
use App\Models\Log as LogModel;
use App\Models\Shop;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\Groups;
use App\Http\Requests\GoodsRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use App\Http\Resources\GroupsResource;
use App\Models\GroupGoods;
use App\Http\Resources\GroupGoodsResource;
use Illuminate\Support\Facades\Cache;
class GroupsController extends Controller
{
public function __construct(Request $request)
{
}
public function index(Request $request)
{
$groups = Groups::query()
->filter()
->with(['shop:id,name'])
->paginate($request->get('per_page'));
return GroupsResource::collection($groups);
}
public function store(Request $request)
{
$rules = (new GroupsRequest())->rules();
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$skus = GoodsSku::query()
->whereIn('id', $request->new_ids)
->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->get()
->toArray();
$changeData = $request->change_data;
$changeData = ArrayUtils::index($changeData, 'id');
$shop = Shop::query()->find($request->shop_id);
DB::beginTransaction();
try {
$group = new Groups();
$group->shop_id = $request->shop_id;
$group->title = $request->title;
$group->is_save_preview = $request->is_save_preview;
$group->start_time = $request->datetimerange[0];
$group->end_time = $request->datetimerange[1];
$group->save();
$groupGoods = [];
foreach ($skus as $sku) {
$price = $shop['ratio'] * $sku['cost'] * 100;
$groupGoods[] = [
'group_id' => $group->id,
'category_name' => $sku['goods']['type']['name'],
'type_id' => $sku['goods']['type']['id'],
'goods_name' => $sku['goods']['title'] . ' ' . $sku['title'],
'goods_id' => $sku['goods_id'],
'limit_buy' => isset($changeData[$sku['id']]) ? $changeData[$sku['id']]['limit_buy'] : 0,
'sku_id' => $sku['id'],
'price_in_fen' => isset($changeData[$sku['id']]) ? $changeData[$sku['id']]['price_in_fen'] * 100 : $price,
'sort' => isset($changeData[$sku['id']]) ? $changeData[$sku['id']]['sort'] : 500,
'external_sku_id' => $sku['goods']['goods_code'] . '_' . $sku['sku_code'],
];
}
(new GroupGoods())->batchInsert($groupGoods);
DB::commit();
event(new GroupSetEvent($group->id));
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
'httpCode' => 400,
'errorCode' => 400500,
'errorMessage' => $exception->getMessage(),
];
}
return response($this->res, $this->res['httpCode']);
}
public function show($id)
{
return new GroupsResource(Groups::query()
->find($id));
}
public function update(Request $request, $id)
{
$rules = (new GroupsRequest())->rules();
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$shop = Shop::query()->find($request->shop_id);
$shop['ratio'] = 1;
$deleteIds = $request->delete_ids;
$ids = GroupGoods::query()
->where('group_id', $id)
->whereNotIn('sku_id', $deleteIds)
->pluck('sku_id')->toArray();
$skus = GoodsSku::query()
->whereIn('id', array_merge($ids, $request->new_ids))
->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->get()
->toArray();
$changeData = $request->change_data;
$changeData = ArrayUtils::index($changeData, 'id');
DB::beginTransaction();
try {
$group = Groups::query()->find($id);
$group->start_time = $request->datetimerange[0];
$group->end_time = $request->datetimerange[1];
$group->save();
GroupGoods::where('group_id', $id)->whereIn('sku_id', $deleteIds)->delete();
foreach ($skus as $sku) {
$price = $shop['ratio'] * $sku['cost'] * 100;
$groupGoods = [
'category_name' => $sku['goods']['type']['name'],
'type_id' => $sku['goods']['type']['id'],
'goods_name' => $sku['goods']['title'] . ' ' . $sku['title'],
'goods_id' => $sku['goods_id'],
'limit_buy' => isset($changeData[$sku['id']]) ? $changeData[$sku['id']]['limit_buy'] : 0,
'price_in_fen' => isset($changeData[$sku['id']]) ? $changeData[$sku['id']]['price_in_fen'] * 100 : $price,
'sort' => isset($changeData[$sku['id']]) ? $changeData[$sku['id']]['sort'] : 500,
'external_sku_id' => $sku['goods']['goods_code'] . '_' . $sku['sku_code'],
];
GroupGoods::updateOrCreate(
['group_id' => $group->id, 'sku_id' => $sku['id']],
$groupGoods
);
}
DB::commit();
event(new GroupSetEvent($id));
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
'httpCode' => 400,
'errorCode' => 400500,
'errorMessage' => $exception->getMessage(),
];
}
return response($this->res, $this->res['httpCode']);
}
public function destroy()
{
}
public function getGoods(Request $request)
{
$shop = Shop::query()->find($request->get('shop_id'));
$shop['ratio'] = 1;
$deleteIds = $request->get('delete_ids') ?: [];
$groupId = $request->get('group_id');
$groupGoods = GroupGoods::query()
->select(['id', 'sku_id', 'sort', 'limit_buy', 'price_in_fen'])
->where('group_id', $groupId)
->whereNotIn('sku_id', $deleteIds)
->get()
->toArray();
$groupGoods = ArrayUtils::index($groupGoods, 'sku_id');
$skuIds = array_keys($groupGoods);
if ($newIds = $request->get('new_ids')) {
$skuIds = array_merge($skuIds, $newIds);
}
$goodsCode = $skuCode = '';
$externalSkuId = $request->get('external_sku_id');
if (false !== strpos($externalSkuId, '_')) {
[$goodsCode, $skuCode] = explode('_', $externalSkuId);
$externalSkuId = '';
}
$goodsIds = Goods::query()
->when($externalSkuId, function ($query, $externalSkuId) {
return $query->where('title', 'like', "%$externalSkuId%");
})
->filter()
->when($goodsCode, function ($query, $goodsCode) {
return $query->where('goods_code', $goodsCode);
})
->pluck('id')
->toArray();
$stockSelect = (int)$request->get('has_stock');
$fields = implode(',', [
'id',
'goods_id',
'title',
'sku_code',
'stock',
'cost',
]);
$goodsSkus = GoodsSku::query()
->select(DB::raw($fields))
->whereIn('id', $skuIds)
->whereIn('goods_id', $goodsIds)
->when($skuCode, function ($query, $skuCode) {
return $query->where('sku_code', $skuCode);
})
->when($stockSelect, function ($query, $stockSelect) {
if ($stockSelect > 0) {
return $query->where('stock', '>', 0);
}
return $query->where('stock', '<=', 0);
})
->filter()
->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->orderBy('updated_at', 'desc')
->paginate($request->get('per_page'));
foreach ($goodsSkus as &$goodsSku) {
if (isset($groupGoods[$goodsSku['id']])) {
$goodsSku['price_in_fen'] = $groupGoods[$goodsSku['id']]['price_in_fen'];
$goodsSku['sort'] = $groupGoods[$goodsSku['id']]['sort'];
$goodsSku['limit_buy'] = $groupGoods[$goodsSku['id']]['limit_buy'];
} else {
$goodsSku['price_in_fen'] = $shop['ratio'] * $goodsSku['cost'];
$goodsSku['sort'] = 500;
$goodsSku['limit_buy'] = 0;
}
$goodsSku['goods_name'] = $goodsSku['goods']['title'] . ' ' . $goodsSku['title'];
$goodsSku['external_sku_id'] = $goodsSku['goods']['goods_code'] . '_' . $goodsSku['sku_code'];
$goodsSku['category_name'] = $goodsSku['goods']['type']['name'];
}
return GoodsSkuResource::collection($goodsSkus);
}
public function addGroupGoods(Request $request)
{
$shop = Shop::query()->find($request->get('shop_id'));
$shop['ratio'] = 1;
$ids = [];
if ($newIds = $request->get('new_ids')) {
$ids = array_merge($ids, $newIds);
}
if ($hasIds = $request->get('has_ids')) {
$ids = array_merge($ids, $hasIds);
}
$goodsSkus = GoodsSku::query()
->whereIn('id', $ids)
->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->orderBy('updated_at', 'desc')
->paginate($request->get('per_page'));
foreach ($goodsSkus as &$goodsSku) {
$goodsSku['price_in_fen'] = $shop['ratio'] * $goodsSku['cost'];
$goodsSku['sort'] = 500;
$goodsSku['limit_buy'] = 0;
$goodsSku['goods_name'] = $goodsSku['goods']['title'] . ' ' . $goodsSku['title'];
$goodsSku['external_sku_id'] = $goodsSku['goods']['goods_code'] . '_' . $goodsSku['sku_code'];
$goodsSku['category_name'] = $goodsSku['goods']['type']['name'];
}
return GoodsSkuResource::collection($goodsSkus);
}
public function goodsList(Request $request)
{
$goodsCode = $skuCode = '';
$goodsKeyword = $request->get('goods_keyword');
if (false !== strpos($goodsKeyword, '_')) {
[$goodsCode, $skuCode] = explode('_', $goodsKeyword);
$goodsKeyword = '';
}
$goodsIds = Goods::query()
->when($goodsKeyword, function ($query, $goodsKeyword) {
return $query->where('title', 'like', "%$goodsKeyword%");
})
->filter()
->when($goodsCode, function ($query, $goodsCode) {
return $query->where('goods_code', $goodsCode);
})
->pluck('id');
$excludeIds = $request->get('has_ids') ?: [];
$deleteIds = $request->get('delete_ids') ?: [];
if ($groupId = $request->get('group_id')) {
$skuIds = GroupGoods::query()
->where('group_id', $groupId)
->whereNotIn('sku_id', $deleteIds)
->pluck('sku_id')
->toArray();
$excludeIds = array_merge($excludeIds, $skuIds);
}
$goodsSkus = GoodsSku::query()
->whereIn('goods_id', $goodsIds)
->whereNotIn('id', $excludeIds)
->when($skuCode, function ($query, $skuCode) {
return $query->where('sku_code', $skuCode);
})
->when($request->get('has_stock'), function ($query) {
return $query->where('stock', '>', 0);
})
->filter()
->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->orderBy('updated_at', 'desc')
->paginate($request->get('per_page'));
return GoodsSkuResource::collection($goodsSkus);
}
}

View File

@ -26,7 +26,7 @@ class MenusController extends Controller
{ {
$permissions = $request->user()->getPermissionsViaRoles()->toArray(); $permissions = $request->user()->getPermissionsViaRoles()->toArray();
$permissions = array_column($permissions, 'name'); $permissions = array_column($permissions, 'name');
$menus = Menu::query()->get()->toArray(); $menus = Menu::query()->orderBy('parent_id')->orderBy('seq')->get()->toArray();
$hasPermissionMenus = []; $hasPermissionMenus = [];
foreach ($menus as $menu) { foreach ($menus as $menu) {
if (in_array($menu['code'], $permissions, true)) { if (in_array($menu['code'], $permissions, true)) {

View File

@ -17,7 +17,7 @@ class ShopsController extends Controller
{ {
public function index(Request $request) public function index(Request $request)
{ {
$shops = Shop::query()->paginate($request->get('per_page')); $shops = Shop::query()->filter()->paginate($request->get('per_page'));
foreach ($shops as $shop) { foreach ($shops as $shop) {
$shop->authUrl = ''; $shop->authUrl = '';
if ('妙选' !== $shop->plat_id && ('未授权' === $shop->status || '重新授权' === $shop->status)) { if ('妙选' !== $shop->plat_id && ('未授权' === $shop->status || '重新授权' === $shop->status)) {
@ -40,6 +40,7 @@ class ShopsController extends Controller
$validator = Validator::make($request->all(), [ $validator = Validator::make($request->all(), [
'name' => 'required|string|max:191|unique:shops,name', 'name' => 'required|string|max:191|unique:shops,name',
'plat_id' => 'required|integer', 'plat_id' => 'required|integer',
'ratio' => 'required|numeric',
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages()); $this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
@ -49,6 +50,7 @@ class ShopsController extends Controller
$shop = new Shop(); $shop = new Shop();
$shop->name = $request->name; $shop->name = $request->name;
$shop->plat_id = $request->plat_id; $shop->plat_id = $request->plat_id;
$shop->ratio = $request->ratio;
if (0 == $request->plat_id) { if (0 == $request->plat_id) {
$shop->status = 2; $shop->status = 2;
} }
@ -57,6 +59,15 @@ class ShopsController extends Controller
return response($this->res, $this->res['httpCode']); return response($this->res, $this->res['httpCode']);
} }
public function update(Request $request, $id)
{
$shop = Shop::query()->find($id);
$shop->ratio = $request->ratio;
$shop->save();
return response($this->res, $this->res['httpCode']);
}
public function authBind(Request $request) public function authBind(Request $request)
{ {
[$shopId, $platId] = explode('_', $request->get('state')); [$shopId, $platId] = explode('_', $request->get('state'));

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class GroupsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'shop_id' => ['required', 'integer', 'exists:shops,id'],
'title' => ['required', 'string'],
'datetimerange' => ['required', 'array'],
'is_save_preview' => ['required', 'integer'],
'group_id' => ['integer'],
'delete_ids' => ['array'],
'new_ids' => ['required_if:group_id,0','array'],
'change_data' => ['array'],
// 'sort' => ['array'],
];
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class GroupGoodsResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class GroupsResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request);
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Listeners;
use App\Events\GroupSetEvent;
use App\Models\Groups;
use App\Models\Shop;
use App\Services\Business\BusinessFactory;
class GroupQueryListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param GroupSetEvent $event
* @return void
*/
public function handle(GroupSetEvent $event)
{
$shopId = Groups::query()->where('group_Id', $event->groupId)->value('shop_id');
$shop = Shop::query()->find($shopId);
$client = BusinessFactory::init()->make($shop['plat_id'])->setShopWithId($shop['id']);
$client->createGroup($event->groupId);
sleep(1);
$client->queryGroupStatus($event->groupId);
}
}

View File

@ -12,6 +12,7 @@ class GoodsSku extends Model
public $fieldSearchable = [ public $fieldSearchable = [
'sku_title', 'sku_title',
'status', 'status',
'exclude_ids'
]; ];
/** /**

45
app/Models/GroupGoods.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace App\Models;
use App\Models\traits\Filter;
class GroupGoods extends Model
{
use Filter;
//查询字段
public $fieldSearchable = [
'group_id',
'goods_name',
'external_sku_id',
];
protected $fillable = [
'category_name',
'type_id',
'goods_name',
'goods_id',
'limit_buy',
'price_in_fen',
'sort',
'external_sku_id',
'sku_id',
'group_id',
];
public function getPriceInFenAttribute($value)
{
return round($value / 100, 2);
}
public function goods()
{
return $this->hasOne(Goods::class, 'id', 'goods_id');
}
public function goodsSku()
{
return $this->hasOne(GoodsSku::class, 'id', 'sku_id');
}
}

57
app/Models/Groups.php Normal file
View File

@ -0,0 +1,57 @@
<?php
namespace App\Models;
use App\Models\traits\Filter;
class Groups extends Model
{
use Filter;
//查询字段
public $fieldSearchable = [
'title',
'shop_id',
'status',
];
public function setStartTimeAttribute($value)
{
$time = strtotime($value);
$this->attributes['start_time'] = $time * 1000;
}
public function getStartTimeAttribute($value)
{
return date('Y-m-d H:i:s', $value / 1000);
}
public function setEndTimeAttribute($value)
{
$time = strtotime($value);
$this->attributes['end_time'] = $time * 1000;
}
public function getEndTimeAttribute($value)
{
return date('Y-m-d H:i:s', $value / 1000);
}
public function getStatusAttribute($value)
{
$map = [
-10 => '待发布/预览中',
-5 => '未开始',
1 => '跟团中',
20 => '已结束',
30 => '已删除',
];
return $map[$value];
}
public function shop()
{
return $this->hasOne(Shop::class, 'id', 'shop_id');
}
}

View File

@ -2,10 +2,18 @@
namespace App\Models; namespace App\Models;
use App\Models\traits\Filter;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Shop extends Model class Shop extends Model
{ {
use Filter;
//查询字段
public $fieldSearchable = [
'plat_id',
];
protected $hidden = [ protected $hidden = [
'access_token', 'access_token',
'expires_in', 'expires_in',

View File

@ -2,13 +2,14 @@
namespace App\Providers; namespace App\Providers;
use App\Listeners\StockWarning;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Listeners\UpdateBusinessGoodsStock;
use App\Events\BusinessOrdersUpdate; use App\Events\BusinessOrdersUpdate;
use App\Events\GroupSetEvent;
use App\Events\StockUpdateEvent; use App\Events\StockUpdateEvent;
use App\Listeners\GroupQueryListener;
use App\Listeners\StockUpdateListener; use App\Listeners\StockUpdateListener;
use App\Listeners\StockWarning;
use App\Listeners\UpdateBusinessGoodsStock;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider class EventServiceProvider extends ServiceProvider
{ {
@ -26,6 +27,9 @@ class EventServiceProvider extends ServiceProvider
StockUpdateListener::class, StockUpdateListener::class,
StockWarning::class, StockWarning::class,
], ],
GroupSetEvent::class => [
GroupQueryListener::class,
],
]; ];
/** /**

View File

@ -85,44 +85,5 @@ class Goods
return [$type, $appendParams]; return [$type, $appendParams];
} }
public static function createGroup()
{
$type = 'pdd.ktt.group.create';
$skuList = [
'external_sku_id' => 'world_123',
'price_in_fen' => 1000000,
'quantity_type' => 0,
'spec_id_list' => [3908559014],
'total_quantity' => 10,
];
$goods = [
'category_name' => '分类名',
'goods_desc' => '测试使用',
'goods_name' => '字母a',
'limit_buy' => 1,
'market_price' => 100000,
'sku_list' => [$skuList]
];
$appendParams = [
'end_time' => 1667385374000,
'goods_list' => json_encode([$goods]),
'is_save_preview' => 0,
'start_time' => 1665385374000,
'title' => '世界鲜花团购大赏',
];
return [$type, $appendParams];
}
public static function queryGroupStatus()
{
$type = 'pdd.ktt.group.query.status';
$appendParams = [
'activity_no' => '0d0t6e4ji-KSYKxdgpMZHmTqFwU0p1Qg'
];
return [$type, $appendParams];
}
} }

View File

@ -0,0 +1,57 @@
<?php
namespace App\Services\Business\KuaiTuanTuan;
use App\Models\Groups as GroupsModel;
use App\Models\GroupGoods;
class Groups
{
public static function createGroup($localGroupId)
{
$type = 'pdd.ktt.group.create';
$group = GroupsModel::query()->find($localGroupId);
$groupGoods = GroupGoods::query()
->where('group_id', $group->id)
->with(['goodsSku:id,stock'])
->get();
$goodsSkus = [];
foreach ($groupGoods as $item) {
$goodsSkus[] = [
'category_name' => $item['category_name'],
'goods_desc' => $item['goods_desc'],
'goods_name' => $item['goods_name'],
'limit_buy' => $item['limit_buy'],
'market_price' => $item['market_price'],
'sku_list' => [
'external_sku_id' => $item['external_sku_id'],
'price_in_fen' => $item['price_in_fen'],
'quantity_type' => 0,
'spec_id_list' => [],
'total_quantity' => $item['goodsSku']['stock'],
]
];
}
$appendParams = [
'end_time' => $group['end_time'] * 1000,
'goods_list' => json_encode([$goodsSkus]),
'is_save_preview' => $group['is_save_preview'],
'start_time' => $group['start_time'] * 1000,
'title' => $group['title'],
];
return [$type, $appendParams];
}
public static function queryGroupStatus($localGroupId)
{
$type = 'pdd.ktt.group.query.status';
$group = GroupsModel::query()->find($localGroupId);
$appendParams = [
'activity_no' => $group->activity_no
];
return [$type, $appendParams];
}
}

View File

@ -4,7 +4,9 @@ namespace App\Services\Business\KuaiTuanTuan;
use App\Models\BusinessGoodsSku; use App\Models\BusinessGoodsSku;
use App\Models\GoodsSku; use App\Models\GoodsSku;
use App\Models\GroupGoods;
use App\Services\Business\BusinessClient; use App\Services\Business\BusinessClient;
use App\Models\Groups as GroupsModel;
class KuaiTuanTuan extends BusinessClient class KuaiTuanTuan extends BusinessClient
{ {
@ -158,17 +160,40 @@ class KuaiTuanTuan extends BusinessClient
return $this->doRequest($type, $appendParams); return $this->doRequest($type, $appendParams);
} }
public function createGroup() public function createGroup($localGroupId)
{ {
[$type, $appendParams] = Goods::createGroup(); [$type, $appendParams] = Groups::createGroup($localGroupId);
$res = $this->doRequest($type, $appendParams);
if (isset($res['response']['success'])) {
$group = GroupsModel::query()->find($localGroupId);
$group->activity_no = $res['response']['activity_no'];
$group->save();
}
return $this->doRequest($type, $appendParams); return $res;
} }
public function queryGroupStatus() public function queryGroupStatus($localGroupId)
{ {
[$type, $appendParams] = Goods::queryGroupStatus(); [$type, $appendParams] = Groups::queryGroupStatus($localGroupId);
$res = $this->doRequest($type, $appendParams);
if (isset($res['response'])) {
$group = GroupsModel::query()->find($localGroupId);
$group->error_msg = $res['response']['error_msg'];
$group->qr_code_url = $res['response']['qr_code_url'];
$group->status = $res['response']['status'];
$group->save();
foreach ($res['response']['goods_list'] as $goods) {
$groupGoods = GroupGoods::query()
->where('group_id', $localGroupId)
->where('external_sku_id', $goods['external_sku_id'])
->find();
$groupGoods->erp_goods_id = $goods['goods_id'];
$groupGoods->erp_sku_id = $goods['sku_list'][0]['sku_id'];
$groupGoods->save();
}
}
return $this->doRequest($type, $appendParams); return $res;
} }
} }

View File

@ -29,6 +29,7 @@ class CreateShopsTable extends Migration
$table->text('scope')->nullable()->comment('接口列表'); $table->text('scope')->nullable()->comment('接口列表');
$table->text('pop_auth_token_create_response')->nullable()->comment('授权认证信息'); $table->text('pop_auth_token_create_response')->nullable()->comment('授权认证信息');
$table->unsignedTinyInteger('status')->index()->default(0)->comment('状态'); $table->unsignedTinyInteger('status')->index()->default(0)->comment('状态');
$table->decimal('ratio')->default(1)->comment('成本倍率');
$table->softDeletes(); $table->softDeletes();
$table->timestamps(); $table->timestamps();
//索引 //索引

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateGroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('groups', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('shop_id');
$table->unsignedBigInteger('end_time');
$table->unsignedTinyInteger('is_save_preview')->comment('是否保存为预览团0-不为预览团,1-预览团');
$table->unsignedBigInteger('start_time');
$table->text('title');
$table->string('activity_no')->nullable()->comment('团号');
$table->unsignedTinyInteger('create_status')->default(3)->comment('1-创建成功,2-创建失败,3-创建中');
$table->string('error_msg')->nullable()->comment('create_status为2时有创建团失败原因');
$table->text('qr_code_url')->nullable()->comment('create_status为1时有团小程序二维码图片地址');
$table->unsignedBigInteger('create_time')->nullable();
$table->unsignedTinyInteger('is_help_sell')->nullable()->comment('是否帮卖0-我发布的,1-我帮卖的');
$table->tinyInteger('status')->default(-10)->comment('团状态(-10:待发布/预览中,-5:未开始1:跟团中20:已结束30:已删除');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('groups');
}
}

View File

@ -0,0 +1,53 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateGroupGoodsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('group_goods', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('group_id');
$table->string('category_name');
$table->unsignedBigInteger('type_id');
$table->string('goods_desc')->nullable();
$table->string('goods_name');
$table->unsignedBigInteger('goods_id');
$table->unsignedInteger('ktt_goods_id');
$table->unsignedInteger('limit_buy')->default(0);
$table->unsignedBigInteger('market_price')->default(0);
$table->text('pic_url_list')->nullable();
$table->unsignedBigInteger('sku_id');
$table->unsignedInteger('ktt_sku_id');
$table->string('external_sku_id');
$table->unsignedBigInteger('price_in_fen');
$table->unsignedTinyInteger('quantity_type')->default(0)->comment('库存类型0-普通 1-无限无限库存时会无视total_quantity字段');
$table->text('spec_id_list')->nullable()->comment('规格id列表无规格为空list如果想规格为红色,M调用生成规格的id红色为1M为3则应传入[1,3]');
$table->text('thumb_url')->nullable()->comment('sku图url注意sku图格式必须是jpg、jpeg、png中的一个且尺寸不得大于1200*1200大小不大于1MB可以不填');
$table->unsignedInteger('total_quantity')->default(0)->comment('总库存,最多100w');
$table->integer('sort')->default(0);
$table->timestamps();
$table->index(['group_id', 'sku_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('group_goods');
}
}

View File

@ -20,20 +20,22 @@ class MenusTableSeeder extends Seeder
['parent_id' => $id, 'code' => 'GOODS_BRAND', 'name' => '商品品牌', 'seq' => 2], ['parent_id' => $id, 'code' => 'GOODS_BRAND', 'name' => '商品品牌', 'seq' => 2],
]); ]);
// 店铺管理 // 店铺管理
DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'SHOP_MANAGE', 'name' => '店铺管理', 'seq' => 1]); DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'SHOP_MANAGE', 'name' => '店铺管理', 'seq' => 10]);
// 用户管理 // 用户管理
DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'USER_MANAGE', 'name' => '用户管理', 'seq' => 2]); DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'USER_MANAGE', 'name' => '用户管理', 'seq' => 20]);
// 系统管理-(角色管理,权限管理,系统日志) // 系统管理-(角色管理,权限管理,系统日志)
$id = DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'SYSTEM_MANAGE', 'name' => '系统管理', 'seq' => 3]); $id = DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'SYSTEM_MANAGE', 'name' => '系统管理', 'seq' => 30]);
DB::table('menus')->insert([ DB::table('menus')->insert([
['parent_id' => $id, 'code' => 'ROLE_MANAGE', 'name' => '角色管理', 'seq' => 0], ['parent_id' => $id, 'code' => 'ROLE_MANAGE', 'name' => '角色管理', 'seq' => 0],
// ['parent_id' => $id,'code' => 'PERMISSION_MANAGE', 'name' => '权限管理', 'seq' => 1], // ['parent_id' => $id,'code' => 'PERMISSION_MANAGE', 'name' => '权限管理', 'seq' => 1],
['parent_id' => $id, 'code' => 'SYSTEM_LOG', 'name' => '系统日志', 'seq' => 2], ['parent_id' => $id, 'code' => 'SYSTEM_LOG', 'name' => '系统日志', 'seq' => 2],
]); ]);
// 平台 // 平台
$id = DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'PLAT', 'name' => '平台', 'seq' => 4]); $id = DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'PLAT', 'name' => '平台', 'seq' => 40]);
DB::table('menus')->insert([ DB::table('menus')->insert([
['parent_id' => $id, 'code' => 'PLAT_GOODS_LIST', 'name' => '货品列表', 'seq' => 0], ['parent_id' => $id, 'code' => 'PLAT_GOODS_LIST', 'name' => '货品列表', 'seq' => 0],
]); ]);
// 团购
DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'GROUP_MANAGEMENT', 'name' => '团购管理', 'seq' => 1]);
} }
} }

View File

@ -1 +1 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a[data-v-72a01e7d]{text-decoration:none;color:#fff}.block[data-v-72a01e7d]{margin-top:20px} #nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a[data-v-538fe600]{text-decoration:none;color:#fff}.block[data-v-538fe600]{margin-top:20px}

View File

@ -1 +0,0 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.width[data-v-60a78277]{transition:all .3s;opacity:0;width:0!important}.width1[data-v-60a78277]{transition:all .3s;opacity:1;width:200px!important}.el-container[data-v-60a78277]{height:100vh}.el-aside[data-v-60a78277]{background-color:#d3dce6;color:#333;overflow-x:hidden}.el-aside[data-v-60a78277]::-webkit-scrollbar{width:8px}.el-aside[data-v-60a78277]::-webkit-scrollbar-thumb{background-color:rgba(144,147,153,.3);border-radius:20px}.el-main[data-v-60a78277]{background-color:#f0f2f5;color:#333;padding:0 0!important}.el-main[data-v-60a78277]::-webkit-scrollbar{width:10px}.el-main[data-v-60a78277]::-webkit-scrollbar-thumb{background-color:rgba(144,147,153,.3)}.box-card[data-v-60a78277]{min-height:calc(100vh - 120px);margin:10px}.conent[data-v-60a78277]{width:100%;min-height:calc(100vh - 200px);position:relative}.add[data-v-60a78277]{cursor:pointer;font-size:25px;color:#606266}.head[data-v-60a78277]{padding:10px;background-color:#fff;border-bottom:1px solid #f6f6f6;box-shadow:0 1px 4px rgba(0,21,41,.08)}.head ul[data-v-60a78277]{display:flex;justify-content:space-between}.head ul li[data-v-60a78277]{display:flex;align-items:center}.head ul li .right[data-v-60a78277]{margin-left:20px}.head ul li .token[data-v-60a78277]{cursor:pointer}.el-aside[data-v-60a78277]{background:#282c34;box-shadow:2px 0 6px rgba(0,21,41,.35)}[data-v-60a78277] .el-menu{border:none}.el-menu-item[data-v-60a78277]:hover{outline:0!important;background:#5470c6!important;border-radius:5px!important}.el-menu-item.is-active[data-v-60a78277]{color:#fff!important;background:#5470c6!important;border-radius:5px!important}.el-menu-item-group__title[data-v-60a78277]{padding:0 0!important}

View File

@ -0,0 +1 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}

View File

@ -0,0 +1 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.width[data-v-2333c1ea]{transition:all .3s;opacity:0;width:0!important}.width1[data-v-2333c1ea]{transition:all .3s;opacity:1;width:200px!important}.el-container[data-v-2333c1ea]{height:100vh}.el-aside[data-v-2333c1ea]{background-color:#d3dce6;color:#333;overflow-x:hidden}.el-aside[data-v-2333c1ea]::-webkit-scrollbar{width:8px}.el-aside[data-v-2333c1ea]::-webkit-scrollbar-thumb{background-color:rgba(144,147,153,.3);border-radius:20px}.el-main[data-v-2333c1ea]{background-color:#f0f2f5;color:#333;padding:0 0!important}.el-main[data-v-2333c1ea]::-webkit-scrollbar{width:10px}.el-main[data-v-2333c1ea]::-webkit-scrollbar-thumb{background-color:rgba(144,147,153,.3)}.box-card[data-v-2333c1ea]{min-height:calc(100vh - 120px);margin:10px}.conent[data-v-2333c1ea]{width:100%;min-height:calc(100vh - 200px);position:relative}.add[data-v-2333c1ea]{cursor:pointer;font-size:25px;color:#606266}.head[data-v-2333c1ea]{padding:10px;background-color:#fff;border-bottom:1px solid #f6f6f6;box-shadow:0 1px 4px rgba(0,21,41,.08)}.head ul[data-v-2333c1ea]{display:flex;justify-content:space-between}.head ul li[data-v-2333c1ea]{display:flex;align-items:center}.head ul li .right[data-v-2333c1ea]{margin-left:20px}.head ul li .token[data-v-2333c1ea]{cursor:pointer}.el-aside[data-v-2333c1ea]{background:#282c34;box-shadow:2px 0 6px rgba(0,21,41,.35)}[data-v-2333c1ea] .el-menu{border:none}.el-menu-item[data-v-2333c1ea]:hover{outline:0!important;background:#5470c6!important;border-radius:5px!important}.el-menu-item.is-active[data-v-2333c1ea]{color:#fff!important;background:#5470c6!important;border-radius:5px!important}.el-menu-item-group__title[data-v-2333c1ea]{padding:0 0!important}

View File

@ -0,0 +1 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}

View File

@ -0,0 +1 @@
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}

View File

@ -1 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>erp</title><link href="css/chunk-0cbcaa56.e05858e7.css" rel="prefetch"><link href="css/chunk-10d9ee19.84a6683c.css" rel="prefetch"><link href="css/chunk-26daa808.62429343.css" rel="prefetch"><link href="css/chunk-288420ae.363cf34f.css" rel="prefetch"><link href="css/chunk-35db73ce.1f9c10ff.css" rel="prefetch"><link href="css/chunk-38b35ffa.1005fa16.css" rel="prefetch"><link href="css/chunk-4f15b41a.2cf53495.css" rel="prefetch"><link href="css/chunk-52fcdd7c.51e3ffbd.css" rel="prefetch"><link href="css/chunk-6ae0a0d3.84a02b23.css" rel="prefetch"><link href="css/chunk-75426f71.902ebb66.css" rel="prefetch"><link href="css/chunk-a3ddd952.902ebb66.css" rel="prefetch"><link href="css/chunk-e5a82016.e6531cef.css" rel="prefetch"><link href="css/chunk-f35dfe36.ea52b615.css" rel="prefetch"><link href="js/chunk-0cbcaa56.114d39a7.js" rel="prefetch"><link href="js/chunk-10d9ee19.a46bd74b.js" rel="prefetch"><link href="js/chunk-26daa808.81ee116f.js" rel="prefetch"><link href="js/chunk-288420ae.9af9438b.js" rel="prefetch"><link href="js/chunk-35db73ce.4d1abceb.js" rel="prefetch"><link href="js/chunk-38b35ffa.03231ad3.js" rel="prefetch"><link href="js/chunk-4f15b41a.059677d1.js" rel="prefetch"><link href="js/chunk-52fcdd7c.a84c5d80.js" rel="prefetch"><link href="js/chunk-63c1eac8.59f3df74.js" rel="prefetch"><link href="js/chunk-6ae0a0d3.d3308c16.js" rel="prefetch"><link href="js/chunk-75426f71.1a12b5c7.js" rel="prefetch"><link href="js/chunk-a3ddd952.7cfd6c27.js" rel="prefetch"><link href="js/chunk-e5a82016.5108e633.js" rel="prefetch"><link href="js/chunk-f35dfe36.683d24b3.js" rel="prefetch"><link href="css/app.6c30acd7.css" rel="preload" as="style"><link href="css/chunk-vendors.9181e156.css" rel="preload" as="style"><link href="js/app.a17cb104.js" rel="preload" as="script"><link href="js/chunk-vendors.13743003.js" rel="preload" as="script"><link href="css/chunk-vendors.9181e156.css" rel="stylesheet"><link href="css/app.6c30acd7.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but erp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.13743003.js"></script><script src="js/app.a17cb104.js"></script></body></html> <!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>erp</title><link href="css/chunk-0cbcaa56.e05858e7.css" rel="prefetch"><link href="css/chunk-10d9ee19.84a6683c.css" rel="prefetch"><link href="css/chunk-20c83087.d0b599f3.css" rel="prefetch"><link href="css/chunk-20ee929b.902ebb66.css" rel="prefetch"><link href="css/chunk-26daa808.62429343.css" rel="prefetch"><link href="css/chunk-35db73ce.1f9c10ff.css" rel="prefetch"><link href="css/chunk-38b35ffa.1005fa16.css" rel="prefetch"><link href="css/chunk-3ebcaff1.902ebb66.css" rel="prefetch"><link href="css/chunk-4caed774.ad94328f.css" rel="prefetch"><link href="css/chunk-4f15b41a.2cf53495.css" rel="prefetch"><link href="css/chunk-52fcdd7c.51e3ffbd.css" rel="prefetch"><link href="css/chunk-5782cef6.902ebb66.css" rel="prefetch"><link href="css/chunk-6995cb27.902ebb66.css" rel="prefetch"><link href="css/chunk-6ae0a0d3.84a02b23.css" rel="prefetch"><link href="css/chunk-75426f71.902ebb66.css" rel="prefetch"><link href="css/chunk-f35dfe36.ea52b615.css" rel="prefetch"><link href="js/chunk-0cbcaa56.46e3dd42.js" rel="prefetch"><link href="js/chunk-10d9ee19.6bc719ae.js" rel="prefetch"><link href="js/chunk-20c83087.a3787c22.js" rel="prefetch"><link href="js/chunk-20ee929b.97f64c98.js" rel="prefetch"><link href="js/chunk-26daa808.a340b60b.js" rel="prefetch"><link href="js/chunk-35db73ce.e1ffc5fa.js" rel="prefetch"><link href="js/chunk-38b35ffa.6daa44bc.js" rel="prefetch"><link href="js/chunk-3ebcaff1.b3f1815c.js" rel="prefetch"><link href="js/chunk-4caed774.92751344.js" rel="prefetch"><link href="js/chunk-4f15b41a.8943bdec.js" rel="prefetch"><link href="js/chunk-52fcdd7c.0f505f93.js" rel="prefetch"><link href="js/chunk-5782cef6.379f5198.js" rel="prefetch"><link href="js/chunk-63c1eac8.59f3df74.js" rel="prefetch"><link href="js/chunk-6995cb27.94c8f05b.js" rel="prefetch"><link href="js/chunk-6ae0a0d3.b08743d0.js" rel="prefetch"><link href="js/chunk-75426f71.1a12b5c7.js" rel="prefetch"><link href="js/chunk-f35dfe36.e7038b09.js" rel="prefetch"><link href="css/app.6c30acd7.css" rel="preload" as="style"><link href="css/chunk-vendors.9181e156.css" rel="preload" as="style"><link href="js/app.7287a242.js" rel="preload" as="script"><link href="js/chunk-vendors.13743003.js" rel="preload" as="script"><link href="css/chunk-vendors.9181e156.css" rel="stylesheet"><link href="css/app.6c30acd7.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but erp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.13743003.js"></script><script src="js/app.7287a242.js"></script></body></html>

2
public/dist/js/app.7287a242.js vendored Normal file

File diff suppressed because one or more lines are too long

1
public/dist/js/app.7287a242.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,24 +1,29 @@
# hello-world # hello-world
## Project setup ## Project setup
```
```nodejs
npm install npm install
``` ```
### Compiles and hot-reloads for development ### Compiles and hot-reloads for development
```
```nodejs
npm run serve npm run serve
``` ```
### Compiles and minifies for production ### Compiles and minifies for production
```
```nodejs
npm run build npm run build
``` ```
### Lints and fixes files ### Lints and fixes files
```
```nodejs
npm run lint npm run lint
``` ```
### Customize configuration ### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/). See [Configuration Reference](https://cli.vuejs.org/config/).

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,7 @@
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"echarts": "^5.3.2",
"element-ui": "^2.15.6", "element-ui": "^2.15.6",
"js-cookie": "^3.0.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-router": "^3.2.0", "vue-router": "^3.2.0",

View File

@ -2,86 +2,95 @@ import http from "@/util/http.js";
//店铺订单 //店铺订单
export function shops(params) { export function shops(params) {
return http({ return http({
url: "/api/count/orders/num", url: "/api/count/orders/num",
method: "get", method: "get",
params, params,
}); });
} }
// 商品管理列表 // 商品管理列表
export function goods(params) { export function goods(params) {
return http({ return http({
url: "/api/goods_skus", url: "/api/goods_skus",
method: "get", method: "get",
params, params,
}); });
} }
// 新建商品 // 新建商品
export function addGoods(data) { export function addGoods(data) {
return http({ return http({
url: "/api/goods", url: "/api/goods",
method: "post", method: "post",
data, data,
}); });
} }
// 查看商品 // 查看商品
export function checkGoods(id) { export function checkGoods(id) {
return http({ return http({
url: `/api/goods_skus/${id}`, url: `/api/goods_skus/${id}`,
method: "get", method: "get",
}); });
} }
// 商品列表 // 商品列表
export function goodsList(params) { export function goodsList(params) {
return http({ return http({
url: "/api/goods", url: "/api/goods",
method: "get", method: "get",
params, params,
}); });
} }
// 更新商品 // 更新商品
export function updateGoods(id, data) { export function updateGoods(id, data) {
return http({ return http({
url: `/api/goods_skus/${id}`, url: `/api/goods_skus/${id}`,
method: "patch", method: "patch",
data, data,
}); });
} }
// 上新/库存盘点/库存 // 上新/库存盘点/库存
export function update(data) { export function update(data) {
return http({ return http({
url: "/api/batch/goods_skus", url: "/api/batch/goods_skus",
method: "patch", method: "patch",
data, data,
}); });
} }
// 单个字段更新 // 单个字段更新
export function singleUpdate(id, data) { export function singleUpdate(id, data) {
return http({ return http({
url: `/api/single/goods_skus/${id}`, url: `/api/single/goods_skus/${id}`,
method: "patch", method: "patch",
data, data,
}); });
} }
// 图片上传 // 图片上传
export function imgUpload(data, item) { export function imgUpload(data, item) {
return http({ return http({
url: "/api/upload", url: "/api/upload",
Headers: item, Headers: item,
method: "post", method: "post",
data, data,
}); });
} }
// 表格导出 // 表格导出
export function tableExport(params) { export function tableExport(params) {
return http({ return http({
url: "/goods_skus/export", url: "/goods_skus/export",
method: "get", method: "get",
params, params,
}); });
}
// 商品列表(添加)
export function getGoodsList(params) {
return http({
url: "/api/goodsList",
method: "get",
params,
});
} }

54
resources/frontend/src/api/group.js vendored Normal file
View File

@ -0,0 +1,54 @@
import http from "@/util/http.js";
// 团购管理列表
export function groupList(params) {
return http({
url: "/api/group",
method: "get",
params
});
}
// 新增
export function addGroup(data) {
return http({
url: "/api/group",
method: "post",
data,
});
}
// 查看
export function showGroup(id) {
return http({
url: `/api/group/${id}`,
method: "get",
});
}
// 编辑
export function editGroup(id, data) {
return http({
url: `/api/group/${id}`,
method: "patch",
data,
});
}
// 获取团购商品列表
export function getGroupGoods(params) {
return http({
url: `/api/groupGoods`,
method: "get",
params,
});
}
// 增加团购商品
export function addGroupGoods(params) {
return http({
url: `/api/groupGoods`,
method: "post",
params,
});
}

View File

@ -1,6 +1,5 @@
import http from '@/util/http.js' import http from '@/util/http.js'
// 商品管理列表
export function getMenu () { export function getMenu () {
return http({ return http({
url: '/api/menus', url: '/api/menus',

View File

@ -1,8 +1,6 @@
import http from "@/util/http.js"; import http from "@/util/http.js";
// 平台页面请求 // 平台货品列表
// 平台商品列表
export function platGoodsList(params) { export function platGoodsList(params) {
return http({ return http({
url: "/api/plat_goods", url: "/api/plat_goods",

View File

@ -1,26 +1,9 @@
/*
* @Description: 排名
* @Author: chenzhiwei (725551805@qq.com)
* @Date: 2021-08-02 16:09:41
* @LastEditors: czw (725551805@qq.com)
* @LastEditTime: 2022-03-03 22:17:09
* @FilePath: /glxt/src/api/rankingData.js
*/
import http from "@/util/http.js"; import http from "@/util/http.js";
// export function rankingData(data) {
// // 传递参数
// return http({
// url: "newh5app/api/mobile/v1/music/rank/16/",
// method: "get",
// params: data // 传递参数
// });
// }
export function postadd(params) { export function postadd(params) {
// 传递id // 传递id
return http({ return http({
url: "/api/admin/auth/login", // 传递id url: "/api/admin/auth/login",
method: "post", method: "post",
params: params, params: params,
}); });
@ -42,7 +25,7 @@ export function storeDetail(params) {
params: params, params: params,
}); });
} }
// 鲜花项目接口从这里开始
// 商品种类列表 // 商品种类列表
export function goods_types(params) { export function goods_types(params) {
return http({ return http({

View File

@ -4,32 +4,40 @@ import http from "@/util/http.js";
// 店铺平台 // 店铺平台
export function shopListId() { export function shopListId() {
return http({ return http({
url: "/api/shop_platforms", url: "/api/shop_platforms",
method: "get", method: "get",
}); });
} }
// 店铺新增 // 店铺新增
export function shopAdd(data) { export function shopAdd(data) {
return http({ return http({
url: "/api/shops", url: "/api/shops",
method: "post", method: "post",
data, data,
}); });
} }
// 店铺列表 // 店铺列表
export function storeList(params) { export function storeList(params) {
return http({ return http({
url: "/api/shops", url: "/api/shops",
method: "get", method: "get",
params, params,
}); });
} }
// 下载商品 // 下载商品
export function downloadGoods(id) { export function downloadGoods(id) {
return http({ return http({
url: `/api/download/${id}/goods`, url: `/api/download/${id}/goods`,
method: "get", method: "get",
}); });
}
export function updateStore(id, params) {
return http({
url: `/api/shops/${id}`,
method: "patch",
params,
});
} }

View File

@ -5,7 +5,7 @@ import store from "./store";
import ElementUI from "element-ui"; import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css"; import "element-ui/lib/theme-chalk/index.css";
import "@/css/style.css"; import "@/css/style.css";
import "./router/index2"; import "./router/main";
Vue.use(ElementUI); Vue.use(ElementUI);
Vue.config.productionTip = false; Vue.config.productionTip = false;

View File

@ -1,6 +1,5 @@
import Vue from "vue"; import Vue from "vue";
import VueRouter from "vue-router"; import VueRouter from "vue-router";
// import axios from "axios";
Vue.use(VueRouter); Vue.use(VueRouter);
@ -12,7 +11,6 @@ const createRouter = () =>
const router = createRouter(); const router = createRouter();
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
// console.log(to,next);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
// 目标路由不是登录页并且还需要token验证还没有token那就直接给返回到登录页 // 目标路由不是登录页并且还需要token验证还没有token那就直接给返回到登录页
if (to.name !== "Login" && !token) { if (to.name !== "Login" && !token) {

View File

@ -1,15 +0,0 @@
/*
* @Description:
* @Author: czw (725551805@qq.com)
* @Date: 2022-02-25 10:40:25
* @LastEditors: czw (725551805@qq.com)
* @LastEditTime: 2022-02-25 12:18:31
* @FilePath: /glxt/src/router/index2.js
*/
import router from './index'
import Home from './index1'
Home.forEach(element => {
router.addRoute(element) // 动态添加更多的路由规则
})

View File

@ -65,6 +65,21 @@ const list = [
name: "货品列表", name: "货品列表",
component: () => import("../views/plat/goodsList.vue"), component: () => import("../views/plat/goodsList.vue"),
}, },
{
path: "GROUP_MANAGEMENT",
name: "团购管理",
component: () => import("../views/group/group.vue"),
},
{
path: "GROUP_GOODS_ADD",
name: "团购商品新增",
component: () => import("../views/group/addGroup.vue"),
},
{
path: "GROUP_GOODS_EDIT",
name: "团购商品修改",
component: () => import("../views/group/editGroup.vue"),
},
], ],
}, },
]; ];

6
resources/frontend/src/router/main.js vendored Normal file
View File

@ -0,0 +1,6 @@
import router from './index'
import List from './list'
List.forEach(element => {
router.addRoute(element) // 动态添加更多的路由规则
})

View File

@ -0,0 +1,467 @@
<template>
<div>
<el-card style="margin-top: 10px" class="box-card">
<el-form ref="group" :rules="rules" :model="group" label-width="80px">
<el-form-item label="店铺" prop="shop_id">
<el-select v-model="group.shop_id">
<el-option v-for="store in stores" :key="store.id" :label="store.name" :value="store.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="活动标题" prop="title">
<el-input type="textarea" v-model="group.title" style="width: 500px;"></el-input>
</el-form-item>
<el-form-item label="团购商品">
<el-button @click="importGoods()">从商品列表导入</el-button>
<el-input placeholder="搜索商品名称、编码" v-model="groupGoodsSearch.external_sku_id"
style="margin-left: 20px; width: 400px;">
<el-button slot="append" @click="getGroupGoodsList();">查询</el-button>
</el-input>
<div style="display: flex; align-items: center;">
<span style="margin-right: 20px;">商品状态</span>
<el-radio-group v-model="groupGoodsSearch.has_stock" @change="getGroupGoodsList()">
<el-radio :label="2">全部</el-radio>
<el-radio :label="1">在售中</el-radio>
<el-radio :label="0">已售罄</el-radio>
</el-radio-group>
</div>
<div style="display: flex; align-items: center;">
<span style="margin-right: 20px;">商品分类</span>
<el-radio-group v-model="groupGoodsSearch.type_id" size="small" @change="getGroupGoodsList()">
<el-radio-button label="0">全部</el-radio-button>
<el-radio-button v-for="goodsType in types" :key="goodsType.id" :label="goodsType.id">
{{goodsType.name}}</el-radio-button>
</el-radio-group>
</div>
<el-table ref="multipleTableGroup" v-loading="groupLoading" :data="groupGoods.data" border
style="width: 100%" height="800" :row-key="getRowKeys">
<el-table-column type="selection" :reserve-selection="true" width="55">
</el-table-column>
<el-table-column label="排序">
<template slot-scope="scope">
<el-input v-model="scope.row.sort" placeholder="排序"
@change="handleCellChange(scope.row)"></el-input>
</template>
</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="category_name" label="分类">
</el-table-column>
<el-table-column prop="stock" label="库存">
</el-table-column>
<el-table-column label="限购数量">
<template slot-scope="scope">
<el-input v-model="scope.row.limit_buy" placeholder="限购数量"
@change="handleCellChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="价格">
<template slot-scope="scope">
<el-input v-model="scope.row.price_in_fen" placeholder="价格"
@change="handleCellChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column prop="options" label="操作">
<template slot-scope="scope">
<!-- <el-button @click="setTop(scope.row)" type="text" size="small">置顶</el-button> -->
<el-button @click="remove(scope.row)" type="text" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<div
style="display: flex; justify-content: space-between; align-items: center; line-height: 32px; margin-top: 20px;">
<el-button type="danger" size="small" @click="batchRemove();">批量删除</el-button>
<el-pagination @size-change="handleSizeChangeGroup" @current-change="getGroupGoodsList"
:current-page.sync="groupGoods.meta.current_page" :page-sizes="[20, 30, 50, 100]"
:page-size="groupGoods.meta.per_page" layout="sizes, prev, pager, next"
:total="groupGoods.meta.total">
</el-pagination>
</div>
</el-form-item>
<el-form-item label="团购时间" prop="datetimerange">
<el-date-picker v-model="group.datetimerange" type="datetimerange" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" value-format="yyyy-MM-dd HH:mm:ss">
</el-date-picker>
</el-form-item>
<el-form-item style="display: flex; justify-content: flex-end;">
<el-button @click="onAdd(1);">保存预览</el-button>
<el-button type="primary" @click="onAdd(0);">发布</el-button>
</el-form-item>
</el-form>
</el-card>
<el-dialog :title="dialogTitle" :visible.sync="centerDialogVisible" width="80%" :close-on-click-modal="false">
<el-form ref="goodsList" :model="goodsList" label-width="80px">
<el-form-item label="商品分类" prop="type_id">
<el-radio-group v-model="goodsList.type_id" size="small" @change="goodsSearch()">
<el-radio-button label="0">全部</el-radio-button>
<el-radio-button v-for="goodsType in types" :key="goodsType.id" :label="goodsType.id">
{{goodsType.name}}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="商品品牌" prop="brand_id">
<el-radio-group v-model="goodsList.brand_id" size="small" @change="goodsSearch()">
<el-radio-button label="0">全部</el-radio-button>
<el-radio-button v-for="goodsBrand in brands" :key="goodsBrand.id" :label="goodsBrand.id">
{{goodsBrand.name}}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="搜索" prop="goods_keyword">
<el-input placeholder="搜索商品名称、编码" v-model="goodsList.goods_keyword" style="width: 400px;">
</el-input>
<el-radio-group v-model="goodsList.has_stock" style="margin: 0 30px">
<el-radio :label="1">有库存</el-radio>
<el-radio :label="0">全部</el-radio>
</el-radio-group>
<el-button type="primary" size="small" @click="goodsSearch();">查询</el-button>
<el-button size="small" @click="resetForm()">重置</el-button>
</el-form-item>
</el-form>
<el-table ref="multipleTable" @select="handleSelect" v-loading="goodsLoading" :data="goods.data" border
style="width: 100%" height="520" :row-key="getRowKeys" @select-all="selectCurrentGoods">
<el-table-column type="selection" :reserve-selection="true" width="55">
</el-table-column>
<el-table-column label="商品信息">
<template slot-scope="scope">
{{scope.row.goods.title + ' ' + scope.row.title}}
</template>
</el-table-column>
<el-table-column label="编码">
<template slot-scope="scope">
{{scope.row.goods.goods_code + '_' + scope.row.sku_code}}
</template>
</el-table-column>
<el-table-column label="品牌">
<template slot-scope="scope">
{{scope.row.goods.brand ? scope.row.goods.brand.name : ''}}
</template>
</el-table-column>
<el-table-column prop="goods.type.name" label="分类">
</el-table-column>
<el-table-column prop="num" label="库存">
</el-table-column>
</el-table>
<div style="display: flex; flex-direction: row-reverse; align-items: center; margin-top: 10px;">
<el-pagination @size-change="handleSizeChange" @current-change="goodsSearch"
:current-page.sync="goods.meta.current_page" :page-sizes="[20, 30, 50, 100]"
:page-size="goods.meta.per_page" layout="sizes, prev, pager, next" :total="goods.meta.total">
</el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<el-button @click="toggleSelection(1)">全选</el-button>
<el-button @click="toggleSelection(0)">取消全选</el-button>
</div>
<div>已选 {{selectNum}} </div>
<div>
<el-button type="primary" @click="addGoods();"> </el-button>
<el-button @click="centerDialogVisible = false"> </el-button>
</div>
</div>
</span>
</el-dialog>
</div>
</template>
<script>
import { storeList } from "../../api/shop";
import { addGroup, addGroupGoods } from "../../api/group";
import { goods_types, Brand_goods_types } from "../../api/rankingData";
import { getGoodsList } from "../../api/goods";
export default {
data() {
return {
group: {
shop_id: '',
title: "",
is_save_preview: 1,
datetimerange: [],
},
rules: {
shop_id: [
{ required: true, message: '请选择店铺' },
],
title: [
{ required: true, message: '请输入活动标题', trigger: 'blur' },
],
datetimerange: [
{ required: true, message: '请选择团购时间', trigger: 'blur' },
],
},
groupGoods: {
data: [],
meta: {
total: 0,
current_page: 1,
per_page: 20,
},
},
groupGoodsSearch: {
external_sku_id: "",
has_stock: 1,
type_id: 0,
page: 1,
per_page: 20,
},
groupLoading: false,
goodsLoading: true,
goods: {
data: [],
meta: {
total: 0,
current_page: 1,
per_page: 20,
}
},
centerDialogVisible: false,
stores: [],
types: [],
brands: [],
goodsList: {
goods_keyword: "",
has_stock: 1,
type_id: 0,
brand_id: 0,
has_ids: [],
},
goodsListPage: {
page: 1,
per_page: 20,
},
dialogTitle: "您的商品库中已有 0 件商品",
selectNum: 0,
selectGoods: [],
allGoods: [],
changeData: [],
}
},
mounted() {
this.getStoreList();
this.getbrandType();
this.getgoodsType();
this.goodsSearch();
},
methods: {
getStoreList() {
let params = {
page: 0,
per_page: 999,
plat_id: 1
};
storeList(params).then((res) => {
this.stores = res.data.data;
});
},
onAdd(is_save_preview) {
this.group.is_save_preview = is_save_preview;
this.group.new_ids = this.goodsList.has_ids;
let changeData = [];
this.changeData.forEach((v, k) => {
if (v) {
changeData.push(v);
}
})
this.group.change_data = changeData;
this.$refs.group.validate((valid) => {
if (valid) {
addGroup(this.group).then((res) => {
this.$message(res.data.message);
this.$router.push({ path: "GROUP_MANAGEMENT"});
})
} else {
return false;
}
});
},
handleSizeChangeGroup(val) {
this.groupGoodsSearch.per_page = val;
this.getGroupGoodsList();
},
getGroupGoodsList(page = 1) {
let params = {
page: page,
per_page: this.groupGoodsSearch.per_page,
goods_keyword: this.groupGoodsSearch.external_sku_id,
has_stock: this.groupGoodsSearch.has_stock,
type_id: this.groupGoodsSearch.type_id,
shop_id: this.group.shop_id,
has_ids: this.goodsList.has_ids,
};
addGroupGoods(params).then((res) => {
this.groupGoods = res.data;
this.groupGoods.data.forEach((sku, index) => {
if (undefined !== this.changeData[sku.id]) {
this.groupGoods.data[index].sort = this.changeData[sku.id].sort;
this.groupGoods.data[index].limit_buy = this.changeData[sku.id].limit_buy;
this.groupGoods.data[index].price_in_fen = this.changeData[sku.id].price_in_fen;
}
})
this.groupGoods.meta.per_page = parseInt(this.groupGoods.meta.per_page);
})
},
getgoodsType() {
let params = {
per_page: 9999,
};
goods_types(params).then((res) => {
this.types = res.data.data;
});
},
getbrandType() {
let params = {
per_page: 9999,
};
Brand_goods_types(params).then((res) => {
this.brands = res.data.data;
});
},
batchRemove() {
this.$refs.multipleTableGroup.selection.forEach((row) => {
let index = this.goodsList.has_ids.indexOf(row.id);
if (index > 0) {
delete this.goodsList.has_ids[index];
}
})
this.$refs.multipleTableGroup.clearSelection();
this.getGroupGoodsList();
},
remove(row) {
this.goodsList.has_ids.forEach((v, k) => {
if (v == row.id) {
delete this.goodsList.has_ids[k];
}
})
this.getGroupGoodsList();
},
handleCellChange(row) {
this.changeData[row.id] = {
id: row.id,
sort: row.sort,
limit_buy: row.limit_buy,
price_in_fen: row.price_in_fen,
};
},
//
importGoods() {
if (this.group.shop_id) {
this.dialogTitle = "您的商品库中已有 " + this.groupGoods.meta.total + " 件商品";
this.goodsSearch();
this.centerDialogVisible = true;
} else {
this.$message.error('请先选择店铺');
}
},
goodsSearch(page = 1) {
this.goodsList.page = page;
this.goodsList.per_page = this.goodsListPage.per_page;
this.goodsLoading = true;
getGoodsList(this.goodsList).then((res) => {
this.goods = res.data;
this.goods.meta.per_page = parseInt(this.goods.meta.per_page);
this.goods.data.forEach((row, i) => {
if (undefined !== this.selectGoods[row.id]) {
this.$refs.multipleTable.toggleRowSelection(row, true);
}
})
this.goodsLoading = false;
})
if (1 === page) {
this.getAllGoods(this.goodsList);
}
},
getAllGoods(params) {
params.page = 1;
params.per_page = 9999;
getGoodsList(params).then((res) => {
this.allGoods = res.data.data;
})
},
handleSizeChange(val) {
this.goodsListPage.per_page = val;
this.goodsSearch();
},
getRowKeys(row) {
return row.id;
},
toggleSelection(isAll) {
if (isAll) {
this.allGoods.forEach((sku, i) => {
if (undefined === this.selectGoods[sku.id]) {
this.selectNum++;
}
this.selectGoods[sku.id] = 1;
})
this.goods.data.forEach((row, i) => {
this.$refs.multipleTable.toggleRowSelection(row, true);
})
} else {
this.allGoods.forEach((sku, i) => {
if (undefined !== this.selectGoods[sku.id]) {
delete this.selectGoods[sku.id];
this.selectNum--;
}
})
this.$refs.multipleTable.clearSelection();
}
},
handleSelect(selection, row) {
if (undefined === this.selectGoods[row.id]) {
this.selectGoods[row.id] = 1;
this.selectNum++;
} else {
delete this.selectGoods[row.id];
this.selectNum--;
}
},
resetForm() {
this.$refs.goodsList.resetFields();
this.goodsSearch();
},
addGoods() {
let new_ids = [];
this.selectGoods.forEach((v, k) => {
if (k !== undefined) {
new_ids.push(k)
}
})
let params = {
shop_id: this.group.shop_id,
has_ids: this.goodsList.has_ids,
new_ids: new_ids,
per_page: this.groupGoods.meta.per_page
}
this.goodsList.has_ids.push(...new_ids);
addGroupGoods(params).then((res) => {
this.groupGoods = res.data;
this.groupGoods.meta.per_page = parseInt(this.groupGoods.meta.per_page);
})
this.$refs.goodsList.resetFields();
this.$refs.multipleTable.clearSelection();
this.selectGoods = [];
this.selectNum = 0;
this.centerDialogVisible = false;
},
selectCurrentGoods(selection) {
if (selection.length) {
selection.forEach((row) => {
if (undefined === this.selectGoods[row.id]) {
this.selectGoods[row.id] = 1;
}
})
this.selectNum += selection.length;
} else {
this.goods.data.forEach((row) => {
if (undefined !== this.selectGoods[row.id]) {
delete this.selectGoods[row.id];
}
})
this.selectNum -= this.goods.data.length;
}
}
}
}
</script>

View File

@ -0,0 +1,469 @@
<template>
<div>
<el-card style="margin-top: 10px" class="box-card">
<el-form ref="group" :rules="rules" :model="group" label-width="80px">
<el-form-item label="店铺" prop="shop_id">
<el-select v-model="group.shop_id" :disabled="true">
<el-option v-for="store in stores" :key="store.id" :label="store.name" :value="store.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="活动标题" prop="title">
<el-input type="textarea" v-model="group.title" style="width: 500px;"></el-input>
</el-form-item>
<el-form-item label="团购商品">
<el-button @click="importGoods()">从商品列表导入</el-button>
<el-input placeholder="搜索商品名称、编码" v-model="groupGoodsSearch.external_sku_id"
style="margin-left: 20px; width: 400px;">
<el-button slot="append" @click="getGroupGoodsList();">查询</el-button>
</el-input>
<div style="display: flex; align-items: center;">
<span style="margin-right: 20px;">商品状态</span>
<el-radio-group v-model="groupGoodsSearch.has_stock" @change="getGroupGoodsList()">
<el-radio :label="0">全部</el-radio>
<el-radio :label="1">在售中</el-radio>
<el-radio :label="-1">已售罄</el-radio>
</el-radio-group>
</div>
<div style="display: flex; align-items: center;">
<span style="margin-right: 20px;">商品分类</span>
<el-radio-group v-model="groupGoodsSearch.type_id" size="small" @change="getGroupGoodsList()">
<el-radio-button label="0">全部</el-radio-button>
<el-radio-button v-for="goodsType in types" :key="goodsType.id" :label="goodsType.id">
{{goodsType.name}}</el-radio-button>
</el-radio-group>
</div>
<el-table ref="multipleTableGroup" v-loading="groupLoading" :data="groupGoods.data" border
style="width: 100%" height="800" :row-key="getRowKeys">
<el-table-column type="selection" :reserve-selection="true" width="55">
</el-table-column>
<el-table-column label="排序">
<template slot-scope="scope">
<el-input v-model="scope.row.sort" placeholder="排序"
@change="handleCellChange(scope.row)"></el-input>
</template>
</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="category_name" label="分类">
</el-table-column>
<el-table-column prop="stock" label="库存">
</el-table-column>
<el-table-column label="限购数量">
<template slot-scope="scope">
<el-input v-model="scope.row.limit_buy" placeholder="限购数量"
@change="handleCellChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="价格">
<template slot-scope="scope">
<el-input v-model="scope.row.price_in_fen" placeholder="价格"
@change="handleCellChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column prop="options" label="操作">
<template slot-scope="scope">
<!-- <el-button @click="setTop(scope.row)" type="text" size="small">置顶</el-button> -->
<el-button @click="remove(scope.row)" type="text" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<div
style="display: flex; justify-content: space-between; align-items: center; line-height: 32px; margin-top: 20px;">
<el-button type="danger" size="small" @click="batchRemove();">批量删除</el-button>
<el-pagination @size-change="handleSizeChangeGroup" @current-change="getGroupGoodsList"
:current-page.sync="groupGoods.meta.current_page" :page-sizes="[20, 30, 50, 100]"
:page-size="groupGoods.meta.per_page" layout="sizes, prev, pager, next"
:total="groupGoods.meta.total">
</el-pagination>
</div>
</el-form-item>
<el-form-item label="团购时间" prop="datetimerange">
<el-date-picker v-model="group.datetimerange" type="datetimerange" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" value-format="yyyy-MM-dd HH:mm:ss">
</el-date-picker>
</el-form-item>
<el-form-item style="display: flex; justify-content: flex-end;">
<el-button type="success" @click="onEdit();">修改团购</el-button>
</el-form-item>
</el-form>
</el-card>
<el-dialog :title="dialogTitle" :visible.sync="centerDialogVisible" width="80%" :close-on-click-modal="false">
<el-form ref="goodsList" :model="goodsList" label-width="80px">
<el-form-item label="商品分类" prop="type_id">
<el-radio-group v-model="goodsList.type_id" size="small" @change="goodsSearch()">
<el-radio-button label="0">全部</el-radio-button>
<el-radio-button v-for="goodsType in types" :key="goodsType.id" :label="goodsType.id">
{{goodsType.name}}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="商品品牌" prop="brand_id">
<el-radio-group v-model="goodsList.brand_id" size="small" @change="goodsSearch()">
<el-radio-button label="0">全部</el-radio-button>
<el-radio-button v-for="goodsBrand in brands" :key="goodsBrand.id" :label="goodsBrand.id">
{{goodsBrand.name}}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="搜索" prop="goods_keyword">
<el-input placeholder="搜索商品名称、编码" v-model="goodsList.goods_keyword" style="width: 400px;">
</el-input>
<el-radio-group v-model="goodsList.has_stock" style="margin: 0 30px">
<el-radio :label="1">有库存</el-radio>
<el-radio :label="0">全部</el-radio>
</el-radio-group>
<el-button type="primary" size="small" @click="goodsSearch();">查询</el-button>
<el-button size="small" @click="resetForm()">重置</el-button>
</el-form-item>
</el-form>
<el-table ref="multipleTable" @select="handleSelect" v-loading="goodsLoading" :data="goods.data" border
style="width: 100%" height="520" :row-key="getRowKeys" @select-all="selectCurrentGoods">
<el-table-column type="selection" :reserve-selection="true" width="55">
</el-table-column>
<el-table-column label="商品信息">
<template slot-scope="scope">
{{scope.row.goods.title + ' ' + scope.row.title}}
</template>
</el-table-column>
<el-table-column label="编码">
<template slot-scope="scope">
{{scope.row.goods.goods_code + '_' + scope.row.sku_code}}
</template>
</el-table-column>
<el-table-column label="品牌">
<template slot-scope="scope">
{{scope.row.goods.brand ? scope.row.goods.brand.name : ''}}
</template>
</el-table-column>
<el-table-column prop="goods.type.name" label="分类">
</el-table-column>
<el-table-column prop="num" label="库存">
</el-table-column>
</el-table>
<div style="display: flex; flex-direction: row-reverse; align-items: center; margin-top: 10px;">
<el-pagination @size-change="handleSizeChange" @current-change="goodsSearch"
:current-page.sync="goods.meta.current_page" :page-sizes="[20, 30, 50, 100]"
:page-size="goods.meta.per_page" layout="sizes, prev, pager, next" :total="goods.meta.total">
</el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<el-button @click="toggleSelection(1)">全选</el-button>
<el-button @click="toggleSelection(0)">取消全选</el-button>
</div>
<div>已选 {{selectNum}} </div>
<div>
<el-button type="primary" @click="addGoods();"> </el-button>
<el-button @click="centerDialogVisible = false"> </el-button>
</div>
</div>
</span>
</el-dialog>
</div>
</template>
<script>
import { storeList } from "../../api/shop";
import { showGroup, editGroup, getGroupGoods } from "../../api/group";
import { goods_types, Brand_goods_types } from "../../api/rankingData";
import { getGoodsList } from "../../api/goods";
export default {
data() {
return {
group: {
shop_id: '',
title: "",
is_save_preview: 1,
datetimerange: [],
start_time: '',
end_time: ''
},
rules: {
shop_id: [
{ required: true, message: '请选择店铺' },
],
title: [
{ required: true, message: '请输入活动标题', trigger: 'blur' },
],
datetimerange: [
{ required: true, message: '请选择团购时间', trigger: 'blur' },
],
},
groupGoods: {
data: [],
meta: {
total: 0,
current_page: 1,
per_page: 20,
},
},
groupGoodsSearch: {
external_sku_id: "",
has_stock: 1,
page: 1,
per_page: 20,
group_id: 0,
delete_ids: [],
new_ids: [],
type_id: 0,
},
groupLoading: false,
goodsLoading: true,
goods: {
data: [],
meta: {
total: 0,
current_page: 1,
per_page: 20,
}
},
centerDialogVisible: false,
stores: [],
types: [],
brands: [],
goodsList: {
goods_keyword: "",
has_stock: 1,
type_id: 0,
brand_id: 0,
delete_ids: [],
new_ids: [],
has_ids: [],
},
goodsListPage: {
page: 1,
per_page: 20,
},
dialogTitle: "您的商品库中已有 0 件商品",
selectNum: 0,
selectGoods: [],
deleteGoods: [],
allGoods: [],
changeData: [],
}
},
mounted() {
this.getStoreList();
this.groupGoodsSearch.group_id = parseInt(this.$route.query.id);
this.getGoupInfo(this.$route.query.id);
this.getGroupGoodsList();
this.getbrandType();
this.getgoodsType();
},
methods: {
getStoreList() {
let params = {
page: 0,
per_page: 999,
plat_id: 1
};
storeList(params).then((res) => {
this.stores = res.data.data;
});
},
onEdit() {
this.group.new_ids = this.goodsList.has_ids;
let changeData = [];
this.changeData.forEach((v, k) => {
if (v) {
changeData.push(v);
}
})
this.group.change_data = changeData;
this.group.delete_ids = this.groupGoodsSearch.delete_ids;
this.$refs.group.validate((valid) => {
if (valid) {
editGroup(this.groupGoodsSearch.group_id, this.group).then((res) => {
this.$message(res.data.message);
// this.$router.push({ path: "GROUP_MANAGEMENT" });
})
} else {
return false;
}
});
},
handleSizeChangeGroup(val) {
this.groupGoodsSearch.per_page = val;
this.getGroupGoodsList();
},
getGroupGoodsList(page = 1) {
this.groupGoodsSearch.page = page;
this.groupGoodsSearch.new_ids = this.goodsList.new_ids;
getGroupGoods(this.groupGoodsSearch).then((res) => {
this.groupGoods = res.data;
this.groupGoods.data.forEach((sku, index) => {
if (undefined !== this.changeData[sku.id]) {
this.groupGoods.data[index].sort = this.changeData[sku.id].sort;
this.groupGoods.data[index].limit_buy = this.changeData[sku.id].limit_buy;
this.groupGoods.data[index].price_in_fen = this.changeData[sku.id].price_in_fen;
}
})
this.groupGoods.meta.per_page = parseInt(this.groupGoods.meta.per_page);
})
},
getGoupInfo(id) {
showGroup(id).then((res) => {
this.group = res.data.data;
this.group.datetimerange = [this.group.start_time, this.group.end_time];
})
},
getgoodsType() {
let params = {
per_page: 9999,
};
goods_types(params).then((res) => {
this.types = res.data.data;
});
},
getbrandType() {
let params = {
per_page: 9999,
};
Brand_goods_types(params).then((res) => {
this.brands = res.data.data;
});
},
batchRemove() {
this.$refs.multipleTableGroup.selection.forEach((row) => {
this.groupGoodsSearch.delete_ids.push(row.id);
let index = this.goodsList.has_ids.indexOf(row.id);
if (index > 0) {
delete this.goodsList.has_ids[index];
}
})
this.$refs.multipleTableGroup.clearSelection();
this.getGroupGoodsList();
},
remove(row) {
this.groupGoodsSearch.delete_ids.push(row.id);
this.goodsList.has_ids.forEach((v, k) => {
if (v == row.id) {
delete this.goodsList.has_ids[k];
}
})
this.getGroupGoodsList();
},
handleCellChange(row) {
this.changeData[row.id] = {
id: row.id,
sort: row.sort,
limit_buy: row.limit_buy,
price_in_fen: row.price_in_fen,
};
},
//
importGoods() {
if (this.group.shop_id) {
this.dialogTitle = "您的商品库中已有 " + this.groupGoods.meta.total + " 件商品";
this.goodsSearch();
this.centerDialogVisible = true;
} else {
this.$message.error('请先选择店铺');
}
},
goodsSearch(page = 1) {
this.goodsList.page = page;
this.goodsList.per_page = this.goodsListPage.per_page;
this.goodsList.group_id = this.groupGoodsSearch.group_id;
this.goodsList.delete_ids = this.groupGoodsSearch.delete_ids;
this.goodsLoading = true;
getGoodsList(this.goodsList).then((res) => {
this.goods = res.data;
this.goods.meta.per_page = parseInt(this.goods.meta.per_page);
this.goods.data.forEach((row, i) => {
if (undefined !== this.selectGoods[row.id]) {
this.$refs.multipleTable.toggleRowSelection(row, true);
}
})
this.goodsLoading = false;
})
if (1 === page) {
this.getAllGoods(this.goodsList);
}
},
getAllGoods(params) {
params.page = 1;
params.per_page = 9999;
getGoodsList(params).then((res) => {
this.allGoods = res.data.data;
})
},
handleSizeChange(val) {
this.goodsListPage.per_page = val;
this.goodsSearch();
},
getRowKeys(row) {
return row.id;
},
toggleSelection(isAll) {
if (isAll) {
this.allGoods.forEach((sku, i) => {
if (undefined === this.selectGoods[sku.id]) {
this.selectNum++;
}
this.selectGoods[sku.id] = 1;
})
this.goods.data.forEach((row, i) => {
this.$refs.multipleTable.toggleRowSelection(row, true);
})
} else {
this.allGoods.forEach((sku, i) => {
if (undefined !== this.selectGoods[sku.id]) {
delete this.selectGoods[sku.id];
this.selectNum--;
}
})
this.$refs.multipleTable.clearSelection();
}
},
handleSelect(selection, row) {
if (undefined === this.selectGoods[row.id]) {
this.selectGoods[row.id] = 1;
this.selectNum++;
} else {
delete this.selectGoods[row.id];
this.selectNum--;
}
},
resetForm() {
this.$refs.goodsList.resetFields();
this.goodsSearch();
},
addGoods() {
this.selectGoods.forEach((v, k) => {
if (k !== undefined) {
this.goodsList.new_ids.push(k)
this.goodsList.has_ids.push(k)
}
})
this.getGroupGoodsList();
this.$refs.goodsList.resetFields();
this.$refs.multipleTable.clearSelection();
this.selectGoods = [];
this.selectNum = 0;
this.centerDialogVisible = false;
},
selectCurrentGoods(selection) {
if (selection.length) {
selection.forEach((row) => {
if (undefined === this.selectGoods[row.id]) {
this.selectGoods[row.id] = 1;
}
})
this.selectNum += selection.length;
} else {
this.goods.data.forEach((row) => {
if (undefined !== this.selectGoods[row.id]) {
delete this.selectGoods[row.id];
}
})
this.selectNum -= this.goods.data.length;
}
}
}
}
</script>

View File

@ -0,0 +1,106 @@
<template>
<div>
<el-card class="box-card" :body-style="{ padding: '20px 20px 0 20px' }">
<el-form :inline="true" :model="formSearch" class="demo-form-inline">
<el-form-item label="店铺">
<el-select v-model="formSearch.store_id" placeholder="全部">
<el-option v-for="store in stores" :key="store.id" :label="store.name" :value="store.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="团购状态">
<el-select v-model="formSearch.status" placeholder="团购状态">
<el-option label="未开始" value="-5"></el-option>
<el-option label="跟团中" value="1"></el-option>
<el-option label="预览中" value="-10"></el-option>
<el-option label="已结束" value="20"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动标题">
<el-input v-model="formSearch.title" placeholder="活动标题"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getGroupList();">查询</el-button>
<el-button type="success" @click="groupAdd();">新增团购</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="margin-top: 10px" class="box-card">
<el-table v-loading="loading" :data="tableData" border style="width: 100%">
<el-table-column prop="shop.name" label="店铺">
</el-table-column>
<el-table-column prop="title" label="活动标题">
</el-table-column>
<el-table-column prop="status" label="团购状态">
</el-table-column>
<el-table-column label="开团时间">
<template slot-scope="scope">
<div>{{scope.row.start_time}}</div>
<div></div>
<div>{{scope.row.end_time}}</div>
</template>
</el-table-column>
<el-table-column label="手机查看">
<template slot-scope="scope">
<el-image style="width: 100px; height: 100px" :src="scope.row.ercode"></el-image>
</template>
</el-table-column>
<el-table-column prop="options" label="操作">
<template slot-scope="scope">
<el-button @click="groupEdit(scope.row.id)" type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
import { storeList } from "../../api/shop";
import { groupList } from "../../api/group";
export default {
data() {
return {
formSearch: {
store_id: "",
status: "",
title: "",
page: 1,
per_page: 20
},
stores: [],
loading: false,
tableData: []
}
},
mounted() {
this.getStoreList();
this.getGroupList();
},
methods: {
getStoreList() {
let params = {
page: 0,
per_page: 999,
plat_id: 1
};
storeList(params).then((res) => {
this.stores = res.data.data;
});
},
getGroupList() {
groupList(this.formSearch).then((res) => {
this.tableData = res.data.data;
})
},
groupAdd() {
this.$router.push({ path: "GROUP_GOODS_ADD", query: { id: 0 } });
},
groupEdit(id) {
this.$router.push({ path: "GROUP_GOODS_EDIT", query: { id: id } });
},
}
}
</script>

View File

@ -5,10 +5,16 @@
<div class="table" style="margin-top: 10px"> <div class="table" style="margin-top: 10px">
<el-table v-loading="loading" :data="tableData" style="width: 100%"> <el-table v-loading="loading" :data="tableData" style="width: 100%">
<el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="id" label="ID"> </el-table-column>
<el-table-column prop="name" label="店铺名称" width="180"> <el-table-column prop="name" label="店铺名称">
</el-table-column> </el-table-column>
<el-table-column prop="plat_id" label="所属平台"></el-table-column> <el-table-column prop="plat_id" label="所属平台"></el-table-column>
<el-table-column label="成本倍率">
<template slot-scope="scope">
<el-input v-model="scope.row.ratio" placeholder="成本倍率" @change="handleCellChange(scope.row)">
</el-input>
</template>
</el-table-column>
<el-table-column label="操作"> <el-table-column label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="danger" v-if="scope.row.status === '未授权'"><a :href="scope.row.authUrl" <el-button type="danger" v-if="scope.row.status === '未授权'"><a :href="scope.row.authUrl"
@ -47,17 +53,20 @@
</div> </div>
<!-- 新增店铺 --> <!-- 新增店铺 -->
<el-dialog title="新增店铺" :visible.sync="dialogFormVisible" :close-on-click-modal="false"> <el-dialog title="新增店铺" :visible.sync="dialogFormVisible" :close-on-click-modal="false" width="20%">
<el-form :model="form"> <el-form ref="form" :rules="rules" :model="form" lable-width="80px">
<el-form-item label="店铺名称"> <el-form-item label="店铺名称">
<el-input v-model="form.name" placeholder="输入店铺名称"></el-input> <el-input v-model="form.name" placeholder="输入店铺名称" style="width: 400px;"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="店铺平台"> <el-form-item label="店铺平台">
<el-select v-model="form.plat_id" placeholder="输入店铺平台"> <el-select v-model="form.plat_id" placeholder="输入店铺平台" style="width: 400px;">
<el-option v-for="(item, index) in storeId" :key="index" :label="item" :value="index"> <el-option v-for="(item, index) in storeId" :key="index" :label="item" :value="index">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="成本倍率">
<el-input v-model="form.ratio" placeholder="成本倍率" style="width: 400px;"></el-input>
</el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button> <el-button @click="dialogFormVisible = false"> </el-button>
@ -68,7 +77,7 @@
</template> </template>
<script> <script>
import { shopListId, shopAdd, storeList, downloadGoods } from "../../api/shop"; import { shopListId, shopAdd, storeList, downloadGoods, updateStore } from "../../api/shop";
export default { export default {
data() { data() {
return { return {
@ -76,6 +85,18 @@ export default {
form: { form: {
name: "", name: "",
plat_id: "", plat_id: "",
ratio: 1,
},
rules: {
name: [
{ required: true, message: '请输入店铺名称', trigger: 'blur' },
],
plat_id: [
{ required: true, message: '请选择店铺平台', trigger: 'blur' },
],
ratio: [
{ required: true, message: '请输入成本倍率', trigger: 'blur', },
],
}, },
storeId: [], // id storeId: [], // id
loading: true, loading: true,
@ -161,6 +182,20 @@ export default {
}); });
}); });
}, },
handleCellChange(row) {
this.$confirm('确认修改成本倍率吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
updateStore(row.id, { ratio: row.ratio }).then((res) => {
this.$message({
type: 'info',
message: res.data.message
})
})
});
},
}, },
}; };
</script> </script>

View File

@ -11,8 +11,7 @@ module.exports = {
proxy: { proxy: {
// 配置代理 // 配置代理
"/api": { "/api": {
// target: 'http://doc.ii090.com/mock/267/', // target: "http://172.23.134.136:81",
// target: "http://erp.staging.miaoxuan66.cn",
target: "http://erp.chutang66.com", target: "http://erp.chutang66.com",
changeOrigin: true, // 开启代理 changeOrigin: true, // 开启代理
pathRewrite: { pathRewrite: {

View File

@ -282,4 +282,35 @@ return [
'name' => '同步库存', 'name' => '同步库存',
'parent_id' => 120, 'parent_id' => 120,
], ],
// 团购管理
'GROUP_MANAGEMENT' => [
'id' => 13,
'name' => '团购管理',
'parent_id' => 0,
],
'group.index' => [
'id' => 130,
'name' => '列表',
'parent_id' => 13,
],
'group.store' => [
'id' => 131,
'name' => '新增',
'parent_id' => 13,
],
'group.show' => [
'id' => 132,
'name' => '查看',
'parent_id' => 13,
],
'group.update' => [
'id' => 133,
'name' => '更新',
'parent_id' => 13,
],
'group.destroy' => [
'id' => 134,
'name' => '删除',
'parent_id' => 13,
],
]; ];

View File

@ -6,6 +6,7 @@ use App\Http\Controllers\UploadController;
use App\Http\Controllers\Shop\ShopsController; use App\Http\Controllers\Shop\ShopsController;
use App\Http\Controllers\Goods\GoodsSkusController; use App\Http\Controllers\Goods\GoodsSkusController;
use App\Http\Controllers\Business\BusinessGoodsSkusController; use App\Http\Controllers\Business\BusinessGoodsSkusController;
use App\Http\Controllers\Group\GroupsController;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -47,6 +48,8 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
// 平台 // 平台
Route::resource('plat_goods', 'Business\BusinessGoodsSkusController', ['only' => ['index', 'update', 'destroy']]); Route::resource('plat_goods', 'Business\BusinessGoodsSkusController', ['only' => ['index', 'update', 'destroy']]);
Route::post('plat/sync/{id}/stock', [BusinessGoodsSkusController::class, 'syncStock'])->name('plat.sync.stock'); Route::post('plat/sync/{id}/stock', [BusinessGoodsSkusController::class, 'syncStock'])->name('plat.sync.stock');
// 团购
// Route::resource('group', 'Group\GroupsController', ['only' => ['index', 'store', 'show', 'update', 'destroy']]);
}); });
// 登录 // 登录
Route::post('/auth/login', [LoginController::class, 'login'])->name('auth.login'); Route::post('/auth/login', [LoginController::class, 'login'])->name('auth.login');
@ -59,6 +62,13 @@ Route::resource('menus', 'Menu\MenusController', ['only' => ['index',
// 获取平台列表 // 获取平台列表
Route::get('shop_platforms', [ShopsController::class, 'getPlatList'])->name('plat.list')->middleware('auth:api'); Route::get('shop_platforms', [ShopsController::class, 'getPlatList'])->name('plat.list')->middleware('auth:api');
// 团购商品添加列表
Route::get('goodsList', [GroupsController::class, 'goodsList'])->name('goods.list')->middleware('auth:api');
Route::get('groupGoods', [GroupsController::class, 'getGoods'])->name('group.get_goods')->middleware('auth:api');
Route::post('groupGoods', [GroupsController::class, 'addGroupGoods'])->name('group.add_goods')->middleware('auth:api');
Route::get('addGoods', [GroupsController::class, 'addGoods'])->name('group.add_goods')->middleware('auth:api');
Route::resource('group', 'Group\GroupsController', ['only' => ['index', 'store', 'show', 'update', 'destroy']]);
// 妙选商城数据推送 // 妙选商城数据推送
Route::post('business', [ShopsController::class, 'business'])->name('shop.put.business'); Route::post('business', [ShopsController::class, 'business'])->name('shop.put.business');