pull/3/head
chen 8 months ago
parent cbc671aaeb
commit d0eae0fcb2

@ -8,15 +8,24 @@ use Illuminate\Database\Eloquent\Model;
class ActiveUserAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '激活';
/**
* 处理激活用户的逻辑
*
* @param User $model 被激活的用户模型
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(User $model)
{
// $model ...
// 将用户的激活状态设置为 1激活
$model->is_active = 1;
// 保存用户模型的更改
$model->save();
// 返回成功响应并刷新页面
return $this->response()->success('操作成功.')->refresh();
}
}

@ -7,22 +7,32 @@ use Illuminate\Database\Eloquent\Model;
class DividerAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '分隔线';
/**
* 处理分隔线的逻辑
*
* @param Model $model 当前行的模型实例
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(Model $model)
{
// $model ...
// 此处可以添加处理逻辑,当前实现中不执行任何操作
// 例如,可以记录日志或执行其他操作
// 返回成功响应并刷新页面
return $this->response()->success('Success message.')->refresh();
}
/**
* Render row action.
* 渲染行操作的HTML
*
* @return string
* @return string 返回HTML字符串用于显示分隔线
*/
public function render()
{
// 返回一个包含分隔线的列表项HTML
return '<li class="divider"></li>';
}
}

@ -8,23 +8,38 @@ use Illuminate\Http\Request;
class ForceDeleteProductAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '删除';
/**
* 处理强制删除产品的逻辑
*
* @param Product $product 被删除的产品模型
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(Product $product)
{
// 调用模型的 forceDelete 方法,永久删除产品
$product->forceDelete();
// 返回成功响应并刷新页面
return $this->response()->success('操作成功.')->refresh();
}
/**
* 从请求中检索产品模型
*
* @param Request $request 当前请求实例
* @return Product|false 返回找到的产品模型或 false
*/
public function retrieveModel(Request $request)
{
// 从请求中获取 '_key' 参数
if (!$key = $request->get('_key')) {
return false;
return false; // 如果没有找到 '_key',返回 false
}
// 使用 withTrashed 方法查询包括已删除的产品,并根据找到的键查找产品
return Product::query()->withTrashed()->findOrFail($key);
}
}

@ -5,30 +5,39 @@ namespace App\Admin\Actions\Post;
use App\Enums\OrderShipStatusEnum;
use App\Enums\OrderStatusEnum;
use App\Models\Order;
use App\Models\User;
use Encore\Admin\Actions\RowAction;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
class OrderReceivedAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '确认收货';
/**
* 处理确认收货的逻辑
*
* @param Order $order 当前订单模型实例
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(Order $order)
{
// 检查订单状态是否为已付款
if ($order->status != OrderStatusEnum::PAID) {
// 如果未付款,返回错误信息
return back()->withErrors('订单未付款', 'error');
}
// 检查订单的发货状态是否为已发货
if ($order->ship_status != OrderShipStatusEnum::DELIVERED) {
// 如果未发货,返回错误信息
return back()->withErrors('订单未发货', 'error');
}
// 更新订单的发货状态为已收货
$order->ship_status = OrderShipStatusEnum::RECEIVED;
// 保存订单的更改
$order->save();
// 返回成功响应并刷新页面
return $this->response()->success('确认收货成功.')->refresh();
}
}

@ -5,55 +5,69 @@ namespace App\Admin\Actions\Post;
use App\Enums\OrderShipStatusEnum;
use App\Enums\OrderStatusEnum;
use App\Models\Order;
use App\Models\User;
use Encore\Admin\Actions\RowAction;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Yansongda\Pay\Pay;
class OrderRefundAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '退款';
/**
* 处理订单退款的逻辑
*
* @param Order $order 当前订单模型实例
* @param Request $request 当前请求实例
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(Order $order, Request $request)
{
// 订单必须申请支付了,才可才可以退款
// 检查订单状态是否为申请退款
if ($order->status != OrderStatusEnum::APPLY_REFUND) {
// 如果当前状态不允许退款,返回错误信息
return $this->response()->error('订单当前状态禁止退款');
}
// 创建支付宝支付实例
$pay = Pay::alipay(config('pay.ali'));
// 退款数据
// 准备退款数据
$refundData = [
'out_trade_no' => $order->no,
'trade_no' => $order->pay_no,
'refund_amount' => $order->pay_amount,
'refund_reason' => '正常退款',
'out_trade_no' => $order->no, // 订单号
'trade_no' => $order->pay_no, // 支付交易号
'refund_amount' => $order->pay_amount, // 退款金额
'refund_reason' => '正常退款', // 退款原因
];
try {
// 将订单状态改为退款
// 发起退款请求
$response = $pay->refund($refundData);
$order->pay_refund_fee = $response->get('refund_fee');
$order->pay_trade_no = $response->get('trade_no');
$order->status = OrderStatusEnum::REFUND;
$order->save();
} catch (\Exception $e) {
// 更新订单的退款信息
$order->pay_refund_fee = $response->get('refund_fee'); // 设置退款金额
$order->pay_trade_no = $response->get('trade_no'); // 设置退款交易号
$order->status = OrderStatusEnum::REFUND; // 更新订单状态为退款
$order->save(); // 保存订单的更改
// 调用异常的处理
// abort(500, $e->getMessage());
return $this->response()->error('服务器异常,请稍后再试');
} catch (\Exception $e) {
// 处理异常情况
// abort(500, $e->getMessage()); // 可选:抛出异常
return $this->response()->error('服务器异常,请稍后再试'); // 返回错误信息
}
// 返回成功响应并刷新页面
return $this->response()->success('退款成功.')->refresh();
}
/**
* 显示退款确认对话框
*
* @return void
*/
public function dialog()
{
// 确认退款操作
$this->confirm('退款会直接把钱退回到支付账户,是否继续');
}
}

@ -5,40 +5,59 @@ namespace App\Admin\Actions\Post;
use App\Enums\OrderShipStatusEnum;
use App\Enums\OrderStatusEnum;
use App\Models\Order;
use App\Models\User;
use Encore\Admin\Actions\RowAction;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
class OrderShipAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '发货';
/**
* 处理订单发货的逻辑
*
* @param Order $order 当前订单模型实例
* @param Request $request 当前请求实例
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(Order $order, Request $request)
{
// 检查订单状态是否为已付款
if ($order->status != OrderStatusEnum::PAID) {
// 如果未付款,返回错误信息
return $this->response()->error('订单未付款');
}
$company = $request->input('company');
$no = $request->input('no');
if (empty($company) || empty($no)) {
// 获取物流公司和物流单号
$company = $request->input('company'); // 物流公司
$no = $request->input('no'); // 物流单号
// 检查物流公司和物流单号是否为空
if (empty($company) || empty($no)) {
// 如果有必填项为空,返回错误信息
return $this->response()->error('必填项不能为空');
}
$order->ship_status = OrderShipStatusEnum::DELIVERED;
$order->express_company = $company;
$order->express_no = $no;
$order->save();
// 更新订单的发货状态和物流信息
$order->ship_status = OrderShipStatusEnum::DELIVERED; // 设置发货状态为已发货
$order->express_company = $company; // 设置物流公司
$order->express_no = $no; // 设置物流单号
$order->save(); // 保存订单的更改
// 返回成功响应并刷新页面
return $this->response()->success('发货成功.')->refresh();
}
/**
* 定义发货表单
*
* @return void
*/
public function form()
{
// 定义物流公司输入框,设置为必填项
$this->text('company', '物流公司')->required();
// 定义物流单号输入框,设置为必填项
$this->text('no', '物流单号')->required();
}
}

@ -8,39 +8,57 @@ use Illuminate\Http\Request;
class ProductStatusAction extends RowAction
{
// 动作名称,显示在界面上的按钮文本
public $name = '';
/**
* 设置动作名称
*
* @param string $name 动作名称
* @return $this 返回当前实例,以便链式调用
*/
public function setName($name)
{
$this->name = $name;
$this->name = $name; // 设置动作名称
return $this;
return $this; // 返回当前实例
}
/**
* 处理商品状态的逻辑
*
* @param Product $product 当前商品模型实例
* @return \Encore\Admin\Actions\Response 返回操作结果的响应
*/
public function handle(Product $product)
{
// $model ...
// 如果商品已经下架
// 检查商品是否已下架
if ($product->trashed()) {
// 重新上架
// 如果商品已下架,则重新上架
$product->restore();
} else {
// 如果商品未下架,则进行下架操作
$product->delete();
}
// 返回成功响应并刷新页面
return $this->response()->success('操作成功.')->refresh();
}
/**
* 从请求中检索商品模型
*
* @param Request $request 当前请求实例
* @return Product|false 返回找到的商品模型实例,或返回 false
*/
public function retrieveModel(Request $request)
{
// 从请求中获取商品的唯一键
if (!$key = $request->get('_key')) {
return false;
return false; // 如果没有提供键,则返回 false
}
// 查找并返回商品模型,包括已删除的商品
return Product::query()->withTrashed()->findOrFail($key);
}
}

@ -14,105 +14,133 @@ use Illuminate\Support\Facades\Validator;
class AdminController extends BaseAuthController
{
// 覆盖默认的
/**
* 显示管理员列表页面
*
* @param Content $content 内容区域
* @return Content 返回构建好的内容
*/
public function index(Content $content)
{
return $content
->header(trans('admin.administrator'))
->description(trans('admin.list'))
->body($this->adminGrid()->render());
->header(trans('admin.administrator')) // 设置页面标题
->description(trans('admin.list')) // 设置页面描述
->body($this->adminGrid()->render()); // 渲染管理员网格
}
/**
* 创建管理员网格
*
* @return Grid 返回管理员网格实例
*/
protected function adminGrid()
{
// 获取用户模型
$userModel = config('admin.database.users_model');
// 创建新的网格实例
$grid = new Grid(new $userModel());
$grid->column('id', 'ID')->sortable();
$grid->column('username', trans('admin.username'));
$grid->column('name', trans('admin.name'));
$grid->column('login_ip', '登录ip');
$grid->roles(trans('admin.roles'))->pluck('name')->label();
$grid->column('created_at', trans('admin.created_at'));
$grid->column('updated_at', trans('admin.updated_at'));
// 定义网格的列
$grid->column('id', 'ID')->sortable(); // ID 列,支持排序
$grid->column('username', trans('admin.username')); // 用户名列
$grid->column('name', trans('admin.name')); // 姓名列
$grid->column('login_ip', '登录ip'); // 登录 IP 列
$grid->roles(trans('admin.roles'))->pluck('name')->label(); // 角色列,显示角色名称
$grid->column('created_at', trans('admin.created_at')); // 创建时间列
$grid->column('updated_at', trans('admin.updated_at')); // 更新时间列
// 自定义操作按钮
$grid->actions(function (Grid\Displayers\DropdownActions $actions) {
// 禁用 ID 为 1 的管理员的删除操作
if ($actions->getKey() == 1) {
$actions->disableDelete();
}
});
// 自定义工具栏
$grid->tools(function (Grid\Tools $tools) {
$tools->batch(function (Grid\Tools\BatchActions $actions) {
// 禁用批量删除操作
$actions->disableDelete();
});
});
return $grid;
return $grid; // 返回创建的网格
}
/**
* 显示操作日志页面
*
* @param Content $content 内容区域
* @return Content 返回构建好的内容
*/
public function indexLogs(Content $content)
{
return $content
->header(trans('admin.operation_log'))
->description(trans('admin.list'))
->body($this->logGrid());
->header(trans('admin.operation_log')) // 设置页面标题
->description(trans('admin.list')) // 设置页面描述
->body($this->logGrid()); // 渲染操作日志网格
}
/**
* @return Grid
* 创建操作日志网格
*
* @return Grid 返回操作日志网格实例
*/
protected function logGrid()
{
// 创建新的操作日志网格实例
$grid = new Grid(new OperationLog());
// 按照 ID 降序排列
$grid->model()->orderBy('id', 'DESC');
$grid->column('id', 'ID')->sortable();
$grid->column('user.name', '用户');
// 定义网格的列
$grid->column('id', 'ID')->sortable(); // ID 列,支持排序
$grid->column('user.name', '用户'); // 用户列,显示用户名
$grid->column('method', '方法')->display(function ($method) {
// 根据方法类型设置颜色
$color = array_get(OperationLog::$methodColors, $method, 'grey');
return "<span class=\"badge bg-$color\">$method</span>";
return "<span class=\"badge bg-$color\">$method</span>"; // 返回带颜色的标签
});
$grid->column('path', '路径')->label('info');
$grid->column('ip', '地址')->label('primary');
$grid->column('path', '路径')->label('info'); // 路径列
$grid->column('ip', '地址')->label('primary'); // IP 地址列
$grid->column('description', '描述')->limit(20)->modal(function ($model) {
// 描述列,点击可弹出详细信息
return new Box('详情', $model->description ?: ' ');
});
$grid->column('input', '输入数据')->limit(20)->expand(function ($model) {
// 输入数据列,点击可展开显示详细信息
$input = json_decode($model->input, true);
$input = array_except($input, ['_pjax', '_token', '_method', '_previous_']);
$codes = empty($input) ?
'<code>{}</code>' :
'<pre>' . json_encode($input, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . '</pre>';
return new Box('详情', $codes);
return new Box('详情', $codes); // 返回输入数据的详细信息
});
$grid->column('created_at', trans('admin.created_at'));
$grid->column('created_at', trans('admin.created_at')); // 创建时间列
// 自定义操作按钮
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableView();
$actions->disableEdit(); // 禁用编辑操作
$actions->disableView(); // 禁用查看操作
});
$grid->disableCreateButton();
$grid->disableCreateButton(); // 禁用创建按钮
// 自定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$userModel = config('admin.database.users_model');
$filter->equal('user_id', 'User')->select($userModel::all()->pluck('name', 'id'));
$filter->equal('method')->select(array_combine(OperationLog::$methods, OperationLog::$methods));
$filter->like('path');
$filter->equal('ip');
// 添加过滤选项
$filter->equal('user_id', 'User')->select($userModel::all()->pluck('name', 'id')); // 按用户过滤
$filter->equal('method')->select(array_combine(OperationLog::$methods, OperationLog::$methods)); // 按方法过滤
$filter->like('path'); // 按路径过滤
$filter->equal('ip'); // 按 IP 过滤
});
return $grid;
return $grid; // 返回创建的操作日志网格
}
}

@ -11,89 +11,96 @@ use Encore\Admin\Show;
class ArticleNotificationController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题
*
* @var string
*/
protected $title = '通知文章';
/**
* Make a grid builder.
* 创建网格构建器
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
// 创建新的网格实例
$grid = new Grid(new ArticleNotification);
// 按照最新的通知排序
$grid->model()->latest();
$grid->column('id', __('Id'));
$grid->column('title', __('Title'));
$grid->column('created_at', __('Created at'));
// 定义网格的列
$grid->column('id', __('Id')); // ID 列
$grid->column('title', __('Title')); // 标题列
$grid->column('created_at', __('Created at')); // 创建时间列
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->like('id', __('Id'));
$filter->like('title', __('Title'));
$filter->like('id', __('Id')); // 按 ID 过滤
$filter->like('title', __('Title')); // 按标题过滤
});
// 自定义操作按钮
$grid->actions(function (Grid\Displayers\DropdownActions $actions) {
$actions->disableEdit();
$actions->disableEdit(); // 禁用编辑操作
});
return $grid;
return $grid; // 返回创建的网格
}
/**
* Make a show builder.
* 创建详情展示构建器
*
* @param mixed $id
* @return Show
* @param mixed $id 通知文章的 ID
* @return Show 返回详情展示实例
*/
protected function detail($id)
{
// 创建新的详情展示实例
$show = new Show(ArticleNotification::findOrFail($id));
$show->field('id', __('Id'));
$show->field('title', __('Title'));
$show->field('content', __('Content'))->unescape();
$show->field('created_at', __('Created at'));
// 定义展示的字段
$show->field('id', __('Id')); // ID 字段
$show->field('title', __('Title')); // 标题字段
$show->field('content', __('Content'))->unescape(); // 内容字段,允许 HTML 解码
$show->field('created_at', __('Created at')); // 创建时间字段
return $show;
return $show; // 返回创建的详情展示
}
/**
* Make a form builder.
* 创建表单构建器
*
* @return Form
* @return Form 返回表单实例
*/
protected function form()
{
// 创建新的表单实例
$form = new Form(new ArticleNotification);
$form->text('title', __('Title'))->help('请再三确认再发布,不可修改');
$form->kindeditor('content', __('Content'));
// 定义表单字段
$form->text('title', __('Title'))->help('请再三确认再发布,不可修改'); // 标题字段,带帮助信息
$form->kindeditor('content', __('Content')); // 内容字段,使用富文本编辑器
// 保存事件
$form->saving(function (Form $form) {
// 检查当前环境是否为开发环境
if (app()->environment('dev')) {
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
admin_toastr('开发环境不允许操作', 'error'); // 提示用户
return back()->withInput(); // 返回到表单
}
});
// 删除事件
$form->deleting(function (Form $form) {
// 检查当前环境是否为开发环境
if (app()->environment('dev')) {
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
admin_toastr('开发环境不允许操作', 'error'); // 提示用户
return back()->withInput(); // 返回到表单
}
});
return $form;
return $form; // 返回创建的表单
}
}

