From 7010822acc6401f2462973562869da61fe9849f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=94=E5=A7=AC=E6=A1=91?= <867057410@qq.com> Date: Tue, 20 Sep 2022 20:36:11 +0800 Subject: [PATCH] =?UTF-8?q?Major=20update:=20=E5=BC=BA=E5=8C=96=E5=8D=A1?= =?UTF-8?q?=E5=88=B8=E7=8E=A9=E6=B3=95=20&=20=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 详情 https://proxypanel.gitbook.io/wiki/coupon --- .../Controllers/Admin/CouponController.php | 48 +++- app/Http/Controllers/PaymentController.php | 52 +--- app/Http/Controllers/UserController.php | 69 ++---- app/Http/Requests/Admin/CouponRequest.php | 17 +- app/Models/Coupon.php | 16 +- app/Services/CouponService.php | 142 +++++++++++ app/helpers.php | 17 ++ .../2022_08_25_204229_improve_coupon.php | 59 +++++ resources/lang/en/user.php | 7 +- resources/lang/zh_CN/user.php | 11 +- resources/views/admin/coupon/create.blade.php | 189 +++++++++++--- resources/views/admin/coupon/index.blade.php | 135 +++++----- resources/views/admin/coupon/show.blade.php | 234 ++++++++++++++++++ resources/views/user/buy.blade.php | 4 +- routes/admin.php | 2 +- routes/user.php | 2 +- 16 files changed, 784 insertions(+), 220 deletions(-) create mode 100644 app/Services/CouponService.php create mode 100644 database/migrations/2022_08_25_204229_improve_coupon.php create mode 100644 resources/views/admin/coupon/show.blade.php diff --git a/app/Http/Controllers/Admin/CouponController.php b/app/Http/Controllers/Admin/CouponController.php index 7a95d718..8865af0e 100644 --- a/app/Http/Controllers/Admin/CouponController.php +++ b/app/Http/Controllers/Admin/CouponController.php @@ -5,6 +5,8 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Http\Requests\Admin\CouponRequest; use App\Models\Coupon; +use App\Models\Level; +use App\Models\UserGroup; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -35,6 +37,16 @@ class CouponController extends Controller return view('admin.coupon.index', ['couponList' => $query->latest()->paginate(15)->appends($request->except('page'))]); } + // 优惠券列表 + public function show(Coupon $coupon) + { + return view('admin.coupon.show', [ + 'coupon' => $coupon, + 'userGroups' => UserGroup::all()->pluck('name', 'id')->toArray(), + 'levels' => Level::all()->pluck('name', 'level')->toArray(), + ]); + } + // 添加优惠券 public function store(CouponRequest $request) { @@ -49,7 +61,28 @@ class CouponController extends Controller $logo = 'upload/'.$fileName; } $num = (int) $request->input('num'); - $data = $request->only(['name', 'type', 'usable_times', 'value', 'rule', 'start_time', 'end_time']); + $data = $request->only(['name', 'type', 'priority', 'usable_times', 'value', 'start_time', 'end_time']); + $data['limit'] = [ + 'minimum' => $request->input('minimum'), + 'used' => $request->input('used'), + 'users' => [ + 'white' => $request->has('users_whitelist') ? array_map('intval', explode(', ', $request->input('users_whitelist'))) : null, + 'black' => $request->has('users_blacklist') ? array_map('intval', explode(', ', $request->input('users_blacklist'))) : null, + 'newbie' => [ + 'coupon' => $request->input('coupon'), + 'order' => $request->input('order'), + 'days' => $request->has('days') ? (int) $request->input(['days']) : null, + ], + 'levels' => $request->has('levels') ? array_map('intval', $request->input('levels')) : null, + 'groups' => $request->has('groups') ? array_map('intval', $request->input('groups')) : null, + ], + 'services' => [ + 'white' => $request->has('services_whitelist') ? array_map('intval', explode(', ', $request->input('services_whitelist'))) : null, + 'black' => $request->has('services_blacklist') ? array_map('intval', explode(', ', $request->input('services_blacklist'))) : null, + ], + ]; + array_clean($data['limit']); + $data['logo'] = $logo; $data['status'] = 0; try { @@ -69,7 +102,10 @@ class CouponController extends Controller // 添加优惠券页面 public function create() { - return view('admin.coupon.create'); + return view('admin.coupon.create', [ + 'userGroups' => UserGroup::all()->pluck('name', 'id')->toArray(), + 'levels' => Level::all()->pluck('name', 'level')->toArray(), + ]); } // 删除优惠券 @@ -108,10 +144,10 @@ class CouponController extends Controller $spreadsheet->setActiveSheetIndex(0); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('抵用券'); - $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '金额(元)', '使用限制(元)']); + $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '金额(元)', '权重', '使用限制']); foreach ($voucherList as $k => $vo) { $dateRange = $vo->start_time.' ~ '.$vo->end_time; - $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->rule], null, 'A'.($k + 2)); + $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->priority, json_encode($vo->limit)], null, 'A'.($k + 2)); } // 折扣券 @@ -119,10 +155,10 @@ class CouponController extends Controller $spreadsheet->setActiveSheetIndex(1); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('折扣券'); - $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '折扣(折)', '使用限制(元)']); + $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '折扣(折)', '权重', '使用限制']); foreach ($discountCouponList as $k => $vo) { $dateRange = $vo->start_time.' ~ '.$vo->end_time; - $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->rule], null, 'A'.($k + 2)); + $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->priority, json_encode($vo->limit)], null, 'A'.($k + 2)); } // 充值券 diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 89dac8c0..f5622923 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -18,6 +18,7 @@ use App\Models\Coupon; use App\Models\Goods; use App\Models\Order; use App\Models\Payment; +use App\Services\CouponService; use Auth; use Exception; use Illuminate\Http\JsonResponse; @@ -127,13 +128,12 @@ class PaymentController extends Controller // 使用优惠券 if ($coupon_sn) { - $ret = $this->couponCheck($coupon_sn, $goods->price); + $ret = (new CouponService($coupon_sn))->search($goods); // 检查券合规性 - if ($ret !== true) { + if (! $ret instanceof Coupon) { return $ret; } - - $coupon = Coupon::whereStatus(0)->whereIn('type', [1, 2])->whereSn($coupon_sn)->firstOrFail(); + $coupon = $ret; // 计算实际应支付总价 $amount = $coupon->type === 2 ? $goods->price * $coupon->value / 100 : $goods->price - $coupon->value; @@ -198,50 +198,6 @@ class PaymentController extends Controller return Response::json(['status' => 'fail', 'message' => '订单创建失败']); } - public function couponCheck($coupon_sn, $price) // 检查券合规性 - { - if (empty($coupon_sn)) { - return Response::json([ - 'status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('validation.required', ['attribute' => trans('user.coupon.attribute')]), - ]); - } - - $coupon = Coupon::whereSn($coupon_sn)->whereIn('type', [1, 2])->first(); - if (! $coupon) { - return Response::json(['status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('user.coupon.error.unknown')]); - } - - if ($coupon->status === 1) { - return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.used')]); - } - if ($coupon->getRawOriginal('end_time') < time()) { - $coupon->status = 2; - $coupon->save(); - - return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.expired')]); - } - - if ($coupon->status === 2) { - if ($coupon->usable_times === 0) { - return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.run_out')]); - } - - return Response::json(['status' => 'fail', 'title' => trans('common.sorry'), 'message' => trans('user.coupon.error.expired')]); - } - - if ($coupon->start_time > date('Y-m-d H:i:s')) { - return Response::json(['status' => 'fail', 'title' => trans('user.coupon.error.inactive'), - 'message' => trans('user.coupon.error.wait', ['time' => $coupon->start_time]), - ]); - } - - if ($price < $coupon->rule) { - return Response::json(['status' => 'fail', 'title' => trans('user.coupon.error.limit'), 'message' => trans('user.coupon.error.higher', ['amount' => $coupon->rule])]); - } - - return true; - } - public function close(Order $order): JsonResponse { if (! $order->close()) { diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index a16f7c69..0f15d889 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -14,6 +14,7 @@ use App\Models\Ticket; use App\Models\User; use App\Notifications\TicketCreated; use App\Notifications\TicketReplied; +use App\Services\CouponService; use Cache; use DB; use Exception; @@ -205,14 +206,11 @@ class UserController extends Controller if ($user && $nodes = $user->userGroup) { $nodes = $nodes->nodes(); - foreach ($goodsList as $goods) { - $goods->node_count = $nodes->where('level', '<=', $goods->level)->count(); - } } else { $nodes = Node::all(); - foreach ($goodsList as $goods) { - $goods->node_count = $nodes->where('level', '<=', $goods->level)->count(); - } + } + foreach ($goodsList as $goods) { + $goods->node_count = $nodes->where('level', '<=', $goods->level)->count(); } return view('user.services', [ @@ -385,14 +383,12 @@ class UserController extends Controller if ($user->invite_num <= 0) { return Response::json(['status' => 'fail', 'message' => trans('user.invite.generate_failed')]); } - - $obj = new Invite(); - $obj->inviter_id = $user->id; - $obj->code = strtoupper(mb_substr(md5(microtime().Str::random()), 8, 12)); - $obj->dateline = date('Y-m-d H:i:s', strtotime(sysConfig('user_invite_days').' days')); - $obj->save(); - if ($obj) { - $user->update(['invite_num' => $user->invite_num - 1]); + $invite = $user->invites()->create([ + 'code' => strtoupper(mb_substr(md5(microtime().Str::random()), 8, 12)), + 'dateline' => date('Y-m-d H:i:s', strtotime(sysConfig('user_invite_days').' days')), + ]); + if ($invite) { + $user->decrement('invite_num'); return Response::json(['status' => 'success', 'message' => trans('common.generate_item', ['attribute' => trans('common.success')])]); } @@ -401,21 +397,24 @@ class UserController extends Controller } // 使用优惠券 - public function redeemCoupon(Request $request): JsonResponse + public function redeemCoupon(Request $request, Goods $good): JsonResponse { $coupon_sn = $request->input('coupon_sn'); - $ret = (new PaymentController())->couponCheck($coupon_sn, $request->input('price')); + if (empty($coupon_sn)) { + return Response::json(['status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('user.coupon.error.unknown')]); + } - if ($ret !== true) { + $ret = (new CouponService($coupon_sn))->search($good); // 检查券合规性 + + if (! $ret instanceof Coupon) { return $ret; } - $coupon = Coupon::whereSn($coupon_sn)->whereIn('type', [1, 2])->firstOrFail(); $data = [ - 'name' => $coupon->name, - 'type' => $coupon->type, - 'value' => $coupon->value, + 'name' => $ret->name, + 'type' => $ret->type, + 'value' => $ret->value, ]; return Response::json(['status' => 'success', 'data' => $data, 'message' => trans('common.applied', ['attribute' => trans('user.coupon.attribute')])]); @@ -534,32 +533,10 @@ class UserController extends Controller return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]); } - $coupon = Coupon::whereSn($request->input('coupon_sn'))->firstOrFail(); - - try { - DB::beginTransaction(); - // 写入日志 - $user = auth()->user(); - Helpers::addUserCreditLog($user->id, null, $user->credit, $user->credit + $coupon->value, $coupon->value, - trans('user.recharge').' - ['.trans('user.coupon.recharge').':'.$request->input('coupon_sn').']'); - - // 余额充值 - $user->updateCredit($coupon->value); - - // 更改卡券状态 - $coupon->update(['status' => 1]); - - // 写入卡券日志 - Helpers::addCouponLog(trans('user.recharge_credit'), $coupon->id); - - DB::commit(); - + if ((new CouponService($request->input('coupon_sn')))->charge()) { return Response::json(['status' => 'success', 'message' => trans('user.recharge').trans('common.success')]); - } catch (Exception $e) { - Log::error(trans('user.recharge').trans('common.failed').$e->getMessage()); - DB::rollBack(); - - return Response::json(['status' => 'fail', 'message' => trans('user.recharge').trans('common.failed')]); } + + return Response::json(['status' => 'fail', 'message' => trans('user.recharge').trans('common.failed')]); } } diff --git a/app/Http/Requests/Admin/CouponRequest.php b/app/Http/Requests/Admin/CouponRequest.php index 91610574..bd1278fb 100644 --- a/app/Http/Requests/Admin/CouponRequest.php +++ b/app/Http/Requests/Admin/CouponRequest.php @@ -10,12 +10,23 @@ class CouponRequest extends FormRequest { return [ 'name' => 'required|string', - 'sn' => 'unique:coupon', + 'sn' => 'exclude_unless:type,3|unique:coupon', 'logo' => 'nullable|image', 'type' => 'required|numeric|between:1,3', - 'usable_times' => 'nullable|numeric', + 'priority' => 'nullable|numeric|min:0|max:255', + 'usable_times' => 'nullable|numeric|min:1', 'value' => 'required|numeric|min:0', - 'rule' => 'nullable|numeric', + 'minimum' => 'nullable|numeric', + 'used' => 'nullable|numeric', + 'levels' => 'nullable|array', + 'groups' => 'nullable|array', + 'users_whitelist' => 'nullable|string', + 'users_blacklist' => 'nullable|string', + 'services_blacklist' => 'nullable|string', + 'services_whitelist' => 'nullable|string', + 'coupon' => 'nullable', + 'order' => 'nullable', + 'days' => 'nullable|numeric', 'num' => 'required|numeric|min:1', 'start_time' => 'required|date|before_or_equal:end_time', 'end_time' => 'required|date|after_or_equal:start_time', diff --git a/app/Models/Coupon.php b/app/Models/Coupon.php index 6737d29e..fe6fcd14 100644 --- a/app/Models/Coupon.php +++ b/app/Models/Coupon.php @@ -13,7 +13,7 @@ class Coupon extends Model use SoftDeletes; protected $table = 'coupon'; - protected $casts = ['start_time' => 'date:Y-m-d', 'end_time' => 'date:Y-m-d']; + protected $casts = ['limit' => 'array', 'start_time' => 'date:Y-m-d', 'end_time' => 'date:Y-m-d']; protected $dates = ['deleted_at']; protected $guarded = []; @@ -32,4 +32,18 @@ class Coupon extends Model { return $this->attributes['end_time'] = strtotime($value); } + + public function used() + { + $this->attributes['status'] = 1; + + return $this->save(); + } + + public function expired() + { + $this->attributes['status'] = 2; + + return $this->save(); + } } diff --git a/app/Services/CouponService.php b/app/Services/CouponService.php new file mode 100644 index 00000000..2fca8904 --- /dev/null +++ b/app/Services/CouponService.php @@ -0,0 +1,142 @@ +code = $code; + $this->user = Auth::getUser(); + } + + public function search(Goods $goods) // 寻找合适的券 + { + $coupons = Coupon::whereSn($this->code)->whereIn('type', [1, 2])->orderByDesc('priority')->get(); + if ($coupons->isNotEmpty()) { + foreach ($coupons as $coupon) { + $ret = $this->check($goods, $coupon); + if ($ret === true) { // passed + return $coupon; + } + } + + return $ret ?? $this->failedReturn(trans('common.failed'), trans('user.coupon.error.unknown')); + } + + return $this->failedReturn(trans('common.failed'), trans('user.coupon.error.unknown')); + } + + private function check(Goods $goods, Coupon $coupon) // 检查券合规性 + { + if ($coupon->status === 1) { + return $this->failedReturn(trans('common.sorry'), trans('user.coupon.error.used')); + } + + if (time() > $coupon->getRawOriginal('end_time')) { + $coupon->expired(); + + return $this->failedReturn(trans('common.sorry'), trans('user.coupon.error.expired')); + } + + if ($coupon->usable_times === 0) { + return $this->failedReturn(trans('common.sorry'), trans('user.coupon.error.run_out')); + } + + if ($coupon->status === 2) { + return $this->failedReturn(trans('common.sorry'), trans('user.coupon.error.expired')); + } + + if (time() < $coupon->getRawOriginal('start_time')) { + return $this->failedReturn(trans('user.coupon.error.inactive'), trans('user.coupon.error.wait', ['time' => $coupon->start_time])); + } + + if (isset($coupon->limit['minimum']) && $goods->price < $coupon->limit['minimum']) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.minimum', ['amount' => $coupon->limit['minimum']])); + } + + if (isset($coupon->limit['users']['black']) && in_array($this->user->id, $coupon->limit['users']['black'], true)) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + + if (isset($coupon->limit['services']['black']) && in_array($goods->id, $coupon->limit['services']['black'], true)) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.services')); + } + + if (isset($coupon->limit['users']['white']) && ! in_array($this->user->id, $coupon->limit['users']['white'], true)) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + + if (isset($coupon->limit['services']['white']) && ! in_array($goods->id, $coupon->limit['services']['white'], true)) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.services')); + } + + if (isset($coupon->limit['users']['levels']) && ! in_array($this->user->level, $coupon->limit['users']['levels'], true)) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + + if (isset($coupon->limit['users']['groups']) && ! in_array($this->user->user_group_id, $coupon->limit['users']['groups'], true)) { + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + + if (isset($coupon->limit['users']['newbie'])) { // 新用户可用 + if (isset($coupon->limit['users']['newbie']['coupon']) && $this->user->orders()->whereNotNull('coupon_id')->exists()) { // 第一次使用优惠券 + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + + if (isset($coupon->limit['users']['newbie']['order']) && $this->user->orders()->exists()) { // 第一个套餐订单 + + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + + if (isset($coupon->limit['users']['newbie']['days']) && (time() > strtotime($this->user->created_at.' +'.$coupon->limit['users']['newbie']['days'].' days') || + $this->user->orders()->whereCouponId($coupon->id)->exists())) { // 创号N天内, 且第一次用优惠券 + + return $this->failedReturn(trans('user.coupon.error.unmet'), trans('user.coupon.error.users')); + } + } + + if (isset($coupon->limit['used']) && $this->user->orders()->whereCouponId($coupon->id)->count() >= $coupon->limit['used']) { + return $this->failedReturn(trans('user.coupon.error.unmet'), + trans_choice('user.coupon.error.overused', $coupon->limit['used'], ['times' => $coupon->limit['used']])); + } + + return true; + } + + private function failedReturn(string $title, string $message) + { + return Response::json(['status' => 'fail', 'title' => $title, 'message' => $message]); + } + + public function charge(): bool + { + $coupon = Coupon::whereSn($this->code)->whereType(3)->first(); + if ($coupon && $coupon->status === 0) { + try { + Helpers::addUserCreditLog($this->user->id, null, $this->user->credit, $this->user->credit + $coupon->value, $coupon->value, + trans('user.recharge').' - ['.trans('user.coupon.recharge').':'.$coupon->sn.']'); // 写入用户余额变动日志 + $this->user->updateCredit($coupon->value); // 余额充值 + $coupon->used(); // 更改卡券状态 + Helpers::addCouponLog(trans('user.recharge_credit'), $coupon->id); // 写入卡券使用日志 + + return true; + } catch (Exception $exception) { + Log::emergency('[重置券处理出现错误] '.$exception->getMessage()); + } + } + + return false; + } +} diff --git a/app/helpers.php b/app/helpers.php index 1adabb85..7f6b0a40 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -109,3 +109,20 @@ if (! function_exists('string_decrypt')) { return openssl_decrypt(base64url_decode($data), 'aes-128-ctr', hash('sha256', config('app.key')), OPENSSL_RAW_DATA, substr(sha1(config('app.key')), 0, 16)); } } + +// Array values and indexes clean +if (! function_exists('array_clean')) { + function array_clean(array &$array): array + { + foreach ($array as $key => &$value) { + if (is_array($value)) { + $value = array_clean($value); + } + if (empty($value)) { + unset($array[$key]); + } + } + + return $array; + } +} diff --git a/database/migrations/2022_08_25_204229_improve_coupon.php b/database/migrations/2022_08_25_204229_improve_coupon.php new file mode 100644 index 00000000..41d78887 --- /dev/null +++ b/database/migrations/2022_08_25_204229_improve_coupon.php @@ -0,0 +1,59 @@ +versionCheck()) { + $table->json('limit')->nullable()->comment('使用限制')->after('rule'); + } else { + $table->text('limit')->nullable()->comment('使用限制')->after('rule'); + } + $table->unsignedTinyInteger('priority')->default(0)->comment('使用权重, 高者优先')->after('limit'); + $table->dropUnique(['sn']); + }); + + foreach (Coupon::whereNotNull('rule')->get() as $coupon) { + $coupon->update(['limit' => ['minimum' => $coupon->rule]]); + } + + Schema::table('coupon', function (Blueprint $table) { + $table->dropColumn('rule'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('coupon', function (Blueprint $table) { + $table->unsignedInteger('rule')->nullable()->comment('使用限制(元)')->after('limit'); + }); + + foreach (Coupon::whereNotNull('limit')->get() as $coupon) { + if (isset($coupon->limit['minimum'])) { + $coupon->update(['rule' => $coupon->limit['minimum']]); + } + } + + Schema::table('coupon', function (Blueprint $table) { + $table->dropColumn('limit', 'priority'); + $table->unique('sn'); + }); + } +} diff --git a/resources/lang/en/user.php b/resources/lang/en/user.php index 5f8b201c..8cdea640 100644 --- a/resources/lang/en/user.php +++ b/resources/lang/en/user.php @@ -96,8 +96,11 @@ return [ 'run_out' => 'Run Out of Usage', 'inactive' => 'Coupon Inactive yet', 'wait' => 'The Event will begin until :time, Please wait', - 'limit' => 'Order\'s price is reach the minimum requirement of this coupon', - 'higher' => 'The minimum requirement of this coupon is ¥:amount', + 'unmet' => 'Conditions of use are not met', + 'minimum' => 'The minimum requirement of this coupon is ¥:amount', + 'overused' => 'You can only use this coupon once|You can only use this coupon :times times', + 'users' => 'This account is not eligible for promotions', + 'services' => 'This item is not qualify for this discount, please check the promotion terms', ], ], 'error_response' => 'Something went wrong, please try again later.', diff --git a/resources/lang/zh_CN/user.php b/resources/lang/zh_CN/user.php index 01a109c4..e4d6180e 100644 --- a/resources/lang/zh_CN/user.php +++ b/resources/lang/zh_CN/user.php @@ -96,8 +96,11 @@ return [ 'run_out' => '优惠券耗尽', 'inactive' => '优惠券尚未生效', 'wait' => '活动将于:time生效,请耐心等待!', - 'limit' => '使用条件未满足', - 'higher' => '本券最低使用金额为 ¥:amount', + 'unmet' => '使用条件未满足', + 'minimum' => '本券最低使用金额为 ¥:amount', + 'overused' => '本券只能使用 :times 次', + 'users' => '帐户不符合促销条件', + 'services' => '商品不符合折扣条件,请查看促销条款', ], ], 'error_response' => '出现了错误,请稍后再试。', @@ -119,7 +122,7 @@ return [ ], 'referral' => [ 'link' => '推广链接', - 'total' => '合计返利 :amount 元( :total 次),满 :money 元可以申请提现。', + 'total' => '合计返利 ¥ :amount( :total 次),满 ¥ :money 可以申请提现。', 'amount' => '消费金额', 'commission' => '返利金额', 'logs' => '佣金记录', @@ -128,7 +131,7 @@ return [ 'msg' => [ 'account' => '账号已过期,请先购买服务吧', 'applied' => '已存在申请,请等待之前的申请处理完', - 'unfulfilled' => '满:amount元才可以提现,继续努力吧', + 'unfulfilled' => '满¥ :amount才可以提现,继续努力吧', 'wait' => '请等待管理员审核', 'error' => '返利单建立失败,请稍后尝试或通知管理员', ], diff --git a/resources/views/admin/coupon/create.blade.php b/resources/views/admin/coupon/create.blade.php index 7931754c..ee90b2b3 100644 --- a/resources/views/admin/coupon/create.blade.php +++ b/resources/views/admin/coupon/create.blade.php @@ -1,7 +1,9 @@ @extends('admin.layouts') @section('css') + + @endsection @section('content')
@@ -58,33 +60,143 @@ 抵用:抵扣商品金额,折扣:商品百分比打折,充值:充值用户账号余额
-
- -
- - -
-
- +
- +
-
- -
-
- - +
+
+ +
+
+ +
+ 同【使用券码】下,符合条件的高权重码将会被优先使用。最高为 255
- 当支付金额超过N值时,才能使用本优惠劵;不设置/0,即为无限制
+
+ +
+ + +
+
+
+
+ +
+
+ + +
+ 当支付金额超过N值时,才能使用本优惠劵;不设置/0,即为无限制 +
+
+
+ +
+
+ + +
+ 符合条件的用户可以使用本券N次;不设置/0,即为无限制 +
+
+
+ +
+ + 用户等级在选定等级内,方可使用本券 +
+
+
+ +
+ + 选定的用户分组,方可使用本券 +
+
+
+ +
+ + 涉及用户均可使用本券,留空为不使用此条件 +
+
+
+ +
+ + 涉及用户均不可使用本券,空为不使用此条件 +
+
+
+ +
+ + 涉及商品方可使用本券,留空为不使用此条件 +
+
+
+ +
+ + 涉及商品不可使用本券,留空为不使用此条件 +
+
+
+ +
+
    +
  • +
    + + +
    +
  • +
  • +
    + + +
    +
  • +
  • +
    +
    + +
    + +
    + +
    +
    +
  • +
