阶段更新

This commit is contained in:
2023-03-09 11:54:13 +08:00
parent e78454540f
commit 3cd75b1d6e
47 changed files with 4844 additions and 1646 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
/public/hot /public/hot
/public/storage /public/storage
/storage/*.key /storage/*.key
/storage/
/vendor /vendor
.env .env
.env.backup .env.backup

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Admin\Actions;
use Encore\Admin\Actions\RowAction;
class LinkCreateAddress extends RowAction
{
public $name = '添加收货地址';
/**
* @return string
*/
public function href(): string
{
return admin_url("mall/addresses/create?user_id=".$this->row->id);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Admin\Actions;
use Encore\Admin\Actions\RowAction;
class LinkStockOrderDeliver extends RowAction
{
public $name = '发货';
/**
* @return string
*/
public function href(): string
{
return admin_url('mall/stock_orders?user_id='.$this->row->user->id);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Admin\Actions;
use Encore\Admin\Actions\RowAction;
class LinkVipOrderRefund extends RowAction
{
public $name = '体验官退款';
/**
* @return string
*/
public function href(): string
{
return admin_url("platform/vip_orders?user[username]=".$this->row->user->username);
}
}

View File

@@ -3,44 +3,244 @@
namespace App\Admin\Controllers; namespace App\Admin\Controllers;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Layout\Column; use Encore\Admin\Layout\Column;
use Encore\Admin\Layout\Content; use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row; use Encore\Admin\Layout\Row;
use Encore\Admin\Widgets\InfoBox;
use Illuminate\Support\Facades\Artisan;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderItem;
use Modules\User\Models\Identity;
use Modules\User\Models\User;
use Modules\User\Models\UserStock;
class HomeController extends Controller class HomeController extends Controller
{ {
public $content;
/** /**
* Notes : 数据看板 * Notes : 数据看板
* *
* @Date : 2021/3/10 5:12 下午 * @Date : 2021/3/10 5:12 下午
* @Author : <Jason.C> * @Author : < Jason.C >
* @param Content $content * @param Content $content
* @return Content * @return Content
*/ */
public function index(Content $content): Content public function index(Content $content)
{ {
if (config('app.debug')) { $this->content = $content->title('数据看板')->description('Description...');
return $content $this->getUserData();
->title(__('admin.menu_titles.dashboard')) $this->getUserStockData();
->description('Description...') $this->getUserStockOrderData();
->row(Dashboard::title()) return $this->content;
->row(function (Row $row) {
$row->column(4, function (Column $column) {
$column->append(Dashboard::environment());
});
$row->column(4, function (Column $column) {
$column->append(Dashboard::dependencies());
});
$row->column(4, function (Column $column) {
$column->append(Dashboard::extensions());
});
});
} else {
return $content
->title(__('admin.menu_titles.dashboard'))
->description('Description...');
}
} }
/**
* Notes: 获取用户数据
*
* @Author: 玄尘
* @Date : 2021/11/17 11:24
*/
public function getUserData()
{
$this->content->row($this->setDivider('用户统计'));
$users = [
'all' => [
'name' => '用户总数',
'color' => 'blue',
'count' => User::count()
],
'free_vip' => [
'name' => '免费会员',
'color' => 'green',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->FreeVip();
})->count()
],
'yk' => [
'name' => '月卡用户数',
'color' => 'red',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->Yk();
})->count()
],
'jk' => [
'name' => '季卡用户数',
'color' => 'red',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->Jk();
})->count()
],
'nk' => [
'name' => '年卡用户数',
'color' => 'yellow',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->Nk();
})->count(),
],
];
$this->content->row(function (Row $row) use ($users) {
foreach ($users as $user) {
$row->column(2, function (Column $column) use ($user) {
$column->append(new InfoBox(
$user['name'],
'users',
$user['color'],
'/admin/users',
$user['count'],
));
});
}
});
return $this->content;
}
/**
* Notes: 用户水数量
*
* @Author: 玄尘
* @Date: 2022/9/1 13:35
* @return mixed
*/
public function getUserStockData()
{
$this->content->row($this->setDivider('会员水库存数'));
$all = UserStock::query()->sum('stock');
$holds = UserStock::query()->sum('hold');
$sy = bcsub($all, $holds);
$users = [
'all' => [
'name' => '总数',
'color' => 'blue',
'count' => UserStock::query()->sum('stock')
],
'stock' => [
'name' => '已提货数',
'color' => 'green',
'count' => UserStock::query()->sum('hold')
],
'sy' => [
'name' => '待提货数',
'color' => 'green',
'count' => $sy
],
];
$this->content->row(function (Row $row) use ($users) {
foreach ($users as $user) {
$row->column(2, function (Column $column) use ($user) {
$column->append(new InfoBox(
$user['name'],
'goods',
$user['color'],
'/admin/stocks',
$user['count'],
));
});
}
});
return $this->content;
}
/**
* Notes: 提货订单数量
*
* @Author: 玄尘
* @Date: 2022/9/1 13:51
*/
public function getUserStockOrderData()
{
$this->content->row($this->setDivider('会员提货订单'));
$users = [
'all' => [
'name' => '订单总数',
'color' => 'blue',
'count' => Order::query()->where('type', Order::TYPE_SAMPLE)->count()
],
'deliver' => [
'name' => '待发货',
'color' => 'green',
'count' => Order::query()
->where('type', Order::TYPE_SAMPLE)
->paid()
->count()
],
'deliverd' => [
'name' => '已发货',
'color' => 'green',
'count' => Order::query()
->where('type', Order::TYPE_SAMPLE)
->whereIn('state', [
Order::STATUS_DELIVERED,
])
->count(),
],
'signed' => [
'name' => '已签收',
'color' => 'green',
'count' => Order::query()
->where('type', Order::TYPE_SAMPLE)
->whereIn('state', [
Order::STATUS_SIGNED,
])
->count()
],
];
$this->content->row(function (Row $row) use ($users) {
foreach ($users as $user) {
$row->column(2, function (Column $column) use ($user) {
$column->append(new InfoBox(
$user['name'],
'goods',
$user['color'],
'/admin/stocks',
$user['count'],
));
});
}
});
return $this->content;
}
/**
* Notes : 清理模型缓存
*
* @Date : 2021/6/8 10:51 上午
* @Author : < Jason.C >
* @return string
*/
public function cleanCache(): string
{
Artisan::call('modelCache:clear');
return '缓存清理成功';
}
public function setDivider($title)
{
return <<<HTML
<div style="height: 20px; border-bottom: 1px solid #eee; text-align: center;margin-top: 20px;margin-bottom: 20px;">
<span style="font-size: 18px; padding: 0 10px;">
{$title}
</span>
</div>
HTML;
}
} }

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Admin\Controllers\Material;
use App\Models\Material;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
class IndexController extends AdminController
{
/**
* Title for current resource.
*
* @var string
*/
protected $title = '物料/素材';
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(new Material());
$grid->column('id', '编号');
$grid->column('title', '名称');
$grid->column('地址')->display(function () {
return $this->cover_url;
});
$grid->column('created_at', '创建时间');
return $grid;
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form(): Form
{
$form = new Form(new Material());
$form->text('title', '名称');
$form->image('cover', '图片')
->move('materials/'.date('Y/m/d'))
->removable()
->required();
return $form;
}
}

View File