@ -1,87 +1,90 @@
<?php
namespace App\Admin\Controllers;
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Controllers\AuthController as BaseAuthController;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Encore\Admin\Auth\Database\Administrator; // 引入管理员模型
use Encore\Admin\Controllers\AuthController as BaseAuthController; // 继承 Encore\Admin 的 AuthController
use Encore\Admin\Facades\Admin; // 引入 Admin 门面
use Encore\Admin\Form; // 引入表单处理类
use Encore\Admin\Grid; // 引入 Grid 类
use Encore\Admin\Layout\Content; // 引入布局类
use Illuminate\Http\Request; // 引入请求类
use Illuminate\Support\Facades\Validator; // 引入验证器
class AuthController extends BaseAuthController
{
/**
* 覆盖默认的登录方法
*
* @param Request $request
*
* @return mixed
*/
public function postLogin(Request $request)
{
// 获取用户名和密码
$credentials = $request->only([$this->username(), 'password']);
/** @var \Illuminate\Validation\Validator $validator */
// 对输入的凭证进行验证
$validator = Validator::make($credentials, [
$this->username() => 'required',
'password' => 'required',
$this->username() => 'required', // 用户名为必填
'password' => 'required', // 密码为必填
]);
// 如果验证失败,返回错误信息
if ($validator->fails()) {
return back()->withInput()->withErrors($validator);
}
// 如果验证通过,尝试进行身份验证
if ($this->guard()->attempt($credentials)) {
// 验证是否登录的 ip
// 登录成功后,执行身份验证后的操作(比如记录 IP 地址)
$this->authenticated($this->guard()->user());
// 记录登录日期
// 记录登录日期并返回成功响应
return $this->sendLoginResponse($request);
}
// 如果身份验证失败,返回失败信息
return back()->withInput()->withErrors([
$this->username() => $this->getFailedLoginMessage(),
$this->username() => $this->getFailedLoginMessage(), // 获取失败的登录信息
]);
}
/**
* 登录之后提示 ip 地址
* 登录之后提示 IP 地址
*
* @param Administrator $user
*/
protected function authenticated(Administrator $user)
{
$ip = request()->getClientIp();
$ip = request()->getClientIp(); // 获取当前登录用户的 IP 地址
// 如果两次 ip 不一样, 提示风险
// 如果当前登录 IP 与上次登录的 IP 不一致,提示风险
if (! is_null($user->login_ip) && $ip != $user->login_ip) {
admin_info('上一次登录的地址与本次不同,如果不是本人操作,建议及时修改密码');
}
// 更新用户的登录 IP 地址
$user->login_ip = $ip;
$user->save();
$user->save(); // 保存更新后的 IP 地址
}
/**
* 设置更新操作
*/
public function putSetting()
{
$form = $this->settingForm();
$form = $this->settingForm(); // 获取设置表单
// 表单提交时的处理逻辑
$form->submitted(function (Form $form) {
// 如果是开发环境,则禁止操作
if (app()->environment('dev')) {
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
admin_toastr('开发环境不允许操作', 'error'); // 显示错误提示
return back()->withInput(); // 返回上一页面并保留输入
}
});
return $form->update(Admin::user()->id);
// 执行设置更新
return $form->update(Admin::user()->id); // 更新当前登录用户的设置
}
}

@ -2,89 +2,92 @@
namespace App\Admin\Controllers;
use App\Models\Car;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use App\Models\Car; // 引入 Car 模型
use Encore\Admin\Controllers\AdminController; // 引入 AdminController 作为基类
use Encore\Admin\Form; // 引入表单构建类
use Encore\Admin\Grid; // 引入网格(列表)构建类
use Encore\Admin\Show; // 引入详情展示类
class CarController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题(在界面上显示)
*
* @var string
*/
protected $title = '购物车数据';
protected $title = '购物车数据'; // 设置控制器的标题为 "购物车数据"
/**
* Make a grid builder.
* 创建网格(列表)视图.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new Car);
$grid = new Grid(new Car); // 实例化 Grid使用 Car 模型作为数据源
$grid->column('id', __('Id'));
// 定义要在网格中显示的列
$grid->column('id', __('Id')); // ID 列
$grid->column('user_id', __('User id')); // 用户 ID 列
$grid->column('product_id', __('Product id')); // 商品 ID 列
$grid->column('user_id', __('User id'));
$grid->column('product_id', __('Product id'));
// 显示用户和商品的名称,假设它们通过 Eloquent 关系关联
$grid->column('user.name', '用户'); // 用户名称列
$grid->column('product.name', '商品'); // 商品名称列
$grid->column('number', __('Number')); // 数量列
$grid->column('user.name', '用户');
$grid->column('product.name', '商品');
$grid->column('number', __('Number'));
$grid->column('created_at', '收藏时间'); // 创建时间列
// 禁用默认操作按钮和创建按钮
$grid->disableActions(); // 禁用行操作按钮
$grid->disableCreateButton(); // 禁用创建按钮
$grid->column('created_at', '收藏时间');
$grid->disableActions();
$grid->disableCreateButton();
// 添加过滤条件设置
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('user_id', '用户ID');
$filter->equal('product_id', '商品ID');
$filter->like('user.name', '用户名');
$filter->like('product.name', '商品');
$filter->equal('user_id', '用户ID'); // 精确匹配用户 ID
$filter->equal('product_id', '商品ID'); // 精确匹配商品 ID
$filter->like('user.name', '用户名'); // 用户名模糊查询
$filter->like('product.name', '商品'); // 商品名称模糊查询
});
return $grid;
return $grid; // 返回配置好的网格实例
}
/**
* Make a show builder.
* 创建详情显示视图.
*
* @param mixed $id
* @return Show
*/
protected function detail($id)
{
$show = new Show(Car::findOrFail($id));
$show = new Show(Car::findOrFail($id)); // 获取指定 ID 的 Car 实例,并实例化 Show 类
$show->field('id', __('Id'));
$show->field('number', __('Number'));
$show->field('product_id', __('Product id'));
$show->field('user_id', __('User id'));
$show->field('created_at', __('Created at'));
$show->field('updated_at', __('Updated at'));
// 定义要在详情页面中显示的字段
$show->field('id', __('Id')); // 显示 ID 字段
$show->field('number', __('Number')); // 显示数量字段
$show->field('product_id', __('Product id')); // 显示商品 ID 字段
$show->field('user_id', __('User id')); // 显示用户 ID 字段
$show->field('created_at', __('Created at')); // 显示创建时间字段
$show->field('updated_at', __('Updated at')); // 显示更新时间字段
return $show;
return $show; // 返回 Show 实例
}
/**
* Make a form builder.
* 创建表单用于添加或编辑数据.
*
* @return Form
*/
protected function form()
{
$form = new Form(new Car);
$form = new Form(new Car); // 创建一个新的 Form 实例,用于 Car 模型的数据
$form->number('number', __('Number'))->default(1);
$form->number('product_id', __('Product id'));
$form->number('user_id', __('User id'));
// 定义表单字段
$form->number('number', __('Number'))->default(1); // 数量字段,默认为 1
$form->number('product_id', __('Product id')); // 商品 ID 字段
$form->number('user_id', __('User id')); // 用户 ID 字段
return $form;
return $form; // 返回配置好的表单实例
}
}

