Merge branch 'yezhenman' of gitee.com:hzchunfen/erp into yezhenman

This commit is contained in:
yezhenman 2022-08-17 16:23:12 +08:00
commit 27495008a5
99 changed files with 3976 additions and 891 deletions

View File

@ -15,7 +15,7 @@
1. `composer install`
2. `cp .env.example .env`
3. 修改 .env 配置项为本地配置
4. 创建数据库 `CREATE DATABASE IF NOT EXISTS `erp` DEFAULT CHARACTER SET utf8;`
4. 创建数据库 `CREATE DATABASE IF NOT EXISTS `erp` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;`
5. `php artisan migrate` 如果数据填充没有执行成功,则需要再次执行 `php artisan migrate:fresh --seed`
6. `php artisan key:generate`
7. `php artisan update:super_admin_permissions` 更新超级管理员角色权限

View File

@ -0,0 +1,103 @@
<?php
namespace App\Console\Commands;
use App\Models\BusinessGoodsSku;
use App\Models\GoodsBrand;
use App\Models\GoodsType;
use App\Models\Goods;
use App\Models\GoodsSku;
use Illuminate\Console\Command;
class BusinessGoodsSkuToLocal extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'goods_sku:to_local';
/**
* The console command description.
*
* @var string
*/
protected $description = '将已下载的 花富贵儿 的商品保存到本地商品列表(注意: 先在店铺列表页面下载商品)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$num = 0;
BusinessGoodsSku::chunk(100, function ($businessGoodsSkus) use ($num) {
foreach ($businessGoodsSkus as $businessGoodsSku) {
if (empty($businessGoodsSku['goods_name']) || empty($businessGoodsSku['external_sku_id'])) {
continue;
}
$businessGoodsName = explode(' ', $businessGoodsSku['goods_name']);
$count = count($businessGoodsName);
if (1 === $count) {
continue;
} elseif (2 === $count) {
// 商品名称 规格名称
$brand = 0;
$type = '未分类';
$goodsName = $businessGoodsName[0];
$skuName = $businessGoodsName[1];
} elseif (3 === $count) {
// 种类 商品名称 规格名称
$brand = 0;
$type = $businessGoodsName[0];
$goodsName = $businessGoodsName[1];
$skuName = $businessGoodsName[2];
} else {
// 品牌 种类 商品名称 规格名称
$brand = $businessGoodsName[0];
$type = $businessGoodsName[1];
$goodsName = $businessGoodsName[2];
$skuName = $businessGoodsName[3];
foreach ($businessGoodsName as $k => $v) {
if ($k > 3) {
$skuName .= $v;
}
}
}
if ($brand) {
$goodsBrand = GoodsBrand::firstOrCreate(['name' => $brand]);
$brand = $goodsBrand->id;
}
$goodsType = GoodsType::firstOrCreate(['name' => $type]);
[$goodsCode, $skuCode] = explode('_', $businessGoodsSku['external_sku_id']);
$goods = [
'title' => $goodsName,
'type_id' => $goodsType->id,
'brand_id' => $brand,
'goods_code' => $goodsCode,
];
$goods = Goods::firstOrCreate($goods);
$goodsSku = [
'goods_id' => $goods->id,
'title' => $skuName,
'sku_code' => $skuCode,
];
GoodsSku::firstOrCreate($goodsSku);
++$num;
}
});
$this->info('导入成功: ' . $num);
}
}

View File

@ -22,7 +22,7 @@ class Inventory extends Command
*
* @var string
*/
protected $description = '定时盘点';
protected $description = '定时库存盘点';
/**
* Create a new command instance.
@ -70,7 +70,7 @@ class Inventory extends Command
$log->message = '成功';
DB::commit();
} catch (\Exception $exception) {
$log->message = '失败';
$log->message = '失败' . $exception->getMessage();
DB::rollBack();
}
$log->save();

View File

@ -0,0 +1,56 @@
<?php
namespace App\Console\Commands;
use App\Services\Business\BusinessFactory;
use App\Utils\DateTimeUtils;
use Illuminate\Console\Command;
use App\Models\Shop;
use Swoole\Timer;
use Swoole\Event;
class Swoole extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'swoole:timer';
/**
* The console command description.
*
* @var string
*/
protected $description = '每秒钟获取增量订单';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Timer::tick(1000, function () {
$shops = Shop::query()->where('plat_id', 1)->where('status', 1)->get();
$endTime = DateTimeUtils::getMicroTime();
$beginTime = $endTime - 10000;
foreach ($shops as $shop) {
BusinessFactory::init()->make($shop->plat_id)->setShop($shop)->downloadOrdersAndSave($beginTime, $endTime, 'increment', 1);
}
});
Event::wait();
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace App\Console\Commands;
use App\Models\Shop;
use App\Services\Business\BusinessFactory;
use App\Utils\DateTimeUtils;
use Illuminate\Console\Command;
class Test extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'test';
/**
* The console command description.
*
* @var string
*/
protected $description = '测试';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$shop = Shop::query()->find(1);
$business = BusinessFactory::init()->make($shop->plat_id);
$business->setShop($shop);
// 下载商品列表
// $business->downloadGoodsListAndBind();
// 下载单个商品
// $business->downloadGoods(1);
// 库存修改
// $business->incrQuantity(1);
// 订单下载
// $beginTime = DateTimeUtils::getMicroTime('2022-08-08');
// $endTime = DateTimeUtils::getMicroTime('2022-08-09');
// $business->downloadOrdersAndSave($beginTime, $endTime);
$this->info('执行测试成功');
}
}

View File