@@ -0,0 +1,205 @@
<?php
namespace App\Admin\Controllers\Platform;
use Encore\Admin\Layout\Column;
use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row;
use Encore\Admin\Widgets\InfoBox;
use Illuminate\Routing\Controller;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderItem;
use Modules\User\Models\User;
use Modules\User\Models\UserStock;
class DashboardController extends Controller
{
public function index(Content $content): Content
{
$this->content = $content->title('数据看板')->description('Description...');
$this->getVipUserData();
$this->getUserStockData();
return $this->content;
}
/**
* Notes: 获取用户数据
*
* @Author: 玄尘
* @Date : 2021/11/17 11:24
*/
public function getVipUserData(): Content
{
$this->content->row($this->setDivider('会员统计'));
$users = [
'all' => [
'name' => '总会员量',
'color' => 'blue',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->where('id', '>', 1);
})->count()
],
'free_vip' => [
'name' => '免费会员',
'color' => 'green',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->FreeVip();
})->count()
],
'yk' => [
'name' => '月卡用户数',
'color' => 'red',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->Yk();
})->count()
],
'jk' => [
'name' => '季卡用户数',
'color' => 'red',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->Jk();
})->count()
],
'nk' => [
'name' => '年卡用户数',
'color' => 'yellow',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->Nk();
})->count(),
],
'onlone' => [
'name' => '在线会员数',
'color' => 'red',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->where('id', '>', 2);
})
->where('status', User::STATUS_INIT)
->count(),
],
'refund' => [
'name' => '退费会员数',
'color' => 'maroon',
'count' => User::query()
->whereHas('identities', function ($q) {
$q->where('id', '>', 2);
})
->where('status', User::STATUS_REFUND)
->count(),
],
];
$this->content->row(function (Row $row) use ($users) {
foreach ($users as $user) {
$row->column(2, function (Column $column) use ($user) {
$column->append(new InfoBox(
$user['name'],
'users',
$user['color'],
'/admin/platform/vips',
$user['count'],
));
});
}
});
return $this->content;
}
/**
* Notes: 用户水数量
*
* @Author: 玄尘
* @Date: 2022/9/1 13:35
* @return mixed
*/
public function getUserStockData()
{
$this->content->row($this->setDivider('会员库存数'));
$all = UserStock::query()->sum('stock');
$holds = UserStock::query()->sum('hold');
$sy = bcsub($all, $holds);
$users = [
'all' => [
'name' => '累计总箱数',
'color' => 'blue',
'count' => $all
],
'stock' => [
'name' => '累计提货数',
'color' => 'green',
'count' => $holds
],
'sy' => [
'name' => '累计剩余',
'color' => 'green',
'count' => $sy
],
'online' => [
'name' => '线上发货',
'color' => 'green',
'count' => OrderItem::query()
->whereHas('order', function ($q) {
$q->whereIn('state', [
Order::STATUS_PAID,
Order::STATUS_DELIVERED,
Order::STATUS_SIGNED,
])->where('channel', Order::CHANNEL_USER);
})
->sum('qty')
],
'offline' => [
'name' => '线下发货',
'color' => 'green',
'count' => OrderItem::query()
->whereHas('order', function ($q) {
$q->whereIn('state', [
Order::STATUS_PAID,
Order::STATUS_DELIVERED,
Order::STATUS_SIGNED,
])->where('channel', Order::CHANNEL_SYSTEM);
})
->sum('qty')
],
];
$this->content->row(function (Row $row) use ($users) {
foreach ($users as $user) {
$row->column(2, function (Column $column) use ($user) {
$column->append(new InfoBox(
$user['name'],
'goods',
$user['color'],
'/admin/users/stocks',
$user['count'],
));
});
}
});
return $this->content;
}
public function setDivider($title)
{
return <<<HTML
<div style="height: 20px; border-bottom: 1px solid #eee; text-align: center;margin-top: 20px;margin-bottom: 20px;">
<span style="font-size: 18px; padding: 0 10px;">
{$title}
</span>
</div>
HTML;
}
}

View File

@@ -0,0 +1,255 @@
<?php
namespace App\Admin\Controllers\Platform;
use App\Admin\Actions\LinkCreateAddress;
use Carbon\Carbon;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\MessageBag;
use Modules\User\Http\Controllers\Admin\Actions\AddUserRemark;
use Modules\User\Http\Controllers\Admin\Actions\JoinIdentity;
use Modules\User\Http\Controllers\Admin\Actions\UserStatusInit;
use Modules\User\Http\Controllers\Admin\Actions\UserStatusRefund;
use Modules\User\Models\Identity;
use Modules\User\Models\IdentityLog;
use Modules\User\Models\IdentityMiddle;
use Modules\User\Models\User;
use Modules\User\Renderable\UserLog;
class VipController extends AdminController
{
protected $title = '会员管理';
/**
* Notes : 用户管理列表
*
* @Date : 2021/3/11 1:59 下午
* @Author : <Jason.C>
* @return Grid
*/
public function grid(): Grid
{
$grid = new Grid(new User());
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableDelete();
$actions->disableView();
if ($actions->row->status == User::STATUS_INIT) {
$actions->add(new UserStatusRefund());
}
if ($actions->row->status == User::STATUS_REFUND) {
$actions->add(new UserStatusInit());
}
$actions->add(new JoinIdentity());
$actions->add(new AddUserRemark());
$actions->add(new LinkCreateAddress());
});
$grid->quickSearch('username')->placeholder('快速搜索用户名');
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('username', '用户名');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('info.nickname', '用户昵称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('identities.id', '身份')
->select(Identity::query()->where('id', '>', 1)->pluck('name', 'id'));
});
});
$grid->model()
->whereHas('identities', function ($q) {
$q->where('id', '>', 1);
})
->withCount(['addresses', 'logs'])
->with(['info', 'parent', 'identities', 'addresses', 'vipOrders', 'userStock', 'logs']);
//序号 姓名 手机号 会员类型 会员编号 缴费金额 加入时间 状态(正常,退费) 用箱数 提货箱数 剩余箱数
$grid->column('id', '序号');
$grid->column('username', '手机号');
$grid->column('identities', '会员类型')
->display(function () {
$data = [];
foreach ($this->identities as $identity) {
$data[] = $identity->name;
}
return $data;
})
->label();
$grid->column('serial', '会员编号')
->display(function () {
$data = [];
foreach ($this->identities as $identity) {
$data[] = $identity->serial_prefix.$identity->getOriginal('pivot_serial');
}
return $data;
})
->label();
$grid->column('price', '缴费金额')
->display(function () {
return $this->getOpenVipPrices();
})
->label();
$grid->column('created_at', '加入时间');
$grid->column('status', '状态')
->using(User::STATUS)
->label();
$grid->column('userStock.stock', '总箱数');
$grid->column('userStock.hold', '提货箱数');
$grid->column('userStock.residue', '剩余箱数');
$grid->column('addresses_count', '收货地址')
->link(function () {
return route('admin.mall.addresses.index', ['user_id' => $this->id]);
}, '_self');
$grid->column('logs_count', '备注')
->modal('备注信息', UserLog::class);
$grid->disableExport(false);
$grid->export(function ($export) {
$export->column('identities', function ($value, $original) {
return strip_tags($value);
});
$export->column('serial', function ($value, $original) {
return strip_tags($value);
});
$export->column('price', function ($value, $original) {
return strip_tags($value);
});
$export->column('status', function ($value, $original) {
return strip_tags($value);
});
// $export->column('use_way', function ($value, $original) {
// return strip_tags($value);
// });
// $export->column('所属用户', function ($value, $original) {
// return iconv('gb2312//ignore', 'utf-8',
// iconv('utf-8', 'gb2312//ignore', strip_tags(str_replace("&nbsp;", " ", $value))));
// });
//
// $export->column('couponGrant.code', function ($value, $original) {
// return $value."\n";
// });
$export->except(['addresses_count', 'logs_count']);
$export->filename($this->title.date("YmdHis"));
});
return $grid;
}
/**
* Notes : 编辑表单
*
* @Date : 2021/7/15 5:09 下午
* @Author : <Jason.C>
* @return Form
* @throws Exception
*/
public function form(): Form
{
// if (! config('user.create_user_by_admin')) {
// throw new Exception('不运允许操作用户');
// }
Admin::script(" $(document.body).append(`<script src='/vendor/js/setStock.js'>`); ");
$form = new Form(new User());
//姓名 手机号 身份 编号 (数字从1开始) 缴费金额 加入日期(当天) 总箱数
$form->text('info.nickname', '姓名')->required();
$form->text('username', '手机号')
->required()
->rules(['phone:CN,mobile', 'unique:users,username,{{id}}'], [
'phone' => '手机号格式错误'
]);
$form->select('join_identity_id', '加入身份')
->options(Identity::where('order', '>', 2)->pluck('name', 'id'))
->required();
$form->text('serial', '编号')->value($form->model()->getNewSerial(8))->required();
$form->number('price', '缴费金额')
->default(1)
->required();
$form->date('join_at', '加入时间')->default(now())->required();
$form->number('stock', '总箱数')
->default(0)
->setLabelClass(['identity_stock'])
->required();
$form->ignore(['join_at', 'price', 'serial', 'stock', 'join_identity_id']);
$form->saving(function (Form $form) {
$exists = IdentityMiddle::query()->where('serial', $form->serial)->first();
if ($exists) {
$error = new MessageBag([
'title' => '错误',
'message' => '编号已经存在',
]);
return back()->withInput()->with(compact('error'));
}
});
$form->saved(function (Form $form) {
$user = $form->model();
$user->update([
'created_at' => Carbon::parse(request()->jion_at)->startOfDay()
]);
$user->createOrder(request()->join_identity_id, 1, request()->price, request()->stock, [
'serial' => request()->serial,
'channel' => IdentityLog::CHANNEL_SYSTEM,
]);//创建订单
});
return $form;
}
/**
* Notes : User 列表选择, 这里没有判断,用户是否已经有店铺了,如果判断的情况,可能导致当前用户 无法被选中
*
* @Date : 2021/5/6 4:35 下午
* @Author : <Jason.C>
*/
public function ajax(Request $request)
{
$q = $request->get('q');
return User::leftJoin('user_infos as info', 'users.id', '=', 'info.user_id')
->where('username', 'like', "%$q%")
->orWhere('info.nickname', 'like', "%$q%")
->select('id', DB::raw('CONCAT(username, " [", info.nickname, "]") as text'))
->paginate();
}
/**
* Notes: 获取库存
*
* @Author: 玄尘
* @Date: 2022/9/7 15:23
* @param Request $request
* @return mixed
*/
public function stock(Request $request)
{
$q = $request->get('q');
$identity = Identity::find($q);
return ['status_code' => 200, 'value' => $identity->stock];
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace App\Admin\Controllers\Platform;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Exception;
use Modules\User\Http\Controllers\Admin\Actions\Refund;
use Modules\User\Models\Order;
class VipOrderController extends AdminController
{
protected $title = '体验官退款';
/**
* Notes: 升级订单
*
* @Author: 玄尘
* @Date : 2021/6/7 15:19
* @return Grid
*/
public function grid(): Grid
{
try {
trait_exists('Modules\Payment\Traits\WithPayments');
$grid = new Grid(new Order());
$grid->model()
->whereHas('identity', function ($q) {
$q->ty();
})
->whereIn('state',[Order::STATE_SUCCESS,Order::STATE_REFUND])
->latest();
$grid->disableCreateButton();
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableDelete();
$actions->disableView();
if ($actions->row->canRefund()) {
$actions->add(new Refund());
}
});
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('user.username', '用户名');
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->equal('state', '状态')->select(Order::STATES);
});
});
$grid->column('id', '用户ID');
$grid->column('升级用户')->display(function () {
return $this->user->username."({$this->user->info->nickname})";
});
$grid->column('identity.name', '身份');
$grid->column('price', '金额');
$grid->column('state', '状态')->using(Order::STATES)->label();
$grid->column('type', '类型')->using(Order::TYPES)->label();
$grid->column('created_at', '升级时间');
return $grid;
} catch (Exception $exception) {
dd('Payment 模块不存在,无法加载订单数据');
}
}
public function form(): Form
{
$form = new Form(new Order());
$form->decimal('price', '金额')->required();
return $form;
}
}

