阶段更新

This commit is contained in:
2023-01-12 14:47:38 +08:00
parent 088dd64b2f
commit 5b8901281c
626 changed files with 39326 additions and 12 deletions

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\Mall\Models\Order;
class Audit extends RowAction
{
public $name = '通过审核';
public function handle(Order $order): Response
{
try {
$order->pay();
return $this->response()->success('审核通过')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Illuminate\Http\Request;
use Modules\Mall\Models\Express;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderExpress;
class Delivered extends RowAction
{
public $name = '商品发货';
public function handle(Order $order, Request $request): Response
{
if ($request->type == OrderExpress::TYPE_EXPRESS && (empty($request->express_id) || empty($request->express_no))) {
return $this->response()->error('缺少快递公司或快递单号');
}
$result = $order->deliver($request->express_id, $request->express_no, $request->type, $request->person);
if ($result === true) {
return $this->response()->success('发货成功')->refresh();
} else {
return $this->response()->error('失败');
}
}
public function form()
{
$order = Order::find($this->getKey());
$expresses = Express::query()->pluck('name', 'id');
$this->select('type', '方式')
->options([
OrderExpress::TYPE_LOGISTICS => '物流',
])
->required();
$this->select('express_id', '物流')
->options($expresses);
$this->text('express_no', '物流单号');
$this->text('person', '经办人');
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\Mall\Models\Order;
class Pay extends RowAction
{
public $name = '支付测试-正式版本移除';
public function handle(Order $order): Response
{
try {
$order->pay();
return $this->response()->success('支付状态调整成功')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Encore\Admin\Facades\Admin;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
class RefundAudit extends RowAction
{
public $name = '审核';
public function handle(Model $model, Request $request): Response
{
$admin = Admin::user();
$state = $request->state;
$remark = $request->remark;
$res = false;
if (!$model->can('agree')) {
return $this->response()->error('不可操作')->refresh();
}
if ($state == 'agree') {
$res = $model->setOperator($admin)->agree($remark);
}
if ($state == 'refuse') {
$res = $model->setOperator($admin)->refuse($remark);
}
if ($res === true) {
return $this->response()->success('操作成功')->refresh();
}
return $this->response()->error('操作失败')->refresh();
}
public function form(Model $model)
{
$this->select('state', '状态')
->options([
'agree' => '通过',
'refuse' => '驳回',
])
->required();
$this->text('remark', '说明')
->default($express->number ?? '')
->required();
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Encore\Admin\Facades\Admin;
use Modules\Mall\Models\Refund;
class RefundReturns extends RowAction
{
public $name = '退款';
public function handle(Refund $refund): Response
{
try {
$admin = Admin::user();
if (!$refund->can('completed')) {
return $this->response()->error('不可操作')->refresh();
}
$res = $refund->setOperator($admin)->returns();
if ($res === true) {
$refund->setOperator($admin)->complete();//设置完成
return $this->response()->success('操作成功')->refresh();
}
return $this->response()->error('操作失败')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function dialog()
{
$this->confirm('您确定要打款吗');
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Encore\Admin\Facades\Admin;
use Illuminate\Database\Eloquent\Model;
class RefundSign extends RowAction
{
public $name = '签收';
public function handle(Model $model): Response
{
try {
$admin = Admin::user();
if (!$model->can('sign')) {
return $this->response()->error('不可操作')->refresh();
}
$res = $model->setOperator($admin)->receive();
if ($res === true) {
return $this->response()->success('操作成功')->refresh();
}
return $this->response()->error('操作失败')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function dialog()
{
$this->confirm('您确定已经收到货了吗');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\Mall\Models\Shop;
class Close extends RowAction
{
public $name = '关闭店铺';
public function handle(Shop $shop): Response
{
try {
if ($shop->close()) {
return $this->response()->success('店铺关闭成功')->refresh();
} else {
return $this->response()->error('店铺关闭失败')->refresh();
}
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function dialog()
{
$this->confirm('确定关闭店铺吗?');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\Mall\Models\Shop;
class Open extends RowAction
{
public $name = '开启店铺';
public function handle(Shop $shop): Response
{
try {
if ($shop->open()) {
return $this->response()->success('店铺开启成功')->refresh();
} else {
return $this->response()->error('店铺开启失败')->refresh();
}
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function dialog()
{
$this->confirm('确定开启店铺吗?');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\Mall\Models\Shop;
class Pass extends RowAction
{
public $name = '审核通过';
public function handle(Shop $shop): Response
{
try {
if ($shop->pass()) {
return $this->response()->success('审核通过成功')->refresh();
} else {
return $this->response()->error('审核通过失败')->refresh();
}
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function dialog()
{
$this->confirm('确定审核通过?');
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Illuminate\Http\Request;
use Modules\Mall\Models\Shop;
class Reject extends RowAction
{
public $name = '驳回申请';
public function handle(Shop $shop, Request $request): Response
{
try {
if ($shop->reject($request->reject_reason)) {
return $this->response()->success('驳回申请成功')->refresh();
} else {
return $this->response()->error('驳回申请失败')->refresh();
}
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function form()
{
$this->textarea('reject_reason', '驳回原因')->rules('required');
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\Mall\Models\Activity;
class ActivityController extends AdminController
{
use WithUploads;
public $title = "活动列表";
protected function grid(): Grid
{
$grid = new Grid(new Activity());
$grid->disableFilter();
$grid->column('id', '#ID#');
$grid->column('title', '活动名称');
$grid->column('description', '简介');
$grid->column('status', '状态')->switch();
$grid->column('created_at', '创建时间');
return $grid;
}
protected function form(): Form
{
$form = new Form(new Activity());
$form->text('title', '活动名称');
$this->cover($form);
$form->textarea('description', '简介');
$form->ueditor('content', '详情')->required();
$form->switch('status', '状态')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Linker\Traits\WithLinker;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Banner;
use Modules\Mall\Models\Region;
use Modules\User\Models\User;
class AddressController extends AdminController
{
use WithUploads,
WithLinker;
public $title = "收货地址";
protected function grid(): Grid
{
$grid = new Grid(new Address());
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('user_id', '所属用户')->select()->ajax(route('admin.user.users.ajax'));
});
});
$grid->model()->with(['user']);
$grid->column('id', '#ID#');
$grid->column('user.username', '所属用户');
$grid->column('name', '姓名');
$grid->column('mobile', '手机号');
$grid->column('province.name', '省');
$grid->column('city.name', '市');
$grid->column('district.name', '区');
$grid->column('address', '详细地址');
$grid->column('is_default', '默认?')->bool();
$grid->column('created_at', '创建时间');
return $grid;
}
protected function form(): Form
{
$form = new Form(new Address);
$form->select('user_id', '所属用户')
->options(function ($userId) {
$user = User::find($userId);
if ($user) {
return [$user->id => $user->username.' ['.$user->info->nickname.']'];
}
})
->value(request()->user_id ?? '')
->ajax(route('admin.user.users.ajax'))
->required();
$form->text('name', '姓名');
$form->text('mobile', '手机号');
$form->select('province_id', '省份')
->options(Region::where('parent_id', 1)->pluck('name', 'id'))
->load('city_id', route('admin.mall.regions.region'))
->required();
$form->select('city_id', '城市')
->options(function ($option) {
$parent = Region::where('id', $option)->value('parent_id');
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
})
->load('district_id', route('admin.mall.regions.region'))
->required();
$form->select('district_id', '区/县')
->options(function ($option) {
$parent = Region::where('id', $option)->value('parent_id');
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
})
->required();
$form->text('address', '详细地址')
->required();
$form->switch('is_default', '默认?')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Modules\Mall\Models\Activity;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSku;
class AjaxController
{
/**
* Notes: 获取用户收货地址
*
* @Author: 玄尘
* @Date: 2022/7/29 13:33
* @param Request $request
* @return mixed
*/
public function address(Request $request)
{
$user_id = $request->get('q');
return Address::ByUserId($user_id)
->oldest('is_default')
->get()
->map(function ($address) {
return [
'id' => $address->id,
'text' => $address->getFullAddress(),
];
});
}
/**
* Notes: 获取商品
*
* @Author: 玄尘
* @Date: 2022/7/29 13:46
* @param Request $request
*/
public function goods(Request $request)
{
$address_id = $request->q;
if (!$address_id){
return [];
}
$address = Address::find($address_id);
return GoodsSku::query()
->whereHas('goods', function ($q) {
$q->where('channel', Goods::CHANNEL_FREE)->where('status', Goods::STATUS_UP);
})
->get()
->map(function ($sku) use ($address) {
$stockData = $address->user->getStockData();
return [
'id' => $sku->id,
'text' => $sku->goods->name."(库存:{$stockData['residue']})",
];
});
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\Linker\Traits\WithLinker;
use Modules\Mall\Models\Banner;
class BannerController extends AdminController
{
use WithUploads,
WithShop,
WithLinker;
public $title = "轮播图管理";
protected function grid(): Grid
{
$grid = new Grid(new Banner);
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('title', '轮播标题');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('status', '状态')->radio([
0 => '禁用',
1 => '正常',
]);
});
});
$grid->model()->with(['shop']);
$grid->column('id', '#ID#');
$grid->column('shop.name', '所属店铺');
$grid->column('cover', '封面图片')->image('', 100, 100);
$grid->column('展示位置')->display(function () {
$data = [];
foreach ($this->position as $position) {
$data[] = $this->position_map[$position];
}
return $data;
})->label();
$grid->column('title', '轮播标题');
$grid->column('status', '状态')->bool();
$grid->column('created_at', '创建时间');
return $grid;
}
protected function form(): Form
{
$form = new Form((new Banner)->disableModelCaching());
$this->shop($form)->help('不选择,默认为平台轮播');
$form->text('title', '标题')
->required();
$form->multipleSelect('position', '展示位置')
->options($form->model()->position_map)
->required();
$this->cover($form);
$this->withUrl($form);
$form->switch('status', '显示')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Modules\Mall\Models\Brand;
class BrandController extends AdminController
{
use WithUploads,
WithShop;
protected $title = '品牌管理';
public function grid(): Grid
{
$grid = new Grid(new Brand());
$grid->model()->with(['shop']);
$grid->column('cover', 'LOGO')->image('', 80);
$grid->column('shop.name', '所属店铺');
$grid->column('name', '品牌名称');
$grid->column('status', '状态')->bool();
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Brand());
$this->shop($form)->required();
$form->text('name', '品牌名称')
->required();
$this->cover($form);
$form->textarea('description', '品牌简介');
$form->switch('status', '状态')->default(1);
return $form;
}
public function ajax(Request $request)
{
$key = $request->q;
return Brand::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Modules\Mall\Models\Category;
class CategoryController extends AdminController
{
use WithShop,
WithUploads;
protected $title = "分类管理";
protected function grid(): Grid
{
$grid = new Grid(new Category());
$parentId = request()->get('parent_id');
$grid->model()
->with(['shop'])
->withCount('goods')
->when($parentId, function ($query) use ($parentId) {
$query->where('parent_id', $parentId);
});
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('trashed', '回收站')->onlyTrashed();
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '分类名称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('slug', '分类简称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('status', '状态')->select([
0 => '禁用',
1 => '正常',
]);
});
});
$grid->column('shop.name', '所属店铺');
$grid->column('parent.name', '上级分类')
->link(function () {
return route('admin.mall.categories.index', ['parent_id' => $this->parent_id]);
}, '_self');;
$grid->column('name', '分类名称')
->link(function () {
return route('admin.mall.categories.index', ['parent_id' => $this->id]);
}, '_self');
$grid->column('slug', '分类简称');
$grid->column('goods_count', '分类商品');
$grid->column('order', '排序');
$grid->column('status', '状态')->bool();
return $grid;
}
/**
* Notes : 编辑表单
* @Date : 2021/4/25 1:41 下午
* @Author : < Jason.C >
* @return \Encore\Admin\Form
*/
protected function form(): Form
{
$form = new Form(new Category);
$this->shop($form)->required();
$form->select('parent_id', '上级分类')
->options(Category::selectOptions(function ($model) {
return $model->where('status', 1);
}, '一级分类'))
->required();
$form->text('name', '分类名称')
->required()
->rules('required');
$form->text('slug', '分类简称');
$form->textarea('description', '分类简介');
$this->cover($form, 'cover', '分类图片');
$form->number('order', '排序')->default(0);
$form->switch('status', '显示')->default(1);
return $form;
}
public function ajax(Request $request)
{
$key = $request->q;
return Category::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Layout\Column;
use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row;
use Encore\Admin\Widgets\InfoBox;
use Illuminate\Routing\Controller;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\Refund;
use Modules\Mall\Models\Shop;
class DashboardController extends Controller
{
public function index(Content $content): Content
{
return $content
->header('商城看板')
->description('商城数据概览')
->row(function (Row $row) {
$row->column(3, function (Column $column) {
$column->append(new InfoBox('店铺数量',
'anchor',
'blue',
route('admin.mall.shops.index'),
Shop::count()
)
);
});
$row->column(3, function (Column $column) {
$column->append(new InfoBox('商品数量',
'anchor',
'blue',
route('admin.mall.goods.index'),
Goods::count()
)
);
});
$row->column(3, function (Column $column) {
$column->append(new InfoBox('订单总数',
'anchor',
'blue',
route('admin.mall.orders.index'),
Order::count()
)
);
});
$row->column(3, function (Column $column) {
$column->append(new InfoBox('退款订单',
'anchor',
'blue',
route('admin.mall.refunds.index'),
Refund::count()
)
);
});
});
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Modules\Mall\Models\Delivery;
class DeliveryController extends AdminController
{
use WithShop;
protected $title = '运费模板';
public function grid(): Grid
{
$grid = new Grid(new Delivery());
$grid->model()
->with(['shop'])
->withCount('rules');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('trashed', '回收站')->onlyTrashed();
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('shop.name', '所属店铺');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '模板名称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('name', '计费方式')->select(Delivery::TYPE_MAP);
});
});
$grid->column('shop.name', '所属店铺');
$grid->column('name', '模板名称');
$grid->column('type', '计费方式')->using(Delivery::TYPE_MAP);
$grid->column('rules_count', '模板规则')->link(function () {
return route('admin.mall.deliveries.rules.index', $this);
}, '_self');
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Delivery());
$this->shop($form)->required();
$form->text('name', '模板名称')->required();
$form->radioButton('type', '计费方式')
->options(Delivery::TYPE_MAP)
->default(Delivery::TYPE_BY_COUNT)
->required();
return $form;
}
/**
* Notes : 选择运费模板
* @Date : 2021/5/11 11:36 上午
* @Author : < Jason.C >
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function ajax(Request $request)
{
$key = $request->get('q');
return Delivery::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Modules\Mall\Models\Delivery;
use Modules\Mall\Models\DeliveryRule;
use Modules\Mall\Models\Region;
class DeliveryRuleController extends AdminController
{
protected $title = '模板规则';
public function index(Content $content): Content
{
$delivery = Delivery::find(request()->delivery);
return $content
->header($delivery->name)
->description('模板规则')
->body($this->grid($delivery));
}
public function grid($delivery): Grid
{
$grid = new Grid(new DeliveryRule());
$grid->model()->where('delivery_id', $delivery->id);
if ($delivery->type === Delivery::TYPE_BY_COUNT) {
$firstTitle = '首件(个)';
$additionalTitle = '续件';
} else {
$firstTitle = '首重(Kg)';
$additionalTitle = '续重';
}
$grid->column('regions', '配送区域')
->display(function () {
return Region::find($this->regions);
})
->pluck('name')
->label();
$grid->column('first', $firstTitle);
$grid->column('first_fee', '运费(元)');
$grid->column('additional', $additionalTitle);
$grid->column('additional_fee', '续费(元)');
return $grid;
}
public function edit($id, Content $content): Content
{
return $content
->title($this->title())
->description($this->description['edit'] ?? trans('admin.edit'))
->body($this->form()->edit(request()->rule));
}
public function update($id)
{
return $this->form()->update(request()->rule);
}
public function form(): Form
{
$delivery = Delivery::find(request()->delivery);
if ($delivery->type === Delivery::TYPE_BY_COUNT) {
$firstTitle = '首件(个)';
$additionalTitle = '续件';
} else {
$firstTitle = '首重(Kg)';
$additionalTitle = '续重';
}
$form = new Form(new DeliveryRule());
$form->multipleSelect('regions', '配送区域')
->options(function ($regions) {
if ($regions) {
return Region::find($regions)->pluck('name', 'id');
}
})
->ajax(route('admin.mall.regions.ajax'));
$form->text('first', $firstTitle)
->required();
$form->currency('first_fee')
->symbol('¥')
->required();
$form->text('additional', $additionalTitle)
->required();
$form->currency('additional_fee')
->required()
->symbol('¥');
$form->hidden('delivery_id')->value($delivery->id);
return $form;
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\Mall\Models\Express;
class ExpressController extends AdminController
{
use WithUploads;
protected $title = '物流管理';
protected function grid(): Grid
{
$grid = new Grid(new Express());
$grid->model()->withCount('shops');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('trashed', '回收站')->onlyTrashed();
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '物流名称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('slug', '物流简称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('status', '状态')->select([
0 => '禁用',
1 => '正常',
]);
});
});
$grid->column('id');
$grid->column('cover', 'LOGO')->image('', 60);
$grid->column('name', '物流名称');
$grid->column('slug', '物流简称');
$grid->column('description', '物流简介');
$grid->column('status', '状态')->bool();
// $grid->column('shops_count', '使用商户');
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Express());
$form->text('name', '物流名称')
->required();
$form->text('slug', '物流简称')
->required();
$form->textarea('description', '物流简介');
$this->cover($form);
$form->switch('status', '状态')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,228 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Support\Arr;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Str;
use Modules\Mall\Models\Brand;
use Modules\Mall\Models\Category;
use Modules\Mall\Models\Delivery;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\Shop;
use Modules\Mall\Models\Tag;
class GoodsController extends AdminController
{
use WithUploads,
WithShop;
protected $title = '商品管理';
protected function grid(): Grid
{
$grid = new Grid(new Goods);
$grid->quickSearch('id')->placeholder('商品编号快速搜索');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('trashed', '回收站')->onlyTrashed();
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '商品名称');
$filter->equal('channel', '类型')->select(Goods::Channels);
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('shop_id', '所属店铺')->select(function ($shopId) {
if ($shopId) {
return Shop::where('id', $shopId)->pluck('name', 'id');
}
})->ajax(route('admin.mall.shops.ajax'));
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('category_id', '分类')->select(Category::shown()->pluck('name', 'id'));
});
});
$grid->model()
->with(['category', 'shop', 'delivery'])
->withCount(['specs', 'skus'])
->orderByDesc('updated_at');
$grid->column('id', '#ID#');
$grid->column('brand.name', '品牌名称');
$grid->column('category.name', '商品分类');
// $grid->column('tags', '标签')
// ->pluck('name')
// ->label();
$grid->column('shop.name', '所属店铺');
$grid->column('name', '商品名称');
$grid->column('type', '规格类型')->using(Goods::TYPE_MAP);
$grid->column('sales', '销量');
$grid->column('original_price', '原价');
$grid->column('channel', '类型')->using(Goods::Channels)->label();
$grid->column('规格属性')
->display(function () {
if ($this->type === Goods::TYPE_MULTIPLE) {
return $this->specs_count;
}
})
->link(function () {
return route('admin.mall.goods.specs.index', $this);
}, '_self');
$grid->column('价格条目')
->display(function () {
return $this->skus_count;
})
->link(function () {
return route('admin.mall.goods.skus.index', $this);
}, '_self');
$grid->column('delivery.name', '运费模板');
$grid->column('status', '状态')->switch([
'on' => ['value' => 1, 'text' => '上架', 'color' => 'primary'],
'off' => ['value' => 3, 'text' => '下架', 'color' => 'default'],
]);
// $grid->column('status', '状态')->display(function () {
// return $this->status_text;
// });
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Goods());
$form->text('name', '商品名称')->required();
$form->textarea('description', '商品简介')->required();
$this->shop($form)->required();
$form->select('category_id', '商品分类')
->options(function ($categoryId) {
$category = Category::find($categoryId);
if ($category) {
return [$category->id => $category->name];
}
})
->ajax(route('admin.mall.categories.ajax'))
->required();
$form->select('brand_id', '所属品牌')
->options(function ($brandId) {
$brand = Brand::find($brandId);
if ($brand) {
return [$brand->id => $brand->name];
}
})
->ajax(route('admin.mall.brands.ajax'))
->required();
// $form->multipleSelect('tags', '商品标签')
// ->options(function ($tagIds) {
// if ($tagIds) {
// return Tag::find($tagIds)->pluck('name', 'id');
// }
// })
// ->ajax(route('admin.mall.tags.ajax'));
$this->cover($form);
$this->pictures($form);
$states = [
'on' => ['value' => 1, 'text' => '是', 'color' => 'success'],
'off' => ['value' => 0, 'text' => '否', 'color' => 'danger'],
];
$form->switch('is_post_sale', '是否允许售后')->states($states)->default(1);
$form->radioButton('deduct_stock_type', '库存扣减')
->default(1)
->options(Goods::DEDUCT_STOCK_MAP)
->required();
$form->radioButton('pay_type', '支付方式')
->default(1)
->options(Goods::PAY_TYPE_MAP)
->required();
$form->select('delivery_id', '运费模板')
->options(function ($deliveryId) {
$delivery = Delivery::find($deliveryId);
if ($delivery) {
return [$delivery->id => $delivery->name];
}
})
->ajax(route('admin.mall.deliveries.ajax'))
->required();
$form->currency('original_price', '展示原价')
->default(0)
->help('仅作展示使用');
$form->radioButton('channel', '商品类型')
->options(Goods::Channels)
->required();
$form->radioButton('type', '规格类型')
->options(Goods::TYPE_MAP)
->default(Goods::CHANNEL_NORMAL)
->required()
->when(Goods::TYPE_SINGLE, function (Form $form) {
$form->hasMany('skus', '单规格', function (Form\NestedForm $form) {
$form->currency('price', '销售价格')
->default(0)
->required();
$form->hidden('score', '积分')
->default(0)
->required();
$form->hidden('assets', '资产')
->default(0)
->required();
$form->number('stock', '商品库存')
->default(0)
->required();
$form->text('weight', '商品重量')
->default(0)
->setWidth(2)
->required();
});
})
->when(Goods::TYPE_MULTIPLE, function ($form) {
})
->default(function () use ($form) {
return $form->isCreating() ? Goods::TYPE_SINGLE : '';
});
$form->ueditor('content', '商品详情')->required();
$form->switch('status', '状态')
->states([
'on' => ['value' => 1, 'text' => '上架', 'color' => 'success'],
'off' => ['value' => 3, 'text' => '下架', 'color' => 'danger'],
])
->default(1);
$form->ignore(['single']);
$form->saving(function (Form $form) {
if ($form->type === Goods::TYPE_SINGLE) {
$form->skus = [Arr::first($form->skus)];
}
if ($form->channel == Goods::CHANNEL_FREE && $form->isCreating()) {
$hasOne = Goods::where('channel', Goods::CHANNEL_FREE)->exists();
if ($hasOne) {
$error = new MessageBag([
'title' => '错误',
'message' => '免费产品只有一个',
]);
return back()->withInput()->with(compact('error'));
}
}
$form->content = Str::of(request()->get('content'))->replace('style=""', '');
});
return $form;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\Mall\Models\Job;
class JobController extends AdminController
{
use WithShop;
protected $title = '职位管理';
public function grid(): Grid
{
$grid = new Grid(new Job());
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('shop.name', '所属店铺');
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('name', '职位名称');
});
});
$grid->column('shop.name', '所属店铺');
$grid->column('name', '职位名称');
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Job());
$this->shop($form)->required();
$form->text('name', '职位名称')->required();
return $form;
}
}

View File

@@ -0,0 +1,277 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Support\MessageBag;
use Modules\Mall\Facades\Item;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Audit;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Delivered;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Pay;
use Modules\Mall\Http\Exporter\OrderExporter;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Express;
use Modules\Mall\Models\GoodsSku;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\Shop;
use Modules\User\Models\User;
use Modules\Mall\Facades\Order as OrderFacade;
class OrderController extends AdminController
{
protected $title = '订单管理';
/**
* Index interface.
*
* @param Content $content
* @return Content
*/
public function index(Content $content)
{
return $content->header('订单列表')->body($this->grid());
}
/**
* 已支付
*
* @param Content $content [description]
* @return Content [type] [description]
* @author 玄尘 2020-03-03
*/
public function paid(Content $content)
{
return $content->header('待发货')->body($this->grid(Order::STATUS_PAID));
}
/**
* 已发货
*
* @param Content $content [description]
* @return \Encore\Admin\Layout\Content [type] [description]
* @author 玄尘 2020-03-03
*/
public function delivered(Content $content)
{
return $content->header('已发货')->body($this->grid(Order::STATUS_DELIVERED));
}
protected function grid($state = ''): Grid
{
$grid = new Grid(new Order());
$grid->model()
->when($state, function ($q) use ($state) {
$q->where('state', $state);
})
->whereIn('type', [Order::TYPE_NORMAL, Order::TYPE_SCORE])
->with(['shop', 'items', 'user'])
->withCount('versions');
$grid->disableExport(false);
$grid->exporter(new OrderExporter);
$grid->disableCreateButton();
$grid->quickSearch('order_no')->placeholder('搜索订单编号');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('unPay', '未付款')->unPay();
$filter->scope('paid', '待发货')->paid();
$filter->scope('delivered', '已发货')->delivered();
$filter->scope('signed', '已签收')->signed();
$filter->scope('completed', '已完成')->completed();
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('order_no', '订单编号');
$filter->equal('shop_id', '所属店铺')->select(Shop::pluck('name', 'id'));
$filter->equal('user_id', '下单用户')->select()->ajax(route('admin.user.users.ajax'));
$filter->equal('type', '订单类型')->select(Order::TYPE_MAP);
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->between('created_at', '下单时间')->datetime();
$filter->between('paid_at', '付款时间')->datetime();
$filter->between('expired_at', '过期时间')->datetime();
});
});
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableDelete();
$actions->disableView();
if ($actions->row->can('pay') && $this->row->type == Order::TYPE_NORMAL) {
$actions->add(new Pay());
}
if ($actions->row->can('deliver')) {
$actions->add(new Delivered);
}
});
$grid->model()->with(['shop', 'user.info']);
$grid->column('order_no', '订单编号')->display(function () {
return sprintf('<a href="%s">%s</a>', route('admin.mall.orders.show', $this), $this->order_no);
});
$grid->column('user.username', '下单用户')
->display(function () {
return $this->user->username."({$this->user->info->nickname})";
});
if ($state == Order::STATUS_PAID) {
$grid->column('收货地址')
->display(function () {
return $this->express ? $this->express->getAllAddress() : '';
});
} else {
$grid->column('type', '订单类型')->using(Order::TYPE_MAP)->label();
$grid->column('expired_at', '过期时间')->sortable();
}
$grid->column('amount', '商品金额');
$grid->column('freight', '运费');
$grid->column('qty', '发货数量')
->display(function () {
return $this->items()->sum('qty');
});
$grid->column('订单金额')->display(function () {
return $this->total;
});
$grid->column('state', '订单状态')
->display(function () {
return $this->state_text;
})
->label();
$grid->column('paid_at', '支付时间')->sortable();
$grid->column('versions_count', '操作日志')->link(function () {
return route('admin.mall.versions', [
'model' => get_class($this),
'key' => $this->id,
]);
}, '_self');
$grid->column('created_at', '下单时间')->sortable();
return $grid;
}
/**
* Notes: 添加订单
*
* @Author: 玄尘
* @Date: 2022/7/29 13:21
* @return Form
*/
public function form(): Form
{
$form = new Form(new Order());
$form->select('user_id', '用户')
->options(function ($userId) {
$user = User::find($userId);
if ($user) {
return [$user->id => $user->username.' ['.$user->info->nickname.']'];
}
})
->ajax(route('admin.user.users.ajax'))
->load('address_id', route('admin.mall.ajax.address'))
->required();
$form->select('address_id', '收货地址')
->load('goods_sku_id', route('admin.mall.ajax.goods'))
->required();
$form->select('goods_sku_id', '商品')
->required();
$form->number('qty', '数量')->default(1);
$form->select('express_id', '物流')
->options(function () {
return Express::pluck('name', 'id');
})
->rules('required', ['required' => '物流公司必须选择']);
$form->text('express_no', '物流单号')->rules('required');
return $form;
}
/**
* Notes: 获取提交数据
*
* @Author: 玄尘
* @Date: 2022/7/29 14:16
* @return mixed|void
* @throws \Exception
*/
public function store()
{
$user_id = request('user_id', 0);
$remark = request('remark', '后台录入');
$address_id = request('address_id', 0);
$goods_sku_id = request('goods_sku_id', 0);
$qty = request('qty', 0);
$express_id = request('express_id');
$express_no = request('express_no');
$user = User::find($user_id);
$address = Address::find($address_id);
$goods_sku = GoodsSku::find($goods_sku_id);
if (! $goods_sku) {
$error = new MessageBag([
'title' => '错误',
'message' => '未找到商品',
]);
return back()->withInput()->with(compact('error'));
}
$stockData = $user->getStockData();
if ($qty > $stockData['residue']) {
$error = new MessageBag([
'title' => '错误',
'message' => '用户库存不足',
]);
return back()->withInput()->with(compact('error'));
} else {
$detail = collect();
$item = new Item($goods_sku, $address, $qty);
$detail->push($item);
$orders = (new OrderFacade)->user($user)
->remark($remark)
->type(Order::TYPE_SAMPLE)
->items($detail)
->address($address)
->create();
foreach ($orders as $order) {
$order->pay();//设置已支付
$order->deliver($express_id, $express_no);//发货
}
admin_toastr('操作完成');
return redirect()->to('/admin/mall/orders?user_id='.$user->id);
}
}
/**
* Notes : 订单详情
*
* @Date : 2021/3/16 1:46 下午
* @Author : < Jason.C >
* @param string $orderNo 订单的 order_no
*/
protected function detail(string $orderNo)
{
$order = Order::query()->firstWhere(['order_no' => $orderNo]);
return view('mall::admin.order.detail', compact('order'));
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Database\Eloquent\Model;
use Modules\Mall\Models\Express;
use Modules\Mall\Models\Reason;
class ReasonController extends AdminController
{
use WithUploads;
protected $title = '退款/货原因';
protected function grid(): Grid
{
$grid = new Grid(new Reason());
$grid->model()->withCount('shops');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('trashed', '回收站')->onlyTrashed();
});
$grid->column('id');
$grid->column('title', '名称');
$grid->column('status', '状态')->bool();
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Reason());
$form->text('title', '名称')->required();
$form->switch('status', '状态')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Modules\Mall\Events\RefundCompleted;
use Modules\Mall\Http\Controllers\Admin\Action\Order\RefundAudit;
use Modules\Mall\Http\Controllers\Admin\Action\Order\RefundReturns;
use Modules\Mall\Http\Controllers\Admin\Action\Order\RefundSign;
use Modules\Mall\Models\Refund;
class RefundController extends AdminController
{
protected $title = '退款订单';
public function grid(): Grid
{
$grid = new Grid(new Refund());
$grid->disableCreateButton();
$grid->actions(function ($actions) {
$actions->disableDelete();
$actions->disableEdit();
$actions->disableView();
if ($actions->row->can('agree')) {
$actions->add(new RefundAudit());
}
if ($actions->row->can('sign')) {
$actions->add(new RefundSign());
}
if ($actions->row->can('completed')) {
$actions->add(new RefundReturns());
}
});
$grid->filter(function (Grid\Filter $filter) {
$filter->disableIdFilter();
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->where(function ($query) {
$query->whereHas('order', function ($query) {
$query->where('order_no', 'like', "%{$this->input}%");
});
}, '订单编号');
$filter->equal('state', '状态')->select(Refund::STATUS_MAP);
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->where(function ($query) {
$query->whereHas('user', function ($query) {
$query->whereHas('info', function ($query) {
$query->where('nickname', 'like', "%{$this->input}%");
});
});
}, '下单用户');
$filter->where(function ($query) {
$query->whereHas('user', function ($query) {
$query->where('username', $this->input);
});
}, '手机号');
});
});
$grid->model()
->with(['shop', 'order', 'user.info'])
->withCount('versions');
$grid->column('id');
$grid->column('shop.name', '所属店铺');
$grid->column('order.order_no', '订单编号')->display(function () {
return sprintf('<a href="%s">%s</a>', route('admin.mall.orders.show', $this->order),
$this->order->order_no);
});
$grid->column('user.username', '下单用户');
$grid->column('refund_total', '退款金额');
$grid->column('actual_total', '实退金额');
$grid->column('状态')
->display(function () {
return $this->status_text;
})
->label();
$grid->column('remark', '备注');
$grid->column('versions_count', '操作日志')->link(function () {
return route('admin.mall.versions', [
'model' => get_class($this),
'key' => $this->id,
]);
}, '_self');
$grid->column('created_at', '申请时间');
return $grid;
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Mall\Models\Region;
class RegionController extends AdminController
{
public function ajax(Request $request)
{
$q = $request->q;
return Region::where('name', 'like', "%$q%")->paginate(null, ['id', 'name as text']);
}
public function region(Request $request)
{
$regionId = $request->get('q');
return Region::where('parent_id', $regionId)->get(['id', DB::raw('name as text')]);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Selectable;
use Encore\Admin\Grid\Filter;
use Encore\Admin\Grid\Selectable;
use Modules\Mall\Models\Express;
class Expresses extends Selectable
{
public $model = Express::class;
public function make()
{
$this->column('id', '#ID#');
$this->column('name', '物流名称');
$this->column('status', '状态')->bool();
$this->column('created_at', '时间');
$this->filter(function (Filter $filter) {
$filter->like('name', '物流名称');
});
}
public static function display()
{
return function ($value) {
if (is_array($value)) {
return implode(';', array_column($value, 'name'));
}
return optional($this->expresses)->name;
};
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin\Selectable;
use Encore\Admin\Grid\Selectable;
use Modules\Mall\Models\Reason;
class Reasons extends Selectable
{
public $model = Reason::class;
public function make()
{
$this->column('id', '#ID#');
$this->column('title', '名称');
$this->column('status', '状态')->bool();
$this->column('created_at', '时间');
}
public static function display()
{
return function ($value) {
if (is_array($value)) {
return implode(';', array_column($value, 'title'));
}
return optional($this->reaons)->name;
};
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Close;
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Open;
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Pass;
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Reject;
use Modules\Mall\Http\Controllers\Admin\Selectable\Expresses;
use Modules\Mall\Http\Controllers\Admin\Selectable\Reasons;
use Modules\Mall\Models\Region;
use Modules\Mall\Models\Shop;
use Modules\User\Models\User;
class ShopController extends AdminController
{
use WithUploads;
protected $title = '店铺管理';
public function grid(): Grid
{
$grid = new Grid(new Shop());
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableView();
// $actions->disableEdit();
$actions->disableDelete();
if ($actions->row->status == Shop::STATUS_APPLYING) {
$actions->add(new Pass);
$actions->add(new Reject);
}
if ($actions->row->status == Shop::STATUS_NORMAL) {
$actions->add(new Close);
}
if ($actions->row->status == Shop::STATUS_CLOSE) {
$actions->add(new Open);
}
});
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '店铺名称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.info.nickname', '用户昵称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('mobile', '联系电话');
});
});
$grid->model()->withCount(['versions', 'staffers'])->with(['user.info']);
$grid->column('name', '店铺名称');
$grid->column('所属用户')->display(fn() => $this->user->username . '[' . $this->user->info->nickname . ']');
$grid->column('is_self', '类型')
->using([
0 => '合作',
1 => '自营',
])->label([
0 => 'info',
1 => 'danger',
]);
$grid->column('mobile', '联系电话');
$grid->column('address', '地址')->display(fn() => $this->getFullAddress());
$grid->column('status', '状态')
->using(Shop::STATUS_MAP)
->label(Shop::LABEL_MAP);
$grid->column('order', '排序')->sortable()->editable();
$grid->column('versions_count', '操作记录')->link(fn() => route('admin.mall.versions', [
'model' => get_class($this),
'key' => $this->id,
]), '_self');
$grid->column('staffers_count', '员工数量')->link(fn() => route('admin.mall.shops.staffers.index', $this), '_self');
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Shop());
$form->select('user_id', '所属用户')
->options(function ($userId) {
$user = User::find($userId);
if ($user) {
return [$user->id => $user->username . ' [' . $user->info->nickname . ']'];
}
})
->ajax(route('admin.user.users.ajax'))
->creationRules([
'required',
"unique:mall_shops",
], [
'unique' => '用户已存在店铺',
])
->updateRules([
'required',
"unique:mall_shops,user_id,{{id}}",
], [
'unique' => '用户已存在店铺',
])
->required();
$form->text('name', '店铺名称')
->creationRules(['required', "unique:mall_shops"], ['unique' => '店铺名称已存在'])
->updateRules(['required', "unique:mall_shops,name,{{id}}"], ['unique' => '店铺名称已存在'])
->required();
$form->switch('is_self', '自营店铺');
$form->textarea('description', '店铺简介')
->required();
$form->text('mobile', '联系电话')
->rules([
'size:11',
'phone:CN',
], [
'size' => '手机号格式不正确',
'phone' => '手机号格式不正确',
])
->creationRules(['required', "unique:mall_shops"], ['unique' => '店铺联系电话已存在'])
->updateRules(['required', "unique:mall_shops,name,{{id}}"], ['unique' => '店铺联系电话已存在'])
->required();
$form->divider('地址信息');
$form->select('province_id', '省份')
->options(Region::where('parent_id', 1)->pluck('name', 'id'))
->load('city_id', route('admin.mall.regions.region'))
->required();
$form->select('city_id', '城市')
->options(function ($option) {
$parent = Region::where('id', $option)->value('parent_id');
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
})
->load('district_id', route('admin.mall.regions.region'))
->required();
$form->select('district_id', '区/县')
->options(function ($option) {
$parent = Region::where('id', $option)->value('parent_id');
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
})
->required();
$form->text('address', '详细地址')
->required();
$form->divider('其他信息');
$this->cover($form, 'cover', '店铺LOGO');
$form->radio('status', '店铺状态')
->options(Shop::STATUS_MAP);
$form->number('order', '排序')
->default('9999')
->help('仅后台可见,用于店铺推荐序列');
$form->belongsToMany('expresses', Expresses::class, '发货物流');
$form->belongsToMany('reasons', Reasons::class, '退款原因');
return $form;
}
/**
* Notes : 获取店铺AJAX
* @Date : 2021/5/7 4:39 下午
* @Author : < Jason.C >
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function ajax(Request $request)
{
$key = $request->get('q');
return Shop::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Routing\Controller;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSku;
class SkuController extends Controller
{
use WithUploads;
public function index(Content $content, Goods $good): Content
{
return $content
->header($good->name)
->description('价格表')
->body($this->grid($good));
}
public function grid($goods): Grid
{
$grid = new Grid(new GoodsSku());
$grid->model()->where('goods_id', $goods->id);
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableView();
$actions->disableDelete();
});
$grid->disableCreateButton();
$grid->column('cover', '封面图')->image('', 80);
$grid->column('unit', '产品单元');
$grid->column('price', '售价');
$grid->column('score', '积分/原石');
$grid->column('assets', '资产');
$grid->column('stock', '库存');
$grid->column('weight', '重量');
$grid->column('created_at', '创建时间');
return $grid;
}
public function edit(Content $content, Goods $good, GoodsSku $sku)
{
return $content
->header($good->name)
->description('编辑价格')
->body($this->form($good)->edit($sku->id));
}
public function form($good): Form
{
$form = new Form(new GoodsSku());
$this->cover($form);
$form->currency('price', '销售价格');
$form->currency('score', '积分/原石');
$form->currency('assets', '资产');
$form->number('stock', '库存');
$form->text('weight', '重量')->setWidth(2);
return $form;
}
public function update(Goods $good, GoodsSku $sku)
{
return $this->form($good)->update($sku->id);
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Form;
use Encore\Admin\Form\NestedForm;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Routing\Controller;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSpec;
class SpecController extends Controller
{
public function index(Content $content, Goods $good): Content
{
return $content
->header($good->name)
->description('属性列表')
->body($this->grid($good));
}
public function grid($good): Grid
{
$grid = new Grid(new GoodsSpec());
$grid->model()
->where('goods_id', $good->id)
->withCount('values');
$grid->column('name', '属性名称');
$grid->column('values_count', '属性值数量')
->link(function () use ($good) {
return route('admin.mall.goods.specs.values.index', [$good, $this]);
}, '_self');
return $grid;
}
public function create(Content $content, Goods $good): Content
{
return $content
->header($good->name)
->description('属性列表')
->body($this->form($good));
}
public function form($good): Form
{
$form = new Form(new GoodsSpec());
$form->text('name', '属性名称');
$form->hidden('goods_id')->value($good->id);
$form->hasMany('values', '属性值列表', function (NestedForm $form) {
$form->text('value', '属性值');
});
return $form;
}
public function store(Goods $good)
{
return $this->form($good)->store();
}
public function edit(Content $content, Goods $good, GoodsSpec $spec): Content
{
return $content
->header($good->name)
->description('属性列表')
->body($this->form($good)->edit($spec->id));
}
public function update(Goods $good, GoodsSpec $spec)
{
return $this->form($good)->update($spec->id);
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Routing\Controller;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSpec;
use Modules\Mall\Models\GoodsSpecValue;
class SpecValueController extends Controller
{
public function index(Content $content, Goods $good, GoodsSpec $spec): Content
{
return $content
->header($spec->name)
->description('属性值列表')
->body($this->grid($spec));
}
public function grid($spec): Grid
{
$grid = new Grid(new GoodsSpecValue());
$grid->model()->where('spec_id', $spec->id);
$grid->column('value', '属性值');
return $grid;
}
public function create(Content $content, Goods $good, GoodsSpec $spec): Content
{
return $content
->header($spec->name)
->description('属性列表')
->body($this->form($spec));
}
public function form($spec): Form
{
$form = new Form(new GoodsSpecValue());
$form->text('value', '属性值');
$form->hidden('spec_id')->value($spec->id);
return $form;
}
public function store(Goods $good, GoodsSpec $spec)
{
return $this->form($spec)->store();
}
public function edit(Content $content, Goods $good, GoodsSpec $spec, GoodsSpecValue $value): Content
{
return $content
->header($spec->name)
->description('属性列表')
->body($this->form($spec)->edit($value->id));
}
public function update(Goods $good, GoodsSpec $spec, GoodsSpecValue $value)
{
return $this->form($spec)->update($value->id);
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Routing\Controller;
use Modules\Mall\Models\Job;
use Modules\Mall\Models\Shop;
use Modules\Mall\Models\ShopStaffer;
use Modules\User\Models\User;
class StafferController extends Controller
{
public function index(Content $content, Shop $shop): Content
{
return $content
->header($shop->name)
->description('员工管理')
->body($this->grid($shop));
}
public function grid($shop): Grid
{
$grid = new Grid(new ShopStaffer());
$grid->model()->byShop($shop);
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.username', '用户名');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.info.nickname', '用户昵称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('job.name', '职位名称');
});
});
$grid->column('所属用户')->display(fn() => $this->user->username . '[' . $this->user->info->nickname . ']');
$grid->column('job.name', '职位名称');
$grid->column('created_at', '创建时间');
return $grid;
}
public function create(Content $content, Shop $shop): Content
{
return $content
->header($shop->name)
->description('新增员工')
->body($this->form($shop));
}
public function store(Shop $shop)
{
return $this->form($shop)->store();
}
public function form(Shop $shop): Form
{
$form = new Form(new ShopStaffer());
$form->hidden('shop_id')->value($shop->getKey());
$form->select('user_id', '所属用户')
->options(function ($userId) {
$user = User::find($userId);
if ($user) {
return [$user->id => $user->username . ' [' . $user->info->nickname . ']'];
}
})
->ajax(route('admin.user.users.ajax'))
->required();
$form->select('job_id', '职位')->options(fn() => Job::byShop($shop)->pluck('name', 'id'));
return $form;
}
public function edit(Content $content, Shop $shop, ShopStaffer $staffer): Content
{
return $content
->header($shop->name)
->description('编辑员工')
->body($this->form($shop)->edit($staffer->getKey()));
}
public function update(Shop $shop, ShopStaffer $staffer)
{
return $this->form($shop)->update($staffer->getKey());
}
}

View File

@@ -0,0 +1,254 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Support\MessageBag;
use Modules\Mall\Facades\Item;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Delivered;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Pay;
use Modules\Mall\Http\Exporter\OrderExporter;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Express;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSku;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderExpress;
use Modules\Mall\Models\Shop;
use Modules\User\Models\User;
use Modules\Mall\Facades\Order as OrderFacade;
class StockOrderBySystemController extends AdminController
{
protected $title = '公司线下发货';
protected function grid(): Grid
{
$grid = new Grid(new Order());
$grid->model()
->where('type', Order::TYPE_SAMPLE)
->where('channel', Order::CHANNEL_SYSTEM)
->with(['shop', 'user', 'items'])
->withCount('versions');
$grid->quickSearch('order_no')->placeholder('搜索订单编号');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('unPay', '未付款')->unPay();
$filter->scope('paid', '待发货')->paid();
$filter->scope('delivered', '已发货')->delivered();
$filter->scope('signed', '已签收')->signed();
$filter->scope('completed', '已完成')->completed();
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('order_no', '订单编号');
// $filter->equal('shop_id', '所属店铺')->select(Shop::pluck('name', 'id'));
$filter->equal('user_id', '提货用户')->select()->ajax(route('admin.user.users.ajax'));
// $filter->equal('type', '订单类型')->select(Order::TYPE_MAP);
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
// $filter->between('created_at', '下单时间')->datetime();
// $filter->between('paid_at', '付款时间')->datetime();
// $filter->between('expired_at', '过期时间')->datetime();
});
});
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableDelete();
$actions->disableView();
if ($actions->row->can('pay') && $this->row->type == Order::TYPE_NORMAL) {
$actions->add(new Pay());
}
if ($actions->row->can('deliver')) {
$actions->add(new Delivered);
}
});
$grid->model()->with(['shop', 'user.info']);
$grid->column('order_no', '订单编号')->display(function () {
return sprintf('<a href="%s">%s</a>', route('admin.mall.stock_orders.show', $this), $this->order_no);
});
// $grid->column('shop.name', '所属店铺');
$grid->column('user.username', '提货用户');
// $grid->column('amount', '商品金额');
// $grid->column('freight', '运费');
$grid->column('qty', '提货数量')
->display(function () {
return $this->items()->sum('qty');
});
// $grid->column('订单金额')->display(function () {
// return $this->total;
// });
$grid->column('state', '订单状态')
->display(function () {
return $this->state_text;
})
->label();
$grid->column('type', '订单类型')->using(Order::TYPE_MAP)->label();
// $grid->column('paid_at', '支付时间')->sortable();
// $grid->column('expired_at', '过期时间')->sortable();
$grid->column('versions_count', '操作日志')->link(function () {
return route('admin.mall.versions', [
'model' => get_class($this),
'key' => $this->id,
]);
}, '_self');
$grid->column('created_at', '下单时间')->sortable();
$grid->disableExport(false);
$grid->export(function ($export) {
$export->column('order_no', function ($value, $original) {
return strip_tags($value)."\n";
});
$export->column('type', function ($value, $original) {
return strip_tags($value);
});
$export->column('state', function ($value, $original) {
return strip_tags($value);
});
$export->except(['versions_count', 'paid_at', 'expired_at']);
$export->filename($this->title.date("YmdHis"));
});
return $grid;
}
/**
* Notes: 添加订单
*
* @Author: 玄尘
* @Date: 2022/7/29 13:21
* @return Form
*/
public function form(): Form
{
$form = new Form(new Order());
$form->select('user_id', '会员')
->options(function ($userId) {
$user = User::find($userId);
if ($user) {
return [$user->id => $user->username.' ['.$user->info->nickname.']'];
}
})
->ajax(route('admin.user.users.ajax'))
->load('address_id', route('admin.mall.ajax.address'))
->required();
$form->select('address_id', '收货地址')
->load('goods_sku_id', route('admin.mall.ajax.goods'))
->required();
$form->html("<div id='showImage' style='margin-top:10px'><a href='/admin/mall/addresses/create'>添加收货地址</a></div>",
'');
$form->select('goods_sku_id', '剩余箱数')->required();
$form->number('qty', '发货箱数')->default(1);
$form->radioButton('type', '方式')
->options(OrderExpress::TYPE_MAP)
->required()
->when(OrderExpress::TYPE_EXPRESS, function ($form) {
$form->select('express_id', '物流')
->options(function () {
return Express::pluck('name', 'id');
})
->rules('required', ['required' => '物流公司必须选择']);
$form->text('express_no', '物流单号')->rules('required');
})
->when(OrderExpress::TYPE_LOGISTICS, function ($form) {
$form->text('person', '经办人');
});
return $form;
}
/**
* Notes: 获取提交数据
*
* @Author: 玄尘
* @Date: 2022/7/29 14:16
* @return mixed|void
* @throws \Exception
*/
public function store()
{
$user_id = request('user_id', 0);
$remark = request('remark', '后台录入');
$address_id = request('address_id', 0);
$goods_sku_id = request('goods_sku_id', 0);
$qty = request('qty', 0);
$express_id = request('express_id');
$express_no = request('express_no');
$type = request('type');
$person = request('person');
$user = User::find($user_id);
$address = Address::find($address_id);
$goods_sku = GoodsSku::find($goods_sku_id);
if (! $goods_sku) {
$error = new MessageBag([
'title' => '错误',
'message' => '未找到商品',
]);
return back()->withInput()->with(compact('error'));
}
$stockData = $user->getStockData();
if ($qty > $stockData['residue']) {
$error = new MessageBag([
'title' => '错误',
'message' => '用户库存不足',
]);
return back()->withInput()->with(compact('error'));
} else {
$detail = collect();
$item = new Item($goods_sku, $address, $qty);
$detail->push($item);
$orders = (new OrderFacade)->user($user)
->remark($remark)
->channel(Order::CHANNEL_SYSTEM)
->type(Order::TYPE_SAMPLE)
->items($detail)
->address($address)
->create();
foreach ($orders as $order) {
$order->pay();//设置已支付
$order->deliver($express_id, $express_no, $type, $person);//发货
}
admin_toastr('操作完成');
return redirect()->to('/admin/mall/stock_orders_by_system?user_id='.$user->id);
}
}
/**
* Notes : 订单详情
*
* @Date : 2021/3/16 1:46 下午
* @Author : < Jason.C >
* @param string $orderNo 订单的 order_no
*/
protected function detail(string $orderNo)
{
$order = Order::query()->firstWhere(['order_no' => $orderNo]);
return view('mall::admin.stock_order.detail', compact('order'));
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Support\MessageBag;
use Modules\Mall\Facades\Item;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Delivered;
use Modules\Mall\Http\Controllers\Admin\Action\Order\Pay;
use Modules\Mall\Http\Exporter\OrderExporter;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Express;
use Modules\Mall\Models\GoodsSku;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\Shop;
use Modules\User\Models\User;
use Modules\Mall\Facades\Order as OrderFacade;
class StockOrderController extends AdminController
{
protected $title = '免费领取订单';
protected function grid(): Grid
{
$grid = new Grid(new Order());
$grid->model()
->where('type', Order::TYPE_SAMPLE)
->with(['shop', 'user', 'items'])
->withCount('versions');
$grid->disableCreateButton();
$grid->quickSearch('order_no')->placeholder('搜索订单编号');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('unPay', '未付款')->unPay();
$filter->scope('paid', '待发货')->paid();
$filter->scope('delivered', '已发货')->delivered();
$filter->scope('signed', '已签收')->signed();
$filter->scope('completed', '已完成')->completed();
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('order_no', '订单编号');
// $filter->equal('shop_id', '所属店铺')->select(Shop::pluck('name', 'id'));
$filter->equal('user_id', '提货用户')->select()->ajax(route('admin.user.users.ajax'));
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->between('created_at', '下单时间')->datetime();
$filter->equal('state', '订单状态')->select([
Order::STATUS_CANCEL => '已取消',
Order::STATUS_PAID => '待发货',
Order::STATUS_DELIVERED => '已发货',
Order::STATUS_SIGNED => '已签收',
]);
// $filter->between('paid_at', '付款时间')->datetime();
// $filter->between('expired_at', '过期时间')->datetime();
});
});
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableDelete();
$actions->disableView();
if ($actions->row->can('pay') && $this->row->type == Order::TYPE_NORMAL) {
$actions->add(new Pay());
}
if ($actions->row->can('deliver')) {
$actions->add(new Delivered);
}
});
$grid->model()->with(['shop', 'user.info']);
$grid->column('order_no', '订单编号')->display(function () {
return sprintf('<a href="%s">%s</a>', route('admin.mall.stock_orders.show', $this), $this->order_no);
});
// $grid->column('shop.name', '所属店铺');
$grid->column('user.username', '提货用户');
// $grid->column('amount', '商品金额');
// $grid->column('freight', '运费');
$grid->column('qty', '提货数量')
->display(function () {
return $this->items()->sum('qty');
});
// $grid->column('订单金额')->display(function () {
// return $this->total;
// });
$grid->column('state', '订单状态')
->display(function () {
return $this->state_text;
})
->label();
// $grid->column('type', '订单类型')->using(Order::TYPE_MAP)->label();
// $grid->column('paid_at', '支付时间')->sortable();
// $grid->column('expired_at', '过期时间')->sortable();
$grid->column('versions_count', '操作日志')->link(function () {
return route('admin.mall.versions', [
'model' => get_class($this),
'key' => $this->id,
]);
}, '_self');
$grid->column('created_at', '下单时间')->sortable();
$grid->disableExport(false);
$grid->export(function ($export) {
$export->column('order_no', function ($value, $original) {
return strip_tags($value)."\n";
});
$export->column('type', function ($value, $original) {
return strip_tags($value);
});
$export->column('state', function ($value, $original) {
return strip_tags($value);
});
$export->except(['versions_count', 'paid_at', 'expired_at']);
$export->filename($this->title.date("YmdHis"));
});
return $grid;
}
/**
* Notes : 订单详情
*
* @Date : 2021/3/16 1:46 下午
* @Author : < Jason.C >
* @param string $orderNo 订单的 order_no
*/
protected function detail(string $orderNo)
{
$order = Order::query()->firstWhere(['order_no' => $orderNo]);
return view('mall::admin.stock_order.detail', compact('order'));
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Http\Request;
use Modules\Mall\Models\Tag;
class TagController extends AdminController
{
use WithShop;
protected $title = '商品标签';
public function grid(): Grid
{
$grid = new Grid(new Tag());
$grid->model()->with(['shop']);
$grid->column('shop.name', '所属店铺');
$grid->column('name', '标签名称');
return $grid;
}
public function form(): Form
{
$form = new Form(new Tag());
$this->shop($form)->required();
$form->text('name', '标签名称')
->required();
return $form;
}
public function ajax(Request $request)
{
$key = $request->q;
return Tag::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Widgets\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Routing\Controller;
use Overtrue\LaravelVersionable\Version;
class VersionController extends Controller
{
public function index(Content $content, $model, $key): Content
{
return $content
->header($model . ' => ' . $key)
->description('数据操作日志')
->body($this->grid($model, $key));
}
public function grid($model, $key): Grid
{
$grid = new Grid(new Version());
$grid->disableCreateButton();
$grid->disableActions();
$grid->disableTools();
$grid->model()->whereHasMorph(
'versionable',
$model,
function (Builder $query) use ($key) {
$query->where('id', $key);
}
)->orderByDesc('id');
$grid->column('操作用户')->display(function () {
if ($this->user_id < config('mall.administrator_max_id')) {
config(['versionable.user_model' => Administrator::class]);
return '[Admin] ' . ($this->user->name ?? '--SYSTEM--');
} else {
return '[USER] ' . ($this->user->username ?? '--USER--');
}
});
$grid->column('versionable_type', '数据变动')->expand(function () {
$data = [];
foreach ($this->contents as $key => $item) {
$data[] = [
$key,
is_array($item) ? json_encode($item, JSON_UNESCAPED_UNICODE) : $item,
];
}
return new Table(['字段名称', '变更值'], $data);
});
$grid->column('操作时间')->display(function () {
return $this->created_at->toDateTimeString();
});
return $grid;
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\Linker\Traits\WithLinker;
use Modules\Mall\Models\Banner;
use Modules\Mall\Models\Video;
class VideoController extends AdminController
{
use WithUploads,
WithShop,
WithLinker;
public $title = "视频管理";
protected function grid(): Grid
{
$grid = new Grid(new Video());
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '视频名称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('status', '状态')->radio([
0 => '禁用',
1 => '正常',
]);
});
});
$grid->column('id', '#ID#');
$grid->column('name', '视频名称');
$grid->column('cover', '封面地址')->image('', 60, 60);
$grid->column('path', '视频地址')
->display(function () {
return $this->path_url;
});
$grid->column('status', '状态')->switch();
$grid->column('created_at', '创建时间');
return $grid;
}
protected function form(): Form
{
$form = new Form((new Video())->disableModelCaching());
$form->text('name', '视频标题')->required();
$this->cover($form);
$this->video($form);
$form->switch('status', '显示')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Modules\Mall\Http\Controllers\Admin;
use Modules\Mall\Models\Shop;
trait WithShop
{
public function shop($form)
{
return $form->select('shop_id', '所属店铺')
->options(function ($shopId) {
$shop = Shop::find($shopId);
if ($shop) {
return [$shop->id => $shop->name];
}
})
->ajax(route('admin.mall.shops.ajax'));
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\Mall\Http\Controllers\Agent;
use App\Api\Controllers\Controller;
use Illuminate\Http\Request;
class IndexController extends Controller
{
public function index(Request $request)
{
return $this->success($request->shop);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Modules\Mall\Http\Controllers\Agent;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Jason\Api\Api;
class ShopController extends Controller
{
public function index(): JsonResponse
{
$user = Api::user();
return $this->success();
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Modules\Mall\Http\Resources\Api\Activity\ActivityBaseResource;
use Modules\Mall\Http\Resources\Api\Activity\ActivityResource;
use Modules\Mall\Models\Activity;
class ActivityController extends Controller
{
/**
* Notes: 活动列表
*
* @Author: 玄尘
* @Date: 2022/7/27 11:26
* @return JsonResponse
*/
public function index(): JsonResponse
{
$activities = Activity::shown()->get();
return $this->success(ActivityBaseResource::collection($activities));
}
public function show(Activity $activity)
{
return $this->success(new ActivityResource($activity));
}
}

View File

@@ -0,0 +1,160 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\Mall\Http\Requests\Address\AddressRequest;
use Modules\Mall\Http\Resources\Api\Address\AddressResource;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Region;
class AddressController extends Controller
{
/**
* Notes: 地址列表
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:09 下午
* @return mixed
*/
public function index()
{
$addresses = Address::byUser(Api::user())->orderBy('is_default', 'desc')->get();
return $this->success(AddressResource::collection($addresses));
}
/**
* Notes: 创建地址,展示地区联动数据
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:10 下午
*/
public function create(Request $request)
{
$parentId = $request->parent_id ?? 1;
$list = Region::where('parent_id', $parentId)->get();
return $this->success($list);
}
/**
* Notes: 保存地址
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:13 下午
* @param \Modules\Mall\Http\Requests\Address\AddressRequest $request
* @return mixed
*/
public function store(AddressRequest $request)
{
$result = Address::create([
'user_id' => Api::userId(),
'name' => $request->name,
'mobile' => $request->mobile,
'province_id' => $request->province_id,
'city_id' => $request->city_id,
'district_id' => $request->district_id,
'address' => $request->address,
'is_default' => $request->is_default,
]);
if ($result) {
return $this->success('操作成功');
} else {
return $this->failed('失败');
}
}
/**
* Notes: 地址详情,如果不是自己的地址,不显示
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:31 下午
* @param Address $address
* @return mixed
*/
public function show(Address $address)
{
if ($address->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
return $this->success(new AddressResource($address));
}
/**
* Notes: 设置默认地址
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:34 下午
* @param Address $address
* @return mixed
*/
public function setDefault(Address $address)
{
if ($address->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
try {
$address->setDefault();
return $this->success('操作成功');
} catch (Exception $exception) {
return $this->failed('失败');
}
}
/**
* Notes: 更新地址
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:40 下午
*/
public function update(AddressRequest $request, Address $address)
{
if ($address->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
$address->update([
'name' => $request->name,
'mobile' => $request->mobile,
'province_id' => $request->province_id,
'city_id' => $request->city_id,
'district_id' => $request->district_id,
'address' => $request->address,
'is_default' => $request->is_default,
]);
return $this->success('操作成功');
}
/**
* Notes: 删除地址
*
* @Author: <C.Jason>
* @Date : 2020/11/5 5:52 下午
* @param Address $address
* @return mixed
*/
public function destroy(Address $address)
{
if ($address->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
try {
$address->delete();
return $this->success('操作成功');
} catch (Exception$exception) {
return $this->failed('失败');
}
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\Mall\Http\Resources\Api\Banner\BannerResource;
use Modules\Mall\Models\Banner;
class BannerController extends Controller
{
/**
* Notes : 获取banner的接口
* @Date : 2021/6/3 11:28 上午
* @Author : <Jason.C>
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
$position = $request->position;
$shopId = $request->shop_id;
// 店铺ID为null的是平台轮播
$banners = Banner::when($shopId, function (Builder $query) use ($shopId) {
$query->where('shop_id', $shopId);
})->when(is_numeric($position), function (Builder $query) use ($position) {
$query->ofPosition($position);
})->get();
return $this->success(BannerResource::collection($banners));
}
}

View File

@@ -0,0 +1,159 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Jason\Api\Api;
use Modules\Mall\Http\Requests\Cart\CartRequest;
use Modules\Mall\Http\Resources\Api\Goods\CartResource;
use Modules\Mall\Http\Resources\Api\Shop\ShopBaseInfoResource;
use Modules\Mall\Models\Cart;
use Modules\Mall\Models\GoodsSku;
use Modules\Mall\Models\Shop;
class CartController extends Controller
{
/**
* Notes : 购物车内商品列表
* @Date : 2021/8/26 3:42 下午
* @Author : <Jason.C>
* @return \Illuminate\Http\JsonResponse
*/
public function index(): JsonResponse
{
$list = Cart::byUser(Api::user())->with('sku')->orderByDesc('updated_at')->get();
$collection = $list->groupBy('shop_id');
$items = [];
foreach ($collection as $shopId => $item) {
$items[] = [
'shop' => new ShopBaseInfoResource(Shop::find($shopId)),
'items' => CartResource::collection($item),
];
}
return $this->success($items);
}
/**
* Notes : 加入购物车
* @Date : 2021/5/14 2:17 下午
* @Author : <Jason.C>
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function store(Request $request)
{
$skuId = $request->sku_id;
$qty = $request->qty ?? 1;
$sku = GoodsSku::findOrFail($skuId);
if (!$sku->canBuy($qty)) {
return $this->failed('超过最大可购买数量');
}
$cart = Cart::where('user_id', Api::userId())->where('sku_id', $skuId)->first();
if ($cart) {
$cart->qty = $cart->qty + $qty;
$cart->save();
} else {
$cart = Cart::create([
'user_id' => Api::userId(),
'shop_id' => $sku->goods->shop_id,
'sku_id' => $skuId,
'qty' => $qty,
]);
}
return $this->success($cart->qty);
}
/**
* Notes : 获取购物车商品数量
* @Date : 2021/5/14 1:47 下午
* @Author : <Jason.C>
*/
public function count(): JsonResponse
{
if (Api::userId()) {
$count = Cart::where('user_id', Api::userId())->count();
} else {
$count = 0;
}
return $this->success($count);
}
/**
* Notes : 更新购物车商品数量
* @Date : 2021/5/13 2:52 下午
* @Author : <Jason.C>
* @param \Modules\Mall\Http\Requests\Cart\CartRequest $request
* @param \Modules\Mall\Models\Cart $cart
* @return mixed
*/
public function update(CartRequest $request, Cart $cart)
{
$skuId = $request->sku_id;
$qty = $request->qty;
if ($cart->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
if ($skuId && ($skuId != $cart->sku_id)) {
$sku = GoodsSku::find($skuId);
if (!$cart->sku->goods->is($sku->goods)) {
return $this->failed('错误的商品');
}
$cart->sku_id = $skuId;
} else {
$sku = $cart->sku;
}
if ($qty < 1 || $qty > $sku->stock) {
return $this->failed('库存不足');
}
$cart->qty = $qty;
$cart->save();
return $this->success($qty);
}
/**
* Notes : 删除购物车商品
* @Date : 2021/5/17 4:00 下午
* @Author : <Jason.C>
* @param string $cart
* @return mixed|string
*/
public function destroy(string $cart)
{
if (Str::contains($cart, ',')) {
$count = Cart::query()->where('user_id', Api::userId())->whereIn('id', explode(',', $cart))->delete();
if (!$count) {
return $this->failed('empty');
}
} else {
$cart = Cart::find($cart);
if ($cart->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
$cart->delete();
}
return $this->success('删除成功');
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\Mall\Http\Resources\Api\Category\CategoryResource;
use Modules\Mall\Models\Category;
class CategoryController extends Controller
{
/**
* Notes : 商品分类列表
*
* @Date : 2021/6/3 12:08 下午
* @Author : <Jason.C>
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
$shopId = $request->shop_id;
$list = Category::query()
->where('id', '<>', 2)
->when($shopId, function (Builder $query) use ($shopId) {
$query->where('shop_id', $shopId);
})->where('parent_id', 0)->get();
return $this->success(CategoryResource::collection($list));
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\Mall\Http\Resources\Api\Goods\GoodsCollection;
use Modules\Mall\Http\Resources\Api\Goods\GoodsResource;
use Modules\Mall\Models\Goods;
class GoodsController extends Controller
{
/**
* Notes: 商品列表
* @Author: Mr.wang
* @Date : 2021/5/11 16:20
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
#todo 商品分类搜索,可展示下级分类下的所有商品,分类数据缓存
$name = $request->get('name');
$shopId = $request->get('shop_id');
$categoryId = $request->get('category_id');
$brandId = $request->get('brand_id');
$payType = $request->get('pay_type');
$tagId = $request->get('tag_id');
$isSelf = $request->get('is_self');
$perPage = $request->get('per_page');
$orderBy = $request->get('order_by');
$goods = Goods::shown()
->select(Goods::LIST_SELECT_FIELDS)
->with(['tags', 'shop'])
->when($name, function (Builder $query) use ($name) {
$query->where('name', 'like', "%$name%");
})
->when($isSelf, function (Builder $query) {
$query->whereHas('shop', function (Builder $query) {
$query->where('is_self', 1);
});
})
->when($shopId, function (Builder $query) use ($shopId) {
$query->where('shop_id', $shopId);
})
->when($categoryId, function (Builder $query) use ($categoryId) {
$query->where('category_id', $categoryId);
})
->when($brandId, function (Builder $query) use ($brandId) {
$query->where('brand_id', $brandId);
})
->when($payType, function (Builder $query) use ($payType) {
$query->where('pay_type', $payType);
})
->when($tagId, function (Builder $query) use ($tagId) {
$query->whereHas('tags', function (Builder $query) use ($tagId) {
$query->whereIn('id', explode(',', $tagId));
});
})
->when($orderBy, function (Builder $query) use ($orderBy) {
switch ($orderBy) {
case 'sales':
$query->orderByDesc('sales');
break;
case 'price':
$query->orderByPrice();
break;
}
})
->paginate($perPage);
return $this->success(new GoodsCollection($goods));
}
public function show(Goods $goods): JsonResponse
{
$goods->incrementClicks();
return $this->success(new GoodsResource($goods));
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use App\Api\Resources\User\UserBaseResource;
use Illuminate\Http\JsonResponse;
use Jason\Api\Api;
use Modules\Cms\Models\Article;
use Modules\Mall\Http\Resources\Api\Goods\GoodsBaseResource;
use Modules\Mall\Models\Banner;
use Modules\Mall\Models\Goods;
class IndexController extends Controller
{
/**
* Notes :
*
* @Date : 2021/3/15 5:25 下午
* @Author : <Jason.C>
* @return JsonResponse
*/
public function index(): JsonResponse
{
$show_goods_id = app('Conf_mall')['show_goods_id'] ?? 0;
$show_goods = '';
if ($show_goods_id > 0) {
$show_goods = Goods::find($show_goods_id);
}
$goods = Goods::query()
->where('id', '<>', $show_goods_id)
->shown()
->where('channel', Goods::CHANNEL_NORMAL)
->get();
$user = Api::user();
$data = [
'user' => $user ? new UserBaseResource($user) : '',
'show_goods' => $show_goods ? new GoodsBaseResource($show_goods) : '',
'goods' => GoodsBaseResource::collection($goods),
];
return $this->success($data);
}
}

View File

@@ -0,0 +1,197 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use App\Api\Resources\Area\AreaCodeResource;
use App\Api\Resources\User\UserBaseResource;
use App\Models\AreaCode;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\Mall\Facades\Item;
use Modules\Mall\Facades\Order;
use Modules\Mall\Models\Order as OrderModel;
use Modules\Mall\Http\Requests\OrderBuy\OrderBuyRequest;
use Modules\Mall\Http\Resources\Api\Address\AddressResource;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Cart;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSku;
class OrderBuyController extends Controller
{
/**
* Notes: 商品确认下单
*
* @Author: 玄尘
* @Date : 2021/5/14 11:54
* @param \Modules\Mall\Http\Requests\OrderBuy\OrderBuyRequest $request
* @return mixed
* @throws \Exception
*/
public function goodsCreate(Request $request)
{
$validator = Validator::make($request->all(), [
'goods_sku_id' => 'required|integer',
'qty' => 'nullable|integer',
], [
'goods_sku_id.required' => '缺少商品规格id',
'goods_sku_id.integer' => '商品规格id必须是数字',
'qty.integer' => '数量必须是数字',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
$goods_sku_id = $request->goods_sku_id;
$qty = $request->qty;
$detail = collect();
$user = Api::user();
$areaCode = $user->info->areaCode;
if (! $areaCode) {
return $this->failed('您没有提货码不可参与此活动');
}
if ($areaCode->status != AreaCode::STATUS_INIT) {
return $this->failed('提货码已被使用,不可重复使用');
}
// $address_id = $request->address_id;
// if ($address_id) {
// $address = Address::find($address_id);
// } else {
// $address = Address::where('user_id', $user->id)->orderBy('is_default', 'desc')->first();
// }
$goods_sku = GoodsSku::find($goods_sku_id);
if (! $goods_sku) {
return $this->failed('未找到商品');
}
if (! $goods_sku->canBuy($qty)) {
return $this->failed($goods_sku->getGoodsName().'商品不可购买');
}
$item = new Item($goods_sku, null, $qty);
$detail->push($item);
$freight = $item->freight();
$amount = $item->total();
$weight = $item->weight();
$detail = (new Order)->items($detail)->splitOrderByShop();
$items = [];
foreach ($detail as $item) {
$items[] = $item;
}
$data = [
'areaCode' => new AreaCodeResource($areaCode),
'detail' => $items,
'amount' => floatval(bcadd($amount, $freight, 2)),
'freight' => $freight,
'weight' => $weight,
'user' => $user ? new UserBaseResource($user) : '',
];
return $this->success($data);
}
/**
* Notes: 商品下单
*
* @Author: 玄尘
* @Date : 2021/5/14 13:53
* @param \Modules\Mall\Http\Requests\OrderBuy\OrderBuyRequest $request
* @return mixed
* @throws \Exception
*/
public function goodsBuy(Request $request)
{
$validator = Validator::make($request->all(), [
'goods_sku_id' => 'required|integer',
'qty' => 'nullable|integer',
], [
'goods_sku_id.required' => '缺少商品规格id',
'goods_sku_id.integer' => '商品规格id必须是数字',
'qty.integer' => '数量必须是数字',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
$user = Api::user();
$remark = $request->remark ?? '';
// $address_id = $request->address_id ?? '';
$goods_sku_id = $request->goods_sku_id;
$qty = $request->qty;
$share_user_id = $request->share_user_id ?? 0;
$areaCode = $user->info->areaCode;
if (! $areaCode) {
return $this->failed('您没有提货码不可参与此活动');
}
if ($areaCode->status != AreaCode::STATUS_INIT) {
return $this->failed('提货码已被使用,不可重复使用');
}
// $address = Address::where('user_id', $user->id)->where('id', $address_id)->first();
// if (! $address) {
// return $this->failed('未找到收货地址');
// }
$detail = collect();
$goods_sku = GoodsSku::find($goods_sku_id);
if (! $goods_sku) {
return $this->failed('未找到商品');
}
if (! $goods_sku->canBuy($qty)) {
return $this->failed($goods_sku->getGoodsName().' 商品不可购买');
}
$item = new Item($goods_sku, null, $qty);
$detail->push($item);
$type = OrderModel::TYPE_NORMAL;
if ($goods_sku->goods->channel == Goods::CHANNEL_FREE) {
$type = OrderModel::TYPE_SAMPLE;
}
if ($goods_sku->goods->channel == Goods::CHANNEL_SCORE) {
$type = OrderModel::TYPE_SCORE;
}
$orders = (new Order)->user($user)
->remark($remark)
->items($detail)
->areaCode($areaCode)
->type($type)
->source(['share_user_id' => $share_user_id,])
->create();
foreach ($orders as $order) {
if ($type == OrderModel::TYPE_SAMPLE) {
$order->pay();
$order->areaCode->used();
}
}
return $this->success([
'order_no' => $orders->first()->order_no,
'total' => $orders->first()->total,
'score' => $user->account->score,
]);
}
}

View File

@@ -0,0 +1,287 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\Mall\Facades\Refund;
use Modules\Mall\Http\Resources\Api\Order\LogisticResource;
use Modules\Mall\Http\Resources\Api\Order\OrderCollection;
use Modules\Mall\Http\Resources\Api\Order\OrderItemResource;
use Modules\Mall\Http\Resources\Api\Order\OrderLogisticResource;
use Modules\Mall\Http\Resources\Api\Order\OrderResource;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderItem;
use Modules\Mall\Models\Reason;
use Modules\Mall\Models\Refund as RefundModel;
use MrwangTc\Kuaidi100\Exceptions\HttpException;
use MrwangTc\Kuaidi100\Express\Synquery;
class OrderController extends Controller
{
/**
* Notes : 订单列表
*
* @Date : 2021/5/13 5:17 下午
* @Author : <Jason.C>
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$state = $request->state ?? '';
$type = $request->type ?? '';// score sample
#todo 类别筛选
#todo 商品名称搜索
#todo 订单编号搜索
$list = Order::byUser(Api::user())
->when($state, function ($query) use ($state) {
switch ($state) {
case 'unpay':
$query->unPay();
break;
case 'paid':
$query->paid();
break;
case 'delivered':
$query->Delivered();
break;
case 'signed':
$query->signed();
break;
case 'completed':
$query->completed();
break;
}
}, function ($query) {
$query->common();
})
// ->when($type, function ($q) use ($type) {
// if ($type == 'score') {
// $q->TypeScore();
// }
//
// if ($type == 'sample') {
// $q->TypeSample();
// }
// })
->paginate();
return $this->success(new OrderCollection($list));
}
/**
* Notes : 订单详情
*
* @Date : 2021/5/13 5:17 下午
* @Author : <Jason.C>
* @param Order $order
* @return mixed
*/
public function show(Order $order)
{
if ($order->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
return $this->success(new OrderResource($order));
}
/**
* Notes : 查看物流
*
* @Date : 2021/5/14 16:52
* @Author : Mr.wang
* @param Order $order
* @return mixed
* @throws HttpException
*/
public function logistic(Order $order)
{
if ($order->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
if (! $order->is_logistic_show) {
return $this->failed('', 404);
}
$express = new Synquery();
$synQuery = $express->pollQuery($order->express->express->slug, $order->express->express_no);
if (isset($synQuery->result) && $synQuery->result === false) {
return $this->failed($synQuery->message);
}
$logistics = $synQuery->data;
return $this->success([
'orderExpress' => new OrderLogisticResource($order->express),
'logistics' => LogisticResource::collection($logistics),
]);
}
/**
* Notes : 签收成功
*
* @Date : 2021/5/17 16:52
* @Author : Mr.wang
* @param Order $order
* @return mixed
* @throws \Exception
*/
public function sign(Order $order)
{
if ($order->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
if ($order->sign() === true) {
return $this->success('操作成功');
} else {
return $this->failed();
}
}
/**
* Notes : 取消订单
*
* @Date : 2021/5/19 11:35
* @Author : Mr.wang
* @param Order $order
* @return mixed
*/
public function cancel(Order $order)
{
if ($order->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
try {
$order->cancel();
return $this->success('操作成功');
} catch (Exception $e) {
return $this->failed($e->getMessage());
}
}
/**
* Notes : 删除订单(对订单进行软删除操作)
*
* @Date : 2021/5/19 11:35
* @Author : Mr.wang
* @param Order $order
* @return mixed
*/
public function destroy(Order $order)
{
if ($order->user()->isNot(Api::user())) {
return $this->failed('', 404);
}
if ($order->canDelete() === false) {
return $this->failed('订单不允许删除');
}
try {
$order->delete();
return $this->success('操作成功');
} catch (Exception $e) {
return $this->failed($e->getMessage());
}
}
/**
* Notes: 订单商品
*
* @Author: 玄尘
* @Date : 2021/5/18 8:47
* @param Order $order
* @return mixed
*/
public function goods(Order $order)
{
$user = Api::user();
if ($order->user()->isNot($user)) {
return $this->failed('', 404);
}
$data = [
'order' => new OrderResource($order),
'title' => Reason::query()->pluck('title'),
];
return $this->success($data);
}
/**
* Notes: 退款/退货
*
* @Author: 玄尘
* @Date : 2021/5/19 9:11
* @param Order $order
* @param Request $request
* @return mixed
*/
public function refund(Order $order, Request $request)
{
$user = Api::user();
if (! $order->type == Order::TYPE_SAMPLE) {
return $this->failed('操作失败,提货单不可退货');
}
if (! $order->can('refund')) {
return $this->failed('操作失败,此订单不可退货');
}
if ($order->user()->isNot($user)) {
return $this->failed('您没有权限进行此操作');
}
$remark = $request->remark ?? '';
$title = $request->title;//退款原因
$pictures = $request->pictures;//图片 many
if (! $order->isPay()) {
return $this->failed('退款失败,未找到支付信息');
}
try {
(new Refund)->user($user)
->remark($remark)
->order($order)
->logs([
'remark' => $remark,
'title' => $title,
'pictures' => $pictures,
])
->create();
return $this->success('提交成功,请等待审核。');
} catch (Exception $e) {
return $this->failed($e->getMessage());
}
}
/**
* Notes : 个人中心对订单的总数
*
* @Date : 2021/6/3 13:36
* @Author : Mr.wang
* @return mixed
*/
public function counts()
{
$orderCount = Order::byUser(Api::user())->common()->count();
$refundCount = RefundModel::byUser(Api::user())->count();
return $this->success([
'orderCount' => $orderCount,
'refundCount' => $refundCount,
]);
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\Mall\Http\Resources\Api\Order\OrderPayResource;
use Modules\Mall\Models\Order;
class PayController extends Controller
{
public function index(Order $order)
{
return $this->success(new OrderPayResource($order));
}
/**
* Notes: 微信支付
*
* @Author: 玄尘
* @Date : 2021/5/20 9:11
* @param \Modules\Mall\Models\Order $order
* @return mixed
* @throws \Exception
*/
public function wechat(Request $request, Order $order)
{
$user = Api::user();
$gateway = $request->type ?? 'mp';
$openid = $request->openid ?? '';
if (! $order->can('pay')) {
return $this->failed('支付失败,订单不可支付');
}
if ($order->user()->isNot($user)) {
return $this->failed('支付失败,您没有权限支付');
}
if (! $openid) {
$openid = $user->wechat->getUserOpenid($gateway);
}
$extends = [
'notify_url' => route('api.payment.notify.wechat'),
'payer' => [
'openid' => $openid,
],
];
$total = $order->total;
$payment = $order->createWechatPayment($user, $total, $gateway);
$notify = $payment->getPaymentParams('商品下单', $extends);
$data = [
'wechat' => $notify->toJson(),
'total' => $payment->total,
];
return $this->success($data);
}
/**
* Notes: 支付宝支付
*
* @Author: 玄尘
* @Date : 2021/5/20 9:13
* @param \Modules\Mall\Models\Order $order
* @return mixed
* @throws \Exception
*/
public function alipay(Order $order)
{
$user = Api::user();
if (! $order->can('pay')) {
return $this->failed('支付失败,订单不可支付');
}
if ($order->user()->isNot($user)) {
return $this->failed('支付失败,您没有权限支付');
}
$payment = $order->createAlipayPayment($user, $order->total, 'app');
$notify = $payment->getPaymentParams('商品下单', [
'notify_url' => route('api.payment.notify.alipay'),
]);
return $this->success($notify->getContent());
}
/**
* Notes: 水滴支付
*
* @Author: 玄尘
* @Date: 2022/9/5 15:51
* @param Order $order
* @return JsonResponse|mixed
* @throws \Exception
*/
public function score(Order $order, Request $request)
{
$gateway = $request->gateway ?? 'web';
$user = Api::user();
if (! $order->can('pay')) {
return $this->failed('支付失败,订单不可支付');
}
if ($order->user()->isNot($user)) {
return $this->failed('支付失败,您没有权限支付');
}
if ($user->account->score < $order->total) {
return $this->failed('支付失败,您水滴积分不足');
}
$payment = $order->createScorePayment($user, $order->total, $gateway);
if ($payment) {
$payment->paid();
$payment->order->pay();
return $this->success('支付成功!');
} else {
return $this->failed('未知错误');
}
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\Mall\Http\Resources\Api\Order\RefundCollection;
use Modules\Mall\Http\Resources\Api\Order\RefundLogResource;
use Modules\Mall\Http\Resources\Api\Order\RefundResource;
use Modules\Mall\Models\Refund;
class RefundController extends Controller
{
/**
* Notes: 走退货流程的订单
* @Author: 玄尘
* @Date : 2021/5/18 9:02
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
$state = $request->state ?? 'refunding';//refunding refunded
$list = Refund::byUser(Api::user())
->when($state, function ($query) use ($state) {
switch ($state) {
case 'refunding':
$query->whereIn('state', [
Refund::REFUND_APPLY,
Refund::REFUND_AGREE,
Refund::REFUND_PROCESS,
Refund::REFUND_DELIVER,
Refund::REFUND_DELIVERED,
Refund::REFUND_SIGNED,
]);
break;
case 'refunded':
$query->whereIn('state', [
Refund::REFUND_REFUSE,
Refund::REFUND_COMPLETED,
]);
break;
}
})
->paginate();
return $this->success(new RefundCollection($list));
}
/**
* Notes: 退单详情
* @Author: 玄尘
* @Date : 2021/5/18 11:35
* @param \Modules\Mall\Models\Refund $refund
* @return mixed
*/
public function show(Refund $refund)
{
if ($refund->user()->isNot(Api::user())) {
return $this->failed('您没有权限查看', 404);
}
return $this->success(new RefundResource($refund));
}
/**
* Notes: 退货
* @Author: 玄尘
* @Date : 2021/5/17 15:02
* @param \Modules\Mall\Models\Refund $refund
* @param \Illuminate\Http\Request $request
* @return mixed
* @throws \Exception
*/
public function deliver(Refund $refund, Request $request)
{
if ($refund->user()->isNot(Api::user())) {
return $this->failed('您没有权限操作');
}
$validator = Validator::make($request->all(), [
'company' => 'required',
'number' => 'required',
], [
'company.required' => '缺少物流公司',
'number.required' => '缺少物流单号',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
// $express = Express::find($request->company);
// if (!$express) {
// return $this->failed('未找到物流公司');
// }
$res = $refund->deliver($request->company, $request->number);
if ($res === true) {
return $this->success('退货成功,请等待退款');
}
return $this->failed('退货失败');
}
/**
* Notes: 退单日志
* @Author: 玄尘
* @Date : 2021/5/18 11:36
* @param \Modules\Mall\Models\Refund $refund
* @return \Illuminate\Http\JsonResponse
*/
public function logs(Refund $refund): JsonResponse
{
$logs = $refund->logs()->latest()->get();
return $this->success(RefundLogResource::collection($logs));
}
}

View File

@@ -0,0 +1,210 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Jason\Api\Api;
use Modules\Mall\Http\Requests\Shop\ShopRequest;
use Modules\Mall\Http\Resources\Api\Region\RegionResource;
use Modules\Mall\Http\Resources\Api\Shop\ShopCollection;
use Modules\Mall\Http\Resources\Api\Shop\ShopEditResource;
use Modules\Mall\Http\Resources\Api\Shop\ShopResource;
use Modules\Mall\Models\Region;
use Modules\Mall\Models\Shop;
use Modules\Mall\Rules\CityRule;
use Modules\Mall\Rules\DistrictRule;
use Modules\Mall\Rules\ProvinceRule;
class ShopController extends Controller
{
/**
* Notes : 全部店铺列表
* @Date : 2021/8/26 3:40 下午
* @Author : <Jason.C>
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
$name = $request->name ?? '';
$list = Shop::where('status', Shop::STATUS_NORMAL)
->when($name, function (Builder $query) use ($name) {
$query->where('name', 'like', "%{$name}%");
})
->paginate();
return $this->success(new ShopCollection($list));
}
/**
* Notes : 店铺详情
* @Date : 2021/5/6 3:28 下午
* @Author : <Jason.C>
*/
public function show(Shop $shop): JsonResponse
{
if ($shop->status !== Shop::STATUS_NORMAL) {
return $this->failed('店铺不存在或已关闭');
}
return $this->success(new ShopResource($shop));
}
/**
* Notes : 申请的前置判断和基础数据
* @Date : 2021/5/6 3:29 下午
* @Author : <Jason.C>
*/
public function create()
{
$user = Api::user();
$checkShop = Shop::firstWhere('user_id', $user->id);
if ($checkShop) {
return $this->failed('用户已有店铺,不能重复申请');
}
$regions = Region::where('depth', 1)->get();
return $this->success(RegionResource::collection($regions));
}
/**
* Notes : 申请一个店铺
* @Date : 2021/5/6 3:29 下午
* @Author : <Jason.C>
*/
public function store(ShopRequest $request)
{
$user = Api::user();
if (Shop::firstWhere('user_id', $user->id)) {
return $this->failed('用户已有店铺,不能重复申请');
}
$result = Shop::create([
'name' => $request->name,
'user_id' => $user->id,
'mobile' => $request->mobile,
'description' => $request->description,
'province_id' => $request->province_id,
'city_id' => $request->city_id,
'district_id' => $request->district_id,
'cover' => $request->cover,
'address' => $request->address,
'status' => Shop::STATUS_APPLYING,
]);
if ($result) {
return $this->success('操作成功');
} else {
return $this->failed('失败');
}
}
/**
* Notes : 编辑店铺需要的数据
* @Date : 2021/5/7 10:26 上午
* @Author : <Jason.C>
*/
public function edit()
{
$user = Api::user();
$shop = Shop::firstWhere('user_id', $user->id);
if (!$shop) {
return $this->failed('用户没有店铺,不能编辑');
}
if ($shop->status == Shop::STATUS_NORMAL) {
return $this->failed('用户已通过审核,不能编辑');
}
return $this->success(new ShopEditResource($shop));
}
/**
* Notes : 更新店铺数据
* @Date : 2021/5/7 10:27 上午
* @Author : <Jason.C>
*/
public function update(Request $request)
{
$user = Api::user();
$shop = Shop::firstWhere('user_id', $user->id);
if (!$shop) {
return $this->failed('用户没有店铺,不能编辑');
}
if ($shop->status == Shop::STATUS_NORMAL) {
return $this->failed('用户已通过审核,不能编辑');
}
$validator = Validator::make(
$request->all(),
[
'name' => ['required', Rule::unique('mall_shops', 'name')->ignore($shop->id)],
'mobile' => [
'required', 'phone:CN', Rule::unique('mall_shops', 'mobile')->ignore($shop->id),
],
'description' => 'required',
'province_id' => ['required', 'integer', new ProvinceRule()],
'city_id' => ['required', 'integer', new CityRule()],
'district_id' => ['required', 'integer', new DistrictRule()],
'address' => 'required',
'cover' => 'required',
], [
'name.required' => '店铺名称必须填写',
'name.unique' => '店铺名称不能重复',
'mobile.required' => '联系方式必须填写',
'mobile.phone' => '联系方式格式不正确',
'mobile.unique' => '联系方式不能重复',
'description.required' => '店铺简介必须填写',
'province_id.required' => '店铺所在省份必须选择',
'province_id.integer' => '店铺所在省份格式不正确',
'city_id.required' => '店铺所在城市必须选择',
'city_id.integer' => '店铺所在城市格式不正确',
'district_id.required' => '店铺所在地区必须选择',
'district_id.integer' => '店铺所在地区格式不正确',
'address.required' => '店铺详细地址必须填写',
'cover.required' => '店铺封面图必须上传',
]
);
if ($validator->fails()) {
return $this->failed($validator->errors()->first(), 422);
}
$result = $shop->update([
'name' => $request->name,
'mobile' => $request->mobile,
'description' => $request->description,
'province_id' => $request->province_id,
'city_id' => $request->city_id,
'district_id' => $request->district_id,
'cover' => $request->cover,
'address' => $request->address,
'status' => Shop::STATUS_APPLYING,
]);
if ($result) {
return $this->success('操作成功');
} else {
return $this->failed('失败');
}
}
/**
* Notes : 关闭店铺
* @Date : 2021/5/6 3:29 下午
* @Author : <Jason.C>
*/
public function destroy(Shop $shop)
{
if ($shop->user()->isNot(Api::user())) {
return $this->failed('', '404');
}
if ($shop->close()) {
return $this->success('店铺关闭成功');
} else {
return $this->failed('失败');
}
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Modules\Mall\Http\Resources\Api\Banner\BannerResource;
use Modules\Mall\Http\Resources\Api\Category\CategoryResource;
use Modules\Mall\Http\Resources\Api\Goods\BrandResource;
use Modules\Mall\Http\Resources\Api\Goods\TagResource;
use Modules\Mall\Http\Resources\Api\Shop\ExpressResource;
use Modules\Mall\Models\Shop;
class ShopExtendController extends Controller
{
/**
* Notes : 店铺的分类列表
* @Date : 2021/5/13 10:28 上午
* @Author : <Jason.C>
* @param \Modules\Mall\Models\Shop $shop
* @return \Illuminate\Http\JsonResponse
*/
public function categories(Shop $shop): JsonResponse
{
$list = $shop->categories()->where('parent_id', 0)->get();
return $this->success(CategoryResource::collection($list));
}
/**
* Notes : 店铺标签
* @Date : 2021/5/13 11:35 上午
* @Author : <Jason.C>
* @param \Modules\Mall\Models\Shop $shop
* @return \Illuminate\Http\JsonResponse
*/
public function tags(Shop $shop): JsonResponse
{
$list = $shop->tags()->get();
return $this->success(TagResource::collection($list));
}
/**
* Notes : 店铺品牌
* @Date : 2021/5/13 11:35 上午
* @Author : <Jason.C>
* @param \Modules\Mall\Models\Shop $shop
* @return \Illuminate\Http\JsonResponse
*/
public function brands(Shop $shop): JsonResponse
{
$list = $shop->brands()->get();
return $this->success(BrandResource::collection($list));
}
/**
* Notes : 支持的物流
* @Date : 2021/5/13 11:36 上午
* @Author : <Jason.C>
* @param \Modules\Mall\Models\Shop $shop
* @return \Illuminate\Http\JsonResponse
*/
public function expresses(Shop $shop): JsonResponse
{
$list = $shop->expresses()->get();
return $this->success(ExpressResource::collection($list));
}
/**
* Notes : 轮播图
* @Date : 2021/5/13 11:36 上午
* @Author : <Jason.C>
* @param \Modules\Mall\Models\Shop $shop
* @return \Illuminate\Http\JsonResponse
*/
public function banners(Shop $shop): JsonResponse
{
$list = $shop->banners()->get();
return $this->success(BannerResource::collection($list));
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Modules\Mall\Http\Controllers\Api;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\Mall\Http\Resources\Api\Goods\TagResource;
use Modules\Mall\Models\Tag;
class TagController extends Controller
{
/**
* Notes : 标签列表
* @Date : 2021/6/3 2:20 下午
* @Author : <Jason.C>
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
$shopId = $request->shop_id;
$limit = $request->limit;
$list = Tag::when($shopId, function (Builder $query) use ($shopId) {
$query->where('shop_id', $shopId);
})->when($limit, function (Builder $query) use ($limit) {
$query->take($limit);
})->get();
return $this->success(TagResource::collection($list));
}
}