+ 本项各条件为 并且 关系,请自行搭配使用 +
+
+
@@ -119,38 +231,41 @@
@endsection @section('javascript') - - + + + + + + @endsection diff --git a/resources/views/admin/coupon/index.blade.php b/resources/views/admin/coupon/index.blade.php index fc9f3ba7..6cc188b4 100644 --- a/resources/views/admin/coupon/index.blade.php +++ b/resources/views/admin/coupon/index.blade.php @@ -52,6 +52,7 @@ 券码 图片 类型 + 权重 使用次数 优惠 有效期 @@ -67,36 +68,32 @@ {{$coupon->sn}} @if($coupon->logo) 优惠码logo @endif - @if($coupon->type === 1) - 抵用券 - @elseif($coupon->type === 2) - 折扣券 - @else - 充值券 - @endif + {{ ['未知卡券','抵用券','折扣券','充值券'][$coupon->type] }} + {{$coupon->priority}} {{$coupon->type === 3 ? '一次性' : ($coupon->usable_times ?? '无限制')}} - {{$coupon->value}}@if($coupon->type === 2)%@else元@endif + {{($coupon->type === 2 ?'减 ':'抵 ').$coupon->value.($coupon->type === 2 ?' %':' 元')}} {{$coupon->start_time}} ~ {{$coupon->end_time}} - @if($coupon->status === 1) - 已使用 - @elseif ($coupon->status === 2) - 已失效 - @else - 生效中 - @endif + {{['生效中','已使用','已失效'][$coupon->status]}} - @if($coupon->status !== 1) - @can('admin.coupon.destroy') - +
+ @can('admin.coupon.show') + + + @endcan - @endif + @if($coupon->status !== 1) + @can('admin.coupon.destroy') + + @endcan + @endif +
@endforeach @@ -122,59 +119,59 @@ @endsection diff --git a/resources/views/admin/coupon/show.blade.php b/resources/views/admin/coupon/show.blade.php new file mode 100644 index 00000000..8d5dbcae --- /dev/null +++ b/resources/views/admin/coupon/show.blade.php @@ -0,0 +1,234 @@ +@extends('admin.layouts') +@section('css') + + + +@endsection +@section('content') +
+
+
+