View File

@@ -0,0 +1,135 @@
<?php
namespace App\Admin\Controllers;
use App\Bonus\IdentityBonus;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Liuhelong\LaravelAdmin\Wechat\Models\WechatOffiaccountUser;
use Modules\Coupon\Models\Coupon;
use Modules\Coupon\Traits\WithCoupon;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
use Modules\User\Models\UserInvite;
use Modules\User\Models\UserStockLog;
use Modules\User\Models\UserWechat;
use Modules\User\Models\UserWechatOfficial;
use Modules\User\Traits\WechatTrait;
use Vinkla\Hashids\Facades\Hashids;
class TestController extends Controller
{
use WechatTrait;
public function index()
{
$this->getAllSubscribeUsers();
dd(1);
$weChat = app('wechat.official_account');
$officialUsers = UserWechatOfficial::query()->get();
foreach ($officialUsers as $officialUser) {
if (! $officialUser->userWechat->unionid) {
$info = $weChat->user->get($officialUser->openid);
$officialUser->userWechat->update([
'unionid' => $info->unionid
]);
}
}
dd(1);
}
/**
* Notes: 清空数据表的操作,为了测试用的
*
* @Author: <C.Jason>
* @Date : 2020/11/23 4:54 下午
*/
public function truncate(Request $request)
{
$name = $request->name;
$is_test = config('app.is_test');
dump('is_test'.$is_test);
if ($name != 'skyxu') {
dd('name不对');
}
if (! $is_test) {
dd('不是测试环境');
}
dd(1);
$tables = [
'admin_operation_log',
'bouns',
'bouns_orders',
'bouns_user_perves',
'coupon_grants',
'coupon_item_use_logs',
'coupon_use_logs',
'failed_jobs',
'gout_case_log_symptoms',
'gout_case_logs',
'gout_case_timelines',
'gout_case_symptom',
'gout_cases',
'gout_surveys',
'gout_votes',
'jobs',
'linker_relations',
'linkers',
'mall_addresses',
'mall_order_expresses',
'mall_order_items',
'mall_orders',
'mall_carts',
'mall_refund_items',
'mall_refund_logs',
'mall_refunds',
'mall_refund_expresses',
'notifications',
'payment_refunds',
'payments',
'user_account_logs',
'user_accounts',
'user_identity',
'user_identity_logs',
'user_identity_coupons',
'user_infos',
'user_invites',
'user_logs',
'user_orders',
'user_perves',
'user_relations',
'user_sign_logs',
'user_signs',
'user_sms',
'user_stock_logs',
'user_stocks',
'user_wechat_apps',
'user_wechat_minis',
'user_wechat_officials',
'user_wechats',
'users',
'versions',
'wechat_offiaccount_event_logs',
'withdraw_alipay_accounts',
'withdraw_bank_accounts',
'withdraw_logs',
'withdraws',
'personal_access_tokens',
];
foreach ($tables as $table) {
DB::table($table)->truncate();
}
dd('清理成功');
}
}

View File

@@ -0,0 +1,10 @@
<?php
use Illuminate\Routing\Router;
Route::group([
'namespace' => 'Material',
], function (Router $router) {
$router->resource('materials', 'IndexController');
});

View File

@@ -0,0 +1,15 @@
<?php
use Illuminate\Routing\Router;
Route::group([
'namespace' => 'Platform',
'prefix' => 'platform',
], function (Router $router) {
$router->resource('experiences', 'ExperienceController');//体验官审核
$router->resource('vip_orders', 'VipOrderController');//体验官审核
$router->resource('vips', 'VipController');//会员管理
$router->get('identity_stock', 'VipController@stock')->name('platform.identity_stock');;//会员管理
$router->get('dashboard', 'DashboardController@index');
});

12
app/Admin/Routes/test.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
Route::group([
'prefix' => 'test',
], function (Router $router) {
$router->get('', 'TestController@index');
$router->get('truncate', 'TestController@truncate');
$router->get('leady', 'LeadyController@index');
});

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Channels;
use Illuminate\Notifications\Notification;
class WechatMiniChannel
{
public function send($notifiable, Notification $notification)
{
$notification->toWeChat($notifiable);
}
}

11
app/Models/Material.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use App\Traits\HasCovers;
class Material extends Model
{
use HasCovers;
}

View File