@ -16,182 +16,180 @@ use Illuminate\Http\Request;
class CategoryController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 引入资源操作的特性
/**
* Index interface.
* 显示商品分类的首页
*
* @param Content $content
* @return Content
* @return Content 返回构建好的内容
*/
public function index(Content $content)
{
return $content
->header('商品分类')
->description('')
->header('商品分类') // 设置页面标题
->description('') // 页面描述
->row(function (Row $row) {
// 只能在同一级排序拖动,不允许二级
// 创建分类树形结构,限制只能在同一级排序
$row->column(6, Category::tree(function (Tree $tree) {
$tree->disableCreate(); // 禁用创建新分类的功能
$tree->disableCreate();
// 允许拖拽排序且最大深度为1
$tree->nestable(['maxDepth' => 1])
->branch(function ($branch) {
// 自定义树节点的显示格式
$icon = "<i class='fa {$branch['icon']}'></i>";
return $icon . ' ' . $branch['title'];
});
}));
// 新建表单
// 创建新分类的表单
$row->column(6, function (Column $column) {
$form = new \Encore\Admin\Widgets\Form();
$form->action(admin_base_path('categories'));
$form->action(admin_base_path('categories')); // 设置表单提交路径
$form->text('title', '分类名')->rules('required|unique:categories,title');
$form->icon('icon', '图标')->default('fa-bars')->rules('required');
$form->image('thumb', '缩略图')->uniqueName()->rules('required');
$form->hidden('_token')->default(csrf_token());
// 定义表单字段
$form->text('title', '分类名')->rules('required|unique:categories,title'); // 分类名,必填且唯一
$form->icon('icon', '图标')->default('fa-bars')->rules('required'); // 图标,必填
$form->image('thumb', '缩略图')->uniqueName()->rules('required'); // 缩略图,必填
$form->hidden('_token')->default(csrf_token()); // CSRF 令牌
// 将表单添加到页面
$column->append((new Box('新增', $form))->style('success'));
});
});
}
/**
* Show interface.
* 显示分类的详细信息
*
* @param mixed $id
* @param mixed $id 分类ID
* @param Content $content
* @return Content
* @return Content 返回构建好的内容
*/
public function show($id, Content $content)
{
return $content
->header('详情')
->description('')
->body($this->detail($id));
->header('详情') // 设置页面标题
->description('') // 页面描述
->body($this->detail($id)); // 显示分类详细信息
}
/**
* Edit interface.
* 显示编辑分类的界面
*
* @param mixed $id
* @param mixed $id 分类ID
* @param Content $content
* @return Content
* @return Content 返回构建好的内容
*/
public function edit($id, Content $content)
{
return $content
->header('编辑')
->description('')
->body($this->form()->edit($id));
->header('编辑') // 设置页面标题
->description('') // 页面描述
->body($this->form()->edit($id)); // 显示编辑表单
}
/**
* Make a show builder.
* 创建分类详细信息的展示构建器
*
* @param mixed $id
* @return Show
* @param mixed $id 分类ID
* @return Show 返回详细信息展示实例
*/
protected function detail($id)
{
$show = new Show(Category::findOrFail($id));
$show = new Show(Category::findOrFail($id)); // 根据ID查找分类
$show->field('id');
$show->field('title', '分类名');
// 定义展示的字段
$show->field('id'); // ID
$show->field('title', '分类名'); // 分类名
$show->field('thumb', '缩略图')->unescape()->as(function ($thumb) {
return image($thumb);
return image($thumb); // 显示缩略图
});
$show->field('description', '描述');
$show->field('order', '排序');
$show->field('created_at', '创建时间');
$show->field('updated_at', '修改时间');
$show->field('description', '描述'); // 描述
$show->field('order', '排序'); // 排序
$show->field('created_at', '创建时间'); // 创建时间
$show->field('updated_at', '修改时间'); // 修改时间
return $show;
return $show; // 返回详细信息展示
}
/**
* Make a form builder.
* 创建分类的表单构建器
*
* @return Form
* @return Form 返回表单实例
*/
protected function form()
{
$form = new Form(new Category);
$form = new Form(new Category); // 创建新的表单实例
$form->text('title', '分类名');
$form->icon('icon', '图标');
$form->image('thumb', '缩略图');
$form->text('description', '描述');
// 定义表单字段
$form->text('title', '分类名'); // 分类名
$form->icon('icon', '图标'); // 图标
$form->image('thumb', '缩略图'); // 缩略图
$form->text('description', '描述'); // 描述
// 保存前的逻辑
$form->saving(function (Form $form) {
if (app()->environment('dev')) {
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
if (app()->environment('dev')) { // 检查是否在开发环境
admin_toastr('开发环境不允许操作', 'error'); // 提示用户
return back()->withInput(); // 返回到表单
}
});
return $form;
return $form; // 返回创建的表单
}
/**
* 分类下有商品,不允许删除
* 删除分类
*
* @param $id
* @return \Illuminate\Http\JsonResponse
* @param $id 分类ID
* @return \Illuminate\Http\JsonResponse 返回 JSON 响应
*/
public function destroy($id)
{
if (app()->environment('dev')) {
if (app()->environment('dev')) { // 检查是否在开发环境
return response()->json(['status' => false, 'message' => '开发环境不允许操作']);
}
/**
* @var $category Category
*/
$category = Category::query()->findOrFail($id);
/** @var $category Category */
$category = Category::query()->findOrFail($id); // 查找分类
// 检查分类下是否有商品
if ($category->products()->exists()) {
return response()->json(['status' => false, 'message' => '分类下有商品存在,不允许删除']);
}
// 尝试删除分类
if ($category->delete()) {
$data = [
'status' => true,
'message' => trans('admin.delete_succeeded'),
'message' => trans('admin.delete_succeeded'), // 删除成功提示
];
} else {
$data = [
'status' => false,
'message' => trans('admin.delete_failed'),
'message' => trans('admin.delete_failed'), // 删除失败提示
];
}
return response()->json($data);
return response()->json($data); // 返回 JSON 响应
}
/**
* 商品下拉列表
* 获取分类下的商品下拉列表
*
* @param Request $request
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection 返回商品集合
*/
public function getProducts(Request $request)
{
$id = $request->get('q');
$id = $request->get('q'); // 获取请求参数中的分类ID
$category = Category::query()->findOrFail($id);
$category = Category::query()->findOrFail($id); // 查找分类
// 尽量促销卖得少的商品
// 返回分类下的商品,按销量降序排列
return $category->products()->orderBy('sale_count', 'desc')->get(['id', 'name as text']);
}
}

@ -12,62 +12,68 @@ use Encore\Admin\Layout\Content;
class CommentController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 引入资源操作的特性
/**
* Index interface.
* 显示评论列表的界面
*
* @param Content $content
* @return Content
* @return Content 返回构建好的内容
*/
public function index(Content $content)
{
return $content
->header('评论列表')
->description('')
->body($this->grid());
->header('评论列表') // 设置页面标题
->description('') // 页面描述
->body($this->grid()); // 显示评论列表
}
/**
* Make a grid builder.
* 创建评论列表的网格构建器
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new Comment);
$grid = new Grid(new Comment); // 创建新的网格实例,基于 Comment 模型
$grid->model()->latest();
$grid->model()->latest(); // 按照创建时间降序排列评论
$grid->column('id');
$grid->column('order_id', '订单');
$grid->column('product.name', '商品');
$grid->column('user.name', '用户');
$grid->column('content', '评论内容');
$grid->column('score', '评分');
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '修改时间');
// 定义网格列
$grid->column('id'); // 评论ID
$grid->column('order_id', '订单'); // 关联的订单ID
$grid->column('product.name', '商品'); // 关联商品的名称
$grid->column('user.name', '用户'); // 关联用户的名称
$grid->column('content', '评论内容'); // 评论内容
$grid->column('score', '评分'); // 评分
$grid->column('created_at', '创建时间'); // 创建时间
$grid->column('updated_at', '修改时间'); // 修改时间
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->disableIdFilter(); // 禁用ID过滤器
$filter->disableIdFilter();
// 用户过滤器
$filter->where(function ($query) {
// 根据用户名称模糊查询用户ID
$collections = User::query()
->where('name', 'like', "%{$this->input}%")
->pluck('id');
// 根据用户ID过滤评论
$query->whereIn('user_id', $collections->all());
}, '用户');
$filter->where(function ($query) {
// 商品过滤器
$filter->where(function ($query) {
// 根据商品名称模糊查询商品ID
$collections = Product::query()
->where('name', 'like', "%{$this->input}%")
->pluck('id');
// 根据商品ID过滤评论
$query->whereIn('product_id', $collections->all());
}, '商品');
});
return $grid;
return $grid; // 返回构建好的网格
}
}

@ -2,189 +2,191 @@
namespace App\Admin\Controllers;
use App\Enums\UserSexEnum;
use App\Enums\UserSourceEnum;
use App\Models\CouponCode;
use App\Models\CouponTemplate;
use App\Models\User;
use App\Notifications\CouponCodeNotification;
use Carbon\Carbon;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use Illuminate\Http\Request;
use Illuminate\Notifications\DatabaseNotification;
use Ramsey\Uuid\Uuid;
use App\Enums\UserSexEnum; // 用户性别枚举
use App\Enums\UserSourceEnum; // 用户来源枚举
use App\Models\CouponCode; // 优惠券兑换码模型
use App\Models\CouponTemplate; // 优惠券模板模型
use App\Models\User; // 用户模型
use App\Notifications\CouponCodeNotification; // 优惠券通知
use Carbon\Carbon; // 日期时间处理库
use Encore\Admin\Controllers\AdminController; // 管理员控制器基类
use Encore\Admin\Form; // 表单构建器
use Encore\Admin\Grid; // 网格构建器
use Encore\Admin\Show; // 展示构建器
use Illuminate\Http\Request; // 请求处理
use Illuminate\Notifications\DatabaseNotification; // 数据库通知模型
use Ramsey\Uuid\Uuid; // UUID生成库
class CouponCodeController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题.
*
* @var string
*/
protected $title = '优惠券兑换码';
protected $title = '优惠券兑换码'; // 控制器标题
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new CouponCode);
$grid = new Grid(new CouponCode); // 创建新的网格实例,基于 CouponCode 模型
$grid->model()->latest();
$grid->model()->latest(); // 按照创建时间降序排列优惠券兑换码
$grid->column('id', __('Id'));
$grid->column('code', '兑换码');
$grid->column('user_id', __('User id'));
$grid->column('template_id', '优惠券ID');
// 定义网格列
$grid->column('id', __('Id')); // 显示ID
$grid->column('code', '兑换码'); // 显示兑换码
$grid->column('user_id', __('User id')); // 显示用户ID
$grid->column('template_id', '优惠券ID'); // 显示优惠券模板ID
$grid->column('user.name', '会员名');
$grid->column('template.title', '优惠券名');
$grid->column('used_at', __('Used at'));
$grid->column('notification_at', '上一次发送通知时间');
$grid->column('created_at', __('Created at'));
// 关联显示用户和优惠券模板的名称
$grid->column('user.name', '会员名'); // 显示会员名称
$grid->column('template.title', '优惠券名'); // 显示优惠券名称
// 显示使用时间和通知时间
$grid->column('used_at', __('Used at')); // 显示使用时间
$grid->column('notification_at', '上一次发送通知时间'); // 显示上一次发送通知的时间
$grid->column('created_at', __('Created at')); // 显示创建时间
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('code', '兑换码');
$filter->like('user.name', '会员名');
$filter->equal('template.title', '优惠券名');
$filter->between('used_at')->datetime();
$filter->equal('code', '兑换码'); // 兑换码过滤
$filter->like('user.name', '会员名'); // 会员名模糊查询
$filter->equal('template.title', '优惠券名'); // 优惠券名过滤
$filter->between('used_at')->datetime(); // 使用时间范围过滤
});
// 禁用编辑和查看操作
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableView();
$actions->disableEdit(); // 禁用编辑按钮
$actions->disableView(); // 禁用查看按钮
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* 存储新的优惠券兑换码.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store()
{
$request = request();
$request = request(); // 获取请求实例
/**
* 发放的优惠券不能为空
* @var $template CouponTemplate
*/
// 根据模板ID查找优惠券模板
$template = CouponTemplate::query()->findOrFail($request->input('template_id'));
$today = Carbon::today();
if ($today->gt(Carbon::make($template->end_date))) {
$today = Carbon::today(); // 获取今天的日期
admin_error('优惠券已过期');
return back()->withInput();
// 检查优惠券是否过期
if ($today->gt(Carbon::make($template->end_date))) {
admin_error('优惠券已过期'); // 显示错误信息
return back()->withInput(); // 返回上一个页面并保留输入
}
// 如果会员 ID 不为空,则代表是指定会员发放
if ($userIds = $request->input('user_ids')) {
// 使用空格拆分 id
$ids = array_values(array_filter(explode(' ', $userIds)));
$users = User::query()->findMany($ids);
}
// 使用空格拆分 ID
$ids = array_values(array_filter(explode(' ', $userIds))); // 过滤空值并重建索引
$users = User::query()->findMany($ids); // 查找指定的用户
} else {
// 否则则是条件范围发放
else {
$query = User::query();
// 性别
$sex = array_filter($request->input('user_sex'));
// 会员来源
$sources = array_filter($request->input('user_source'));
// 登录次数
$loginCount = (int)$request->input('login_count');
// 会员总积分
$scoreAll = (int)$request->input('user_score');
$query = User::query(); // 创建用户查询
// 获取过滤条件
$sex = array_filter($request->input('user_sex')); // 性别
$sources = array_filter($request->input('user_source')); // 会员来源
$loginCount = (int)$request->input('login_count'); // 登录次数
$scoreAll = (int)$request->input('user_score'); // 总积分
// 应用过滤条件
$query->whereIn('sex', $sex)
->whereIn('source', $sources)
->where('login_count', '>=', $loginCount)
->where('score_all', '>=', $scoreAll);
$users = $query->get();
$users = $query->get(); // 获取符合条件的用户
}
// 开始根据用户发放
$now = Carbon::now()->toDateTimeString();
$notifications = collect();
// 开始根据用户发放优惠券
$now = Carbon::now()->toDateTimeString(); // 获取当前时间
$notifications = collect(); // 创建通知集合
$codes = $users->map(function (User $user) use ($template, $notifications, $now) {
$code = strtoupper(str_random(16)); // 生成随机兑换码
$code = strtoupper(str_random(16));
// 创建通知数据
$notification = [
'id' => Uuid::uuid4()->toString(),
'type' => CouponCodeNotification::class,
'notifiable_id' => $user->id,
'notifiable_type' => get_class($user),
'data' => json_encode((new CouponCodeNotification($template, $code))->toArray($user), JSON_UNESCAPED_UNICODE),
'created_at' => $now,
'updated_at' => $now,
'id' => Uuid::uuid4()->toString(), // 生成唯一ID
'type' => CouponCodeNotification::class, // 通知类型
'notifiable_id' => $user->id, // 可通知的用户ID
'notifiable_type' => get_class($user), // 用户类型
'data' => json_encode((new CouponCodeNotification($template, $code))->toArray($user), JSON_UNESCAPED_UNICODE), // 通知数据
'created_at' => $now, // 创建时间
'updated_at' => $now, // 更新时间
];
$notifications->push($notification);
$notifications->push($notification); // 将通知添加到集合
return [
'code' => $code,
'user_id' => $user->id,
'template_id' => $template->id,
'notification_at' => $now,
'created_at' => $now,
'updated_at' => $now,
'code' => $code, // 兑换码
'user_id' => $user->id, // 用户ID
'template_id' => $template->id, // 模板ID
'notification_at' => $now, // 通知时间
'created_at' => $now, // 创建时间
'updated_at' => $now, // 更新时间
];
});
$size = 1000;
$size = 1000; // 每次插入的数量
foreach (array_chunk($codes->all(), $size, true) as $chunk) {
// 优惠券码
CouponCode::query()->insert($codes->all());
// 批量插入优惠券码
CouponCode::query()->insert($chunk);
}
foreach (array_chunk($notifications->all(), $size, true) as $chunk) {
// 通知
// 批量插入通知
DatabaseNotification::query()->insert($chunk);
}
admin_toastr("发布成功,总共有{$users->count()}位会员符合发放条件");
return response()->redirectTo(admin_url('/coupon_codes'));
admin_toastr("发布成功,总共有{$users->count()}位会员符合发放条件"); // 显示成功提示
return response()->redirectTo(admin_url('/coupon_codes')); // 重定向到优惠券兑换码列表
}
/**
* Make a form builder.
* 创建表单构建器.
*
* @return Form
* @return Form 返回表单实例
*/
protected function form()
{
$form = new Form(new CouponCode);
$form = new Form(new CouponCode); // 创建新的表单实例,基于 CouponCode 模型
$today = Carbon::today()->toDateString();
$today = Carbon::today()->toDateString(); // 获取今天的日期
$form->divider('指定会员发放');
$form->text('user_ids', '会员')->help('请输入会员的ID, 多个会员用空格隔开,如果为空则代表是范围发放');
$form->divider('指定会员发放'); // 分隔符
$form->text('user_ids', '会员')->help('请输入会员的ID, 多个会员用空格隔开,如果为空则代表是范围发放'); // 会员ID输入框
$form->divider('范围发放');
$form->divider('范围发放'); // 分隔符
// 获取有效的优惠券模板
$templates = CouponTemplate::query()->where('end_date', '>=', $today)->pluck('title', 'id');
$form->checkbox('user_sex', '会员性别')->options([UserSexEnum::MAN => '男', UserSexEnum::WOMAN => '女'])->canCheckAll();
$form->checkbox('user_sex', '会员性别')->options([UserSexEnum::MAN => '男', UserSexEnum::WOMAN => '女'])->canCheckAll(); // 性别选择框
$form->checkbox('user_source', '会员来源')->options([
UserSourceEnum::MOON => '前台注册',
UserSourceEnum::GITHUB => 'Github',
UserSourceEnum::QQ => 'QQ',
UserSourceEnum::WEIBO => '微博',
])->canCheckAll();
$form->number('login_count', '会员登录次数')->default(0)->help('会员登录次数大于等于给定的次数');
$form->number('user_score', '会员总积分')->default(0)->help('会员给定的积分大于等于总积分');
$form->divider('优惠券');
])->canCheckAll(); // 来源选择框
$form->number('login_count', '会员登录次数')->default(0)->help('会员登录次数大于等于给定的次数'); // 登录次数输入框
$form->number('user_score', '会员总积分')->default(0)->help('会员给定的积分大于等于总积分'); // 总积分输入框
$form->select('template_id', '优惠券')->help('发放的优惠券')->options($templates)->required();
$form->divider('优惠券'); // 分隔符
$form->select('template_id', '优惠券')->help('发放的优惠券')->options($templates)->required(); // 优惠券选择框
return $form;
return $form; // 返回构建好的表单
}
}

@ -2,56 +2,60 @@
namespace App\Admin\Controllers;
use App\Admin\Transforms\YesNoTransform;
use App\Models\UserHasCoupon;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use App\Admin\Transforms\YesNoTransform; // 引入 YesNoTransform 类,用于转换布尔值
use App\Models\UserHasCoupon; // 引入用户优惠券记录模型
use Encore\Admin\Controllers\AdminController; // 引入管理员控制器基类
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Show; // 引入展示构建器
class CouponLogController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题.
*
* @var string
*/
protected $title = '会员领取记录';
protected $title = '会员领取记录'; // 控制器标题
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new UserHasCoupon);
$grid->model()->latest();
$grid->column('id', __('Id'));
$grid->column('user_id', '用户 ID');
$grid->column('user.name', '用户昵称');
$grid->column('title', __('Title'));
$grid->column('amount', '满减金额');
$grid->column('full_amount', __('Full amount'));
$grid->column('start_date', __('Start date'));
$grid->column('end_date', __('End date'));
$grid->column('is_used', '是否使用')->display(function () {
$grid = new Grid(new UserHasCoupon); // 创建新的网格实例,基于 UserHasCoupon 模型
$grid->model()->latest(); // 按照记录创建时间降序排列
// 定义网格列
$grid->column('id', __('Id')); // 显示记录ID
$grid->column('user_id', '用户 ID'); // 显示用户ID
$grid->column('user.name', '用户昵称'); // 显示用户昵称
$grid->column('title', __('Title')); // 显示优惠券标题
$grid->column('amount', '满减金额'); // 显示满减金额
$grid->column('full_amount', __('Full amount')); // 显示满额金额
$grid->column('start_date', __('Start date')); // 显示优惠券开始日期
$grid->column('end_date', __('End date')); // 显示优惠券结束日期
return YesNoTransform::trans(! is_null($this->used_at));
// 显示是否使用的状态,使用 YesNoTransform 转换
$grid->column('is_used', '是否使用')->display(function () {
return YesNoTransform::trans(! is_null($this->used_at)); // 如果 used_at 不为空,则表示已使用
});
$grid->column('used_at', '使用时间');
$grid->column('created_at', __('Created at'));
$grid->disableActions();
$grid->disableCreateButton();
$grid->column('used_at', '使用时间'); // 显示使用时间
$grid->column('created_at', __('Created at')); // 显示创建时间
$grid->filter(function (Grid\Filter $filter) {
// 禁用操作按钮和创建按钮
$grid->disableActions(); // 禁用操作按钮
$grid->disableCreateButton(); // 禁用创建按钮
$filter->like('title', __('Title'));
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->like('title', __('Title')); // 允许通过优惠券标题进行模糊查询
});
return $grid;
return $grid; // 返回构建好的网格
}
}