卡券信息

+
+ 返 回 +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+ @if($coupon->logo) +
+ 卡券图片 +
+ 优惠码logo +
+
+ @endif +
+ 类型 +
+
+ + +
+
+
+
+ +
+

+ @switch ($coupon->type) + @case(1) + 抵用 {{$coupon->value}} 元 + @break + @case(2) + 减 {{$coupon->value}} % + @break + @case(3) + 充值 {{$coupon->value}} 元 + @break + @default + 未知卡券 + @endswitch +

+
+
+ @isset($coupon->priority) +
+ 权 重 +
+ {{$coupon->priority}} +
+
+ @endisset + @isset($coupon->usable_times) +
+ 剩余使用次数 +
+ {{$coupon->usable_times}} +
+
+ @endisset + @if(!empty($coupon->limit)) +
+ @isset($coupon->limit['minimum']) +
+ +
+

当支付金额超过 {{$coupon->limit['minimum']}}元 时,才能使用本优惠劵

+
+
+ @endisset + @isset($coupon->limit['used']) +
+ 个人限用 +
+

符合条件的用户可以使用本券 {{$coupon->limit['used']}}次

+
+
+ @endisset + @isset($coupon->limit['users']['levels']) +
+ +
+ + 以上用户等级,方可使用本券 +
+
+ @endisset + @isset($coupon->limit['users']['groups']) +
+ +
+ + 以上用户分组,方可使用本券 +
+
+ @endisset + @isset($coupon->limit['users']['white']) +
+ +
+ + 以上用户均可使用本券 +
+
+ @endisset + @isset($coupon->limit['users']['black']) +
+ +
+ + 以上用户均不可使用本券 +
+
+ @endisset + @isset($coupon->limit['services']['white']) +
+ +
+ + 以上商品方可使用本券 +
+
+ @endisset + @isset($coupon->limit['services']['black']) +
+ +
+ + 以上商品不可使用本券 +
+
+ @endisset + @isset($coupon->limit['users']['newbie']) +
+ +
+
    +
  • +
    + limit['users']['newbie']['coupon']) ? 'checked' : '' }} disabled/> + +
    +
  • +
  • +
    + limit['users']['newbie']['order']) ? 'checked' : '' }} disabled/> + +
    +
  • + @isset($coupon->limit['users']['newbie']['days']) +
  • + 且 创号 {{$coupon->limit['users']['newbie']['days']}} +
  • + @endisset +