@@ -0,0 +1,96 @@
<?php
namespace App\Notifications;
use App\Channels\WechatMiniChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Channels\DatabaseChannel;
use Illuminate\Notifications\Notification;
use Modules\User\Models\Identity;
use Modules\User\Models\IdentityMiddle;
use Modules\User\Models\User;
class SystemOpenVip extends Notification
{
use Queueable;
protected $identityMiddle;
protected $identity;
protected $title;
protected $remark;
protected $url;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(IdentityMiddle $identityMiddle)
{
$identity = $identityMiddle->identity;
$remark = '赠送'.$identity->stock.'箱水';
$this->title = "恭喜您!开通{$identityMiddle->identity->name}成功!";
$this->identityMiddle = $identityMiddle;
$this->identity = $identity;
$this->remark = $remark;
$this->url = config('user.web.base');
}
public function via(): array
{
return [DatabaseChannel::class, WechatMiniChannel::class];
}
/**
* Notes: 开通会员
*
* @Author: 玄尘
* @Date: 2022/8/9 10:44
* @param User $notifiable
* @return bool
*/
public function toWeChat(User $notifiable): bool
{
if ($notifiable->isOfficialSubscribe()) {
$app = app('wechat.official_account');
$start_at = $this->identityMiddle->started_at ?? '';
$end_at = $this->identityMiddle->ended_at ?? '';
$time = $start_at.' ~ '.$end_at;
if (empty($start_at) || empty($end_at)) {
$time = '永久';
}
$app->template_message->send([
'touser' => $notifiable->wechat->official_openid,
'template_id' => 'gtS1LS9Irw7h2RtQLT5Cxx4p28-k8PrPyH53HBU2oWk',
'url' => $this->url,
'data' => [
'first' => $this->title,
'keyword1' => $time,
'keyword2' => $this->remark,
'remark' => '',
],
]);
}
return true;
}
/**
* 发送到数据库
*
* @param mixed $notifiable
* @return array
*/
public function toDatabase(User $notifiable): array
{
return [
'title' => $this->title,
'content' => $this->remark,
'url' => $this->url,
];
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace App\Notifications;
use App\Channels\WechatMiniChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Channels\DatabaseChannel;
use Illuminate\Notifications\Notification;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderExpress;
use Modules\User\Models\User;
class SystemOrderDelivered extends Notification
{
use Queueable;
protected $order;
protected $title;
protected $url;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($title, Order $order, $url = '')
{
$this->title = $title;
$this->order = $order;
$this->url = $url;
}
public function via(): array
{
return [DatabaseChannel::class, WechatMiniChannel::class];
}
/**
* Notes: 订单发货
*
* @Author: 玄尘
* @Date: 2022/8/4 16:22
* @param User $notifiable
* @return bool
*/
public function toWeChat(User $notifiable): bool
{
if ($notifiable->isOfficialSubscribe()) {
$app = app('wechat.official_account');
$remark = '您的宝贝已经发货,请耐心等待';
if ($this->order->express->type == OrderExpress::TYPE_LOGISTICS) {
$remark .= ',经办人:'.$this->order->express->person;
}
$res = $app->template_message->send([
'touser' => $notifiable->wechat->official_openid,
'template_id' => 'UvUA6wvPSegvT7i8IVrLipktbtCmyjtdnuKD8EvyOO8',
'url' => $this->url,
'data' => [
'first' => $this->title,
'keyword1' => $this->order->order_no,
'keyword2' => $this->order->express->deliver_at,
'keyword3' => $this->order->express->express_id > 0 ? $this->order->express->express->name : '',
'keyword4' => $this->order->express->express_no ?? '',
'keyword5' => $this->order->express->getFullAddress(),
'remark' => $remark,
],
]);
}
return true;
}
/**
* Notes: 数据库
*
* @Author: 玄尘
* @Date: 2022/8/4 16:38
* @param User $notifiable
* @return array
*/
public function toDatabase(User $notifiable): array
{
return [
'title' => $this->title,
'content' => '订单编号:'.$this->order->order_no.' 已发货',
'url' => $this->url,
];
}
}

View File

@@ -15,13 +15,29 @@
"fruitcake/laravel-cors": "^2.0.4", "fruitcake/laravel-cors": "^2.0.4",
"genealabs/laravel-model-caching": "^0.11.3", "genealabs/laravel-model-caching": "^0.11.3",
"guzzlehttp/guzzle": "^7.4.0", "guzzlehttp/guzzle": "^7.4.0",
"iidestiny/laravel-filesystem-oss": "^2.1",
"intervention/image": "^2.5",
"jasonc/api": "^5.0.4", "jasonc/api": "^5.0.4",
"joshbrw/laravel-module-installer": "^2.0",
"laravel-admin-ext/grid-lightbox": "^1.0",
"laravel/framework": "^8.71.0", "laravel/framework": "^8.71.0",
"laravel/sanctum": "^2.12.2", "liuhelong/laravel-admin-wechat": "^1.3",
"maatwebsite/excel": "^3.1",
"nosun/ueditor": "^3.0.2", "nosun/ueditor": "^3.0.2",
"nwidart/laravel-modules": "^8.2.0", "nwidart/laravel-modules": "^8.2.0",
"overtrue/chinese-calendar": "^1.0",
"overtrue/easy-sms": "^2.3",
"overtrue/laravel-favorite": "^4.0",
"overtrue/laravel-lang": "~5.0",
"overtrue/laravel-subscribe": "3.1.0",
"overtrue/laravel-versionable": "^2.6",
"overtrue/laravel-wechat": "^6.0",
"overtrue/socialite": "^3.2",
"pragmarx/google2fa-laravel": "^2.0", "pragmarx/google2fa-laravel": "^2.0",
"simplesoftwareio/simple-qrcode": "^4.2" "propaganistas/laravel-phone": "^4.4",
"simplesoftwareio/simple-qrcode": "^4.2",
"symfony/workflow": "^5.2",
"vinkla/hashids": "^9.1"
}, },
"require-dev": { "require-dev": {
"facade/ignition": "^2.16.0", "facade/ignition": "^2.16.0",
@@ -35,7 +51,10 @@
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,
"preferred-install": "dist", "preferred-install": "dist",
"sort-packages": true "sort-packages": true,
"allow-plugins": {
"easywechat-composer/easywechat-composer": true
}
}, },
"extra": { "extra": {
"laravel": { "laravel": {

4604
composer.lock generated

File diff suppressed because it is too large Load Diff

146
config/wechat.php Normal file
View File

@@ -0,0 +1,146 @@
<?php
/*
* This file is part of the overtrue/laravel-wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
return [
/*
* 默认配置,将会合并到各模块中
*/
'defaults' => [
/*
* 指定 API 调用返回结果的类型array(default)/collection/object/raw/自定义类名
*/
'response_type' => 'array',
/*
* 使用 Laravel 的缓存系统
*/
'use_laravel_cache' => true,
/**
* 日志配置
*
* level: 日志级别, 可选为:
* debug/info/notice/warning/error/critical/alert/emergency
* path日志文件位置(绝对路径!!!),要求可写权限
*/
'log' => [
'default' => env('APP_DEBUG', false) ? 'dev' : 'prod', // 默认使用的 channel生产环境可以改为下面的 prod
'channels' => [
// 测试环境
'dev' => [
'driver' => 'single',
'path' => '/tmp/easywechat.log',
'level' => 'debug',
],
// 生产环境
'prod' => [
'driver' => 'daily',
'path' => '/tmp/easywechat.log',
'level' => 'info',
],
],
],
],
/*
* 路由配置
*/
'route' => [
/*
* 开放平台第三方平台路由配置
*/
// 'open_platform' => [
// 'uri' => 'serve',
// 'action' => Overtrue\LaravelWeChat\Controllers\OpenPlatformController::class,
// 'attributes' => [
// 'prefix' => 'open-platform',
// 'middleware' => null,
// ],
// ],
],
/*
* 公众号
*/
'official_account' => [
'default' => [
'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', 'your-app-id'), // AppID
'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', 'your-app-secret'), // AppSecret
'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', 'your-token'), // Token
'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', ''), // EncodingAESKey
/*
* OAuth 配置
*
* scopes公众平台snsapi_userinfo / snsapi_base开放平台snsapi_login
* callbackOAuth授权完成后的回调页地址(如果使用中间件,则随便填写。。。)
* enforce_https是否强制使用 HTTPS 跳转
*/
// 'oauth' => [
// 'scopes' => array_map('trim', explode(',', env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_SCOPES', 'snsapi_userinfo'))),
// 'callback' => env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_CALLBACK', '/examples/oauth_callback.php'),
// 'enforce_https' => true,
// ],
],
],
/*
* 开放平台第三方平台
*/
// 'open_platform' => [
// 'default' => [
// 'app_id' => env('WECHAT_OPEN_PLATFORM_APPID', ''),
// 'secret' => env('WECHAT_OPEN_PLATFORM_SECRET', ''),
// 'token' => env('WECHAT_OPEN_PLATFORM_TOKEN', ''),
// 'aes_key' => env('WECHAT_OPEN_PLATFORM_AES_KEY', ''),
// ],
// ],
/*
* 小程序
*/
'mini_program' => [
'default' => [
'app_id' => env('WECHAT_MINI_PROGRAM_APPID', ''),
'secret' => env('WECHAT_MINI_PROGRAM_SECRET', ''),
'token' => env('WECHAT_MINI_PROGRAM_TOKEN', ''),
'aes_key' => env('WECHAT_MINI_PROGRAM_AES_KEY', ''),
],
],
/*
* 微信支付
*/
// 'payment' => [
// 'default' => [
// 'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false),
// 'app_id' => env('WECHAT_PAYMENT_APPID', ''),
// 'mch_id' => env('WECHAT_PAYMENT_MCH_ID', 'your-mch-id'),
// 'key' => env('WECHAT_PAYMENT_KEY', 'key-for-signature'),
// 'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'), // XXX: 绝对路径!!!!
// 'key_path' => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'), // XXX: 绝对路径!!!!
// 'notify_url' => 'http://example.com/payments/wechat-notify', // 默认支付结果通知地址
// ],
// // ...
// ],
/*
* 企业微信
*/
// 'work' => [
// 'default' => [
// 'corp_id' => 'xxxxxxxxxxxxxxxxx',
// 'agent_id' => 100020,
// 'secret' => env('WECHAT_WORK_AGENT_CONTACTS_SECRET', ''),
// //...
// ],
// ],
];