@ -7,7 +7,7 @@ use Illuminate\Console\Command;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class UpdateSuperPermissions extends Command
class UpdateSuperAdminPermissions extends Command
{
/**
* The name and signature of the console command.

View File

@ -2,6 +2,7 @@
namespace App\Console;
use App\Console\Commands\Inventory;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@ -24,8 +25,9 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
// 服务器添加cron入口
// * * * * * cd /home/wwwroot/erp.staging.chutang66.com && php artisan schedule:run >> /dev/null 2>&1
$schedule->command(Inventory::class)->dailyAt('07:00');
}
/**

View File

@ -0,0 +1,58 @@
<?php
namespace App\Events;
use App\Models\BusinessOrderItem;
use App\Models\GoodsSku;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class BusinessOrdersUpdate
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $num;
public $businessOrderItem;
public $goodsSku;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(BusinessOrderItem $item, $num)
{
$this->businessOrderItem = $item;
$this->num = $num;
$this->updateStock();
}
private function updateStock()
{
[$goodsCode, $skuCode] = explode('_', $this->businessOrderItem->external_sku_id);
$this->goodsSku = GoodsSku::query()->where('sku_code', $skuCode)
->with(['goods' => function ($query) use ($goodsCode) {
$query->where('goods_code', $goodsCode);
}])
->first();
if ($this->goodsSku) {
$this->goodsSku->stock += $this->num;
$this->goodsSku->save();
}
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Events;
use App\Models\GoodsSku;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class StockUpdateEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $goodsSku;
public $goodsSkus;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($data)
{
if (is_array($data)) {
$this->goodsSkus = GoodsSku::query()->whereIn('id', $data)->with(['goods:id,goods_code'])->get();
} else {
$this->goodsSku = $data;
}
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

@ -52,8 +52,8 @@ class LoginController extends Controller
if (Auth::attempt($credentials)) {
// 通过认证..
return response()->json(['token' => $request->user()->api_token]);
}else {
return response()->json(['error' => 'auth login fail']);
}
return response()->json(['error' => 'auth login fail']);
}
}

View File

@ -52,8 +52,8 @@ class RegisterController extends Controller
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'unique:users', 'max:255'],
'email' => ['string', 'email', 'max:255', 'unique:users'],
'name' => ['required', 'string', 'unique:users', 'max:191'],
'email' => ['string', 'email', 'max:191', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'role_id' => ['required', 'numeric', 'exists:roles,id'],
]);

View File

@ -13,6 +13,7 @@ class Controller extends BaseController
protected $res = [
'httpCode' => 200,
'message' => '操作成功',
'errorCode' => 0,
'errorMessage' => '',
];

View File

@ -32,7 +32,7 @@ class GoodsBrandsController extends Controller
{
$validator = Validator::make($request->all(), [
'names' => 'required|array',
'names.*' => 'required|string|max:255|unique:goods_brands,name',
'names.*' => 'required|string|max:191|unique:goods_brands,name',
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
@ -68,7 +68,7 @@ class GoodsBrandsController extends Controller
'name' => [
'required',
'string',
'max:255',
'max:191',
Rule::unique('goods_brands')->ignore($id),
]
]);

View File

@ -6,13 +6,14 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\GoodsSkuRequest;
use App\Http\Resources\GoodsResource;
use App\Models\Log as LogModel;
use App\Utils\FormatUtils;
use App\Utils\DateTimeUtils;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\Goods;
use App\Http\Requests\GoodsRequest;
use App\Models\DailyStockRecord;
use Illuminate\Support\Facades\Storage;
class GoodsController extends Controller
{
@ -58,6 +59,7 @@ class GoodsController extends Controller
$goodsSkus = [];
foreach ($request->skus as $item) {
$item['goods_id'] = $goods->id;
$item['stock'] = $item['num'];
$item['reference_price'] = $item['cost'] * 1.5;
$goodsSkus[] = $item;
}
@ -68,7 +70,7 @@ class GoodsController extends Controller
foreach ($collection as $sku) {
$newRecords[] = [
'sku_id' => $sku['id'],
'day' => FormatUtils::date(),
'day' => DateTimeUtils::getToday(),
];
}
$record = new DailyStockRecord();
@ -85,4 +87,14 @@ class GoodsController extends Controller
return response($this->res, $this->res['httpCode']);
}
public function download()
{
$file = resource_path('templates/goods_skus_import.xlsx');
$headers = [
'Content-Type: application/xlsx',
];
return response()->download($file, 'goods_skus_import.xlsx', $headers);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers\Goods;
use App\Events\StockUpdateEvent;
use App\Exports\GoodsSkusExport;
use App\Http\Controllers\Controller;
use App\Http\Requests\GoodsRequest;
@ -9,7 +10,7 @@ use App\Http\Requests\GoodsSkuRequest;
use App\Models\Goods;
use App\Models\Log;
use App\Models\Log as LogModel;
use App\Utils\FormatUtils;
use App\Utils\DateTimeUtils;
use Illuminate\Http\Request;
use App\Models\GoodsSku;
use App\Http\Resources\GoodsSkuResource;
@ -45,7 +46,7 @@ class GoodsSkusController extends Controller
->pluck('sku_id')
->toArray();
}
$day = FormatUtils::date();
$day = DateTimeUtils::getToday();
$goodsSkus = GoodsSku::query()
->whereIn('goods_id', $goodsIds)
->when($ids, function ($query, $ids) {
@ -56,8 +57,9 @@ class GoodsSkusController extends Controller
$query->with(['type:id,name', 'brand:id,name']);
}])
->with(['daily' => function ($query) use ($day) {
$query->where('day', $day)->with(['daily:id,sku_id,day,arrived_today_num,loss_num,inventory']);
$query->where('day', $day);
}])
->orderBy('updated_at', 'desc')
->paginate();
return GoodsSkuResource::collection($goodsSkus);
@ -92,10 +94,15 @@ class GoodsSkusController extends Controller
$this->addLog($id, 'update');
// 商品更新
$goods = Goods::query()->find($sku->goods_id);
$this->log = new LogModel([
'module' => 'goods',
'action' => $request->getMethod(),
'target_type' => 'goods',
]);
$this->setBeforeUpdate($goods->toArray());
$goods->update($request->goods);
$this->setAfterUpdate($goods->toArray());
$this->addLog($sku->goods_id, 'update', 'goods');
$this->addLog($sku->goods_id, 'update');
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
@ -119,7 +126,8 @@ class GoodsSkusController extends Controller
Rule::exists('goods_skus', 'id'),
],
];
$validator = $this->validateUpdate($request->all(), $appendRules);
$skuRules = (new GoodsSkuRequest())->arrayRules('skus.*.');
$validator = Validator::make($request->all(), array_merge($appendRules, $skuRules));
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
@ -155,7 +163,7 @@ class GoodsSkusController extends Controller
$costLog['after_update'] = $goodsSku->cost;
$logs[] = $costLog;
// 今日到货
$record = DailyStockRecord::query()->where('sku_id', $sku['id'])->where('day', FormatUtils::date())->first(['id', 'arrived_today_num']);
$record = DailyStockRecord::query()->where('sku_id', $sku['id'])->where('day', DateTimeUtils::getToday())->first(['id', 'arrived_today_num']);
$arrivedLog['target_field'] = 'arrived_today_num';
$arrivedLog['before_update'] = $record->arrived_today_num;
$record->arrived_today_num += $sku['arrived_today_num'];
@ -166,6 +174,7 @@ class GoodsSkusController extends Controller
$log = new LogModel();
$log->batchInsert($logs);
DB::commit();
event(new StockUpdateEvent(array_column($request->skus, 'id')));
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
@ -191,8 +200,7 @@ class GoodsSkusController extends Controller
'target_id' => $sku['id'],
'user_id' => $request->user()->id
];
// 今日到货
$record = DailyStockRecord::query()->where('sku_id', $sku['id'])->where('day', FormatUtils::date())->first(['id', 'inventory']);
$record = DailyStockRecord::query()->where('sku_id', $sku['id'])->where('day', DateTimeUtils::getToday())->first(['id', 'inventory']);
$inventoryLog['target_field'] = 'inventory';
$inventoryLog['before_update'] = $record->inventory;
$record->inventory = $sku['inventory'];
@ -215,25 +223,28 @@ class GoodsSkusController extends Controller
return response($this->res, $this->res['httpCode']);
}
private function stock($skus)
private function stock($request)
{
$skus = $request->skus;
$update = reset($skus);
DB::beginTransaction();
try {
$sku = GoodsSku::query()->where('id', $update['id'])->get(['id', 'two_days_ago_num', 'yesterday_num', 'num', 'stock']);
$sku = GoodsSku::query()->where('id', $update['id'])->first(['id', 'two_days_ago_num', 'yesterday_num', 'num', 'stock', 'reserve']);
$record = DailyStockRecord::query()
->where('sku_id', $sku->id)
->where('day', FormatUtils::date())
->where('day', DateTimeUtils::getToday())
->first();
$this->setBeforeUpdate([
'two_days_ago_num' => $sku->two_days_ago_num,
'yesterday_num' => $sku->yesterday_num,
'num' => $sku->num,
'arrived_today_num' => $record->arrived_today_num,
'num' => $sku->num,
'stock' => $sku->stock,
]);
$sku->two_days_ago_num = $update['two_days_ago_num'];
$sku->yesterday_num = $update['yesterday_num'];
$sku->num = $update['two_days_ago_num'] + $update['yesterday_num'] + $sku->stock;
$sku->num = $update['two_days_ago_num'] + $update['yesterday_num'] + $update['arrived_today_num'];
$sku->stock += ($update['two_days_ago_num'] + $update['yesterday_num'] + $update['arrived_today_num'] - $record->arrived_today_num - $sku->two_days_ago_num - $sku->yesterday_num);
$sku->save();
$record->arrived_today_num = $update['arrived_today_num'];
$record->save();
@ -241,9 +252,12 @@ class GoodsSkusController extends Controller
'two_days_ago_num' => $sku->two_days_ago_num,
'yesterday_num' => $sku->yesterday_num,
'arrived_today_num' => $record->arrived_today_num,
'num' => $sku->num,
'stock' => $sku->stock,
]);
$this->addLog($sku->id, 'stock');
DB::commit();
event(new StockUpdateEvent($sku));
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
@ -290,33 +304,40 @@ class GoodsSkusController extends Controller
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
goto end;
}
$updateField = \request('updateField');
$sku = GoodsSku::query()->find($id);
if ('loss_num' === $updateField) {
$model = DailyStockRecord::query()
$record = DailyStockRecord::query()
->where('sku_id', $id)
->where('day', FormatUtils::date())
->where('day', DateTimeUtils::getToday())
->first(['id', 'loss_num']);
$this->log->message = $request->get('reason');
$this->setBeforeUpdate($model->loss_num);
$model->loss_num += $request->loss_num;
$this->setBeforeUpdate($record->loss_num);
$record->loss_num += $request->loss_num;
$record->save();
$this->setAfterUpdate($record->loss_num);
$sku->stock -= $request->loss_num;
} else {
$model = GoodsSku::query()->find($id);
$this->setBeforeUpdate($model->$updateField);
if ('reserve' === $updateField) {
$changeNum = $model->reserve - $request->reserve;
$model->stock += $changeNum;
$model->reserve = $request->reserve;
$model->num += $changeNum;
} else {
$model->$updateField = $request->$updateField;
}
$sku->$updateField = $request->$updateField;
}
$model->save();
$this->setAfterUpdate($model->$updateField);
$this->setBeforeUpdate($sku->$updateField);
if ('reserve' === $updateField) {
$changeNum = $sku->reserve - $request->reserve;
if (0 > $changeNum + $sku->stock) {
$this->setValidatorFailResponse('预留量超过库存数量');
goto end;
}
$sku->stock += $changeNum;
}
$sku->save();
if (in_array($updateField, ['reserve', 'loss_num'])) {
event(new StockUpdateEvent($sku));
}
$this->setAfterUpdate($sku->$updateField);
$this->addLog($id, $updateField);
end:
return response($this->res, $this->res['httpCode']);
}
@ -331,8 +352,9 @@ class GoodsSkusController extends Controller
];
}
try {
$collection = Excel::import(new GoodsSkusImport(), $request->file('goodsSkus'));
$this->setAfterUpdate($collection->toArray());
$import = new GoodsSkusImport();
$path = $request->file('goodsSkus');
Excel::import($import, $path);
$this->addLog(0, 'import');
} catch (ValidationException $exception) {
$this->setValidatorFailResponse($exception->validator->getMessageBag()->getMessages());

View File

@ -32,7 +32,7 @@ class GoodsTypesController extends Controller
{
$validator = Validator::make($request->all(), [
'names' => 'required|array',
'names.*' => 'required|string|max:255|unique:goods_types,name',
'names.*' => 'required|string|max:191|unique:goods_types,name',
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
@ -68,7 +68,7 @@ class GoodsTypesController extends Controller
'name' => [
'required',
'string',
'max:255',
'max:191',
Rule::unique('goods_types')->ignore($id),
]
]);

View File

@ -12,6 +12,7 @@ class LogsController extends Controller
public function index(Request $request)
{
$res = Log::query()
->orderBy('id', 'desc')
->with(['user:id,name'])
->filter()
->paginate();

View File

@ -6,8 +6,6 @@ use App\Http\Controllers\Controller;
use App\Models\Log as LogModel;
use App\Models\Menu;
use App\Http\Resources\MenusResource;
use App\Models\User;
use App\Utils\ArrayUtils;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

View File

@ -23,23 +23,27 @@ class PermissionsController extends Controller
]);
}
public function index()
public function index(Request $request)
{
$permissions = Permission::query()->get()->toArray();
$permissions = $request->user()->getPermissionsViaRoles()->toArray();
$permissions = ArrayUtils::index($permissions, 'name');
$routes = include(resource_path('lang/zh-CN/permission.php'));
foreach ($routes as $key => &$route) {
$route['id'] = $permissions[$key]['id'];
$allowedPermissions = [];
foreach ($routes as $route => $conf) {
if (isset($permissions[$route])) {
$conf['id'] = $permissions[$route]['id'];
$allowedPermissions[] = $conf;
}
}
$routes = FormatUtils::formatTreeData($routes, 0);
$allowedPermissions = FormatUtils::formatTreeData($allowedPermissions, 0);
return PermissionsResource::collection($routes);
return PermissionsResource::collection($allowedPermissions);
}
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255|unique:permissions,name',
'name' => 'required|string|max:191|unique:permissions,name',
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
@ -63,7 +67,7 @@ class PermissionsController extends Controller
public function update($id, Request $request)
{
$validator = Validator::make($request->all(), [
'name' => ['required', 'string', 'max:255', Rule::unique('permissions')->ignore($id),]
'name' => ['required', 'string', 'max:191', Rule::unique('permissions')->ignore($id),]
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers\Role;
use App\Http\Controllers\Controller;
use App\Models\Log as LogModel;
use App\Utils\ArrayUtils;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
@ -22,9 +23,22 @@ class RolesController extends Controller
]);
}
public function index()
public function index(Request $request)
{
$roles = Role::query()->get();
$roles = Role::query()->with('permissions')->where('id', '<>', 1)->get()->toArray();
$routes = include(resource_path('lang/zh-CN/permission.php'));
$allPermissions = Permission::query()->get()->toArray();
$allPermissions = ArrayUtils::index($allPermissions, 'name');
foreach ($roles as &$role) {
$permissions = [];
foreach ($role['permissions'] as $item) {
$permissions[] = [
'id' => $allPermissions[$item['name']]['id'],
'name' => $routes[$item['name']]['name'],
];
}
$role['permissions'] = $permissions;
}
return RolesResource::collection($roles);
}
@ -32,7 +46,7 @@ class RolesController extends Controller
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255|unique:roles,name',
'name' => 'required|string|max:191|unique:roles,name',
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
@ -67,7 +81,7 @@ class RolesController extends Controller
public function update($id, Request $request)
{
$validator = Validator::make($request->all(), [
'name' => ['required', 'string', 'max:255', Rule::unique('roles')->ignore($id),]
'name' => ['required', 'string', 'max:191', Rule::unique('roles')->ignore($id),]
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());

View File

@ -6,13 +6,23 @@ use App\Http\Controllers\Controller;
use App\Models\Shop;
use App\Http\Resources\ShopsResource;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Services\Business\BusinessFactory;
use Illuminate\Validation\Rule;
use App\Models\BusinessOrderItem;
class ShopsController extends Controller
{
public function index()
{
$shops = Shop::query()->paginate();
foreach ($shops as $shop) {
$shop->authUrl = '';
if ('妙选' !== $shop->plat_id && ('未授权' === $shop->status || '重新授权' === $shop->status)) {
$shop->authUrl = BusinessFactory::init()->make($shop->plat_id)->getAuthUrl($shop->id, $shop->getOriginal('plat_id'));
}
}
return ShopsResource::collection($shops);
}
@ -27,7 +37,7 @@ class ShopsController extends Controller
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255|unique:shops,name',
'name' => 'required|string|max:191|unique:shops,name',
'plat_id' => 'required|integer',
]);
if ($validator->fails()) {
@ -38,8 +48,97 @@ class ShopsController extends Controller
$shop = new Shop();
$shop->name = $request->name;
$shop->plat_id = $request->plat_id;
if (0 == $request->plat_id) {
$shop->status = 2;
}
$shop->save();
return response($this->res, $this->res['httpCode']);
}
public function authBind(Request $request)
{
[$shopId, $platId] = explode('_', $request->get('state'));
$shop = new Shop();
$platList = $shop->getPlatList();
$shop = $shop->find($shopId);
if ($platList[$platId] === $shop->plat_id) {
BusinessFactory::init()->make($shop->plat_id)->authCallback($request->get('code'), $shop);
} else {
$this->res = [
'httpCode' => 403,
'errorCode' => 403400,
'errorMessage' => '信息不匹配',
];
}
return response($this->res, $this->res['httpCode']);
}
public function business(Request $request)
{
$validator = Validator::make($request->all(), [
'type' => ['required', 'string', Rule::in(['goods', 'orders'])],
'erp_shop_id' => ['required', 'integer', 'exists:shops,id'],
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$shop = new Shop();
$shop = $shop->find($request->get('erp_shop_id'));
$business = BusinessFactory::init()->make($shop->plat_id);
$business->setShop($shop);
if ('goods' === $request->get('type')) {
$business->bindGoods($request->get('data'));
}
if ('orders' === $request->get('type')) {
$business->saveOrders($request->get('data'));
}
return response(['Code' => 10000, 'Message' => 'SUCCESS']);
}
public function countOrdersNumWithSkuCode(Request $request)
{
$validator = Validator::make($request->all(), [
'sku_code' => ['required', 'array'],
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$fields = implode(',', [
'shop_id',
'external_sku_id',
'count(id) as count',
]);
$res = BusinessOrderItem::query()
->select(DB::raw($fields))
->whereIn('external_sku_id', $request->get('sku_code'))
->groupBy(['shop_id', 'external_sku_id'])
->with(['shop:id,name'])
->get();
$data = [];
foreach ($res as $item) {
$data[$item->external_sku_id][] = [
'shop_name' => $item->shop->name,
'count' => $item->count,
];
}
return $data;
}
public function downloadGoods($id, Request $request)
{
$shop = Shop::query()->find($id);
$business = BusinessFactory::init()->make($shop->plat_id);
$business->setShop($shop);
$business->downloadGoodsListAndBind();
return response($this->res, $this->res['httpCode']);
}
}

View File

@ -6,7 +6,6 @@ use App\Http\Controllers\Controller;
use App\Models\Log as LogModel;
use App\Models\User;
use Illuminate\Http\Request;
use Faker\Generator as Faker;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use App\Http\Resources\UsersResource;
@ -30,10 +29,10 @@ class UsersController extends Controller
return UsersResource::collection($users);
}
public function store(Request $request, Faker $faker)
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255|unique:users,name',
'name' => 'required|string|max:191|unique:users,name',
'password' => 'required|string|min:8|confirmed',
'email' => 'email',
'role_name' => 'required|string|exists:roles,name'
@ -45,7 +44,6 @@ class UsersController extends Controller
}
$user = new User();
$user->name = $request->name;
$user->email = \request('email', $faker->unique()->safeEmail);
$user->password = $request->password;
$user->api_token = Str::random(60);
$user->save();
@ -67,7 +65,7 @@ class UsersController extends Controller
'name' => [
'required',
'string',
'max:255',
'max:191',
Rule::unique('users')->ignore($id),
],
// 'old_password' => 'sometimes|required|string|min:8',

View File

@ -38,7 +38,7 @@ class Kernel extends HttpKernel
],
'api' => [
'throttle:60,1',
// 'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];

View File

@ -31,7 +31,7 @@ class CheckPermissions
$res = [
'httpCode' => 403,
'errorCode' => 403403,
'errorMessage' => '您没有使用此功能的权限',
'errorMessage' => '您没有使用此功能的权限' . $currentRouteName,
];
return response($res, 403);
}

View File

@ -26,8 +26,8 @@ class GoodsRequest extends FormRequest
{
return [
'id' => ['sometimes', 'required', 'integer', 'exists:goods,id'],
'title' => ['required', 'string', 'max:255'],
'img_url' => ['required', 'string', 'max:255'],
'title' => ['required', 'string', 'max:191'],
'img_url' => ['required', 'string', 'max:191'],
'type_id' => ['required', 'integer', 'exists:goods_types,id'],
'brand_id' => ['integer', 'exists:goods_brands,id'],
'goods_code' => ['required', 'alpha_dash', 'max:32', Rule::unique('goods')->ignore(request('goods_id'))],

View File

@ -27,11 +27,11 @@ class GoodsSkuRequest extends FormRequest
return [
'id' => ['sometimes', 'required', 'integer', 'exists:goods_skus,id'],
'goods_id' => ['sometimes', 'required', 'integer', 'exists:goods,id'],
'title' => ['required', 'string', 'max:255'],
'sku_code' => ['required', 'distinct', 'alpha_dash', 'max:32'],
'status' => ['required', 'integer', Rule::in([0, 1, 2])],
'num' => ['required', 'integer'],
'cost' => ['required', 'numeric'],
'title' => ['sometimes', 'required', 'string', 'max:191'],
'sku_code' => ['sometimes', 'required', 'distinct', 'alpha_dash', 'max:32'],
'status' => ['sometimes', 'required', 'integer', Rule::in([0, 1, 2])],
'num' => ['sometimes', 'required', 'integer'],
'cost' => ['sometimes', 'required', 'numeric'],
'reference_price' => [
'sometimes',
'numeric',
@ -45,6 +45,18 @@ class GoodsSkuRequest extends FormRequest
'sometimes',
'integer',
],
'arrived_today_num' => [
'sometimes',
'integer',
],
'yesterday_num' => [
'sometimes',
'integer',
],
'two_days_ago_num' => [
'sometimes',
'integer',
],
'inventory' => [
'sometimes',
'integer',

View File

@ -2,11 +2,14 @@
namespace App\Imports;
use App\Models\DailyStockRecord;
use App\Models\Goods;
use App\Models\GoodsBrand;
use App\Models\GoodsSku;
use App\Models\GoodsType;
use App\Utils\DateTimeUtils;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
@ -30,11 +33,11 @@ class GoodsSkusImport implements ToCollection, SkipsEmptyRows
unset($collection[0], $collection[1]);
$arr = $collection->toArray();
$validator = Validator::make($arr, [
'*.0' => ['required', 'string', 'max:255'],
'*.1' => ['required', 'string', 'max:255', 'exists:goods_types,name'],
'*.2' => ['string', 'max:255', 'exists:goods_brands,name'],
'*.3' => ['required', 'alpha_dash', 'max:32', 'unique:goods,goods_code'],
'*.4' => ['required', 'string', 'max:255'],
'*.0' => ['required', 'string', 'max:191'],
'*.1' => ['required', 'string', 'max:191', 'exists:goods_types,name'],
'*.2' => ['string', 'max:191', 'exists:goods_brands,name'],
'*.3' => ['required', 'alpha_dash', 'max:32'],
'*.4' => ['required', 'string', 'max:191'],
'*.5' => ['required', 'distinct', 'alpha_dash', 'max:32'],
'*.6' => ['required', 'string', Rule::in(['下架', '在售', '预警'])],
'*.7' => ['required', 'max:10'],
@ -76,16 +79,33 @@ class GoodsSkusImport implements ToCollection, SkipsEmptyRows
}
$skus[] = $sku;
}
if ($newGoods) {
$goods = new Goods();
$goods->batchInsert(array_values($newGoods));
$hasGoods = Goods::query()->whereIn('goods_code', array_column($newGoods, 'goods_code'))->get(['id', 'goods_code'])->toArray();
$hasGoods = ArrayUtils::index($hasGoods, 'goods_code');
foreach ($skus as &$sku) {
$sku['goods_id'] = isset($hasGoods[$sku['goods_id']]) ? $hasGoods[$sku['goods_id']]['id'] : $sku['goods_id'];
DB::beginTransaction();
try {
if ($newGoods) {
$goods = new Goods();
$goods->batchInsert(array_values($newGoods));
$hasGoods = Goods::query()->whereIn('goods_code', array_column($newGoods, 'goods_code'))->get(['id', 'goods_code'])->toArray();
$hasGoods = ArrayUtils::index($hasGoods, 'goods_code');
foreach ($skus as &$newGoodsSku) {
$newGoodsSku['goods_id'] = isset($hasGoods[$newGoodsSku['goods_id']]) ? $hasGoods[$newGoodsSku['goods_id']]['id'] : $newGoodsSku['goods_id'];
}
unset($newGoodsSku);
}
$goodsSku = new GoodsSku();
$goodsSku->batchInsert(array_values($skus));
$collection = GoodsSku::query()->whereIn('sku_code', array_column($skus, 'sku_code'))->get(['id', 'sku_code'])->toArray();
$newRecords = [];
foreach ($collection as $sku) {
$newRecords[] = [
'sku_id' => $sku['id'],
'day' => DateTimeUtils::getToday(),
];
}
$record = new DailyStockRecord();
$record->batchInsert($newRecords);
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
}
$goodsSku = new GoodsSku();
$goodsSku->batchInsert(array_values($skus));
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Jobs;
use App\Services\Business\BusinessFactory;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class BusinessGoodsSkuIncrQuantity implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $shop;
public $businessOrderItem;
public $num;
public $isIncremental = true;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($shop, $businessOrderItem, $num, $isIncremental)
{
$this->shop = $shop;
$this->businessOrderItem = $businessOrderItem;
$this->num = $num;
$this->isIncremental = $isIncremental;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
if ($this->businessOrderItem) {
BusinessFactory::init()->make($this->shop['plat_id'])->setShopWithId($this->shop['id'])->incrQuantity($this->businessOrderItem, $this->num, $this->isIncremental);
}
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Listeners;
use App\Models\Shop;
use Illuminate\Auth\Events\Registered;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class BindBusinessGoods
{
protected $shop;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(Shop $shop)
{
$this->shop = $shop;
}
/**
* Handle the event.
*
* @param Registered $event
* @return void
*/
public function handle(Registered $event)
{
//
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Listeners;
use App\Events\StockUpdateEvent;
use App\Jobs\BusinessGoodsSkuIncrQuantity;
use App\Models\BusinessGoodsSku;
use App\Models\Shop;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class StockUpdateListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param StockUpdateEvent $event
* @return void
*/
public function handle(StockUpdateEvent $event)
{
$shops = Shop::query()->where('status', 1)->get(['id', 'plat_id']);
if (empty($shops)) {
return;
}
foreach ($shops as $shop) {
if (isset($event->goodsSku)) {
$num = $event->goodsSku->stock;
$businessGoodsSku = BusinessGoodsSku::query()->where('shop_id', $shop->id)->where('external_sku_id', $event->goodsSku->goods->goods_code . '_' . $event->goodsSku->sku_code)->first();
BusinessGoodsSkuIncrQuantity::dispatch($shop, $businessGoodsSku, $num, false);
}
if (isset($event->goodsSkus)) {
foreach ($event->goodsSkus as $goodsSku) {
$num = $goodsSku->stock;
$businessGoodsSku = BusinessGoodsSku::query()->where('shop_id', $shop->id)->where('external_sku_id', $goodsSku->goods->goods_code . '_' . $goodsSku->sku_code)->first();
BusinessGoodsSkuIncrQuantity::dispatch($shop, $businessGoodsSku, $num, false);
}
}
}
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use App\Events\BusinessOrdersUpdate;
class StockWarning implements ShouldQueue
{
use InteractsWithQueue;
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
public function handle($event)
{
if (isset($event->goodsSku->stock) && 5 >= $event->goodsSku->stock) {
// 修改状态为预警,发送通知给管理员
$event->goodsSku->status = 2;
$event->goodsSku->save();
}
if (isset($event->goodsSkus)) {
$data = [];
foreach ($event->goodsSkus as $goodsSku) {
$data[] = [
'id' => $goodsSku->id,
'status' => 2
];
}
if ($data) {
$event->goodsSkus->update($data);
}
}
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace App\Listeners;
use App\Models\Log;
use App\Models\Shop;
use App\Services\Business\BusinessFactory;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use App\Events\BusinessOrdersUpdate;
use App\Jobs\BusinessGoodsSkuIncrQuantity;
class UpdateBusinessGoodsStock implements ShouldQueue
{
use InteractsWithQueue;
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param BusinessOrdersUpdate $event
* @return void
*/
public function handle(BusinessOrdersUpdate $event)
{
if (empty($event->goodsSku)) {
$log = new Log();
$log->module = 'goods';
$log->action = 'PATCH';
$log->target_type = 'goods_sku';
$log->target_id = $event->goodsSku->id;
$log->target_field = 'stock';
$log->user_id = $event->businessOrderItem->shop_id;
$log->message = ($event->businessOrderItem->external_sku_id ?: '商品') . '未找到';
$log->save();
return;
}
$shops = Shop::query()->where('id', '<>', $event->businessOrderItem->shop_id)->where('status', 1)->get(['id', 'plat_id']);
if (empty($shops)) {
return;
}
foreach ($shops as $shop) {
$num = $event->num;
$isIncremental = true;
if ('妙选' === $shop->plat_id) {
$num = $event->goodsSku->stock;
$isIncremental = false;
}
BusinessGoodsSkuIncrQuantity::dispatch($shop, $event->businessOrderItem, $num, $isIncremental);
}
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace App\Models;
class BusinessGoodsSku extends Model
{
/**
* @var mixed
*/
public $goods_id;
/**
* @var mixed
*/
public $sku_id;
/**
* @var mixed
*/
public $external_sku_id;
/**
* 不可批量赋值的属性。为空则所有熟悉都可以批量赋值
*
* @var array
*/
protected $fillable = [
'shop_id',
'business_order_id',
'already_cancel_number',
'cancel_status',
'category_name',
'external_sku_id',
'goods_amount',
'goods_cost_price',
'goods_id',
'goods_name',
'goods_number',
'goods_price',
'goods_purchase_price',
'goods_specification',
'help_sell_amount',
'is_supplier',
'need_verification_number',
'shipping_status',
'sku_id',
'sub_order_sn',
'theoretically_refund_amount',
'thumb_url',
'verification_number',
];
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Models;
class BusinessOrder extends Model
{
/**
* 不可批量赋值的属性。为空则所有熟悉都可以批量赋值
*
* @var array
*/
protected $fillable = [
'shop_id',
'receiver_address_detail',
'receiver_address_province',
'self_pick_site_no',
'discount_amount',
'theoretical_refund_amount',
'receiver_address_district',
'verification_status',
'inner_transaction_id',
'is_supplier',
'service_amount',
'supply_participate_no',
'updated_at',
'order_amount',
'receiver_address_city',
'receiver_name',
'business_note',
'buyer_memo',
'logistics_type',
'help_sell_nickname',
'activity_title',
'after_sales_status',
'mall_activity_type',
'transaction_id',
'activity_no',
'confirm_at',
'platform_discount_amount',
'participate_no',
'receiver_mobile',
'shipping_status',
'shipping_amount',
'cancel_status',
'nick_name',
'order_sn',
];
public function items()
{
return $this->hasMany(BusinessOrderItem::class, 'business_order_id');
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Models;
class BusinessOrderItem extends Model
{
/**
* @var mixed
*/
public $shop_id;
/**
* @var mixed
*/
public $external_sku_id;
/**
* 不可批量赋值的属性。为空则所有熟悉都可以批量赋值
*
* @var array
*/
protected $fillable = [
'shop_id',
'business_order_id',
'already_cancel_number',
'cancel_status',
'category_name',
'external_sku_id',
'goods_amount',
'goods_cost_price',
'goods_id',
'goods_name',
'goods_number',
'goods_price',
'goods_purchase_price',
'goods_specification',
'help_sell_amount',
'is_supplier',
'need_verification_number',
'shipping_status',
'sku_id',
'sub_order_sn',
'theoretically_refund_amount',
'thumb_url',
'verification_number',
];
public function order()
{
return $this->hasOne(BusinessOrder::class, 'id', 'business_order_id');
}
public function shop()
{
return $this->hasOne(Shop::class, 'id', 'shop_id');
}
}

View File

@ -4,5 +4,5 @@ namespace App\Models;
class DailyStockRecord extends Model
{
protected $hidden = ['created_at', 'updated_at'];
}

View File

@ -15,7 +15,22 @@ class Goods extends Model
'brand_id',
];
protected $guarded = [];
protected $fillable = [
'title',
'img_url',
'type_id',
'brand_id',
'goods_code',
];
public function getImgUrlAttribute($value)
{
if (false !== strpos($value, 'ju8hn6/erp/shop')) {
$value = config('filesystems.disks.aliyun.url') . $value;
}
return $value;
}
/**
* 多规格

View File

@ -19,7 +19,19 @@ class GoodsSku extends Model
*
* @var array
*/
protected $guarded = [];
protected $fillable = [
'goods_id',
'title',
'sku_code',
'status',
'num',
'stock',
'cost',
'two_days_ago_num',
'yesterday_num',
'reference_price',
'reserve',
];
protected $hidden = ['created_at'];
@ -54,4 +66,9 @@ class GoodsSku extends Model
{
return $this->hasOne(DailyStockRecord::class, 'sku_id', 'id');
}
public function order()
{
return $this->hasOne(BusinessOrderItem::class, 'external_sku_id', 'id');
}
}

View File

@ -17,7 +17,8 @@ class Log extends Model
'target_id',
'target_field',
'user_id',
'created_at',
'start_time',
'end_time',
];
public $fillable = [
@ -38,9 +39,11 @@ class Log extends Model
'permission' => '权限',
'role' => '角色',
'user' => '用户',
'plat' => '平台',
'file' => '文件',
];
return $map[$value];
return $map[$value] ?? $value;
}
public function getActionAttribute($value)
@ -52,7 +55,7 @@ class Log extends Model
'DELETE' => '删除',
];
return $map[$value];
return $map[$value] ?? $value;
}
public function getTargetTypeAttribute($value)
@ -65,9 +68,13 @@ class Log extends Model
'role' => '角色',
'menu' => '菜单',
'user' => '用户',
'upload' => '上传',
'kuaituantuan' => '快团团',
'miaoxuan' => '妙选',
'goods' => '商品',
];
return $map[$value];
return $map[$value] ?? $value;
}
public function getTargetFieldAttribute($value)
@ -80,9 +87,12 @@ class Log extends Model
'import' => '导入',
'export' => '导出',
'set' => '设置',
'cost' => '成本',
'stock' => '库存',
'inventory' => '库存盘点',
];
return $map[$value];
return $map[$value] ?? $value;
}
public function setUserIdAttribute($value)