+
+
+ @endisset +
+ @endif +
+ +
+
+ +
+ {{$coupon->start_time}} +
+ +
+ {{$coupon->end_time}} +
+
+
+
+
+@endsection +@section('javascript') + + + + + +@endsection diff --git a/resources/views/user/buy.blade.php b/resources/views/user/buy.blade.php index 855d01aa..7ba09013 100644 --- a/resources/views/user/buy.blade.php +++ b/resources/views/user/buy.blade.php @@ -77,9 +77,9 @@ const goods_price = '{{$goods->price}}'; $.ajax({ method: 'POST', - url: '{{route('redeemCoupon')}}', + url: '{{route('redeemCoupon', $goods)}}', dataType: 'json', - data: {_token: '{{csrf_token()}}', coupon_sn: coupon_sn, price: '{{$goods->price}}'}, + data: {_token: '{{csrf_token()}}', coupon_sn: coupon_sn}, success: function(ret) { $('.input-group-prepend').remove(); if (ret.status === 'success') { diff --git a/routes/admin.php b/routes/admin.php index 538676e9..4dffb515 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -59,7 +59,7 @@ Route::prefix('admin')->name('admin.')->group(function () { }); Route::resource('goods', 'ShopController')->except('show'); // 商品管理 - Route::resource('coupon', 'CouponController')->except('show', 'edit', 'update'); // 优惠券 + Route::resource('coupon', 'CouponController')->except('edit', 'update'); // 优惠券 Route::get('coupon/export', 'CouponController@exportCoupon')->name('coupon.export'); // 导出优惠券 Route::prefix('aff')->name('aff.')->group(function () { diff --git a/routes/user.php b/routes/user.php index 1904130d..95fe51ef 100644 --- a/routes/user.php +++ b/routes/user.php @@ -14,8 +14,8 @@ Route::get('invoices', 'UserController@invoices')->name('invoice'); // 订单列 Route::post('closePlan', 'UserController@closePlan')->name('cancelPlan'); // 激活预支付套餐 Route::get('invoice/{sn}', 'UserController@invoiceDetail')->name('invoiceInfo'); // 订单明细 Route::post('resetUserTraffic', 'UserController@resetUserTraffic')->name('resetTraffic'); // 重置用户流量 +Route::post('buy/{good}/redeem', 'UserController@redeemCoupon')->name('redeemCoupon'); // 使用优惠券 Route::get('buy/{good}', 'UserController@buy')->name('buy'); // 购买商品 -Route::post('redeemCoupon', 'UserController@redeemCoupon')->name('redeemCoupon'); // 使用优惠券 Route::get('invite', 'UserController@invite')->name('invite'); // 邀请码 Route::post('makeInvite', 'UserController@makeInvite')->name('createInvite'); // 生成邀请码 Route::match(['get', 'post'], 'profile', 'UserController@profile')->name('profile'); // 修改个人信息