View File

@@ -1,2 +1,11 @@
{ {
"Cms": true,
"Configuration": true,
"Mall": true,
"Payment": true,
"Storage": true,
"Task": true,
"User": true,
"Notification": true,
"Linker": true
} }

View File

@@ -8,7 +8,6 @@ use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\Gout\Traits\MorphManyTimeline;
use Modules\Mall\Models\Traits\BelongsToShop; use Modules\Mall\Models\Traits\BelongsToShop;
use Modules\Mall\Models\Traits\OrderActions; use Modules\Mall\Models\Traits\OrderActions;
use Modules\Mall\Models\Traits\OrderCando; use Modules\Mall\Models\Traits\OrderCando;
@@ -29,7 +28,6 @@ class Order extends Model
WithWorkflow, WithWorkflow,
OrderActions, OrderActions,
WithPayments, WithPayments,
MorphManyTimeline,
OrderScopes, OrderScopes,
SoftDeletes; SoftDeletes;

View File

@@ -14,7 +14,7 @@
"User" "User"
], ],
"config": true, "config": true,
"configName": "用户模块", "configName": "用户商城模块",
"version": "1.0.0", "version": "1.0.0",
"author": "Jason.Chen" "author": "Jason.Chen"
} }

View File

@@ -16,19 +16,19 @@ return [
'types' => [ 'types' => [
'App\\Notifications\\SystemOpenVip' => [ 'App\\Notifications\\SystemOpenVip' => [
'name' => '开通会员', 'name' => '开通会员',
'icon' => 'http://api.siyuankunlun.com/storage/materials/2022/08/09/newsIcon_04.jpg', 'icon' => 'http://api.siyuankunlun.cn/storage/materials/2022/08/09/newsIcon_04.jpg',
], ],
'App\\Notifications\\SystemOrderDelivered' => [ 'App\\Notifications\\SystemOrderDelivered' => [
'name' => '发货', 'name' => '发货',
'icon' => 'http://api.siyuankunlun.com/storage/materials/2022/08/09/newsIcon_02.png', 'icon' => 'http://api.siyuankunlun.cn/storage/materials/2022/08/09/newsIcon_02.png',
], ],
'App\\Notifications\\SystemRemindUserSign' => [ 'App\\Notifications\\SystemRemindUserSign' => [
'name' => '打卡', 'name' => '打卡',
'icon' => 'http://api.siyuankunlun.com/storage/materials/2022/08/09/newsIcon_01.png', 'icon' => 'http://api.siyuankunlun.cn/storage/materials/2022/08/09/newsIcon_01.png',
],
'App\\Notifications\\SystemUpdateCase' => [
'name' => '上传报告',
'icon' => 'http://api.siyuankunlun.com/storage/materials/2022/08/09/newsIcon_05.png',
], ],
// 'App\\Notifications\\SystemUpdateCase' => [
// 'name' => '上传报告',
// 'icon' => 'http://api.siyuankunlun.com/storage/materials/2022/08/09/newsIcon_05.png',
// ],
], ],
]; ];

View File

@@ -10,10 +10,6 @@ return [
'price' => '开通金额', 'price' => '开通金额',
], ],
'rules' => [ 'rules' => [
'buy_crystal' => '购物贡献比例', 'give_crystal' => '开通赠水滴',
'give_crystal' => '开通贡献值',
'store_sales' => '店铺销售',
'barter_in' => '易货(进)',
'barter_out' => '易货(出)',
], ],
]; ];

View File

@@ -30,7 +30,8 @@ class UserSign
$date = Carbon::parse($date);//签到日期 $date = Carbon::parse($date);//签到日期
$params = SignConfig::getParams(); $params = SignConfig::getParams();
if (! $params['open']) {
if (!isset($params['open'])) {
throw new Exception('签到功能未开启'); throw new Exception('签到功能未开启');
} }

View File