@ -2,85 +2,94 @@
namespace App\Admin\Controllers;
use App\Admin\Transforms\YesNoTransform;
use App\Models\CouponTemplate;
use Carbon\Carbon;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use App\Admin\Transforms\YesNoTransform; // 引入 YesNoTransform 类,用于转换布尔值
use App\Models\CouponTemplate; // 引入优惠券模板模型
use Carbon\Carbon; // 引入 Carbon 日期时间处理库
use Encore\Admin\Controllers\AdminController; // 引入管理员控制器基类
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Show; // 引入展示构建器
class CouponTemplateController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题.
*
* @var string
*/
protected $title = '优惠券';
protected $title = '优惠券'; // 控制器标题
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new CouponTemplate);
$grid = new Grid(new CouponTemplate); // 创建新的网格实例,基于 CouponTemplate 模型
$grid->model()->latest('start_date');
$grid->model()->latest('start_date'); // 按照开始日期降序排列优惠券模板
$grid->column('id', __('Id'));
$grid->column('title', __('Title'));
$grid->column('amount', '优惠金额');
$grid->column('full_amount', __('Full amount'));
$grid->column('score', '需兑换积分');
$grid->column('exp_date', '有效日期')->display(function () {
// 定义网格列
$grid->column('id', __('Id')); // 显示记录ID
$grid->column('title', __('Title')); // 显示优惠券标题
$grid->column('amount', '优惠金额'); // 显示优惠金额
$grid->column('full_amount', __('Full amount')); // 显示满额金额
$grid->column('score', '需兑换积分'); // 显示需兑换的积分
return $this->start_date . ' ~ ' . $this->end_date;
// 显示有效日期范围
$grid->column('exp_date', '有效日期')->display(function () {
return $this->start_date . ' ~ ' . $this->end_date; // 显示开始日期和结束日期
});
$today = Carbon::today();
$today = Carbon::today(); // 获取今天的日期
// 显示优惠券是否有效(未过期)
$grid->column('overtime', '是否有效(未过期)')->display(function () use ($today) {
$endDate = Carbon::make($this->end_date); // 将结束日期转换为 Carbon 实例
$startDate = Carbon::make($this->start_date); // 将开始日期转换为 Carbon 实例
$endDate = Carbon::make($this->end_date);
$startDate = Carbon::make($this->start_date);
// 如果没有结束日期,代表永远不过期
// 检查是否有结束日期和开始日期
if (is_null($endDate) || is_null($startDate)) {
$isOver = true;
$isOver = true; // 如果没有结束日期,代表永远不过期
} else {
// 检查今天的日期是否在有效日期范围内
$isOver = $today->gte($startDate) && $today->lte($endDate);
}
return YesNoTransform::trans($isOver);
return YesNoTransform::trans($isOver); // 使用 YesNoTransform 转换布尔值为可读格式
});
$grid->column('created_at', __('Created at'));
$grid->filter(function (Grid\Filter $filter) {
$grid->column('created_at', __('Created at')); // 显示创建时间
$filter->like('title', __('Title'));
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->like('title', __('Title')); // 允许通过优惠券标题进行模糊查询
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* Make a form builder.
* 创建表单构建器.
*
* @return Form
* @return Form 返回表单实例
*/
protected function form()
{
$form = new Form(new CouponTemplate);
$form->text('title', __('Title'));
$form->decimal('amount', '优惠金额');
$form->decimal('full_amount', __('Full amount'));
$form->number('score', __('Score'))->default(0)->help('设置为 0 代表无需积分即可兑换优惠券');
$form->date('start_date', __('Start date'))->default(date('Y-m-d'));
$form->date('end_date', __('End date'))->default(Carbon::today()->addMonth());
return $form;
$form = new Form(new CouponTemplate); // 创建新的表单实例,基于 CouponTemplate 模型
$form->text('title', __('Title')); // 输入优惠券标题
$form->decimal('amount', '优惠金额'); // 输入优惠金额
$form->decimal('full_amount', __('Full amount')); // 输入满额金额
$form->number('score', __('Score')) // 输入需兑换积分
->default(0) // 默认值为 0
->help('设置为 0 代表无需积分即可兑换优惠券'); // 帮助提示
$form->date('start_date', __('Start date')) // 输入开始日期
->default(date('Y-m-d')); // 默认设置为今天
$form->date('end_date', __('End date')) // 输入结束日期
->default(Carbon::today()->addMonth()); // 默认设置为一个月后
return $form; // 返回构建好的表单
}
}

@ -2,83 +2,89 @@
namespace App\Admin\Controllers;
use App\Admin\Extensions\Div;
use App\Http\Controllers\Controller;
use App\Models\SiteCount;
use App\Models\User;
use App\Services\SiteCountService;
use Carbon\Carbon;
use Encore\Admin\Auth\Database\Menu;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row;
use Encore\Admin\Widgets\Box;
use App\Admin\Extensions\Div; // 引入自定义的 Div 类
use App\Http\Controllers\Controller; // 引入基础控制器
use App\Models\SiteCount; // 引入站点统计模型
use App\Models\User; // 引入用户模型
use App\Services\SiteCountService; // 引入站点统计服务
use Carbon\Carbon; // 引入 Carbon 日期时间处理库
use Encore\Admin\Auth\Database\Menu; // 引入菜单模型
use Encore\Admin\Facades\Admin; // 引入 Admin 门面
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Layout\Row; // 引入行布局
use Encore\Admin\Widgets\Box; // 引入盒子组件
class HomeController extends Controller
{
/**
* 显示仪表盘首页.
*
* @param Content $content 内容布局实例
* @param SiteCountService $service 站点统计服务实例
* @return Content 返回内容布局
*/
public function index(Content $content, SiteCountService $service)
{
// 用于更新菜单数据到文件, 可删除
// file_put_contents(database_path('data/menus.json'), Menu::all()->toJson(JSON_UNESCAPED_UNICODE));
// 使用 echart
// 引入 ECharts 图表库
Admin::js('/js/echarts.min.js');
return $content
->header('仪表盘')
->row(function (Row $row) use ($service) {
->header('仪表盘') // 设置页面标题
->row(function (Row $row) use ($service) { // 创建一行布局
/**
* 今日统计,今天的特殊,需要从缓存 redis 中读取
* 今日统计, 今天的特殊情况,需要从缓存 redis 中读取
*
* @var $todaySite SiteCount
*/
$now = Carbon::now();
$today = $now->toDateString();
$todaySite = SiteCount::query()->firstOrNew(['date' => $today]);
$todaySite = $service->syncByCache($todaySite);
$now = Carbon::now(); // 获取当前时间
$today = $now->toDateString(); // 获取今天的日期字符串
$todaySite = SiteCount::query()->firstOrNew(['date' => $today]); // 获取今天的统计记录,如果不存在则创建新记录
$todaySite = $service->syncByCache($todaySite); // 从缓存中同步今天的统计数据
// 七日统计
$lastWeekDate = $now->subDay(7);
$lastWeekDate = $now->subDay(7); // 计算七天前的日期
$weekSites = SiteCount::query()
->where('date', '!=', $today)
->where('date', '>', $lastWeekDate)
->get()
->push($todaySite)
->sortBy('date');
->where('date', '!=', $today) // 排除今天的记录
->where('date', '>', $lastWeekDate) // 只获取最近七天的记录
->get() // 获取记录
->push($todaySite) // 将今天的记录添加到结果集中
->sortBy('date'); // 按日期排序
// 本月统计
$month = $now->format('Y-m');
$month = $now->format('Y-m'); // 获取当前月份格式YYYY-MM
$monthSites = SiteCount::query()
->where('date', '!=', $today)
->where('date', '>', $month)
->get()
->push($todaySite)
->sortBy('date');
->where('date', '!=', $today) // 排除今天的记录
->where('date', '>', $month) // 只获取本月的记录
->get() // 获取记录
->push($todaySite) // 将今天的记录添加到结果集中
->sortBy('date'); // 按日期排序
$row->column(4, new Box('今日用户注册来源', new Div('todayRegister')));
$row->column(4, new Box('七日用户注册来源', new Div('weekRegister')));
$row->column(4, new Box('本月用户注册来源', new Div('monthRegister')));
// 创建统计信息的盒子组件
$row->column(4, new Box('今日用户注册来源', new Div('todayRegister'))); // 今日用户注册来源
$row->column(4, new Box('七日用户注册来源', new Div('weekRegister'))); // 七日用户注册来源
$row->column(4, new Box('本月用户注册来源', new Div('monthRegister'))); // 本月用户注册来源
$row->column(4, new Box('今日订单', new Div('todayOrders')));
$row->column(4, new Box('近期订单量', new Div('weekSites')));
$row->column(4, new Box('交易金额', new Div('saleMoney')));
$row->column(4, new Box('今日订单', new Div('todayOrders'))); // 今日订单
$row->column(4, new Box('近期订单量', new Div('weekSites'))); // 近期订单量
$row->column(4, new Box('交易金额', new Div('saleMoney'))); // 交易金额
$allSites = compact('todaySite', 'weekSites', 'monthSites');
$row->column(12, view('admin.chars.echart', $allSites));
// 将所有统计数据传递给视图
$allSites = compact('todaySite', 'weekSites', 'monthSites'); // 打包统计数据
$row->column(12, view('admin.chars.echart', $allSites)); // 渲染 ECharts 视图并传递数据
});
}
/**
* 自定义 404 页面
* 自定义 404 页面.
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function noFound()
{
return redirect('admin');
return redirect('admin'); // 重定向到管理员首页
}
}

@ -2,191 +2,191 @@
namespace App\Admin\Controllers;
use App\Models\Level;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Show;
use App\Models\Level; // 引入 Level 模型
use App\Http\Controllers\Controller; // 引入基础控制器
use Encore\Admin\Controllers\HasResourceActions; // 引入资源控制器特性
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Show; // 引入展示构建器
class LevelController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源控制器特性,使得该控制器支持资源操作
/**
* Index interface.
* 显示列表页面.
*
* @param Content $content
* @return Content
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function index(Content $content)
{
return $content
->header('列表')
->description('')
->body($this->grid());
->header('列表') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->grid()); // 渲染网格
}
/**
* Show interface.
* 显示详情页面.
*
* @param mixed $id
* @param Content $content
* @return Content
* @param mixed $id 资源 ID
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function show($id, Content $content)
{
return $content
->header('详情')
->description('')
->body($this->detail($id));
->header('详情') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->detail($id)); // 渲染详情视图
}
/**
* Edit interface.
* 显示编辑页面.
*
* @param mixed $id
* @param Content $content
* @return Content
* @param mixed $id 资源 ID
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function edit($id, Content $content)
{
return $content
->header('Edit')
->description('')
->body($this->form()->edit($id));
->header('编辑') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->form()->edit($id)); // 渲染编辑表单
}
/**
* Create interface.
* 显示创建页面.
*
* @param Content $content
* @return Content
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function create(Content $content)
{
return $content
->header('新建')
->description('')
->body($this->form());
->header('新建') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->form()); // 渲染创建表单
}
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new Level);
$grid = new Grid(new Level); // 创建新的网格实例,基于 Level 模型
$grid->model()->orderBy('min_score', 'desc');
$grid->column('id', 'id');
$grid->column('icon', '图标')->image('', 90, 90);
$grid->column('name', '名字')->editable();
$grid->column('level', '等级');
$grid->column('min_score', '分阶');
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '更新时间');
$grid->model()->orderBy('min_score', 'desc'); // 按 min_score 降序排列
// 定义网格的列
$grid->column('id', 'ID'); // 显示 ID 列
$grid->column('icon', '图标')->image('', 90, 90); // 显示图标列,设置图像大小
$grid->column('name', '名字')->editable(); // 显示名字列,可编辑
$grid->column('level', '等级'); // 显示等级列
$grid->column('min_score', '分阶'); // 显示分阶列
$grid->column('created_at', '创建时间'); // 显示创建时间列
$grid->column('updated_at', '更新时间'); // 显示更新时间列
// 自定义操作按钮
$grid->actions(function (Grid\Displayers\Actions $actions) {
$level = $actions->row;
if (! $level->can_delete) {
$actions->disableDelete();
$level = $actions->row; // 获取当前行的数据
if (!$level->can_delete) { // 检查是否可以删除
$actions->disableDelete(); // 禁用删除按钮
}
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* Make a show builder.
* 创建详情构建器.
*
* @param mixed $id
* @return Show
* @param mixed $id 资源 ID
* @return Show 返回展示实例
*/
protected function detail($id)
{
$show = new Show(Level::findOrFail($id));
$show->field('id', 'id');
$show->field('icon', '图标')->image();
$show->field('name', '名字');
$show->field('level', '等级');
$show->field('min_score', '分阶');
$show->field('created_at', '创建时间');
$show->field('updated_at', '更新时间');
return $show;
$show = new Show(Level::findOrFail($id)); // 查找并显示指定 ID 的 Level 记录
// 定义详情展示的字段
$show->field('id', 'ID'); // 显示 ID
$show->field('icon', '图标')->image(); // 显示图标
$show->field('name', '名字'); // 显示名字
$show->field('level', '等级'); // 显示等级
$show->field('min_score', '分阶'); // 显示分阶
$show->field('created_at', '创建时间'); // 显示创建时间
$show->field('updated_at', '更新时间'); // 显示更新时间
return $show; // 返回构建好的详情视图
}
/**
* Make a form builder.
* 创建表单构建器.
*
* @return Form
* @return Form 返回表单实例
*/
protected function form()
{
$form = new Form(new Level);
$form = new Form(new Level); // 创建新的表单实例,基于 Level 模型
// 添加图标字段,设置唯一名称
$icon = $form->image('icon', '图标')->uniqueName();
if (! windows_os()) {
$icon->resize(160, 160);;
if (!windows_os()) { // 如果不是 Windows 系统
$icon->resize(160, 160); // 调整图标大小
}
$form->text('name', '名字');
$form->number('level', '等级');
$form->number('min_score', '积分');
// 添加其他字段
$form->text('name', '名字'); // 添加名字字段
$form->number('level', '等级'); // 添加等级字段
$form->number('min_score', '积分'); // 添加积分字段
// 添加保存前的钩子
$form->saving(function (Form $form) {
if (app()->environment('dev')) {
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
if (app()->environment('dev')) { // 如果当前环境是开发环境
admin_toastr('开发环境不允许操作', 'error'); // 显示错误提示
return back()->withInput(); // 返回并保留输入
}
});
return $form;
return $form; // 返回构建好的表单
}
/**
* Remove the specified resource from storage.
* 删除指定资源.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id 资源 ID
* @return \Illuminate\Http\Response 返回响应
* @throws \Exception
*/
public function destroy($id)
{
$level = Level::query()->findOrFail($id);
if (! $level->can_delete) {
$level = Level::query()->findOrFail($id); // 查找指定 ID 的 Level 记录
if (!$level->can_delete) { // 检查是否可以删除
return response()->json([
'status' => false,
'message' => '这个等级不允许删除',
'message' => '这个等级不允许删除', // 返回错误消息
]);
}
// 尝试删除记录
if ($level->delete()) {
$data = [
'status' => true,
'message' => trans('admin.delete_succeeded'),
'message' => trans('admin.delete_succeeded'), // 返回成功消息
];
} else {
$data = [
'status' => false,
'message' => trans('admin.delete_failed'),
'message' => trans('admin.delete_failed'), // 返回失败消息
];
}
return response()->json($data);
return response()->json($data); // 返回 JSON 响应
}
}

@ -2,266 +2,242 @@
namespace App\Admin\Controllers;
use App\Admin\Actions\Post\OrderReceivedAction;
use App\Admin\Actions\Post\OrderRefundAction;
use App\Admin\Actions\Post\OrderShipAction;
use App\Admin\Extensions\ReceivedButton;
use App\Admin\Extensions\ShipButton;
use App\Admin\Transforms\OrderDetailTransform;
use App\Admin\Transforms\OrderPayTypeTransform;
use App\Admin\Transforms\OrderShipStatusTransform;
use App\Admin\Transforms\OrderStatusTransform;
use App\Admin\Transforms\OrderTypeTransform;
use App\Admin\Transforms\YesNoTransform;
use App\Enums\OrderShipStatusEnum;
use App\Enums\OrderStatusEnum;
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\User;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Grid;
use Encore\Admin\Grid\Displayers\Actions;
use Encore\Admin\Grid\Filter;
use Encore\Admin\Layout\Content;
use Encore\Admin\Show;
use Encore\Admin\Widgets\Form;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Yansongda\Pay\Pay;
use App\Admin\Actions\Post\OrderReceivedAction; // 引入订单已收货操作
use App\Admin\Actions\Post\OrderRefundAction; // 引入订单退款操作
use App\Admin\Actions\Post\OrderShipAction; // 引入订单发货操作
use App\Admin\Extensions\ReceivedButton; // 引入收货按钮扩展
use App\Admin\Extensions\ShipButton; // 引入发货按钮扩展
use App\Admin\Transforms\OrderDetailTransform; // 引入订单详情转换器
use App\Admin\Transforms\OrderPayTypeTransform; // 引入订单支付方式转换器
use App\Admin\Transforms\OrderShipStatusTransform; // 引入订单物流状态转换器
use App\Admin\Transforms\OrderStatusTransform; // 引入订单状态转换器
use App\Admin\Transforms\OrderTypeTransform; // 引入订单类型转换器
use App\Admin\Transforms\YesNoTransform; // 引入是/否转换器
use App\Enums\OrderShipStatusEnum; // 引入订单物流状态枚举
use App\Enums\OrderStatusEnum; // 引入订单状态枚举
use App\Http\Controllers\Controller; // 引入基础控制器
use App\Models\Order; // 引入订单模型
use App\Models\User; // 引入用户模型
use Encore\Admin\Controllers\HasResourceActions; // 引入资源控制器特性
use Encore\Admin\Facades\Admin; // 引入 Admin 门面
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Grid\Displayers\Actions; // 引入操作显示器
use Encore\Admin\Grid\Filter; // 引入过滤器
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Show; // 引入展示构建器
use Encore\Admin\Widgets\Form; // 引入表单构建器
use Illuminate\Http\Request; // 引入请求类
use Illuminate\Support\Facades\DB; // 引入数据库门面
use Yansongda\Pay\Pay; // 引入支付处理类
class OrderController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源控制器特性,使该控制器支持资源操作
/**
* Index interface.
* 显示订单列表页面.
*
* @param Content $content
* @return Content
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function index(Content $content)
{
return $content
->header('订单列表')
->description('')
->body($this->grid());
->header('订单列表') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->grid()); // 渲染网格
}
/**
* Show interface.
* 显示订单详情页面.
*
* @param mixed $id
* @param Content $content
* @return Content
* @param mixed $id 订单 ID
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function show($id, Content $content)
{
return $content
->header('详情')
->description('')
->body($this->detail($id));
->header('详情') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->detail($id)); // 渲染订单详情
}
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new Order);
$grid->model()->withTrashed()->latest();
$grid->column('id');
$grid->column('no', '流水号');
$grid->column('user.name', '用户');
$grid->column('origin_amount', '订单原价');
$grid->column('post_amount', '邮费');
$grid->column('coupon_amount', '优惠');
$grid->column('amount', '总价');
$grid = new Grid(new Order); // 创建新的网格实例,基于 Order 模型
$grid->model()->withTrashed()->latest(); // 显示软删除的记录,并按创建时间降序排列
// 定义网格的列
$grid->column('id'); // 显示订单 ID
$grid->column('no', '流水号'); // 显示订单流水号
$grid->column('user.name', '用户'); // 显示用户名称
$grid->column('origin_amount', '订单原价'); // 显示订单原价
$grid->column('post_amount', '邮费'); // 显示邮费
$grid->column('coupon_amount', '优惠'); // 显示优惠金额
$grid->column('amount', '总价'); // 显示总价
$grid->column('status', '状态')->display(function ($status) {
// 如果订单是付款, 那么就修改为物流状态
// 如果订单已付款,显示物流状态
if ($status == OrderStatusEnum::PAID) {
return OrderShipStatusTransform::trans($this->ship_status);
return OrderShipStatusTransform::trans($this->ship_status); // 转换并显示物流状态
}
return OrderStatusTransform::trans($status);
return OrderStatusTransform::trans($status); // 转换并显示订单状态
});
$grid->column('type', '订单类型')->display(function ($type) {
return OrderTypeTransform::trans($type);
return OrderTypeTransform::trans($type); // 转换并显示订单类型
});
$grid->column('pay_type', '支付方式')->display(function ($type) {
return OrderPayTypeTransform::trans($type);
return OrderPayTypeTransform::trans($type); // 转换并显示支付方式
});
$grid->column('pay_no', '支付流水号');
$grid->column('paid_at', '支付时间');
$grid->column('consignee_name', '收货人姓名');
$grid->column('consignee_phone', '收货人手机');
$grid->column('created_at', '创建时间');
$grid->column('pay_no', '支付流水号'); // 显示支付流水号
$grid->column('paid_at', '支付时间'); // 显示支付时间
$grid->column('consignee_name', '收货人姓名'); // 显示收货人姓名
$grid->column('consignee_phone', '收货人手机'); // 显示收货人手机
$grid->column('created_at', '创建时间'); // 显示创建时间
// 禁用行选择器和创建按钮
$grid->disableRowSelector();
$grid->disableCreateButton();
$grid->actions(function (Grid\Displayers\DropdownActions $actions) {
/**
* @var $order Order
*/
$order = $actions->row;
// 自定义操作按钮
$grid->actions(function (Grid\Displayers\DropdownActions $actions) {
$order = $actions->row; // 获取当前行的订单数据
// 如果出现了申请,显示可以退款按钮
// 根据订单状态添加相应的操作按钮
if ($order->status == OrderStatusEnum::APPLY_REFUND) {
$actions->add(new OrderRefundAction());
$actions->add(new OrderRefundAction()); // 添加退款操作按钮
} elseif ($order->status == OrderStatusEnum::PAID) {
if ($order->ship_status == OrderShipStatusEnum::PENDING) {
$actions->add(new OrderShipAction());
$actions->add(new OrderShipAction()); // 添加发货操作按钮
} elseif ($order->ship_status == OrderShipStatusEnum::DELIVERED) {
$actions->add(new OrderReceivedAction());
$actions->add(new OrderReceivedAction()); // 添加确认收货操作按钮
}
}
$actions->disableEdit();
$actions->disableEdit(); // 禁用编辑按钮
});
// 添加过滤器
$grid->filter(function (Filter $filter) {
$filter->disableIdFilter();
$filter->like('no', '流水号');
$filter->disableIdFilter(); // 禁用 ID 过滤
$filter->like('no', '流水号'); // 添加流水号模糊查询
$filter->where(function ($query) {
// 根据用户名称查询用户 ID
$users = User::query()->where('name', 'like', "%{$this->input}%")->pluck('id');
$query->whereIn('user_id', $users->all());
$query->whereIn('user_id', $users->all()); // 根据用户 ID 查询订单
}, '用户');
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* Make a show builder.
* 创建订单详情展示构建器.
*
* @param mixed $id
* @return Show
* @param mixed $id 订单 ID
* @return Show 返回展示实例
*/
protected function detail($id)
{
$show = new Show(Order::query()->withTrashed()->findOrFail($id));
$show = new Show(Order::query()->withTrashed()->findOrFail($id)); // 查找并显示指定 ID 的订单记录
$show->field('id');
$show->field('no', '流水号');
// 定义详情展示的字段
$show->field('id'); // 显示订单 ID
$show->field('no', '流水号'); // 显示订单流水号
$show->field('user', '用户')->as(function ($user) {
return optional($user)->name;
return optional($user)->name; // 显示用户名称
});
$show->divider(); // 添加分隔线
$show->divider();
$show->field('amount', '总计');
$show->field('amount', '总计'); // 显示订单总计
$show->field('status', '状态')->as(function ($status) {
// 如果订单是付款, 那么就修改为物流状态
// 如果订单已付款,显示物流状态
if ($status == OrderStatusEnum::PAID) {
return OrderShipStatusTransform::trans($this->ship_status);
return OrderShipStatusTransform::trans($this->ship_status); // 转换并显示物流状态
}
return OrderStatusTransform::trans($status);
return OrderStatusTransform::trans($status); // 转换并显示订单状态
});
$show->field('type', '订单类型')->as(function ($type) {
return OrderTypeTransform::trans($type);
return OrderTypeTransform::trans($type); // 转换并显示订单类型
});
$show->divider();
$show->divider(); // 添加分隔线
$show->field('express_company', '物流公司');
$show->field('express_no', '物流单号');
$show->field('express_company', '物流公司'); // 显示物流公司
$show->field('express_no', '物流单号'); // 显示物流单号
$show->divider();
$show->divider(); // 添加分隔线
$show->field('consignee_name', '收货人');
$show->field('consignee_phone', '收货人手机');
$show->field('consignee_address', '收货地址');
$show->field('consignee_name', '收货人'); // 显示收货人姓名
$show->field('consignee_phone', '收货人手机'); // 显示收货人手机
$show->field('consignee_address', '收货地址'); // 显示收货地址
$show->divider();
$show->divider(); // 添加分隔线
$show->field('pay_type', '支付类型')->as(function ($type) {
return OrderPayTypeTransform::trans($type);
return OrderPayTypeTransform::trans($type); // 转换并显示支付类型
});
$show->field('refund_reason', '退款理由');
$show->field('pay_trade_no', '退款单号');
$show->field('pay_no', '支付单号');
$show->field('paid_at', '支付时间');
$show->field('created_at', '创建时间');
$show->field('updated_at', '修改时间');
// 详情
$show->field('refund_reason', '退款理由'); // 显示退款理由
$show->field('pay_trade_no', '退款单号'); // 显示退款单号
$show->field('pay_no', '支付单号'); // 显示支付单号
$show->field('paid_at', '支付时间'); // 显示支付时间
$show->field('created_at', '创建时间'); // 显示创建时间
$show->field('updated_at', '修改时间'); // 显示修改时间
// 显示订单详情
$show->details('详情', function (Grid $details) {
$details->column('id');
$details->column('product.name', '商品名字');
$details->column('price', '单价');
$details->column('number', '数量');
$details->column('id'); // 显示订单详情 ID
$details->column('product.name', '商品名字'); // 显示商品名称
$details->column('price', '单价'); // 显示单价
$details->column('number', '数量'); // 显示数量
$details->column('is_commented', '是否评论')->display(function ($is) {
return YesNoTransform::trans($is);
return YesNoTransform::trans($is); // 转换并显示是否评论
});
$details->column('total', '小计');
$details->column('total', '小计'); // 显示小计
// 禁用行选择器、创建按钮、过滤器和操作按钮
$details->disableRowSelector();
$details->disableCreateButton();
$details->disableFilter();
$details->disableActions();
});
return $show;
return $show; // 返回构建好的详情视图
}
/**
* 后台删除订单就是真的删除了
* @param $id
* @return \Illuminate\Http\JsonResponse
* 删除指定订单.
*
* @param mixed $id 订单 ID
* @return \Illuminate\Http\JsonResponse 返回 JSON 响应
*/
public function destroy($id)
{
try {
DB::transaction(function () use ($id) {
/**
* @var $order Order
*/
$order = Order::withTrashed()->findOrFail($id);
$order->details()->delete();
$order->forceDelete();
$order = Order::withTrashed()->findOrFail($id); // 查找指定 ID 的订单
$order->details()->delete(); // 删除订单详情
$order->forceDelete(); // 强制删除订单
});
$data = [
'status' => true,
'message' => trans('admin.delete_succeeded'),
'message' => trans('admin.delete_succeeded'), // 返回成功消息
];
} catch (\Throwable $e) {
$data = [
'status' => false,
'message' => trans('admin.delete_failed') . $e->getMessage(),
'message' => trans('admin.delete_failed') . $e->getMessage(), // 返回失败消息及错误信息
];
}
return response()->json($data);
return response()->json($data); // 返回 JSON 响应
}
}

@ -2,248 +2,241 @@
namespace App\Admin\Controllers;
use App\Admin\Actions\Post\DividerAction;
use App\Admin\Actions\Post\ForceDeleteProductAction;
use App\Admin\Actions\Post\ProductStatusAction;
use App\Admin\Transforms\YesNoTransform;
use App\Http\Controllers\Controller;
use App\Models\Category;
use App\Models\Product;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Show;
use App\Admin\Actions\Post\DividerAction; // 引入分隔符操作
use App\Admin\Actions\Post\ForceDeleteProductAction; // 引入强制删除商品操作
use App\Admin\Actions\Post\ProductStatusAction; // 引入商品状态操作
use App\Admin\Transforms\YesNoTransform; // 引入是/否转换器
use App\Http\Controllers\Controller; // 引入基础控制器
use App\Models\Category; // 引入分类模型
use App\Models\Product; // 引入商品模型
use Encore\Admin\Controllers\HasResourceActions; // 引入资源控制器特性
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Show; // 引入展示构建器
class ProductController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源控制器特性,使该控制器支持资源操作
/**
* Index interface.
* 显示商品列表界面.
*
* @param Content $content
* @return Content
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function index(Content $content)
{
return $content
->header('商品列表')
->description('')
->body($this->grid());
->header('商品列表') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->grid()); // 渲染商品网格
}
/**
* Show interface.
* 显示商品详情界面.
*
* @param mixed $id
* @param Content $content
* @return Content
* @param mixed $id 商品 ID
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function show($id, Content $content)
{
return $content
->header('详情')
->description('')
->body($this->detail($id));
->header('详情') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->detail($id)); // 渲染商品详情
}
/**
* Edit interface.
* 显示编辑商品界面.
*
* @param mixed $id
* @param Content $content
* @return Content
* @param mixed $id 商品 ID
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function edit($id, Content $content)
{
return $content
->header('编辑')
->description('')
->body($this->form()->edit($id));
->header('编辑') // 设置页面标题
->description('') // 设置页面描述(可选)
->body($this->form()->edit($id)); // 渲染编辑表单
}
/**
* Create interface.
* 显示添加商品界面.
*
* @param Content $content
* @return Content
* @param Content $content 内容布局实例
* @return Content 返回内容布局
*/
public function create(Content $content)
{
return $content
->header('添加商品')
->description('为你的商城添加一个商品')
->body($this->form());
->header('添加商品') // 设置页面标题
->description('为你的商城添加一个商品') // 设置页面描述
->body($this->form()); // 渲染添加商品表单
}
/**
* Make a grid builder.
* 创建商品网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new Product);
$grid = new Grid(new Product); // 创建新的网格实例,基于 Product 模型
$grid->model()->withTrashed()->latest();
$grid->model()->withTrashed()->latest(); // 显示软删除的记录,并按创建时间降序排列
$grid->column('id');
$grid->column('category.title', '商品类别');
// 定义网格的列
$grid->column('id'); // 显示商品 ID
$grid->column('category.title', '商品类别'); // 显示商品类别
$grid->column('name', '商品名')->display(function ($name) {
return str_limit($name, 30);
return str_limit($name, 30); // 显示商品名,限制字符数为 30
});
$grid->column('thumb', '首图')->image('', 50, 50);
$grid->column('thumb', '首图')->image('', 50, 50); // 显示商品缩略图
$grid->column('price', '价格')->display(function ($price) {
return $price . '/' . $this->original_price;
return $price . '/' . $this->original_price; // 显示销售价和原价
});
$grid->column('view_count', '浏览次数')->sortable();
$grid->column('sale_count', '售出数量')->sortable();
$grid->column('count', '库存量')->sortable();
$grid->column('view_count', '浏览次数')->sortable(); // 显示并支持排序的浏览次数
$grid->column('sale_count', '售出数量')->sortable(); // 显示并支持排序的售出数量
$grid->column('count', '库存量')->sortable(); // 显示并支持排序的库存量
$grid->column('deleted_at', '是否上架')->display(function ($isAlive) {
return YesNoTransform::trans(is_null($isAlive));
return YesNoTransform::trans(is_null($isAlive)); // 转换并显示是否上架
});
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '修改时间');
$grid->column('created_at', '创建时间'); // 显示创建时间
$grid->column('updated_at', '修改时间'); // 显示修改时间
// 查询过滤
$grid->filter(function (Grid\Filter $filter) {
$categories = Category::query()
->orderBy('order')
->latest()
->pluck('title', 'id')
->all();
->all(); // 获取分类列表
$filter->disableIdFilter();
$filter->equal('category_id', '分类')->select($categories);
$filter->equal('id', 'ID');
$filter->equal('uuid', 'UUID');
$filter->like('name', '商品名字');
$filter->disableIdFilter(); // 禁用 ID 过滤
$filter->equal('category_id', '分类')->select($categories); // 分类过滤
$filter->equal('id', 'ID'); // ID 过滤
$filter->equal('uuid', 'UUID'); // UUID 过滤
$filter->like('name', '商品名字'); // 商品名字模糊查询
});
// 增加一个上架,下架功能
// 增加一个上架/下架功能
$grid->actions(function (Grid\Displayers\DropdownActions $actions) {
$actions->disableDelete(); // 禁用删除按钮
$actions->add(new ForceDeleteProductAction()); // 添加强制删除商品操作
$actions->add(new DividerAction()); // 添加分隔符
// 根据商品是否上架设置操作按钮名称
$name = is_null($actions->row->deleted_at) ? "下架" : "上架";
$statusAction = new ProductStatusAction(); // 创建商品状态操作
$statusAction->setName($name); // 设置操作按钮名称
$actions->disableDelete();
$actions->add(new ForceDeleteProductAction());
$actions->add(new DividerAction());
$name = is_null($actions->row->deleted_at) ?
"下架":
"上架";
$statusAction = new ProductStatusAction();
$statusAction->setName($name);
$actions->add($statusAction);
$actions->add($statusAction); // 添加状态操作按钮
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* Make a show builder.
* 创建商品详情展示构建器.
*
* @param mixed $id
* @return Show
* @param mixed $id 商品 ID
* @return Show 返回展示实例
*/
protected function detail($id)
{
$show = new Show(Product::query()->withTrashed()->findOrFail($id));
$show->field('id');
$show->field('category.title', '商品类别');
$show->field('name', '商品名');
$show->field('title', '卖点');
$show->field('thumb', '缩略图')->image();
$show = new Show(Product::query()->withTrashed()->findOrFail($id)); // 查找并显示指定 ID 的商品记录
// 定义详情展示的字段
$show->field('id'); // 显示商品 ID
$show->field('category.title', '商品类别'); // 显示商品类别
$show->field('name', '商品名'); // 显示商品名
$show->field('title', '卖点'); // 显示商品卖点
$show->field('thumb', '缩略图')->image(); // 显示商品缩略图
$show->field('price', '价格')->as(function ($price) {
return $price . '/' . $this->original_price;
return $price . '/' . $this->original_price; // 显示销售价和原价
});
$show->field('view_count', '浏览次数');
$show->field('sale_count', '售出数量');
$show->field('count', '库存量');
$show->field('view_count', '浏览次数'); // 显示浏览次数
$show->field('sale_count', '售出数量'); // 显示售出数量
$show->field('count', '库存量'); // 显示库存量
$show->field('deleted_at', '是否上架')->as(function ($isAlive) {
return is_null($isAlive) ? '上架' : '下架';
return is_null($isAlive) ? '上架' : '下架'; // 显示商品是否上架
});
$show->field('created_at', '创建时间');
$show->field('updated_at', '修改时间');
$show->field('created_at', '创建时间'); // 显示创建时间
$show->field('updated_at', '修改时间'); // 显示修改时间
return $show;
return $show; // 返回构建好的详情视图
}
/**
* Make a form builder.
* 创建商品表单构建器.
*
* @return Form
* @return Form 返回表单实例
*/
protected function form()
{
$form = new Form(new Product);
$form = new Form(new Product); // 创建新的表单实例,基于 Product 模型
$form->select('category_id', '类别')->options(Category::selectOrderAll())->rules('required|exists:categories,id');
// 定义表单字段
$form->select('category_id', '类别')->options(Category::selectOrderAll())->rules('required|exists:categories,id'); // 选择商品类别
$form->text('name', '商品名字')->rules(function (Form $form) {
$rules = 'required|max:50|unique:products,name';
$rules = 'required|max:50|unique:products,name'; // 商品名字的验证规则
if ($id = $form->model()->id) {
$rules .= ',' . $id;
$rules .= ',' . $id; // 在编辑时排除当前商品
}
return $rules;
return $rules; // 返回验证规则
});
$form->textarea('title', '卖点')->rules('required|max:199');
$form->currency('price', '销售价')->symbol('$')->rules('required|numeric');
$form->currency('original_price', '原价')->symbol('$')->rules('required|numeric');
$form->number('count', '库存量')->rules('required|integer|min:0');
$form->textarea('title', '卖点')->rules('required|max:199'); // 商品卖点
$form->currency('price', '销售价')->symbol('¥')->rules('required|numeric'); // 商品销售价
$form->currency('original_price', '原价')->symbol('¥')->rules('required|numeric'); // 商品原价
$form->number('count', '库存量')->rules('required|integer|min:0'); // 商品库存量
$form->image('thumb', '缩略图')->uniqueName()->move('products/thumb')->rules('required');
$form->multipleImage('pictures', '轮播图')->uniqueName()->move('products/lists');
$form->image('thumb', '缩略图')->uniqueName()->move('products/thumb')->rules('required'); // 商品缩略图
$form->multipleImage('pictures', '轮播图')->uniqueName()->move('products/lists'); // 商品轮播图
$form->editor('detail.content', '详情')->rules('required');
$form->editor('detail.content', '详情')->rules('required'); // 商品详情
// 保存前的钩子
$form->saving(function (Form $form) {
if (app()->environment('dev')) {
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
if (app()->environment('dev')) { // 在开发环境中禁止操作
admin_toastr('开发环境不允许操作', 'error'); // 显示错误提示
return back()->withInput(); // 返回输入
}
});
return $form;
return $form; // 返回构建好的表单
}
/**
* 删除指定商品.
*
* @param mixed $id 商品 ID
* @return \Illuminate\Http\JsonResponse 返回 JSON 响应
*/
public function destroy($id)
{
$product = Product::query()->withTrashed()->findOrFail($id);
if (app()->environment('dev')) {
$product = Product::query()->withTrashed()->findOrFail($id); // 查找指定 ID 的商品
admin_toastr('开发环境不允许操作', 'error');
return back()->withInput();
if (app()->environment('dev')) { // 在开发环境中禁止操作
admin_toastr('开发环境不允许操作', 'error'); // 显示错误提示
return back()->withInput(); // 返回输入
}
// 尝试强制删除商品
if ($product->forceDelete()) {
$data = [
'status' => true,
'message' => trans('admin.delete_succeeded'),
'message' => trans('admin.delete_succeeded'), // 返回成功消息
];
} else {
$data = [
'status' => false,
'message' => trans('admin.delete_failed'),
'message' => trans('admin.delete_failed'), // 返回失败消息
];
}
return response()->json($data);
return response()->json($data); // 返回 JSON 响应
}
}

@ -2,58 +2,59 @@
namespace App\Admin\Controllers;
use App\Models\ProductHasUser;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use App\Models\ProductHasUser; // 引入用户与商品关联模型
use Encore\Admin\Controllers\AdminController; // 引入管理控制器基类
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Show; // 引入展示构建器
class ProductLikeController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题.
*
* @var string
*/
protected $title = '商品喜好';
protected $title = '商品喜好'; // 设置资源的标题为“商品喜好”
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new ProductHasUser);
$grid = new Grid(new ProductHasUser); // 创建新的网格实例,基于 ProductHasUser 模型
$grid->model()->latest();
$grid->model()->latest(); // 按照创建时间降序排列数据
$grid->column('user_id', __('User id'));
$grid->column('product_id', __('Product id'));
// 定义网格的列
$grid->column('user_id', __('User id')); // 显示用户 ID
$grid->column('product_id', __('Product id')); // 显示商品 ID
$grid->column('user.name', '用户');
$grid->column('created_at', '收藏时间');
$grid->column('product.name', '商品');
$grid->column('user.name', '用户'); // 显示用户姓名
$grid->column('created_at', '收藏时间'); // 显示商品收藏的时间
$grid->column('product.name', '商品'); // 显示商品名称
$grid->column('product.price', '价格')->display(function ($price) {
return $price . '/' . $this->product['original_price'];
// 显示商品价格,并附加原价
return $price . '/' . $this->product['original_price']; // 返回格式化的价格
});
$grid->column('product.thumb', '首图')->image('', 50, 50);
$grid->column('product.thumb', '首图')->image('', 50, 50); // 显示商品缩略图,设置显示大小
$grid->disableActions();
$grid->disableCreateButton();
$grid->disableBatchActions();
// 禁用某些操作
$grid->disableActions(); // 禁用行操作按钮
$grid->disableCreateButton(); // 禁用创建按钮
$grid->disableBatchActions(); // 禁用批量操作按钮
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->disableIdFilter();
$filter->like('user_id', '用户ID');
$filter->like('product_id', '商品ID');
$filter->like('user.name', '用户名');
$filter->equal('product.name', '商品');
$filter->disableIdFilter(); // 禁用 ID 过滤器
$filter->like('user_id', '用户ID'); // 用户 ID 模糊查询
$filter->like('product_id', '商品ID'); // 商品 ID 模糊查询
$filter->like('user.name', '用户名'); // 用户名模糊查询
$filter->equal('product.name', '商品'); // 商品名称精确查询
});
return $grid;
return $grid; // 返回构建好的网格
}
}

@ -2,49 +2,51 @@
namespace App\Admin\Controllers;
use App\Models\ScoreLog;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
use App\Models\ScoreLog; // 引入积分日志模型
use Encore\Admin\Controllers\AdminController; // 引入管理控制器基类
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Show; // 引入展示构建器
class ScoreLogController extends AdminController
{
/**
* Title for current resource.
* 当前资源的标题.
*
* @var string
*/
protected $title = '积分日志';
protected $title = '积分日志'; // 设置资源的标题为“积分日志”
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
* @return Grid 返回网格实例
*/
protected function grid()
{
$grid = new Grid(new ScoreLog);
$grid = new Grid(new ScoreLog); // 创建新的网格实例,基于 ScoreLog 模型
$grid->model()->latest();
$grid->model()->latest(); // 按照创建时间降序排列数据
$grid->column('id', __('Id'));
$grid->column('user_id', __('User id'));
$grid->column('user.name', '用户名');
$grid->column('description', __('Description'));
$grid->column('score', __('Score'));
$grid->column('created_at', __('Created at'));
$grid->column('updated_at', __('Updated at'));
// 定义网格的列
$grid->column('id', __('Id')); // 显示日志 ID
$grid->column('user_id', __('User id')); // 显示用户 ID
$grid->column('user.name', '用户名'); // 显示用户名
$grid->column('description', __('Description')); // 显示日志描述
$grid->column('score', __('Score')); // 显示积分
$grid->column('created_at', __('Created at')); // 显示创建时间
$grid->column('updated_at', __('Updated at')); // 显示更新时间
$grid->disableActions();
$grid->disableCreateButton();
// 禁用某些操作
$grid->disableActions(); // 禁用行操作按钮
$grid->disableCreateButton(); // 禁用创建按钮
// 定义过滤器
$grid->filter(function (Grid\Filter $filter) {
$filter->like('user.name', '用户名');
$filter->equal('score', '积分');
$filter->like('user.name', '用户名'); // 用户名模糊查询
$filter->equal('score', '积分'); // 积分精确查询
});
return $grid;
return $grid; // 返回构建好的网格
}
}

@ -2,22 +2,22 @@
namespace App\Admin\Controllers;
use App\Enums\ScoreRuleIndexEnum;
use App\Models\ScoreRule;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Show;
use Illuminate\Http\Request;
use App\Enums\ScoreRuleIndexEnum; // 引入积分规则索引枚举
use App\Models\ScoreRule; // 引入积分规则模型
use App\Http\Controllers\Controller; // 引入控制器基类
use Encore\Admin\Controllers\HasResourceActions; // 引入资源操作特性
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Show; // 引入展示构建器
use Illuminate\Http\Request; // 引入请求处理
class ScoreRuleController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源操作特性,提供 CRUD 操作
/**
* Index interface.
* 列表界面.
*
* @param Content $content
* @return Content
@ -25,13 +25,13 @@ class ScoreRuleController extends Controller
public function index(Content $content)
{
return $content
->header('列表')
->description(':xxx 是变量模板,建议不要操作')
->body($this->grid());
->header('列表') // 设置页面标题
->description(':xxx 是变量模板,建议不要操作') // 设置页面描述
->body($this->grid()); // 设置页面主体为网格
}
/**
* Show interface.
* 显示详细信息界面.
*
* @param mixed $id
* @param Content $content
@ -40,13 +40,13 @@ class ScoreRuleController extends Controller
public function show($id, Content $content)
{
return $content
->header('详情')
->description('')
->body($this->detail($id));
->header('详情') // 设置页面标题
->description('') // 设置页面描述
->body($this->detail($id)); // 设置页面主体为详细信息
}
/**
* Edit interface.
* 编辑界面.
*
* @param mixed $id
* @param Content $content
@ -55,13 +55,13 @@ class ScoreRuleController extends Controller
public function edit($id, Content $content)
{
return $content
->header('Edit')
->description('')
->body($this->form($id)->edit($id));
->header('Edit') // 设置页面标题
->description('') // 设置页面描述
->body($this->form($id)->edit($id)); // 设置页面主体为编辑表单
}
/**
* Create interface.
* 创建界面.
*
* @param Content $content
* @return Content
@ -69,130 +69,125 @@ class ScoreRuleController extends Controller
public function create(Content $content)
{
return $content
->header('新建')
->description('')
->body($this->form());
->header('新建') // 设置页面标题
->description('') // 设置页面描述
->body($this->form()); // 设置页面主体为创建表单
}
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new ScoreRule);
$grid = new Grid(new ScoreRule); // 创建新的网格实例,基于 ScoreRule 模型
$grid->model()->latest();
$grid->model()->latest(); // 按照创建时间降序排列数据
$grid->column('id', 'id');
$grid->column('description', '描述');
$grid->column('replace_text', '替换文本');
$grid->column('score', '积分');
// 定义网格的列
$grid->column('id', 'id'); // 显示日志 ID
$grid->column('description', '描述'); // 显示描述
$grid->column('replace_text', '替换文本'); // 显示替换文本
$grid->column('score', '积分'); // 显示积分
$grid->column('times', '次数')->display(function ($times) {
// 显示次数,如果没有则返回空
return $times ? $times : '';
});
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '修改时间');
$grid->column('created_at', '创建时间'); // 显示创建时间
$grid->column('updated_at', '修改时间'); // 显示修改时间
// 定义行操作
$grid->actions(function (Grid\Displayers\Actions $actions) {
$rule = $actions->row;
if (! $rule->can_delete) {
$actions->disableDelete();
$rule = $actions->row; // 获取当前行数据
if (! $rule->can_delete) { // 如果该规则不可删除
$actions->disableDelete(); // 禁用删除按钮
}
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* Make a show builder.
* 创建展示构建器.
*
* @param mixed $id
* @return Show
*/
protected function detail($id)
{
$show = new Show(ScoreRule::findOrFail($id));
$show = new Show(ScoreRule::findOrFail($id)); // 创建展示实例,查找指定 ID 的记录
$show->field('id', 'id');
$show->field('description', '描述');
$show->field('replace_text', '替换文本');
$show->field('score', '积分');
// 定义展示的字段
$show->field('id', 'id'); // 显示 ID
$show->field('description', '描述'); // 显示描述
$show->field('replace_text', '替换文本'); // 显示替换文本
$show->field('score', '积分'); // 显示积分
$show->field('times', '次数')->as(function ($times) {
// 显示次数,如果没有则返回空
return $times ? $times : '';
});
$show->field('created_at', '创建时间');
$show->field('updated_at', '修改时间');
$show->field('created_at', '创建时间'); // 显示创建时间
$show->field('updated_at', '修改时间'); // 显示修改时间
return $show;
return $show; // 返回展示实例
}
/**
* Make a form builder.
* 创建表单构建器.
*
* @param null $id
* @return Form
*/
protected function form($id = null)
{
$form = new Form(new ScoreRule);
// 只有新增才能改变类型
$options = [ScoreRuleIndexEnum::CONTINUE_LOGIN => '连续登录', ScoreRuleIndexEnum::VISITED_PRODUCT => '每日浏览商品'];
$form = new Form(new ScoreRule); // 创建新的表单实例,基于 ScoreRule 模型
if (is_null($id)) {
// 定义可选的积分规则类型
$options = [
ScoreRuleIndexEnum::CONTINUE_LOGIN => '连续登录',
ScoreRuleIndexEnum::VISITED_PRODUCT => '每日浏览商品'
];
$form->select('index_code', '类型')->options($options)->rules('required');
if (is_null($id)) { // 如果是创建新记录
$form->select('index_code', '类型')->options($options)->rules('required'); // 选择积分类型,必填
}
$form->number('score', '积分');
if (! is_null($id)) {
// 只有当时连续登录和修改的才有次数
$scoreRule = ScoreRule::query()->findOrFail($id);
$form->textarea('replace_text', '替换文本');
$form->textarea('description', '描述');
$form->number('score', '积分'); // 输入积分
if (array_key_exists($scoreRule->index_code, $options)) {
if (! is_null($id)) { // 如果是编辑现有记录
// 只有当是连续登录和修改的才有次数
$scoreRule = ScoreRule::query()->findOrFail($id); // 查找指定 ID 的规则
$form->textarea('replace_text', '替换文本'); // 输入替换文本
$form->textarea('description', '描述'); // 输入描述
$form->number('times', '次数');
if (array_key_exists($scoreRule->index_code, $options)) { // 如果规则类型在选项中
$form->number('times', '次数'); // 输入次数
}
} else {
$form->number('times', '次数');
$form->number('times', '次数'); // 输入次数
}
// 表单保存前的处理
$form->saving(function (Form $form) {
// 如果是新建复制模板
// 如果是新建记录,复制模板
if (! $form->model()->exists) {
$rule = ScoreRule::query()
->where('can_delete', 0)
->where('index_code', $form->index_code)
->firstOrFail();
->where('can_delete', 0) // 查找不可删除的规则
->where('index_code', $form->index_code) // 根据类型查找
->firstOrFail(); // 查找失败则抛出异常
// 复制规则的描述和替换文本
$form->model()->description = $rule->description;
$form->model()->replace_text = $rule->replace_text;
}
});
return $form;
return $form; // 返回构建好的表单
}
/**
* Remove the specified resource from storage.
* 从存储中删除指定资源.
*
* @param int $id
* @return \Illuminate\Http\Response
@ -200,28 +195,28 @@ class ScoreRuleController extends Controller
*/
public function destroy($id)
{
$rule = ScoreRule::query()->findOrFail($id);
if (! $rule->can_delete) {
$rule = ScoreRule::query()->findOrFail($id); // 查找指定 ID 的规则
if (! $rule->can_delete) { // 如果该规则不可删除
return response()->json([
'status' => false,
'message' => '这个等级不允许删除',
'message' => '这个等级不允许删除', // 返回错误信息
]);
}
// 尝试删除规则
if ($rule->delete()) {
$data = [
'status' => true,
'message' => trans('admin.delete_succeeded'),
'message' => trans('admin.delete_succeeded'), // 返回成功信息
];
} else {
$data = [
'status' => false,
'message' => trans('admin.delete_failed'),
'message' => trans('admin.delete_failed'), // 返回失败信息
];
}
return response()->json($data);
return response()->json($data); // 返回 JSON 响应
}
}

@ -2,26 +2,26 @@
namespace App\Admin\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreSeckillRequest;
use App\Models\Category;
use App\Models\Product;
use App\Models\Seckill;
use Carbon\Carbon;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use App\Http\Controllers\Controller; // 引入控制器基类
use App\Http\Requests\StoreSeckillRequest; // 引入秒杀请求验证类
use App\Models\Category; // 引入分类模型
use App\Models\Product; // 引入商品模型
use App\Models\Seckill; // 引入秒杀模型
use Carbon\Carbon; // 引入日期时间处理库
use Encore\Admin\Controllers\HasResourceActions; // 引入资源操作特性
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Layout\Content; // 引入内容布局
use Illuminate\Http\Request; // 引入请求处理
use Illuminate\Support\Facades\DB; // 引入数据库操作
use Illuminate\Support\Facades\Redis; // 引入 Redis 操作
class SeckillController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源操作特性,提供 CRUD 操作
/**
* Index interface.
* 列表界面.
*
* @param Content $content
* @return Content
@ -29,13 +29,13 @@ class SeckillController extends Controller
public function index(Content $content)
{
return $content
->header('秒杀列表')
->description('')
->body($this->grid());
->header('秒杀列表') // 设置页面标题
->description('') // 设置页面描述
->body($this->grid()); // 设置页面主体为网格
}
/**
* Create interface.
* 创建界面.
*
* @param Content $content
* @return Content
@ -43,124 +43,130 @@ class SeckillController extends Controller
public function create(Content $content)
{
return $content
->header('新建秒杀')
->description('')
->body($this->form());
->header('新建秒杀') // 设置页面标题
->description('') // 设置页面描述
->body($this->form()); // 设置页面主体为创建表单
}
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new Seckill);
$grid = new Grid(new Seckill); // 创建新的网格实例,基于 Seckill 模型
$grid->model()->latest();
$grid->model()->latest(); // 按照创建时间降序排列数据
$grid->column('id');
// 定义网格的列
$grid->column('id'); // 显示秒杀 ID
$grid->column('product.id', '商品ID');
$grid->column('product.id', '商品ID'); // 显示商品 ID
$grid->column('product.name', '商品名字')->display(function ($name) {
// 显示商品名字限制显示长度为30个字符
return str_limit($name, 30);
});
$grid->column('product.thumb', '商品图')->display(function ($thumb) {
// 显示商品缩略图
return image($thumb);
});
$grid->column('price', '秒杀价');
$grid->column('number', '秒杀数量');
$grid->column('start_at', '开始时间');
$grid->column('end_at', '结束时间');
$grid->column('rollback_count', '回滚量');
$grid->column('price', '秒杀价'); // 显示秒杀价格
$grid->column('number', '秒杀数量'); // 显示秒杀数量
$grid->column('start_at', '开始时间'); // 显示开始时间
$grid->column('end_at', '结束时间'); // 显示结束时间
$grid->column('rollback_count', '回滚量'); // 显示回滚量
$grid->column('is_rollback', '是否回滚数量')->display(function ($is) {
// 显示是否回滚数量
return $is ? '是' : '否';
});
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '修改时间');
$grid->column('created_at', '创建时间'); // 显示创建时间
$grid->column('updated_at', '修改时间'); // 显示修改时间
// 定义行操作
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableView();
$actions->disableEdit();
$actions->disableView(); // 禁用查看按钮
$actions->disableEdit(); // 禁用编辑按钮
});
return $grid;
return $grid; // 返回构建好的网格
}
/**
* Make a form builder.
* 创建表单构建器.
*
* @return Form
*/
protected function form()
{
$form = new Form(new Seckill);
$form = new Form(new Seckill); // 创建新的表单实例,基于 Seckill 模型
// 获取所有分类
$categories = Category::selectOrderAll();
// 选择分类,加载商品
$form->select('category_id', '分类')
->options($categories)
->load('product_id', admin_url('api/products'));
$form->select('product_id', '秒杀商品');
->load('product_id', admin_url('api/products')); // 根据分类动态加载商品
$form->number('price', '秒杀价')
->default(1);
$form->number('number', '秒杀数量')
->default(1)
->help('保证商品的库存数量大于此数量,会从库存中减去');
$form->select('product_id', '秒杀商品'); // 选择秒杀商品
$now = Carbon::now();
$form->datetime('start_at', '开始时间')
->default($now->format('Y-m-d H:00:00'));
$form->datetime('end_at', '结束时间')
->default($now->addHour(2)->format('Y-m-d H:00:00'))
->rules('required|date|after_or_equal:start_at');
$form->number('price', '秒杀价') // 输入秒杀价
->default(1); // 默认值为1
$form->number('number', '秒杀数量') // 输入秒杀数量
->default(1) // 默认值为1
->help('保证商品的库存数量大于此数量,会从库存中减去'); // 提示用户
$now = Carbon::now(); // 获取当前时间
$form->datetime('start_at', '开始时间') // 输入开始时间
->default($now->format('Y-m-d H:00:00')); // 默认值为当前时间整点
$form->datetime('end_at', '结束时间') // 输入结束时间
->default($now->addHour(2)->format('Y-m-d H:00:00')) // 默认值为当前时间后2小时
->rules('required|date|after_or_equal:start_at'); // 验证规则
return $form;
return $form; // 返回构建好的表单
}
/**
* 存储秒杀信息.
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws \Exception
*/
public function store(Request $request)
{
$number = $request->input('number', 0);
$product = Product::query()->findOrFail($request->input('product_id'));
$number = $request->input('number', 0); // 获取秒杀数量
$product = Product::query()->findOrFail($request->input('product_id')); // 查找商品
// 验证秒杀数量不能大于库存数量
if ($number > $product->count) {
return back()->withInput()->withErrors(['number' => '秒杀数量不能大于库存数量']);
}
DB::beginTransaction();
DB::beginTransaction(); // 开始数据库事务
try {
// 获取请求中的相关属性
$attributes = $request->only(['category_id', 'product_id', 'price', 'number', 'start_at', 'end_at']);
Seckill::create($attributes);
Seckill::create($attributes); // 创建新的秒杀记录
// 减去库存数量
$product->decrement('count', $number);
$product->decrement('count', $number); // 从商品库存中减去秒杀数量
} catch (\Error $e) {
DB::rollBack();
return back()->withInput()->withErrors(['category_id' => $e->getMessage()]);
DB::rollBack(); // 回滚事务
return back()->withInput()->withErrors(['category_id' => $e->getMessage()]); // 返回错误信息
}
DB::commit();
DB::commit(); // 提交事务
admin_toastr('添加成功');
return back();
admin_toastr('添加成功'); // 显示成功消息
return back(); // 返回上一个页面
}
/**
* Remove the specified resource from storage.
* 从存储中删除指定资源.
*
* @param int $id
* @return \Illuminate\Http\Response
@ -172,51 +178,43 @@ class SeckillController extends Controller
* @var $seckill Seckill
* @var $product Product
*/
$seckill = Seckill::query()->findOrFail($id);
$seckill = Seckill::query()->findOrFail($id); // 查找指定 ID 的秒杀记录
// 如果已经到了开始抢购时间,就不能删除了
// 获取当前时间和秒杀的开始和结束时间
$now = Carbon::now();
$startTime = Carbon::make($seckill->start_at);
$endTime = Carbon::make($seckill->end_at);
// 如果正处于抢购的时间,不允许删除
if ($now->gte($startTime) && $now->lte($endTime)) {
return response()->json([
'status' => false,
'message' => '秒杀已经开始,不能删除',
'message' => '秒杀已经开始,不能删除', // 返回错误信息
]);
}
DB::beginTransaction();
DB::beginTransaction(); // 开始数据库事务
try {
// 先把 redis 数据删除掉
// 虽然过期会自动清理,但是如果用户是
// 删除还没有开始的秒杀,只能在这里手动清理
// 删除 Redis 中的秒杀数据
\Redis::connection()->del([$seckill->getRedisModelKey(), $seckill->getRedisQueueKey()]);
$seckill->delete();
$seckill->delete(); // 删除秒杀记录
$data = [
'status' => false,
'message' => trans('admin.delete_succeeded'),
'status' => true,
'message' => trans('admin.delete_succeeded'), // 返回成功信息
];
} catch (\Exception $e) {
$data = [
'status' => true,
'message' => trans('admin.delete_failed'),
'status' => false,
'message' => trans('admin.delete_failed'), // 返回失败信息
];
DB::rollBack();
DB::rollBack(); // 回滚事务
}
DB::commit();
return response()->json($data);
DB::commit(); // 提交事务
return response()->json($data); // 返回 JSON 响应
}
}

@ -2,24 +2,24 @@
namespace App\Admin\Controllers;
use App\Enums\SettingKeyEnum;
use App\Models\Setting;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row;
use Encore\Admin\Show;
use Encore\Admin\Widgets\Box;
use Illuminate\Http\Request;
use App\Enums\SettingKeyEnum; // 引入设置键枚举
use App\Models\Setting; // 引入设置模型
use App\Http\Controllers\Controller; // 引入控制器基类
use Encore\Admin\Controllers\HasResourceActions; // 引入资源操作特性
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Layout\Row; // 引入行布局
use Encore\Admin\Show; // 引入显示构建器
use Encore\Admin\Widgets\Box; // 引入盒子组件
use Illuminate\Http\Request; // 引入请求处理
class SettingController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源操作特性,提供 CRUD 操作
/**
* Index interface.
* 配置列表界面.
*
* @param Content $content
* @return Content
@ -27,73 +27,89 @@ class SettingController extends Controller
public function index(Content $content)
{
return $content
->header('配置列表')
->description('')
->body(function (Row $row) {
->header('配置列表') // 设置页面标题
->description('') // 设置页面描述
->body(function (Row $row) { // 设置页面主体为行布局
// 获取所有设置键
$settingKeys = $this->getSettingKeys();
// 初始化设置数组
$settings = [];
foreach ($settingKeys as $key) {
// 获取每个设置键的值
$settings[$key] = setting(new SettingKeyEnum($key));
}
// 创建一个新的表单实例
$form = new \Encore\Admin\Widgets\Form($settings);
$form->action(admin_url('settings'));
$form->method('POST');
$form->hidden('_token', csrf_token());
$form->action(admin_url('settings')); // 设置表单提交地址
$form->method('POST'); // 设置表单提交方法
$form->hidden('_token', csrf_token()); // 添加 CSRF 令牌
$form->text(SettingKeyEnum::USER_INIT_PASSWORD, '会员初始密码')->required();
$form->decimal(SettingKeyEnum::UN_PAY_CANCEL_TIME, '订单自动取消时间')->required()->help('单位:分钟');
$form->decimal(SettingKeyEnum::POST_AMOUNT, '邮费')->required()->help('设置为 0 免邮');
// 添加表单字段
$form->text(SettingKeyEnum::USER_INIT_PASSWORD, '会员初始密码')->required(); // 会员初始密码,必填
$form->decimal(SettingKeyEnum::UN_PAY_CANCEL_TIME, '订单自动取消时间')->required()->help('单位:分钟'); // 订单自动取消时间,必填,单位为分钟
$form->decimal(SettingKeyEnum::POST_AMOUNT, '邮费')->required()->help('设置为 0 免邮'); // 邮费必填设置为0时免邮
// 定义开关状态
$states = [
'on' => ['value' => 1, 'text' => '打开', 'color' => 'success'],
'off' => ['value' => 0, 'text' => '关闭', 'color' => 'danger'],
];
// 获取秒杀状态并设置提示信息
$seckillStatus = \setting(new SettingKeyEnum(SettingKeyEnum::IS_OPEN_SECKILL)) ? '开启' : '关闭';
$seckillHelp = "秒杀现在是 {$seckillStatus} 状态";
$form->switch(SettingKeyEnum::IS_OPEN_SECKILL, '是否开启秒杀')->states($states)->help($seckillHelp);
$form->switch(SettingKeyEnum::IS_OPEN_SECKILL, '是否开启秒杀')->states($states)->help($seckillHelp); // 是否开启秒杀开关
// 将表单放入盒子组件中并显示
$row->column(12, new Box('网站配置', $form));
});
}
/**
* 存储设置.
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{
// 对秒杀这个特殊的 key 做处理
// 对秒杀这个特殊的 key 做处理,将开关状态转换为 0 或 1
$val = strtolower($request->input(SettingKeyEnum::IS_OPEN_SECKILL)) == 'on' ? 1 : 0;
$request->offsetSet(SettingKeyEnum::IS_OPEN_SECKILL, $val);
$request->offsetSet(SettingKeyEnum::IS_OPEN_SECKILL, $val); // 更新请求中的秒杀状态
// 验证输入数据
$this->validate($request, [
SettingKeyEnum::USER_INIT_PASSWORD => 'required|string',
SettingKeyEnum::UN_PAY_CANCEL_TIME => 'required|integer|min:0',
SettingKeyEnum::IS_OPEN_SECKILL => 'required|int|in:0,1',
SettingKeyEnum::POST_AMOUNT => 'required|numeric|min:0',
SettingKeyEnum::USER_INIT_PASSWORD => 'required|string', // 会员初始密码,必填且为字符串
SettingKeyEnum::UN_PAY_CANCEL_TIME => 'required|integer|min:0', // 订单自动取消时间,必填且为非负整数
SettingKeyEnum::IS_OPEN_SECKILL => 'required|int|in:0,1', // 秒杀状态必填且为0或1
SettingKeyEnum::POST_AMOUNT => 'required|numeric|min:0', // 邮费,必填且为非负数字
]);
// 获取所有设置键并更新数据库
$settingKeys = $this->getSettingKeys();
foreach ($settingKeys as $key) {
Setting::query()->where('key', $key)->update(['value' => $request->input($key)]);
Setting::query()->where('key', $key)->update(['value' => $request->input($key)]); // 更新每个设置的值
}
admin_success('修改成功');
return back();
admin_success('修改成功'); // 显示成功消息
return back(); // 返回上一个页面
}
/**
* 获取所有设置键.
*
* @return array
*/
private function getSettingKeys()
{
return [
SettingKeyEnum::USER_INIT_PASSWORD,
SettingKeyEnum::UN_PAY_CANCEL_TIME,
SettingKeyEnum::POST_AMOUNT,
SettingKeyEnum::IS_OPEN_SECKILL,
SettingKeyEnum::USER_INIT_PASSWORD, // 会员初始密码
SettingKeyEnum::UN_PAY_CANCEL_TIME, // 订单自动取消时间
SettingKeyEnum::POST_AMOUNT, // 邮费
SettingKeyEnum::IS_OPEN_SECKILL, // 是否开启秒杀
];
}
}

@ -2,38 +2,42 @@
namespace App\Admin\Controllers;
use App\Exceptions\UploadException;
use App\Http\Controllers\Controller;
use App\Services\UploadServe;
use Illuminate\Support\Facades\Storage;
use App\Exceptions\UploadException; // 引入自定义上传异常类
use App\Http\Controllers\Controller; // 引入控制器基类
use App\Services\UploadServe; // 引入上传服务类
use Illuminate\Support\Facades\Storage; // 引入存储门面,便于文件存储操作
class UploadController extends Controller
{
/**
* @param UploadServe $uploadServe
* @return array
* 通过编辑器上传文件.
*
* @param UploadServe $uploadServe 上传服务实例
* @return array 返回上传结果数组
*/
public function uploadByEditor(UploadServe $uploadServe)
{
$disk = 'public';
$disk = 'public'; // 定义使用的存储磁盘
try {
$files = $uploadServe->setFileInput('pictures')
->setMaxSize('10M')
->setExtensions(['jpg', 'jpeg', 'png', 'bmp', 'gif'])
->validate()
->storeMulti('upload/editor', compact('disk'));
// 设置文件输入名称、最大文件大小和允许的文件扩展名,并进行验证和存储
$files = $uploadServe->setFileInput('pictures') // 设置文件输入名称为 'pictures'
->setMaxSize('10M') // 设置最大文件大小为 10MB
->setExtensions(['jpg', 'jpeg', 'png', 'bmp', 'gif']) // 设置允许的文件扩展名
->validate() // 验证上传的文件
->storeMulti('upload/editor', compact('disk')); // 存储文件,路径为 'upload/editor'
// 将存储的文件路径转换为可访问的 URL
$files = collect($files)->map(function ($file) use ($disk) {
return Storage::disk($disk)->url($file);
})->all();
return Storage::disk($disk)->url($file); // 获取文件的 URL
})->all(); // 转换为数组
} catch (UploadException $e) {
return ['errno' => 1, 'msg' => $e->getMessage()];
// 捕获上传异常并返回错误信息
return ['errno' => 1, 'msg' => $e->getMessage()]; // 返回错误代码和消息
}
return ['errno' => 0, 'data' => $files];
// 返回成功的上传结果
return ['errno' => 0, 'data' => $files]; // 返回成功代码和文件 URL 列表
}
}

@ -2,28 +2,28 @@
namespace App\Admin\Controllers;
use App\Admin\Actions\Post\ActiveUserAction;
use App\Admin\Transforms\UserSexTransform;
use App\Admin\Transforms\YesNoTransform;
use App\Enums\UserSexEnum;
use App\Enums\UserStatusEnum;
use App\Http\Controllers\Controller;
use App\Models\Level;
use App\Models\User;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Grid\Filter;
use Encore\Admin\Layout\Content;
use Encore\Admin\Show;
use Illuminate\Validation\Rule;
use App\Admin\Actions\Post\ActiveUserAction; // 引入激活用户操作
use App\Admin\Transforms\UserSexTransform; // 引入性别转换器
use App\Admin\Transforms\YesNoTransform; // 引入是/否转换器
use App\Enums\UserSexEnum; // 引入性别枚举
use App\Enums\UserStatusEnum; // 引入用户状态枚举
use App\Http\Controllers\Controller; // 引入控制器基类
use App\Models\Level; // 引入等级模型
use App\Models\User; // 引入用户模型
use Encore\Admin\Controllers\HasResourceActions; // 引入资源操作特性
use Encore\Admin\Form; // 引入表单构建器
use Encore\Admin\Grid; // 引入网格构建器
use Encore\Admin\Grid\Filter; // 引入网格过滤器
use Encore\Admin\Layout\Content; // 引入内容布局
use Encore\Admin\Show; // 引入显示构建器
use Illuminate\Validation\Rule; // 引入验证规则
class UserController extends Controller
{
use HasResourceActions;
use HasResourceActions; // 使用资源操作特性,提供 CRUD 操作
/**
* Index interface.
* 显示会员列表界面.
*
* @param Content $content
* @return Content
@ -31,43 +31,43 @@ class UserController extends Controller
public function index(Content $content)
{
return $content
->header('会员列表')
->description('')
->body($this->grid());
->header('会员列表') // 设置页面标题
->description('') // 设置页面描述
->body($this->grid()); // 设置页面主体为网格
}
/**
* Show interface.
* 显示用户详情界面.
*
* @param mixed $id
* @param mixed $id 用户 ID
* @param Content $content
* @return Content
*/
public function show($id, Content $content)
{
return $content
->header('详情')
->description('')
->body($this->detail($id));
->header('详情') // 设置页面标题
->description('') // 设置页面描述
->body($this->detail($id)); // 设置页面主体为用户详情
}
/**
* Edit interface.
* 显示编辑用户界面.
*
* @param mixed $id
* @param mixed $id 用户 ID
* @param Content $content
* @return Content
*/
public function edit($id, Content $content)
{
return $content
->header('Edit')
->description('')
->body($this->form()->edit($id));
->header('Edit') // 设置页面标题
->description('') // 设置页面描述
->body($this->form()->edit($id)); // 设置页面主体为编辑表单
}
/**
* Create interface.
* 显示创建用户界面.
*
* @param Content $content
* @return Content
@ -75,131 +75,128 @@ class UserController extends Controller
public function create(Content $content)
{
return $content
->header('新建')
->description('')
->body($this->form());
->header('新建') // 设置页面标题
->description('') // 设置页面描述
->body($this->form()); // 设置页面主体为创建表单
}
/**
* Make a grid builder.
* 创建网格构建器.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new User);
$grid = new Grid(new User); // 创建用户网格
// 获取所有等级,并按最小分数降序排序
$levels = Level::query()->orderBy('min_score', 'desc')->get();
// 排序最新的
// 按照最新的用户排序
$grid->model()->latest();
$grid->column('id', 'Id');
$grid->column('name', '用户名');
// 定义网格列
$grid->column('id', 'Id'); // 用户 ID
$grid->column('name', '用户名'); // 用户名
$grid->column('sex', '性别')->display(function ($sex) {
return UserSexTransform::trans($sex);
return UserSexTransform::trans($sex); // 显示性别
});
$grid->column('email', '邮箱')->display(function ($email) {
return str_limit($email, 20);
return str_limit($email, 20); // 限制显示邮箱长度
});
$grid->column('avatar', '头像')->image('', 50, 50);
$grid->column('github_name', 'Github');
$grid->column('qq_name', 'QQ');
$grid->column('weibo_name', '微博');
$grid->column('avatar', '头像')->image('', 50, 50); // 显示用户头像
$grid->column('github_name', 'Github'); // Github 昵称
$grid->column('qq_name', 'QQ'); // QQ 昵称
$grid->column('weibo_name', '微博'); // 微博 昵称
$grid->column('level', '等级')->display(function () use ($levels) {
// 根据用户总积分获取对应等级
$level = $levels->where('min_score', '<=', $this->score_all)->first();
return optional($level)->name;
return optional($level)->name; // 显示等级名称
});
$grid->column('score_all', '总积分')->sortable();
$grid->column('score_now', '剩余积分')->sortable();
$grid->column('login_ip', '登录地址');
$grid->column('login_count', '登录次数')->sortable();
$grid->column('score_all', '总积分')->sortable(); // 总积分,支持排序
$grid->column('score_now', '剩余积分')->sortable(); // 剩余积分,支持排序
$grid->column('login_ip', '登录地址'); // 登录地址
$grid->column('login_count', '登录次数')->sortable(); // 登录次数,支持排序
$grid->column('is_active', '是否激活')->display(function ($isActive) {
return YesNoTransform::trans($isActive);
return YesNoTransform::trans($isActive); // 显示是否激活状态
});
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '修改时间');
$grid->column('created_at', '创建时间'); // 创建时间
$grid->column('updated_at', '修改时间'); // 修改时间
// 定义网格操作
$grid->actions(function (Grid\Displayers\DropdownActions $actions) {
// 如果用户未激活,则添加激活用户操作
if (!$actions->row->is_active) {
$actions->add(new ActiveUserAction());
}
});
// 筛选功能
$levelOptions = $levels->pluck('name', 'id');
$levelOptions = $levels->pluck('name', 'id'); // 获取等级选项
$grid->filter(function (Filter $filter) use ($levelOptions) {
$filter->disableIdFilter();
$filter->like('name', '用户名');
$filter->like('email', '邮箱');
$filter->disableIdFilter(); // 禁用 ID 筛选
$filter->like('name', '用户名'); // 用户名模糊筛选
$filter->like('email', '邮箱'); // 邮箱模糊筛选
// 按等级筛选
$filter->where(function ($query) {
// 找到这个等级
// 找到选中的等级
$level = Level::query()->findOrFail($this->input);
// 找到下一个等级
$high = Level::query()->where('min_score', '>', $level->min_score)->orderBy('min_score', 'asc')->first();
// 筛选总积分在当前等级范围内的用户
$query->where('score_all', '>=', $level->min_score);
if (!is_null($high)) {
$query->where('score_all', '<', $high->min_score);
}
}, '等级')->select($levelOptions);
}, '等级')->select($levelOptions); // 添加等级选择
});
return $grid;
return $grid; // 返回网格
}
/**
* Make a show builder.
* 创建显示构建器.
*
* @param mixed $id
* @param mixed $id 用户 ID
* @return Show
*/
protected function detail($id)
{
$show = new Show(User::findOrFail($id));
$show = new Show(User::findOrFail($id)); // 创建用户详情显示构建器
$show->field('id', 'Id');
$show->field('name', '用户名');
// 定义显示字段
$show->field('id', 'Id'); // 用户 ID
$show->field('name', '用户名'); // 用户名
$show->field('sex', '性别')->as(function ($sex) {
return UserSexTransform::trans($sex);
return UserSexTransform::trans($sex); // 显示性别
});
$show->field('email', '邮箱');
$show->field('avatar', '头像')->image();
$show->field('github_name', 'Github昵称');
$show->field('qq_name', 'QQ昵称');
$show->field('weibo_name', '微博昵称');
$show->field('login_ip', '登录地址');
$show->field('login_count', '登录次数');
$show->field('email', '邮箱'); // 邮箱
$show->field('avatar', '头像')->image(); // 显示头像
$show->field('github_name', 'Github昵称'); // Github 昵称
$show->field('qq_name', 'QQ昵称'); // QQ 昵称
$show->field('weibo_name', '微博昵称'); // 微博 昵称
$show->field('login_ip', '登录地址'); // 登录地址
$show->field('login_count', '登录次数'); // 登录次数
$show->field('is_active', '是否激活')->as(function ($isActive) {
return YesNoTransform::trans($isActive); // 显示是否激活状态
})->unescape(); // 取消 HTML 转义
$show->field('created_at', '创建时间'); // 创建时间
$show->field('updated_at', '修改时间'); // 修改时间
return YesNoTransform::trans($isActive);
})->unescape();
$show->field('created_at', '创建时间');
$show->field('updated_at', '修改时间');
// 显示用户的收货地址
$show->addresses('收货地址', function (Grid $grid) {
$grid->model()->latest();
$grid->column('name', '收货人');
$grid->column('phone', '收货人联系方式');
$grid->column('detail_address', '详细地址');
$grid->model()->latest(); // 按最新排序
$grid->column('name', '收货人'); // 收货人姓名
$grid->column('phone', '收货人联系方式'); // 收货人联系方式
$grid->column('detail_address', '详细地址'); // 详细地址
$grid->column('is_default', '是否默认')->display(function ($is) {
return YesNoTransform::trans($is);
return YesNoTransform::trans($is); // 显示是否默认
});
$grid->column('created_at', '创建时间');
$grid->column('created_at', '创建时间'); // 创建时间
// 禁用一些操作
$grid->disableActions();
$grid->disableCreateButton();
$grid->disableFilter();
@ -207,13 +204,14 @@ class UserController extends Controller
$grid->disableRowSelector();
});
// 显示用户的积分日志
$show->scoreLogs('积分', function (Grid $grid) {
$grid->model()->latest(); // 按最新排序
$grid->column('description', '描述'); // 积分描述
$grid->column('score', '积分'); // 积分
$grid->column('created_at', '创建时间'); // 创建时间
$grid->model()->latest();
$grid->column('description', '描述');
$grid->column('score', '积分');
$grid->column('created_at', '创建时间');
// 禁用一些操作
$grid->disableActions();
$grid->disableCreateButton();
$grid->disableFilter();
@ -221,11 +219,11 @@ class UserController extends Controller
$grid->disableRowSelector();
});
return $show;
return $show; // 返回用户详情显示构建器
}
/**
* Make a form builder.
* 创建表单构建器.
*
* @return Form
*/
@ -233,53 +231,61 @@ class UserController extends Controller
{
// 前台用户注册必须要有这个 token兼容一下
$form = new Form(tap(new User, function ($user) {
$user->active_token = str_random(60);
$user->active_token = str_random(60); // 生成随机激活 token
}));
// 用户名字段
$form->text('name', '用户名')->rules(function (Form $form) {
$rules = 'required|unique:users,id';
$rules = 'required|unique:users,name'; // 用户名必填且唯一
// 更新操作
// 更新操作时,排除当前用户 ID
if (!is_null($id = $form->model()->getKey())) {
$rules .= ",{$id}";
}
return $rules;
return $rules; // 返回验证规则
});
$sexOptions = [UserSexEnum::MAN => '男', UserSexEnum::WOMAN => '女'];
$form->select('sex', '性别')->rules(['required', Rule::in(array_keys($sexOptions))])->options($sexOptions)->default(1);
// 性别字段
$sexOptions = [UserSexEnum::MAN => '男', UserSexEnum::WOMAN => '女']; // 性别选项
$form->select('sex', '性别')->rules(['required', Rule::in(array_keys($sexOptions))])
->options($sexOptions)->default(1); // 默认选择男
// 邮箱字段
$form->email('email', '邮箱')->rules(function (Form $form) {
$rules = 'required|email|unique:users,email';
$rules = 'required|email|unique:users,email'; // 邮箱必填且唯一
// 更新操作
// 更新操作时,排除当前用户 ID
if (!is_null($id = $form->model()->getKey())) {
$rules .= ",{$id}";
}
return $rules;
return $rules; // 返回验证规则
});
// dd(windows_os());
$form->password('password', '密码');
$avatar = $form->image('avatar', '头像')->uniqueName()->move('avatars');
// 密码字段
$form->password('password', '密码'); // 密码字段
// 头像字段
$avatar = $form->image('avatar', '头像')->uniqueName()->move('avatars'); // 上传头像并指定存储路径
// 如果不是 Windows 系统,调整头像尺寸
if (!windows_os()) {
$avatar->resize(160, 160);;
$avatar->resize(160, 160);
}
// 激活状态开关
$form->switch('is_active', '激活');
// 加密密码
// 在保存表单前加密密码
$form->saving(function (Form $form) {
if ($form->password) {
$form->password = bcrypt($form->password);
$form->password = bcrypt($form->password); // 加密密码
} else {
$form->password = $form->model()->password;
$form->password = $form->model()->password; // 保持原密码
}
});
return $form;
return $form; // 返回表单构建器
}
}

@ -1,8 +1,12 @@
<?php
// 引入 WangEditor 扩展类
use App\Admin\Extensions\WangEditor;
// 引入 Encore\Admin\Form 类
use Encore\Admin\Form;
// 忘记默认的 'map' 和 'editor' 字段,以便自定义处理
Form::forget(['map', 'editor']);
// 扩展表单功能,注册 WangEditor 作为一个新的表单字段类型
Form::extend('editor', WangEditor::class);

Loading…
Cancel
Save