View File

@ -8,7 +8,6 @@ class Shop extends Model
{
protected $hidden = [
'access_token',
'expires_at',
'expires_in',
'refresh_token',
'refresh_token_expires_at',
@ -16,6 +15,10 @@ class Shop extends Model
'pop_auth_token_create_response',
];
protected $fillable = [
'access_token', 'expires_at', 'expires_in', 'owner_id', 'owner_name', 'refresh_token', 'refresh_token_expires_at', 'refresh_token_expires_in', 'scope', 'pop_auth_token_create_response', 'status'
];
public function getStatusAttribute($value)
{
$map = [
@ -24,6 +27,9 @@ class Shop extends Model
2 => '无需授权',
3 => '停用',
];
if (1 === (int)$value && ($this->attributes['expires_at'] - time()) / 3600 <= 72) {
return '重新授权';
}
return $map[$value];
}

View File

@ -2,10 +2,13 @@
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
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\StockUpdateEvent;
use App\Listeners\StockUpdateListener;
class EventServiceProvider extends ServiceProvider
{
@ -15,8 +18,13 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
BusinessOrdersUpdate::class => [
UpdateBusinessGoodsStock::class,
StockWarning::class,
],
StockUpdateEvent::class => [
StockUpdateListener::class,
StockWarning::class,
],
];

View File

@ -0,0 +1,160 @@
<?php
namespace App\Services\Business;
use App\Events\BusinessOrdersUpdate;
use App\Models\BusinessGoodsSku;
use App\Models\BusinessOrder;
use App\Models\BusinessOrderItem;
use App\Models\GoodsSku;
use App\Models\Log;
use App\Models\Shop;
use GuzzleHttp\Client;
abstract class BusinessClient
{
protected $redirectUri = 'http://erp.chutang66.com/callback';
protected $code;
protected $shop;
protected $skuId = 0;
abstract public function auth();
abstract public function downloadGoodsListAndBind();
abstract public function downloadGoods($skuId);
abstract public function bindGoods($goods);
abstract public function incrQuantity($businessGoodsSku, $num, $incremental);
abstract public function downloadOrdersAndSave($beginTime, $endTime, $downloadType = 'default', $page = 1);
public function saveOrders($orders)
{
$shopId = $this->getShop()->id;
foreach ($orders as $order) {
unset($order['custom_item_list'], $order['logistics_list'], $order['gift_order_list']);
$order['shop_id'] = $shopId;
$orderRecord = BusinessOrder::firstOrNew(['shop_id' => $shopId, 'order_sn' => $order['order_sn']], $order);
if (empty($orderRecord->id)) {
$orderRecord->save();
} else {
$orderRecord->update($order);
}
foreach ($order['sub_order_list'] as $item) {
$item['shop_id'] = $shopId;
$orderItem = BusinessOrderItem::firstOrNew(['shop_id' => $shopId, 'business_order_id' => $orderRecord->id, 'goods_id' => $item['goods_id'], 'sku_id' => $item['sku_id']], $item);
$num = 0;
if (empty($orderItem->id)) {
if ($item['cancel_status']) {
if ($num = $item['goods_number'] - $item['already_cancel_number']) {
// 扣库存 $reduceNum
$num = 0 - $num;
}
} else {
// 扣库存
$num = 0 - $item['goods_number'];
}
$orderItem->save();
} else {
if ($item['cancel_status'] !== $orderItem->cancel_status) {
if ($item['cancel_status']) {
// 加库存
$num = $item['already_cancel_number'];
} else {
// 扣库存
$num = 0 - $item['goods_number'];
}
}
$orderItem->update($item);
}
// 增量更新库存
if ($num) {
event(new BusinessOrdersUpdate($orderItem, $num));
}
}
}
}
public function authCallback($code, $shopId)
{
$this->setCode($code);
$this->setShop($shopId);
$this->auth();
return $this;
}
public function setShopWithId($shopId)
{
$this->shop = Shop::query()->find($shopId);
return $this;
}
public function setShop(Shop $shop)
{
$this->shop = $shop;
return $this;
}
public function getShop()
{
return $this->shop;
}
public function setCode($code)
{
$this->code = $code;
return $this;
}
public function getCode()
{
return $this->code;
}
public function setSkuId($skuId)
{
$this->skuId = $skuId;
return $this;
}
public function getSkuId()
{
return $this->skuId;
}
public function formDataPostRequest($url, $params)
{
$method = 'POST';
$headers = [
'headers' => ['Content-type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
'form_params' => $params
];
$res = (new Client())->request($method, $url, $headers);
$size = $res->getBody()->getSize();
$res = json_decode($res->getBody()->getContents(), true);
if ('pdd.ktt.increment.order.query' === $params['type']) {
$log = Log::query()->where('user_id', $this->getShop()->id)->where('target_field', $params['type'])->first();
} else {
$log = new Log();
}
$log->module = 'plat';
$log->action = $method;
$log->target_type = $this->getShop()->plat_id;
$log->target_id = $this->getSkuId();
$log->target_field = $params['type'];
$log->user_id = $this->getShop()->id;
if ($size < 64000) {
$log->message = json_encode($res, 256);
}
$log->save();
return $res;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Services\Business;
use App\Services\Business\KuaiTuanTuan\KuaiTuanTuan;
use App\Services\Business\MiaoXuan\MiaoXuan;
class BusinessFactory
{
private $platList;
public function __construct()
{
$this->platList['快团团'] = KuaiTuanTuan::class;
$this->platList['妙选'] = MiaoXuan::class;
}
public function make($platName)
{
return new $this->platList[$platName];
}
public static function init()
{
return new self();
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Services\Business\KuaiTuanTuan;
use App\Models\BusinessGoodsSku;
class Goods
{
public static function downloadGoods($activityNo, $page = 1, $size = 100)
{
$type = 'pdd.ktt.goods.query.list';
$appendParams = [
// 'activity_no' => $activityNo, // 非必填,团号(团号和创建时间只能传一个)
'page' => $page,
'size' => $size,
// 'update_time_end' => '', // 非必填,结束最后更新时间(毫秒级时间戳)
// 'update_time_start' => '', // 非必填,起始最后更新时间(毫秒级时间戳)
// 'create_time_end' => '', // 非必填,开始时间结束(毫秒级时间戳)
// 'create_time_start' => '' // 非必填, 开始时间起始(毫秒级时间戳)
];
return [$type, $appendParams];
}
public static function bindGoods(array $goodsList, $shopId)
{
foreach ($goodsList as $businessGood) {
$skuList = $businessGood['sku_list'];
unset($businessGood['sku_list']);
$businessGood['goods_image_list'] = json_encode($businessGood['goods_image_list'], 256);
foreach ($skuList as $sku) {
$sku['spec_list'] = json_encode($sku['spec_list'], 256);
$data = array_merge($businessGood, $sku);
BusinessGoodsSku::updateOrCreate(
['shop_id' => $shopId, 'activity_no' => $businessGood['activity_no'], 'goods_id' => $businessGood['goods_id'], 'sku_id' => $sku['sku_id']],
$data
);
}
}
}
public static function downloadSingle($goodsId)
{
$type = 'pdd.ktt.goods.query.single';
$appendParams = [
'goods_id' => $goodsId,
'page' => 1,
'size' => 100,
];
return [$type, $appendParams];
}
public static function incrQuantity($goodsId, $skuId, $quantity, $modifyType = 2)
{
$type = 'pdd.ktt.goods.incr.quantity';
$appendParams = [
'goods_id' => $goodsId,
'quantity_delta' => $quantity,
'sku_id' => $skuId,
// 非必填
'modify_quantity_type' => $modifyType, // 修改库存的类型不传或1代表增量修改2代表全量修改
];
return [$type, $appendParams];
}
}

View File

@ -0,0 +1,144 @@
<?php
namespace App\Services\Business\KuaiTuanTuan;
use App\Models\BusinessGoodsSku;
use App\Models\GoodsSku;
use App\Services\Business\BusinessClient;
class KuaiTuanTuan extends BusinessClient
{
// 所有的请求和响应数据编码皆为utf-8格式url里的所有参数值请做urlencode编码。
// 如果请求的content-type是 application/x-www-form-urlencoded所有参数值也做urlencode编码
// 如果是multipart/form-data格式每个表单字段的参数值无需编码但每个表单字段的charset需要指定为utf-8
// 如果指定接口返回数据格式为JSON请指明header头content-type: application/json
protected $clientId = '8d7ca13bc27247b6a04e08404b51dfd8';
protected $clientSecret = '4478bc82dc1e1f68fe06c9f2bc683f1dcb3e6d83';
protected $publicParams = [
'type' => '',
'client_id' => '',
'access_token' => '', // 非必填,通过code获取的access_token
'timestamp' => '',
'data_type' => '', // 非必填,响应格式即返回数据的格式JSON或者XML二选一默认JSON注意是大写
'version' => '', // 非必填, API协议版本号默认为V1可不填
'sign' => ''
];
public function auth()
{
$accessToken = $this->getAccessTokenWithCode();
$accessToken['scope'] = json_encode($accessToken['scope'], 256);
$accessToken['pop_auth_token_create_response'] = json_encode($accessToken, 256);
$accessToken['status'] = 1;
$this->shop->update($accessToken);
return $this->shop;
}
public function downloadGoodsListAndBind($page = 1)
{
[$type, $appendParams] = Goods::downloadGoods($this->shop->owner_id, $page);
$res = $this->doRequest($type, $appendParams);
$goods = $res['ktt_goods_query_list_response']['goods_list'];
$this->bindGoods($goods);
$pageNum = ceil($res['ktt_goods_query_list_response']['total'] / $appendParams['size']);
if ($pageNum > $page && 10 >= $page) {
$this->downloadGoodsListAndBind($page + 1);
}
}
public function bindGoods($goods)
{
Goods::bindGoods($goods, $this->shop->id);
}
public function incrQuantity($businessGoodsSku, $num, $incremental)
{
[$type, $appendParams] = Goods::incrQuantity($businessGoodsSku->goods_id, $businessGoodsSku->sku_id, $num, $incremental ? 1 : 2);
$this->doRequest($type, $appendParams);
}
/**
* 下载没有发起售后,未取消的订单
*
* @param $beginTime
* @param $endTime
* @param int $page
* @param string $downloadType
* @return void
*/
public function downloadOrdersAndSave($beginTime, $endTime, $downloadType = 'default', $page = 1)
{
if ('increment' === $downloadType) {
[$type, $appendParams] = Order::downloadIncrementOrders($beginTime, $endTime, $page);
$responseName = 'ktt_increment_order_query_response';
} else {
[$type, $appendParams] = Order::downloadOrders($beginTime, $endTime, $page);
$responseName = 'ktt_order_list_response';
}
$res = $this->doRequest($type, $appendParams);
$this->saveOrders($res[$responseName]['order_list']);
$pageNum = ceil($res[$responseName]['total_count'] / $appendParams['page_size']);
if ($pageNum > $page && 10 >= $page) {
$this->downloadOrdersAndSave($beginTime, $endTime, $page + 1);
}
}
protected function getAccessTokenWithCode()
{
$type = 'pdd.pop.auth.token.create';
$res = $this->doRequest($type, ['code' => $this->code]);
return $res['pop_auth_token_create_response'];
}
protected function getSign($params)
{
ksort($params);
$str = '';
foreach ($params as $key => $val) {
$str .= $key . $val;
}
$str = $this->clientSecret . $str . $this->clientSecret;
return strtoupper(md5($str));
}
public function doRequest($type, $appendParams = [], $url = 'https://gw-api.pinduoduo.com/api/router')
{
$publicParams = [
'type' => $type,
'client_id' => $this->clientId,
'timestamp' => time()
];
if ('pdd.pop.auth.token.create' !== $type) {
$publicParams['access_token'] = $this->getShop()->access_token;
}
$publicParams = array_merge($publicParams, $appendParams);
$publicParams['sign'] = $this->getSign($publicParams);
return $this->formDataPostRequest($url, $publicParams);
}
public function downloadGoods($skuId)
{
$goodsSku = GoodsSku::query()
->with(['goods:id,goods_code'])
->find($skuId);
$code = $goodsSku->goods->goods_code . '_' . $goodsSku->sku_code;
$business = BusinessGoodsSku::query()->where('shop_id', $this->shop->id)->where('external_sku_id', $code)->first(['goods_id', 'sku_id']);
[$type, $appendParams] = Goods::downloadSingle($business->goods_id);
$res = $this->doRequest($type, $appendParams);
$goods = $res['response']['result'];
$this->bindGoods([$goods]);
}
public function getAuthUrl($shopId, $platId)
{
$state = $shopId . '_' . $platId;
return "https://oauth.pinduoduo.com/authorize/ktt?client_id={$this->clientId}&redirect_uri={$this->redirectUri}&state={$state}";
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Services\Business\KuaiTuanTuan;
class Order
{
/**
* 根据成交时间拉取订单列表
*/
public static function downloadOrders($beginTime, $endTime, $page = 1)
{
$type = 'pdd.ktt.order.list';
$appendParams = [
'confirm_at_begin' => $beginTime, // 成交启始时间, 必填,毫秒时间戳
'confirm_at_end' => $endTime, // 成交结束时间,必填, 毫秒时间戳,成交结束时间 - 成交启始时间 <= 24h
'page_number' => $page, // 页码, 必填
'page_size' => 100, // 数量, 必填, 1100
// 非必填
// 'activity_no' => $activityNo, // 团号
// 'after_sales_status' => 0, // 售后状态, 可选 0-未发起售后 1-退款中 2-退款成功 3-待处理 4-拒绝退款 6-待(顾客)退货 7-待(团长)确认退货 8-(顾客)撤销 9-(系统)关闭
// 'cancel_status' => 0, // 取消状态, 可选 0-未取消 1-已取消
// 'shipping_status' => '', // 发货状态 0-未发货 1-已发货 2-部分发货 3-已收货
// 'verification_status' => '', // 核销状态, 可选 0-未核销 1-已核销 2-部分核销
];
return [$type, $appendParams];
}
/**
* 快团团增量查订单
*/
public static function downloadIncrementOrders($beginTime, $endTime, $page = 1)
{
$type = 'pdd.ktt.increment.order.query';
$appendParams = [
'start_updated_at' => $beginTime, // 更新起始时间
'end_updated_at' => $endTime, // 更新结束时间
'page_number' => $page, // 页码
'page_size' => 100, // 数量
// 非必填
// 'activity_no' => $activityNo, // 团号
// 'after_sales_status' => 0, // 售后状态, 可选 0-未发起售后 1-退款中 2-退款成功 3-待处理 4-拒绝退款 6-待(顾客)退货 7-待(团长)确认退货 8-(顾客)撤销 9-(系统)关闭
// 'cancel_status' => 0, // 取消状态, 可选 0-未取消 1-已取消
// 'shipping_status' => '', // 发货状态 0-未发货 1-已发货 2-部分发货 3-已收货
// 'verification_status' => '', // 核销状态, 可选 0-未核销 1-已核销 2-部分核销
];
return [$type, $appendParams];
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Services\Business\MiaoXuan;
use App\Models\BusinessGoodsSku;
class Goods
{
public static function bindGoods(array $goods, $shopId)
{
foreach ($goods as $item) {
BusinessGoodsSku::updateOrCreate(
['shop_id' => $shopId, 'goods_id' => $item['goods_id'], 'sku_id' => $item['sku_id']],
$item
);
}
}
public static function incrQuantity($shopId, $quantity, BusinessGoodsSku $businessGoods)
{
return [
'data' => [
'stock' => $quantity,
'business_sku_id' => $businessGoods->sku_id,
'business_goods_id' => $businessGoods->goods_id,
'erp_shop_id' => $shopId,
'erp_sku_id' => $businessGoods->external_sku_id,
],
'type' => '更新库存',
];
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Services\Business\MiaoXuan;
use App\Models\BusinessGoodsSku;
use App\Services\Business\BusinessClient;
class MiaoXuan extends BusinessClient
{
public function auth()
{
// TODO: Implement auth() method.
}
public function downloadGoodsListAndBind()
{
}
public function bindGoods($goods)
{
Goods::bindGoods($goods, $this->shop->id);
}
public function incrQuantity($businessGoodsSku, $num, $incremental)
{
$appendParams = Goods::incrQuantity($this->shop->id, $num, $businessGoodsSku);
$url = 'http://shop.chutang66.com/miaoxuan/stock';
$this->formDataPostRequest($url, $appendParams);
}
public function downloadOrdersAndSave($beginTime, $endTime, $downloadType = 'default', $page = 1)
{
}
public function downloadGoods($skuId)
{
// TODO: Implement downloadGoods() method.
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace App\Services\Business\MiaoXuan;
class Order
{
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Utils;
class DateTimeUtils
{
/**
* 今天7点到明天7点算作今天
*/
public static function getToday()
{
$time = time();
$inventoryTime = strtotime(date('Y-m-d 07:00:00'));
if ($time < $inventoryTime) {
$time = strtotime('-1 day');
}
return date('Y-m-d', $time);
}
public static function getMicroTime($dateTime = null)
{
$time = microtime(true);
if ($dateTime && is_string($dateTime)) {
$time = strtotime($dateTime);
}
if ($dateTime && is_int($dateTime)) {
$time = $dateTime;
}
$time *= 1000;
return ceil($time);
}
}

View File

@ -33,18 +33,4 @@ class FormatUtils
}
return $data;
}
/**
* 今天7点到明天7点算作今天
*/
public static function date()
{
$time = time();
$inventoryTime = strtotime(date('Y-m-d 07:00:00'));
if ($time < $inventoryTime) {
$time = strtotime('-1 day');
}
return date('Y-m-d', $time);
}
}

0
artisan Executable file → Normal file
View File

View File

@ -9,7 +9,9 @@
"license": "MIT",
"require": {
"php": "^7.2.5|^8.0",
"ext-json": "*",
"aliyuncs/oss-sdk-php": "^2.5",
"beyondcode/laravel-websockets": "^1.13",
"fideloper/proxy": "^4.4",
"intervention/image": "^2.7",
"laravel/framework": "^6.20.26",

2734
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -67,7 +67,7 @@ return [
|
*/
'timezone' => 'UTC',
'timezone' => 'Asia/Shanghai',
/*
|--------------------------------------------------------------------------

View File

@ -52,8 +52,8 @@ return [
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
@ -71,7 +71,7 @@ return [
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'charset' => 'utf8mb4',
'prefix' => '',
'prefix_indexes' => true,
'schema' => 'public',
@ -86,7 +86,7 @@ return [
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'charset' => 'utf8mb4',
'prefix' => '',
'prefix_indexes' => true,
],

View File

@ -22,7 +22,7 @@ $factory->define(User::class, function (Faker $faker) {
'name' => 'erpAdmin',
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'password' => 'password', // password
'api_token' => Str::random(60),
'remember_token' => Str::random(10),
];

View File

@ -13,16 +13,19 @@ class CreateUsersTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->string('email')->nullable()->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('api_token', 80)->unique()->nullable(false);
$table->softDeletes();
$table->rememberToken();
$table->timestamps();
// 索引
$table->unique('name');
});
}

View File

@ -13,6 +13,7 @@ class CreateGoodsTypesTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('goods_types', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->nullable(false);

View File

@ -13,6 +13,7 @@ class CreateGoodsBrandsTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('goods_brands', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->nullable(false);

View File

@ -13,6 +13,7 @@ class CreateGoodsTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('goods', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title')->nullable(false);

View File

@ -13,6 +13,7 @@ class CreateGoodsSkusTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('goods_skus', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('goods_id')->nullable(false)->comment('商品id');
@ -28,6 +29,7 @@ class CreateGoodsSkusTable extends Migration
$table->unsignedInteger('reserve')->default(0)->comment('预留量');
$table->timestamps();
// 索引
$table->unique(['goods_id', 'sku_code']);
});
}

View File

@ -20,8 +20,9 @@ class CreateDailyStockRecordsTable extends Migration
$table->unsignedInteger('arrived_today_num')->default(0)->comment('今日到货');
$table->unsignedInteger('loss_num')->default(0)->comment('损耗');
$table->unsignedInteger('inventory')->default(0)->comment('库存盘点');
$table->unique('sku_id', 'day');
$table->timestamps();
// 索引
$table->unique(['sku_id', 'day']);
});
}

View File

@ -13,6 +13,7 @@ class CreateMenusTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('menus', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('code', 32)->nullable(false)->comment('菜单编码');

View File

@ -13,21 +13,22 @@ class CreateShopsTable extends Migration
*/
public function up()
{
Schema::defaultStringLength(191);
Schema::create('shops', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique();
$table->unsignedTinyInteger('plat_id')->comment('平台id');
$table->string('access_token')->nullable();
$table->unsignedMediumInteger('expires_at')->nullable()->comment('access_token过期时间点');
$table->unsignedBigInteger('expires_at')->nullable()->comment('access_token过期时间点');
$table->unsignedInteger('expires_in')->nullable()->comment('access_token过期时间段10表示10秒后过期');
$table->string('owner_id')->nullable()->comment('商家店铺id');
$table->string('owner_name')->nullable()->comment('商家账号名称');
$table->string('refresh_token')->nullable()->comment('refresh token可用来刷新access_token');
$table->unsignedMediumInteger('refresh_token_expires_at')->nullable()->comment('Refresh token过期时间点');
$table->unsignedBigInteger('refresh_token_expires_at')->nullable()->comment('Refresh token过期时间点');
$table->unsignedInteger('refresh_token_expires_in')->nullable()->comment('refresh_token过期时间段10表示10秒后过期');
$table->text('scope')->nullable()->comment('接口列表');
$table->text('pop_auth_token_create_response')->nullable()->comment('授权认证信息');
$table->string('status')->default(0)->comment('状态');
$table->unsignedTinyInteger('status')->default(0)->comment('状态');
$table->softDeletes();
$table->timestamps();
});

View File

@ -0,0 +1,56 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBusinessGoodsSkusTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('business_goods_skus', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('shop_id');
$table->bigInteger('self_sku_id')->nullable();
$table->string('activity_no')->nullable();
$table->string('category_name')->nullable();
$table->bigInteger('create_time')->nullable();
$table->text('goods_desc')->nullable();
$table->string('goods_id')->nullable();
$table->text('goods_image_list')->nullable();
$table->string('goods_name')->nullable();
$table->integer('is_activity_delete')->nullable();
$table->integer('limit_buy')->nullable();
$table->bigInteger('market_price')->nullable();
$table->bigInteger('update_time')->nullable();
$table->string('external_sku_id')->nullable();
$table->bigInteger('goods_purchase_price')->nullable();
$table->bigInteger('price_in_fen')->nullable();
$table->bigInteger('quantity')->nullable();
$table->integer('quantity_type')->nullable();
$table->bigInteger('reserve_quantity')->nullable();
$table->bigInteger('sku_id')->nullable();
$table->bigInteger('sold_quantity')->nullable();
$table->text('spec_list')->nullable();
$table->string('spec_name')->nullable();
$table->string('thumb_url')->nullable();
$table->bigInteger('total_quantity')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('business_goods');
}
}

View File

@ -0,0 +1,70 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBusinessOrdersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('business_orders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('shop_id');
$table->string('activity_no')->nullable();
$table->string('activity_title')->nullable();
$table->bigInteger('after_sales_status')->nullable();
$table->string('business_note')->nullable();
$table->string('buyer_memo')->nullable();
$table->integer('cancel_status')->nullable();
$table->bigInteger('confirm_at')->nullable();
$table->bigInteger('discount_amount')->nullable();
$table->string('help_sell_nickname')->nullable();
$table->string('inner_transaction_id')->nullable();
$table->boolean('is_supplier')->nullable();
$table->integer('logistics_type')->nullable();
$table->integer('mall_activity_type')->nullable();
$table->string('nick_name')->nullable();
$table->bigInteger('order_amount')->nullable();
$table->string('order_sn')->nullable();
$table->integer('participate_no')->nullable();
$table->bigInteger('platform_discount_amount')->nullable();
$table->string('receiver_address_city')->nullable();
$table->string('receiver_address_detail')->nullable();
$table->string('receiver_address_district')->nullable();
$table->string('receiver_address_province')->nullable();
$table->string('receiver_mobile')->nullable();
$table->string('receiver_name')->nullable();
$table->string('secret_remark')->nullable();
$table->string('self_pick_site_no')->nullable();
$table->string('self_pick_up_address')->nullable();
$table->string('self_pick_up_contact_mobile')->nullable();
$table->string('self_pick_up_contact_name')->nullable();
$table->string('self_pick_up_site_name')->nullable();
$table->bigInteger('service_amount')->nullable();
$table->bigInteger('shipping_amount')->nullable();
$table->integer('shipping_status')->nullable();
$table->string('supply_activity_no')->nullable();
$table->integer('supply_participate_no')->nullable();
$table->bigInteger('theoretical_refund_amount')->nullable();
$table->string('transaction_id')->nullable();
$table->integer('verification_status')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('business_orders');
}
}

View File

@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBusinessOrderItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('business_order_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('shop_id');
$table->bigInteger('business_order_id');
$table->integer('already_cancel_number')->nullable();
$table->integer('cancel_status')->nullable();
$table->string('category_name')->nullable();
$table->string('external_sku_id')->nullable();
$table->bigInteger('goods_amount')->nullable();
$table->bigInteger('goods_cost_price')->nullable();
$table->bigInteger('goods_id')->nullable();
$table->string('goods_name')->nullable();
$table->integer('goods_number')->nullable();
$table->bigInteger('goods_price')->nullable();
$table->bigInteger('goods_purchase_price')->nullable();
$table->string('goods_specification')->nullable();
$table->bigInteger('help_sell_amount')->nullable();
$table->boolean('is_supplier')->nullable();
$table->integer('need_verification_number')->nullable();
$table->integer('shipping_status')->nullable();
$table->bigInteger('sku_id')->nullable();
$table->string('sub_order_sn')->nullable();
$table->bigInteger('theoretically_refund_amount')->nullable();
$table->string('thumb_url')->nullable();
$table->integer('verification_number')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('business_order_items');
}
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('jobs');
}
}

View File

@ -27,7 +27,7 @@ class MenusTableSeeder extends Seeder
$id = DB::table('menus')->insertGetId(['parent_id' => 0,'code' => 'SYSTEM_MANAGE', 'name' => '系统管理', 'seq' => 3]);
DB::table('menus')->insert([
['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],
]);
// 系统日志
DB::table('menus')->insertGetId(['parent_id' => 0,'code' => 'SYSTEM_LOG', 'name' => '系统日志', 'seq' => 4]);

View File

@ -2,6 +2,7 @@
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Permission;
class PermissionsTableSeeder extends Seeder
{
@ -13,10 +14,9 @@ class PermissionsTableSeeder extends Seeder
public function run()
{
$routes = include(resource_path('lang/zh-CN/permission.php'));
$data = [];
foreach ($routes as $key => $route) {
$data[] = ['name' => $key, 'guard_name' => 'api'];
$data = ['id' => $route['id'], 'name' => $key, 'guard_name' => 'api'];
Permission::firstOrCreate($data);
}
DB::table('permissions')->insert($data);
}
}

View File

@ -12,7 +12,7 @@ class RolesTableSeeder extends Seeder
*/
public function run()
{
DB::table('roles')->insert([
DB::table('roles')->insertOrIgnore([
['name' => '超级管理员', 'guard_name' => 'api'],
]);
}

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)}}.el-upload--picture-card[data-v-140f5156]{width:50px;height:50px}.el-form-item[data-v-140f5156]{margin-left:60px}.addto[data-v-140f5156]{display:inline-block;width:30px;height:30px;background-color:#00f;color:#fff;font-size:25px;text-align:center;line-height:30px;border-radius:5px;margin-top:4px}.avatar-uploader .el-upload[data-v-140f5156]{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload[data-v-140f5156]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-140f5156]{font-size:28px;color:#8c939d;width:148px;height:148px;line-height:148px;text-align:center}.avatar[data-v-140f5156]{width:178px;height:178px;display:block}

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)}}a[data-v-7d43bb54]{text-decoration:none;color:#fff}.conent[data-v-7d43bb54]{width:100%;min-height:calc(100vh - 200px);position:relative}.btn[data-v-7d43bb54]{height:104px;border-radius:5px;display:flex;align-items:center}.btn .el-button[data-v-7d43bb54]{width:114px;height:44px;border-radius:3px}.table[data-v-7d43bb54]{margin-top:20px}.block[data-v-7d43bb54]{margin-top:30px}

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)}}.loss[data-v-7ad4e002]{position:relative}.table[data-v-7ad4e002]{margin-top:40px}.btn[data-v-7ad4e002]{float:right}[data-v-7ad4e002] .cell{display:flex;align-items:center}.commodityimg[data-v-7ad4e002]{width:59px;height:59px;background:hsla(0,0%,89%,.39);opacity:1;display:block;margin-right:12px}.confirmbtn[data-v-7ad4e002]{width:114px;height:44px;border-radius:3px;margin-top:21px;margin-bottom:8px}.import-right[data-v-7ad4e002]{margin-top:30px}.import-right a[data-v-7ad4e002]{text-decoration:none;color:#000}[data-v-7ad4e002] .btn11{padding:0;width:14px;height:14px}.page[data-v-7ad4e002]{margin-top:20px}

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>hello-world</title><link href="css/chunk-1c29c14c.5f516208.css" rel="prefetch"><link href="css/chunk-4a36a8d0.e437602b.css" rel="prefetch"><link href="css/chunk-59f3bcab.f15bb106.css" rel="prefetch"><link href="css/chunk-5ed10db2.12c276ba.css" rel="prefetch"><link href="css/chunk-61dfd850.94d448e7.css" rel="prefetch"><link href="css/chunk-62101cb8.67947a26.css" rel="prefetch"><link href="css/chunk-7136ffb6.9ae72c1b.css" rel="prefetch"><link href="css/chunk-75f0e99c.df77b785.css" rel="prefetch"><link href="css/chunk-8eb4b592.9e793ba8.css" rel="prefetch"><link href="css/chunk-959f9a24.ed76f224.css" rel="prefetch"><link href="css/chunk-add81472.d2951bcc.css" rel="prefetch"><link href="js/chunk-1c29c14c.9f96fb2f.js" rel="prefetch"><link href="js/chunk-2d23156c.0622f885.js" rel="prefetch"><link href="js/chunk-4a36a8d0.2590a0b3.js" rel="prefetch"><link href="js/chunk-59f3bcab.45013db3.js" rel="prefetch"><link href="js/chunk-5ed10db2.c024642d.js" rel="prefetch"><link href="js/chunk-61dfd850.062a0fb8.js" rel="prefetch"><link href="js/chunk-62101cb8.11abfa4f.js" rel="prefetch"><link href="js/chunk-7136ffb6.db45e982.js" rel="prefetch"><link href="js/chunk-75f0e99c.171e77ee.js" rel="prefetch"><link href="js/chunk-8eb4b592.3e5e4cc9.js" rel="prefetch"><link href="js/chunk-959f9a24.ebf2ab57.js" rel="prefetch"><link href="js/chunk-add81472.aed3eb4f.js" rel="prefetch"><link href="css/app.62fa08a2.css" rel="preload" as="style"><link href="css/chunk-vendors.a6a7f90c.css" rel="preload" as="style"><link href="js/app.b4b4e137.js" rel="preload" as="script"><link href="js/chunk-vendors.dc4080e5.js" rel="preload" as="script"><link href="css/chunk-vendors.a6a7f90c.css" rel="stylesheet"><link href="css/app.62fa08a2.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but hello-world doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.dc4080e5.js"></script><script src="js/app.b4b4e137.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>hello-world</title><link href="css/chunk-37d81871.8c2ae35d.css" rel="prefetch"><link href="css/chunk-4a36a8d0.e437602b.css" rel="prefetch"><link href="css/chunk-4d75363c.f04ac99e.css" rel="prefetch"><link href="css/chunk-59f3bcab.f15bb106.css" rel="prefetch"><link href="css/chunk-5ed10db2.12c276ba.css" rel="prefetch"><link href="css/chunk-61dfd850.94d448e7.css" rel="prefetch"><link href="css/chunk-62101cb8.67947a26.css" rel="prefetch"><link href="css/chunk-7136ffb6.9ae72c1b.css" rel="prefetch"><link href="css/chunk-744a6ffe.fec807f1.css" rel="prefetch"><link href="css/chunk-8eb4b592.9e793ba8.css" rel="prefetch"><link href="css/chunk-959f9a24.ed76f224.css" rel="prefetch"><link href="js/chunk-2d23156c.0622f885.js" rel="prefetch"><link href="js/chunk-37d81871.da518dd8.js" rel="prefetch"><link href="js/chunk-4a36a8d0.9136f98d.js" rel="prefetch"><link href="js/chunk-4d75363c.a68f2dc8.js" rel="prefetch"><link href="js/chunk-59f3bcab.45013db3.js" rel="prefetch"><link href="js/chunk-5ed10db2.c024642d.js" rel="prefetch"><link href="js/chunk-61dfd850.65d633aa.js" rel="prefetch"><link href="js/chunk-62101cb8.0d2ed3f5.js" rel="prefetch"><link href="js/chunk-7136ffb6.3fc0cbd6.js" rel="prefetch"><link href="js/chunk-744a6ffe.85ecc07f.js" rel="prefetch"><link href="js/chunk-8eb4b592.a7ab2ed3.js" rel="prefetch"><link href="js/chunk-959f9a24.49c53be2.js" rel="prefetch"><link href="css/app.62fa08a2.css" rel="preload" as="style"><link href="css/chunk-vendors.a6a7f90c.css" rel="preload" as="style"><link href="js/app.f221151c.js" rel="preload" as="script"><link href="js/chunk-vendors.dc4080e5.js" rel="preload" as="script"><link href="css/chunk-vendors.a6a7f90c.css" rel="stylesheet"><link href="css/app.62fa08a2.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but hello-world doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.dc4080e5.js"></script><script src="js/app.f221151c.js"></script></body></html>

2
public/dist/js/app.f221151c.js vendored Normal file

File diff suppressed because one or more lines are too long

1
public/dist/js/app.f221151c.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

View File

@ -0,0 +1,4 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-61dfd850"],{"0a5a":function(e,t,n){"use strict";n.d(t,"a",(function(){return i})),n.d(t,"b",(function(){return s}));const r="admin_token";function i(){return localStorage.getItem("token")}function s(){return localStorage.removeItem(r)}},"13cd":function(e,t,n){"use strict";n("28b1")},"1e4b":function(e,t,n){"use strict";n.r(t);var r=function(){var e=this,t=e._self._c;return t("div",[t("el-container",[t("el-container",[t("el-aside",{class:e.show?"width":"width1"},[t("el-menu",{attrs:{router:"","background-color":"#282c34","text-color":"#fff","default-active":e.$route.path}},e._l(e.menu,(function(n){return t("div",{key:n.id},[n.children?t("el-submenu",{attrs:{index:n.code}},[t("template",{slot:"title"},[t("span",[e._v(e._s(n.name))])]),e._l(n.children,(function(n){return t("el-menu-item",{key:n.id,attrs:{index:n.code}},[e._v(e._s(n.name))])}))],2):t("el-menu-item",{attrs:{index:n.code}},[t("span",[e._v(e._s(n.name))])])],1)})),0)],1),t("el-main",[t("div",{staticClass:"head"},[t("ul",[t("li",[t("div",{staticClass:"add",on:{click:e.add}},[e.show?t("i",{staticClass:"el-icon-s-unfold"}):t("i",{staticClass:"el-icon-s-fold"})]),t("div",{staticClass:"right"},[t("el-breadcrumb",{attrs:{"separator-class":"el-icon-arrow-right"}},e._l(e.titie,(function(n,r){return t("el-breadcrumb-item",{key:r},[e._v(e._s(n.name))])})),1)],1)]),t("li",[t("div",{staticClass:"token",on:{click:e.hanleLogout}},[e._v("退出")])])])]),t("div",{staticClass:"box-card"},[t("router-view")],1)])],1)],1)],1)},i=[],s=n("0a5a"),a=n("adb5");function o(){return Object(a["a"])({url:"/api/menus",method:"get"})}var u={mounted(){o().then(e=>{this.menu=e.data.data})},data(){return{menu:[],show:!1,levelData:[],titie:[],head:"",onindex:0,openeds:["1"]}},watch:{$route:{handler:function(e){this.titie=e.matched,this.head=e.name,this.levelData.push({name:e.name,path:e.path});const t=[],n={};for(var r=0;r<this.levelData.length;r++)n[this.levelData[r].name]||(t.push(this.levelData[r]),n[this.levelData[r].name]=!0);this.levelData=t},deep:!0,immediate:!0}},methods:{next(){this.hanletop()},hanletop(){document.getElementById("bottom").scrollIntoView({behavior:"smooth"})},hanlebottom(){document.getElementById("top").scrollIntoView({behavior:"smooth"})},hanleLogout(){Object(s["b"])(),this.$router.push({path:"/Login"})},handlerclick(e){this.$route.path!==e&&this.$router.push({path:e})},add(){this.show=!this.show},hanblDelete(e,t){var n=this.levelData[e].name;if(this.onindex=e,this.levelData.splice(this.onindex,1),t===this.head){var r,i;for(let e=0;e<this.levelData.length;e++)r=this.levelData[e].path,i=this.levelData[e].name;this.levelData.length&&i!==n&&this.$router.push({path:r})}}}},c=u,l=(n("13cd"),n("0b56")),d=Object(l["a"])(c,r,i,!1,null,"604626ee",null);t["default"]=d.exports},"28b1":function(e,t,n){},"38bc":function(e,t,n){var r,i;
/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
* @license MIT */(function(s,a){r=a,i="function"===typeof r?r.call(t,n,t,e):r,void 0===i||(e.exports=i)})(0,(function(){var e={version:"0.2.0"},t=e.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function n(e,t,n){return e<t?t:e>n?n:e}function r(e){return 100*(-1+e)}function i(e,n,i){var s;return s="translate3d"===t.positionUsing?{transform:"translate3d("+r(e)+"%,0,0)"}:"translate"===t.positionUsing?{transform:"translate("+r(e)+"%,0)"}:{"margin-left":r(e)+"%"},s.transition="all "+n+"ms "+i,s}e.configure=function(e){var n,r;for(n in e)r=e[n],void 0!==r&&e.hasOwnProperty(n)&&(t[n]=r);return this},e.status=null,e.set=function(r){var o=e.isStarted();r=n(r,t.minimum,1),e.status=1===r?null:r;var u=e.render(!o),c=u.querySelector(t.barSelector),l=t.speed,d=t.easing;return u.offsetWidth,s((function(n){""===t.positionUsing&&(t.positionUsing=e.getPositioningCSS()),a(c,i(r,l,d)),1===r?(a(u,{transition:"none",opacity:1}),u.offsetWidth,setTimeout((function(){a(u,{transition:"all "+l+"ms linear",opacity:0}),setTimeout((function(){e.remove(),n()}),l)}),l)):setTimeout(n,l)})),this},e.isStarted=function(){return"number"===typeof e.status},e.start=function(){e.status||e.set(0);var n=function(){setTimeout((function(){e.status&&(e.trickle(),n())}),t.trickleSpeed)};return t.trickle&&n(),this},e.done=function(t){return t||e.status?e.inc(.3+.5*Math.random()).set(1):this},e.inc=function(t){var r=e.status;return r?("number"!==typeof t&&(t=(1-r)*n(Math.random()*r,.1,.95)),r=n(r+t,0,.994),e.set(r)):e.start()},e.trickle=function(){return e.inc(Math.random()*t.trickleRate)},function(){var t=0,n=0;e.promise=function(r){return r&&"resolved"!==r.state()?(0===n&&e.start(),t++,n++,r.always((function(){n--,0===n?(t=0,e.done()):e.set((t-n)/t)})),this):this}}(),e.render=function(n){if(e.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var i=document.createElement("div");i.id="nprogress",i.innerHTML=t.template;var s,o=i.querySelector(t.barSelector),c=n?"-100":r(e.status||0),l=document.querySelector(t.parent);return a(o,{transition:"all 0 linear",transform:"translate3d("+c+"%,0,0)"}),t.showSpinner||(s=i.querySelector(t.spinnerSelector),s&&d(s)),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(i),i},e.remove=function(){c(document.documentElement,"nprogress-busy"),c(document.querySelector(t.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&d(e)},e.isRendered=function(){return!!document.getElementById("nprogress")},e.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),a=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;var r,i=e.length,s=t.charAt(0).toUpperCase()+t.slice(1);while(i--)if(r=e[i]+s,r in n)return r;return t}function i(e){return e=n(e),t[e]||(t[e]=r(e))}function s(e,t,n){t=i(t),e.style[t]=n}return function(e,t){var n,r,i=arguments;if(2==i.length)for(n in t)r=t[n],void 0!==r&&t.hasOwnProperty(n)&&s(e,n,r);else s(e,i[1],i[2])}}();function o(e,t){var n="string"==typeof e?e:l(e);return n.indexOf(" "+t+" ")>=0}function u(e,t){var n=l(e),r=n+t;o(n,t)||(e.className=r.substring(1))}function c(e,t){var n,r=l(e);o(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function l(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function d(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return e}))},"70e7":function(e,t,n){},adb5:function(e,t,n){"use strict";var r=n("4ff3"),i=n.n(r),s=n("0a5a"),a=n("38bc"),o=n.n(a),u=(n("70e7"),n("5422")),c=(n("a18c"),i.a.create({timeout:1e4}));c.interceptors.request.use(e=>(e.headers.Authorization="Bearer "+Object(s["a"])(),o.a.start(),e),e=>(console.log(e,"222222"),Promise.reject(e))),c.interceptors.response.use(e=>{o.a.done();const t=e.status;if(200===t||201===t)return e;Object(u["Message"])({message:"Error",type:"error"})},e=>(Object(u["Message"])({message:e,type:"error"}),console.log(e,"44444"),Promise.reject(e))),t["a"]=c}}]);
//# sourceMappingURL=chunk-61dfd850.65d633aa.js.map

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

@ -37,7 +37,7 @@ return [
'name' => '规格查看',
'parent_id' => 2,
],
'goods_skus.udpate' => [
'goods_skus.update' => [
'id' => 25,
'name' => '规格更新',
'parent_id' => 2,
@ -52,6 +52,11 @@ return [
'name' => '字段更新',
'parent_id' => 2,
],
'goods_sku.orders_num' => [
'id' => 28,
'name' => '店铺订单',
'parent_id' => 2,
],
'GOODS_TYPE' => [
'id' => 3,
'name' => '商品种类',
@ -143,33 +148,38 @@ return [
'name' => '删除',
'parent_id' => 5,
],
'business.goods_sku.download' => [
'id' => 55,
'name' => '商品下载',
'parent_id' => 5,
],
// 用户管理
'USER_MANAGE' => [
'id' => 6,
'name' => '用户管理',
'parent_id' => 0,
],
'user.index' => [
'users.index' => [
'id' => 60,
'name' => '列表',
'parent_id' => 6,
],
'user.store' => [
'users.store' => [
'id' => 61,
'name' => '新增',
'parent_id' => 6,
],
'user.show' => [
'users.show' => [
'id' => 62,
'name' => '查看',
'parent_id' => 6,
],
'user.update' => [
'users.update' => [
'id' => 63,
'name' => '更新',
'parent_id' => 6,
],
'user.destroy' => [
'users.destroy' => [
'id' => 64,
'name' => '删除',
'parent_id' => 6,
@ -185,41 +195,46 @@ return [
'name' => '角色管理',
'parent_id' => 7,
],
'role.index' => [
'roles.index' => [
'id' => 80,
'name' => '列表',
'parent_id' => 8,
],
'role.store' => [
'roles.store' => [
'id' => 81,
'name' => '新增',
'parent_id' => 8,
],
'role.show' => [
'roles.show' => [
'id' => 82,
'name' => '查看',
'parent_id' => 8,
],
'role.update' => [
'roles.update' => [
'id' => 83,
'name' => '更新',
'parent_id' => 8,
],
'role.permission' => [
'roles.permission' => [
'id' => 84,
'name' => '设置权限',
'parent_id' => 8,
],
'PERMISSION_MANAGE' => [
'id' => 9,
'name' => '权限管理',
'parent_id' => 7,
],
// 'PERMISSION_MANAGE' => [
// 'id' => 9,
// 'name' => '权限管理',
// 'parent_id' => 7,
// ],
'permissions.index' => [
'id' => 90,
'name' => '列表',
'parent_id' => 9,
],
'upload.file' => [
'id' => 11,
'name' => '文件上传',
'parent_id' => 7,
],
// 系统日志
'SYSTEM_LOG' => [
'id' => 10,

View File

@ -33,9 +33,11 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::patch('single/goods_skus/{id}', [GoodsSkusController::class, 'updateField'])->name('goods_sku.single_update');
// 店铺
Route::resource('shops', 'Shop\ShopsController', ['only' => ['index', 'store', 'show', 'update', 'destroy']]);
Route::get('count/orders/num', [ShopsController::class, 'countOrdersNumWithSkuCode'])->name('goods_sku.orders_num');
Route::get('download/{id}/goods', [ShopsController::class, 'downloadGoods'])->name('business.goods_sku.download');
// 角色
Route::resource('roles', 'Role\RolesController', ['only' => ['index', 'store', 'show', 'update']]);
Route::post('roles/{id}/permissions', [RolesController::class, 'addPermissions'])->name('role.permission');
Route::post('roles/{id}/permissions', [RolesController::class, 'addPermissions'])->name('roles.permission');
// 权限
Route::resource('permissions', 'Permission\PermissionsController', ['only' => ['index',
// 'store', 'show', 'update', 'destroy'
@ -49,4 +51,7 @@ Route::post('/auth/login', [LoginController::class, 'login'])->name('auth.login'
Route::resource('menus', 'Menu\MenusController', ['only' => ['index',
// 'store', 'show', 'update', 'destroy'
]])->middleware('auth:api');
Route::get('shop_platforms', [ShopsController::class, 'getPlatList'])->name('plat.list')->middleware('auth:api');
Route::post('business', [ShopsController::class, 'business'])->name('shop.put.business');

View File

@ -1,6 +1,8 @@
<?php
use App\Http\Controllers\Goods\GoodsSkusController;
use App\Http\Controllers\Goods\GoodsController;
use App\Http\Controllers\Shop\ShopsController;
/*
|--------------------------------------------------------------------------
@ -14,19 +16,11 @@ use App\Http\Controllers\Goods\GoodsSkusController;
*/
Route::get('/', function () {
return view('welcome');
header('Location: ' . url()->current() . "/dist");
});
Route::get('/home', function () {
return view('home');
})->name('home');
Route::get('/login', function () {
return view('welcome');
})->name('login');
Route::get('/register', function () {
return view('welcome');
})->name('register');
Route::get('goods_skus/export', [GoodsSkusController::class, 'export'])->name('goods_skus.export')->middleware('check.permissions');
Route::get('goods/import/template', [GoodsController::class, 'download'])->name('download.goods_import.template');
Route::get('callback', [ShopsController::class, 'authBind'])->name('shop.auth_bind.callback');