@@ -5,9 +5,10 @@ namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response; use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction; use Encore\Admin\Actions\RowAction;
use Exception; use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Modules\User\Models\Identity; use Modules\User\Models\Identity;
use Modules\User\Models\Order;
use Modules\User\Models\User;
class JoinIdentity extends RowAction class JoinIdentity extends RowAction
{ {
@@ -38,11 +39,6 @@ class JoinIdentity extends RowAction
$order = Order::create($data); $order = Order::create($data);
$order->pay(); $order->pay();
//
// $user->joinIdentity($identity_id, 'System', [
// 'remark' => $remark,
// ]);
return $this->response()->success('加入身份成功')->refresh(); return $this->response()->success('加入身份成功')->refresh();
} catch (Exception $e) { } catch (Exception $e) {
return $this->response()->error($e->getMessage())->refresh(); return $this->response()->error($e->getMessage())->refresh();
@@ -52,13 +48,9 @@ class JoinIdentity extends RowAction
public function form(User $user) public function form(User $user)
{ {
$userIdentity = $user->identityFirst(); $userIdentity = $user->identityFirst();
if (empty($userIdentity)) {
$identities = Identity::whereIn('order', [2, 3, 4, 5])->pluck('name', 'id'); $identities = Identity::where('order', '>', $userIdentity->order)->pluck('name', 'id');
} elseif ($userIdentity->job == Identity::JOB_YK) {
$identities = Identity::whereIn('order', [2, 3, 4, 5])->pluck('name', 'id');
} else {
$identities = Identity::where('order', '>', $userIdentity->order)->pluck('name', 'id');
}
$this->select('join_identity_id', '加入身份') $this->select('join_identity_id', '加入身份')
->options($identities) ->options($identities)
->required(); ->required();

View File

@@ -136,11 +136,7 @@ class IdentitiesController extends AdminController
->default(1); ->default(1);
$form->radioButton('job', '身份') $form->radioButton('job', '身份')
->options(Identity::JOBS) ->options(Identity::JOBS)
->default(0) ->default(0);
->when(Identity::JOB_TY, function (Form $form) {
$form->number('total', '可开通总数')->default(100);
$form->date('end_at', '结束日期');
});
$form->divider(); $form->divider();
$form->table('conditions', '升级条件', function (NestedForm $form) { $form->table('conditions', '升级条件', function (NestedForm $form) {

View File

@@ -11,7 +11,9 @@ use Illuminate\Support\Facades\DB;
use Modules\User\Http\Controllers\Admin\Actions\JoinIdentity; use Modules\User\Http\Controllers\Admin\Actions\JoinIdentity;
use Modules\User\Http\Controllers\Admin\Actions\RemoveIdentity; use Modules\User\Http\Controllers\Admin\Actions\RemoveIdentity;
use Modules\User\Http\Controllers\Admin\Actions\UpdateRelation; use Modules\User\Http\Controllers\Admin\Actions\UpdateRelation;
use Modules\User\Models\Identity;
use Modules\User\Models\User; use Modules\User\Models\User;
use Vinkla\Hashids\Facades\Hashids;
class IndexController extends AdminController class IndexController extends AdminController
{ {

View File

@@ -3,9 +3,12 @@
namespace Modules\User\Http\Controllers\Admin; namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController; use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid; use Encore\Admin\Grid;
use Exception; use Exception;
use Modules\User\Http\Controllers\Admin\Actions\Pay; use Modules\User\Http\Controllers\Admin\Actions\Pay;
use Modules\User\Http\Controllers\Admin\Actions\Refund;
use Modules\User\Models\Identity;
use Modules\User\Models\Order; use Modules\User\Models\Order;
class OrderController extends AdminController class OrderController extends AdminController

View File

@@ -5,7 +5,6 @@ namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController; use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid; use Encore\Admin\Grid;
use Modules\User\Models\UserStock; use Modules\User\Models\UserStock;
use Modules\User\Models\UserStockLog;
class StockController extends AdminController class StockController extends AdminController
{ {
@@ -43,7 +42,7 @@ class StockController extends AdminController
}); });
$grid->column('stock', '总数'); $grid->column('stock', '总数');
$grid->column('hold', '提货数') $grid->column('logs_count', '变动记录')
->link(function () { ->link(function () {
return admin_url('/users/stocks/'.$this->id.'/logs'); return admin_url('/users/stocks/'.$this->id.'/logs');
}, '_blank'); }, '_blank');

View File

@@ -5,12 +5,14 @@ namespace Modules\User\Http\Controllers\Api\Auth;
use App\Api\Controllers\Controller; use App\Api\Controllers\Controller;
use Exception; use Exception;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Arr;
use Jason\Api\Api; use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess; use Modules\User\Events\UserLoginSuccess;
use Modules\User\Facades\Sms; use Modules\User\Facades\Sms;
use Modules\User\Http\Requests\LoginSmsRequest; use Modules\User\Http\Requests\LoginSmsRequest;
use Modules\User\Http\Requests\SmsRequest; use Modules\User\Http\Requests\SmsRequest;
use Modules\User\Models\User; use Modules\User\Models\User;
use Vinkla\Hashids\Facades\Hashids;
class SmsController extends Controller class SmsController extends Controller
{ {
@@ -30,9 +32,14 @@ class SmsController extends Controller
try { try {
Sms::sendVerificationCode($mobile); Sms::sendVerificationCode($mobile);
$isExists = User::where('username', $mobile)->exists(); $isExists = User::where('username', $mobile)->exists();
if (Arr::get(Sms::getConfig(), 'debug')) {
$message = '短信发送成功,测试短信码'.Arr::get(Sms::getConfig(), 'debug_code');
} else {
$message = '短信发送成功';
}
return $this->success([ return $this->success([
'new' => ! $isExists, 'new' => ! $isExists,
'message' => '短信发送成功', 'message' => $message,
]); ]);
} catch (Exception $exception) { } catch (Exception $exception) {
return $this->failed($exception->getException('aliyun')->getMessage()); return $this->failed($exception->getException('aliyun')->getMessage());
@@ -49,18 +56,10 @@ class SmsController extends Controller
*/ */
public function login(LoginSmsRequest $request): JsonResponse public function login(LoginSmsRequest $request): JsonResponse
{ {
$mobileNo = $request->mobileNo; $mobileNo = $request->mobileNo;
$code = $request->code; $code = $request->code;
$invite_code = $request->invite ?? ''; $invite_code = $request->invite ?? '';
$channel_code = $request->channel ?? '';//渠道 $parent = 0;
$channel = '';
if ($channel_code) {
$channel = UserChannel::query()
->where('code', $channel_code)
->first();
}
$parent = 0;
if ($invite_code) { if ($invite_code) {
$invite = Hashids::connection('code')->decode($invite_code); $invite = Hashids::connection('code')->decode($invite_code);
@@ -84,9 +83,9 @@ class SmsController extends Controller
$user = User::firstOrCreate([ $user = User::firstOrCreate([
'username' => $mobileNo, 'username' => $mobileNo,
], [ ], [
'parent_id' => $parent, 'parent_id' => $parent,
'password' => 111111, 'password' => 111111,
]); ]);
$is_new = $user->wasRecentlyCreated; $is_new = $user->wasRecentlyCreated;
@@ -95,10 +94,8 @@ class SmsController extends Controller
if ($user->parent && $parent && $user->parent->id != $parent) { if ($user->parent && $parent && $user->parent->id != $parent) {
$message = "您已与用户{$user->parent->info->nickname}绑定隶属关系,此次邀请码无效"; $message = "您已与用户{$user->parent->info->nickname}绑定隶属关系,此次邀请码无效";
} }
} }
$token = Api::login($user); $token = Api::login($user);
event(new UserLoginSuccess($user, $request, '手机验证码')); event(new UserLoginSuccess($user, $request, '手机验证码'));

View File

@@ -6,11 +6,13 @@ use App\Api\Controllers\Controller;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api; use Jason\Api\Api;
use Modules\User\Http\Resources\IdentityMiddleResource; use Modules\User\Http\Resources\IdentityMiddleResource;
use Modules\User\Http\Resources\UserIdentityResource; use Modules\User\Http\Resources\UserIdentityResource;
use Modules\User\Models\Identity; use Modules\User\Models\Identity;
use Modules\User\Models\Order; use Modules\User\Models\Order;
use Validator;
class IndexController extends Controller class IndexController extends Controller
{ {
@@ -73,29 +75,12 @@ class IndexController extends Controller
} }
// $price = $identity->getCondition('price', '0');
// if ($identity->job == Identity::JOB_JK) {
// $coupon =
// }
$price = $identity->getCondition('price', '0'); $price = $identity->getCondition('price', '0');
$cost = $identity->getCondition('cost', '0'); $cost = $identity->getCondition('cost', '0');
if (! $cost) { if (! $cost) {
$cost = $price; $cost = $price;
} }
$coupon_price = 0;
if ($identity->job == Identity::JOB_JK) {
$coupons = $this->getCreateOrderCoupon($user, $identity, 0);
if ($coupons->isNotEmpty()) {
$user_coupon = $coupons->first();
$coupon_price = $user_coupon->price;
if ($user_coupon->coupon->type == Coupon::TYPE_REDUCTION) {
$price = $price > $user_coupon->price ? bcsub($price, $coupon_price, 2) : 0;
}
}
}
$data = [ $data = [
'identity' => [ 'identity' => [
@@ -103,7 +88,6 @@ class IndexController extends Controller
'name' => $identity->name, 'name' => $identity->name,
'cover' => $identity->cover_url, 'cover' => $identity->cover_url,
'description' => $ended_at ? '有效期至'.$ended_at : $identity->description, 'description' => $ended_at ? '有效期至'.$ended_at : $identity->description,
'coupon_price' => $coupon_price,
'cost' => $cost, 'cost' => $cost,
'price' => $price, 'price' => $price,
'can_buy' => (bool) $identity->can_buy, 'can_buy' => (bool) $identity->can_buy,
@@ -130,48 +114,22 @@ class IndexController extends Controller
{ {
$user = Api::user(); $user = Api::user();
$price = $request->price ?? 0; $price = $request->price ?? 0;
if ($identity->job != Identity::JOB_TY) { $validator = \Validator::make($request->all(), [
$validator = Validator::make($request->all(), [ 'name' => 'required',
'name' => 'required', // 'card_no' => 'required|numeric',
// 'card_no' => 'required|numeric', 'cover' => 'required',
'cover' => 'required', 'price' => 'required',
'price' => 'required', ], [
], [ 'name.required' => '缺少姓名',
'name.required' => '缺少姓名', 'card_no.required' => '缺少银行卡号',
'card_no.required' => '缺少银行卡号', 'card_no.numeric' => '银行卡号只能是数字',
'card_no.numeric' => '银行卡号只能是数字', 'cover.required' => '缺少打款凭证',
'cover.required' => '缺少打款凭证', 'price.required' => '缺少打款金额',
'price.required' => '缺少打款金额', ]);
]);
if ($validator->fails()) { if ($validator->fails()) {
return $this->failed($validator->errors()->first()); return $this->failed($validator->errors()->first());
}
// if ($identity->job == Identity::JOB_NK && ! $user->parent) {
// return $this->failed('没有推荐人不可开通年卡会员');
// }
} else {
$total = $identity->users()->count();
if ($total >= 100) {
return $this->failed('体验官最多可开通100人');
}
$end_at = $identity->end_at;
if ($end_at) {
$end_at = Carbon::parse($end_at)->endOfDay();
if (now()->gt($end_at)) {
return $this->failed('体验官活动已过期');
}
}
$tencentMap = app('xuanchen.tencent.map');
$res = $tencentMap->api()->ip(request()->ip())->toArray();
if (! in_array($res['ad_info']['city'], ['深圳', '深圳市'])) {
// return $this->failed('体验官活动只限于深圳用户参加');
}
} }
@@ -198,16 +156,15 @@ class IndexController extends Controller
} }
$hasOne = Order::query() $hasOne = Order::query()
->byUser($user) ->byUser($user)
->where('identity_id', $identity->id) ->where('identity_id', $identity->id)
->where('state', Order::STATE_INIT) ->where('state', Order::STATE_INIT)
->exists(); ->exists();
if ($hasOne) {
return $this->failed('您已经提交过了,请等待审核');
}
if ($hasOne) {
return $this->failed('您已经提交过了,请等待审核');
}
if (! $price) { if (! $price) {
@@ -231,21 +188,7 @@ class IndexController extends Controller
$order = Order::create($data); $order = Order::create($data);
if ($order) { if ($order) {
if ($coupon_price > 0) { return $this->success('提交成功,请等待后台审核');
$order->useCouponLog()->create([
'sourceable_type' => get_class($order),
'sourceable_id' => $order->id,
'coupon_grant_id' => $user_coupon->id,
]);
}
if ($identity->job == Identity::JOB_TY) {
return $this->success([
'order_id' => $order->id,
'openids' => $user->wechat->getOpenids()
]);
} else {
return $this->success('提交成功,请等待后台审核');
}
} else { } else {
return $this->failed('创建订单失败,请稍后再试'); return $this->failed('创建订单失败,请稍后再试');
} }

View File

@@ -115,12 +115,6 @@ class IndexController extends Controller
$address = Address::find($address_id); $address = Address::find($address_id);
$userIdentity = $user->identityFirst(); $userIdentity = $user->identityFirst();
if ($userIdentity->job == Identity::JOB_TY) {
$shenzhen = Region::query()->where('name', '深圳市')->first();
if ($address->city_id != $shenzhen->id) {
return $this->failed('体验官收货地址只能选择深圳');
}
}
$goods_sku = GoodsSku::query() $goods_sku = GoodsSku::query()
->whereHas('goods', function ($q) { ->whereHas('goods', function ($q) {

View File

@@ -4,15 +4,10 @@ namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Jason\Api\Api; use Jason\Api\Api;
use Modules\Coupon\Models\Coupon;
use Modules\Coupon\Traits\WithCoupon;
use Modules\User\Models\Identity;
use Modules\User\Models\Order; use Modules\User\Models\Order;
class UserIdentityResource extends JsonResource class UserIdentityResource extends JsonResource
{ {
use WithCoupon;
public function toArray($request): array public function toArray($request): array
{ {
$user = Api::user(); $user = Api::user();
@@ -44,36 +39,17 @@ class UserIdentityResource extends JsonResource
} }
} }
if ($this->job == Identity::JOB_JK) {
$openIdentity = Identity::find($this->id);
$coupons = $this->getCreateOrderCoupon($user, $openIdentity, 0);
if ($coupons->isNotEmpty()) {
$user_coupon = $coupons->first();
$coupon_price = $user_coupon->price;
if ($user_coupon->coupon->type == Coupon::TYPE_REDUCTION) {
$price = $price > $user_coupon->price ? bcsub($price, $coupon_price, 2) : 0;
}
}
}
if ($this->job == Identity::JOB_HH && $identity->job == Identity::JOB_HH) {
$star = $identity->getOriginal('pivot_star', 0);
if ($star > 0) {
$identityName = config('identity.stars.'.$star, '').$identityName;
}
}
} else { } else {
$open = true; $open = true;
} }
} }
return [ return [
'identity_id' => $this->id, 'identity_id' => $this->id,
'name' => $identityName, 'name' => $identityName,
'stock' => $this->stock, 'stock' => $this->stock,
'years' => $this->years, 'years' => $this->years,
'times' => $this->when($user && $this->id == $user->identityFirst()->id, function () use ($user) { 'times' => $this->when($user && $this->id == $user->identityFirst()->id, function () use ($user) {
return new IdentityMiddleResource($user->identityMiddle()->first()); return new IdentityMiddleResource($user->identityMiddle()->first());
}, [ }, [
'name' => '---', 'name' => '---',
@@ -81,22 +57,22 @@ class UserIdentityResource extends JsonResource
'started_at' => '---', 'started_at' => '---',
'ended_at' => '---', 'ended_at' => '---',
]), ]),
'cover' => $this->cover_url, 'cover' => $this->cover_url,
'order' => $this->order, 'order' => $this->order,
'description' => $this->description ?? "", 'description' => $this->description ?? "",
'coupon_price' => floatval($coupon_price),//开通金额 'coupon_price' => floatval($coupon_price),//开通金额
'cost' => floatval($cost),//开通金额 'cost' => floatval($cost),//开通金额
'price' => floatval($price),//开通金额 'price' => floatval($price),//开通金额
'can' => [ 'can' => [
'buy' => (bool) $this->can_buy, 'buy' => (bool) $this->can_buy,
'open' => $this->can_buy ? $open : false,//开通 'open' => $this->can_buy ? $open : false,//开通
'renew' => $this->can_buy ? $renew : false,//续费 'renew' => $this->can_buy ? $renew : false,//续费
], ],
'buttonText' => $text, 'buttonText' => $text,
'rights' => $this->rights, 'rights' => $this->rights,
'rules' => $this->getRules(), 'rules' => $this->getRules(),
'not_rules' => $this->getNotRules(), 'not_rules' => $this->getNotRules(),
'is_open' => $user && $this->id == $user->identityFirst()->id 'is_open' => $user && $this->id == $user->identityFirst()->id
]; ];
} }

View File

@@ -18,7 +18,6 @@ class UserInfoBaseResource extends JsonResource
'identity' => new UserIdentityBaseResource($this->identities->first()), 'identity' => new UserIdentityBaseResource($this->identities->first()),
'status' => $this->getStateData(), 'status' => $this->getStateData(),
'canPick' => $this->canPick(), 'canPick' => $this->canPick(),
'nowStatus' => $this->getNowStatus(),
'tag' => $this->tag 'tag' => $this->tag
]; ];
} }

View File

@@ -37,12 +37,9 @@ class UserInfoResource extends JsonResource
'created_at' => (string) $this->created_at, 'created_at' => (string) $this->created_at,
'sign' => $this->getSignData(), 'sign' => $this->getSignData(),
'status' => $this->getStateData(), 'status' => $this->getStateData(),
'nowStatus' => $this->getNowStatus(),
'canPick' => $this->canPick(), 'canPick' => $this->canPick(),
'count' => [ 'count' => [
'coupon' => $this->couponGrants()->count(),//<2F>Ż<EFBFBD>ȯ<EFBFBD><C8AF><EFBFBD><EFBFBD>
'relation' => $this->getRelationCount(),//<2F>¼<EFBFBD> 'relation' => $this->getRelationCount(),//<2F>¼<EFBFBD>
'invites' => $this->invites()->count(),//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
'notifications' => $this->unreadNotifications()->count(),//<2F><>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD> 'notifications' => $this->unreadNotifications()->count(),//<2F><>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>
'orders' => Order::byUser(Api::user())->common()->count(),//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'orders' => Order::byUser(Api::user())->common()->count(),//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
'refunds' => RefundModel::byUser(Api::user())->count(),//<2F>˿<CBBF><EEB5A5><EFBFBD><EFBFBD> 'refunds' => RefundModel::byUser(Api::user())->count(),//<2F>˿<CBBF><EEB5A5><EFBFBD><EFBFBD>

View File

@@ -3,7 +3,6 @@
namespace Modules\User\Listeners; namespace Modules\User\Listeners;
use App\Notifications\SystemOpenVip; use App\Notifications\SystemOpenVip;
use App\Notifications\SystemOrderDelivered;
use Exception; use Exception;
use Modules\User\Events\UserOrderPaid; use Modules\User\Events\UserOrderPaid;
use Modules\User\Models\IdentityLog; use Modules\User\Models\IdentityLog;

View File

@@ -8,11 +8,13 @@ use App\Traits\OrderByOrderAsc;
use GeneaLabs\LaravelModelCaching\Traits\Cachable; use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Arr;
use Modules\User\Models\Traits\HasIdentityScopes;
class Identity extends Model class Identity extends Model
{ {
// use Cachable; use Cachable;
use HasCovers, use HasCovers,
HasIdentityScopes, HasIdentityScopes,
OrderByOrderAsc, OrderByOrderAsc,
@@ -40,28 +42,17 @@ class Identity extends Model
self::CHANNEL_OFFLINE => '线下' self::CHANNEL_OFFLINE => '线下'
]; ];
const EXPERIENCE_YES = 1; const JOB_VISITOR = 0;
const EXPERIENCE_NO = 0; const JOB_FREE_VIP = 1;
const JOB_YK = 2;
const EXPERIENCES = [ const JOB_JK = 3;
self::EXPERIENCE_YES => '是', const JOB_NK = 4;
self::EXPERIENCE_NO => '否' const JOBS = [
]; self::JOB_VISITOR => '游客',
self::JOB_FREE_VIP => '免费会员',
const JOB_YK = 0; self::JOB_YK => '月卡',
const JOB_TY = 1; self::JOB_JK => '季卡',
const JOB_JK = 2; self::JOB_NK => '年卡',
const JOB_NK = 3;
const JOB_CS = 4;
const JOB_HH = 5;
const JOBS = [
self::JOB_YK => '游客',
self::JOB_TY => '体验官',
self::JOB_JK => '季卡',
self::JOB_NK => '年卡',
self::JOB_CS => '创始',
self::JOB_HH => '合伙人',
]; ];
protected $table = 'user_identities'; protected $table = 'user_identities';
@@ -148,21 +139,16 @@ class Identity extends Model
$rules = $this->rules; $rules = $this->rules;
if ($this->job == Identity::JOB_JK) { if ($this->job == Identity::JOB_JK) {
return [ return [
'give_crystal' => [ 'give_crystal' => [
'cover' => $this->getRuleIcon('give_crystal'), 'cover' => $this->getRuleIcon('give_crystal'),
'value' => $this->getRule('give_crystal'), 'value' => $this->getRule('give_crystal'),
'text' => '赠送水滴' 'text' => '赠送水滴'
], ],
'recommend_coupon' => [ 'stock' => [
'cover' => $this->getRuleIcon('recommend_coupon'),
'value' => $this->getRule('recommend_coupon'),
'text' => '赠送抵值券'
],
'stock' => [
'value' => $this->stock, 'value' => $this->stock,
'text' => "赠送{$this->stock}箱水" 'text' => "赠送{$this->stock}箱水"
], ],
'year' => [ 'year' => [
'value' => $this->years, 'value' => $this->years,
'text' => $this->years."个月有效期" 'text' => $this->years."个月有效期"
], ],

View File

@@ -9,7 +9,7 @@ use Modules\User\Traits\BelongsToUser;
class IdentityMiddle extends Pivot class IdentityMiddle extends Pivot
{ {
use BelongsToUser, MorphManyTimeline; use BelongsToUser;
protected $table = 'user_identity'; protected $table = 'user_identity';
protected $primaryKey = 'user_id'; protected $primaryKey = 'user_id';
@@ -21,11 +21,7 @@ class IdentityMiddle extends Pivot
{ {
parent::boot(); parent::boot();
self::created(function ($identity) {
if ($identity->identity->order > 1) {
$identity->addTimeline();
}
});
} }
public function identity(): BelongsTo public function identity(): BelongsTo

View File

@@ -5,6 +5,7 @@ namespace Modules\User\Models;
use App\Models\Model; use App\Models\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Modules\Payment\Traits\WithPayments; use Modules\Payment\Traits\WithPayments;
use Modules\User\Events\UserOrderPaid;
use Modules\User\Models\Traits\OrderActions; use Modules\User\Models\Traits\OrderActions;
use Modules\User\Traits\BelongsToUser; use Modules\User\Traits\BelongsToUser;

View File

@@ -30,14 +30,14 @@ class Sign extends Model
{ {
parent::boot(); parent::boot();
self::saved(function ($sign) { // self::saved(function ($sign) {
$params = SignConfig::getParams(); // $params = SignConfig::getParams();
//
if ($params['open'] == 1 && $sign->need_case == 0 && $sign->continue_days >= $params['cycle_day']) { // if ($params['open'] == 1 && $sign->need_case == 0 && $sign->continue_days >= $params['cycle_day']) {
$sign->update(['need_case' => 1, 'is_finish' => 1]); // $sign->update(['need_case' => 1, 'is_finish' => 1]);
} // }
//
}); // });
} }
/** /**

View File

@@ -9,16 +9,29 @@ trait HasIdentityScopes
{ {
/** /**
* Notes: 体验官 * Notes: 免费会员
* *
* @Author: 玄尘 * @Author: 玄尘
* @Date: 2022/8/18 15:25 * @Date: 2022/8/18 15:25
* @param Builder $query * @param Builder $query
* @return Builder * @return Builder
*/ */
public function scopeTy(Builder $query): Builder public function scopeFreeVip(Builder $query): Builder
{ {
return $query->where('job', Identity::JOB_TY); return $query->where('job', Identity::JOB_FREE_VIP);
}
/**
* Notes: 月卡
*
* @Author: 玄尘
* @Date: 2022/8/18 15:25
* @param Builder $query
* @return Builder
*/
public function scopeYk(Builder $query): Builder
{
return $query->where('job', Identity::JOB_YK);
} }
/** /**
@@ -47,31 +60,4 @@ trait HasIdentityScopes
return $query->where('job', Identity::JOB_NK); return $query->where('job', Identity::JOB_NK);
} }
/**
* Notes: 创始
*
* @Author: 玄尘
* @Date: 2022/8/18 15:27
* @param Builder $query
* @return Builder
*/
public function scopeCs(Builder $query): Builder
{
return $query->where('job', Identity::JOB_CS);
}
/**
* Notes: 合伙人
*
* @Author: 玄尘
* @Date: 2022/8/18 15:27
* @param Builder $query
* @return Builder
*/
public function scopeHh(Builder $query): Builder
{
return $query->where('job', Identity::JOB_HH);
}
} }

View File

@@ -46,9 +46,6 @@ trait HasStock
{ {
$identity = $this->identityFirst(); $identity = $this->identityFirst();
$min = 1; $min = 1;
if ($identity->job == Identity::JOB_TY) {
$min = $identity->stock;
}
$deliver = OrderItem::query() $deliver = OrderItem::query()
->whereHas('order', function ($q) { ->whereHas('order', function ($q) {

View File

@@ -12,17 +12,13 @@ use Illuminate\Foundation\Auth\User as Authenticate;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\HasApiTokens;
use Modules\Coupon\Traits\UserHasCoupon;
use Modules\Mall\Traits\HasAddresses; use Modules\Mall\Traits\HasAddresses;
use Modules\Mall\Traits\HasOrders; use Modules\Mall\Traits\HasOrders;
use Modules\Task\Traits\HasTasks; use Modules\Task\Traits\HasTasks;
use Modules\User\Models\Traits\HasChannel;
use Modules\User\Models\Traits\HasInvite;
use Modules\User\Models\Traits\HasLog; use Modules\User\Models\Traits\HasLog;
use Modules\User\Models\Traits\HasStock; use Modules\User\Models\Traits\HasStock;
use Modules\User\Models\Traits\HasVipOrders; use Modules\User\Models\Traits\HasVipOrders;
use Modules\User\Models\Traits\HasWechat; use Modules\User\Models\Traits\HasWechat;
use Modules\Withdraw\Traits\HasWithdraws;
use Modules\User\Models\Order as UserOrder; use Modules\User\Models\Order as UserOrder;
use Overtrue\LaravelFavorite\Traits\Favoriter; use Overtrue\LaravelFavorite\Traits\Favoriter;
use Overtrue\LaravelSubscribe\Traits\Subscriber; use Overtrue\LaravelSubscribe\Traits\Subscriber;
@@ -37,13 +33,9 @@ class User extends Authenticate
Macroable, Macroable,
HasStock, HasStock,
HasLog, HasLog,
HasGout,
HasWithdraws,
HasOrders, HasOrders,
HasVipOrders, HasVipOrders,
HasWechat, HasWechat,
HasInvite,
HasAddresses, HasAddresses,
Notifiable, Notifiable,
HasTasks, HasTasks,
@@ -57,7 +49,7 @@ class User extends Authenticate
const STATUS_INIT = 1; const STATUS_INIT = 1;
const STATUS_REFUND = 2; const STATUS_REFUND = 2;
const STATUS = [ const STATUS = [
self::STATUS_INIT => '正常', self::STATUS_INIT => '正常',
self::STATUS_REFUND => '退费', self::STATUS_REFUND => '退费',
]; ];

View File

@@ -5,6 +5,7 @@ namespace Modules\User\Providers;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Modules\User\Console\Commands\UserIdentityOver;
use Modules\User\Facades\Sms; use Modules\User\Facades\Sms;
use Modules\User\Models\User; use Modules\User\Models\User;
use Overtrue\EasySms\EasySms; use Overtrue\EasySms\EasySms;

View File

@@ -79,6 +79,7 @@ Route::group([
//获取支付数据 //获取支付数据
$router->get('pay/{order}/wechat', 'IndexController@wechat'); $router->get('pay/{order}/wechat', 'IndexController@wechat');
$router->get('pay/{order}/alipay', 'IndexController@alipay'); $router->get('pay/{order}/alipay', 'IndexController@alipay');
});
Route::group([ Route::group([
'namespace' => 'Identity', 'namespace' => 'Identity',
'prefix' => 'identities', 'prefix' => 'identities',
@@ -86,7 +87,6 @@ Route::group([
], function (Router $router) { ], function (Router $router) {
$router->get('{identity}', 'IndexController@show'); $router->get('{identity}', 'IndexController@show');
}); });
Route::group([ Route::group([
'namespace' => 'Sign', 'namespace' => 'Sign',
'prefix' => 'sign', 'prefix' => 'sign',
@@ -176,7 +176,6 @@ Route::group([
}); });
//我的收藏 //我的收藏
Route::group([ Route::group([
'namespace' => 'Favorite', 'namespace' => 'Favorite',