diff --git a/app/common/dao/user/UserInviteCodeDao.php b/app/common/dao/user/UserInviteCodeDao.php new file mode 100644 index 0000000..5bf1753 --- /dev/null +++ b/app/common/dao/user/UserInviteCodeDao.php @@ -0,0 +1,63 @@ +when(isset($params['id']) && $params['id'] !== '',function($query) use ($params){ + $query->where('id', (int)$params['id']); + }) + ->when(isset($params['batch_title']) && $params['batch_title'] !== '',function($query) use ($params){ + $query->where('batch_title', $params['batch_title']); + }) + ->when(isset($params['batch_unique']) && $params['batch_unique'] !== '',function($query) use ($params){ + $query->where('batch_unique', $params['batch_unique']); + }) + ->when(isset($params['exchange_code']) && $params['exchange_code'] !== '',function($query) use ($params){ + $query->where('exchange_code', $params['exchange_code']); + }) + ->when(isset($params['status']) && $params['status'] !== '',function($query) use ($params){ + $query->where('status', (int)$params['status']); + }) + ->when(isset($params['activate_uid']) && $params['activate_uid'] !== '',function($query) use ($params){ + $query->where('activate_uid', (int)$params['activate_uid']); + }) + ->when(isset($params['use_user_id']) && $params['use_user_id'] !== '',function($query) use ($params){ + $query->where('use_user_id', (int)$params['use_user_id']); + }) + ->when(isset($params['group_data_id']) && $params['group_data_id'] !== '',function($query) use ($params){ + $query->where('group_data_id', (int)$params['group_data_id']); + }) + ->with([ + 'vipInfo' => function($query){ + $query->field(['group_data_id','value','value as svip_name'])->withAttr('svip_name',function($val){ + $value = json_decode($val,TRUE); + return $value['svip_name'] ?? ''; + })->bind(['svip_name']); + }, + 'activateUser' => function($query){ + $query->field('uid,nickname,avatar'); + }, + 'useUser' => function($query){ + $query->field('uid,nickname,avatar'); + }, + ]) + ->order('create_time DESC,id DESC') + ->append(['qr_code_text']); + } + +} diff --git a/app/common/dao/user/VipExchangeCodeDao.php b/app/common/dao/user/VipExchangeCodeDao.php index 723028a..f0eb965 100644 --- a/app/common/dao/user/VipExchangeCodeDao.php +++ b/app/common/dao/user/VipExchangeCodeDao.php @@ -60,7 +60,8 @@ class VipExchangeCodeDao extends BaseDao{ $query->field('service_id,nickname as staff_nickname,avatar as staff_avatar')->bind(['staff_nickname','staff_avatar']); }, ]) - ->order('create_time DESC,id DESC'); + ->order('create_time DESC,id DESC') + ->append(['qr_code_text']); } diff --git a/app/common/model/user/UserInviteCode.php b/app/common/model/user/UserInviteCode.php new file mode 100644 index 0000000..f0d2234 --- /dev/null +++ b/app/common/model/user/UserInviteCode.php @@ -0,0 +1,37 @@ +exchange_code; + } + + + + + public function vipInfo(){ + return $this->hasOne(SystemGroupData::class, 'group_data_id', 'group_data_id'); + } + public function activateUser(){ + return $this->hasOne(User::class, 'uid', 'activate_uid'); + } + public function useUser(){ + return $this->hasOne(User::class, 'uid', 'use_user_id'); + } + + + +} diff --git a/app/common/model/user/UserVipExchangeCode.php b/app/common/model/user/UserVipExchangeCode.php index 2af3d5b..d99f960 100644 --- a/app/common/model/user/UserVipExchangeCode.php +++ b/app/common/model/user/UserVipExchangeCode.php @@ -16,6 +16,12 @@ class UserVipExchangeCode extends BaseModel{ } + // 二维码内容 + public function getQrCodeTextAttr(){ + return "type=exchange&code=" . $this->exchange_code; + } + + public function mer(){ return $this->hasOne(Merchant::class, 'mer_id', 'mer_id'); diff --git a/app/common/repositories/user/UserInviteCodeRepository.php b/app/common/repositories/user/UserInviteCodeRepository.php new file mode 100644 index 0000000..96cee7b --- /dev/null +++ b/app/common/repositories/user/UserInviteCodeRepository.php @@ -0,0 +1,238 @@ +dao = $dao; + } + /** + * Common: 公共查询模型 + * Author: wu-hui + * Time: 2024/04/02 16:59 + * @param $search + * @return \app\common\model\user\UserInviteCode + */ + public function getSearchModel($search){ + return $this->dao->searchList($search); + } + /** + * Common: 获取信息列表 + * Author: wu-hui + * Time: 2024/04/02 16:59 + * @param array $params + * @param int $page + * @param int $limit + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(array $params,int $page,int $limit):array{ + $query = $this->dao->searchList($params); + $count = $query->count(); + $list = $query->page($page,$limit)->select()->toArray(); + + return compact('count','list'); + } + /** + * Common: 生成编辑表单数据 + * Author: wu-hui + * Time: 2024/04/02 17:16 + * @return \FormBuilder\Form + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function getEditFormData(){ + // 获取有效的会员卡列表 + $groupId = app()->make(GroupRepository::class)->getSearch(['group_key' => 'svip_pay'])->value('group_id'); + $vipList = app()->make(GroupDataRepository::class) + ->getSearch([]) + ->field(['group_data_id as value','value as label']) + ->withAttr('label', function ($val) { + $value = json_decode($val, true); + + return $value['svip_name'] ?? ''; + }) + ->where('mer_id', 0) + ->where('status', 1) + ->where('group_id', $groupId) + ->order('sort DESC,group_data_id ASC') + ->select() + ->toArray(); + + $formData = []; + $url = Route::buildUrl('systemUserInviteCodeEditInfo')->build(); + $form = Elm::createForm($url); + $rules = [ + Elm::input('batch_title','当前批次名称')->required()->col(16), + Elm::radio('generation_method', '生成方式', 0)->options([ + ['value' => 0, 'label' => '随机生成'], + ['value' => 1, 'label' => '顺序生成'], + ])->appendRule('suffix',[ + 'type' => 'div', + 'style' => ['color' => '#999999'], + 'domProps' => [ + 'innerHTML' => '随机生成:使用字母和数字随机生成;顺序生成:根据指定前缀,指定初始值和结束值进行生成', + ] + ])->control([ + [ + 'value' => 0, + 'rule' => [ + Elm::input('create_num','生成数量')->required()->col(16) + ->type('number') + ->min('1') + ->max('999999') + ->step('1'), + ] + ], + [ + 'value' => 1, + 'rule' => [ + Elm::input('prefix','前缀')->required()->col(16), + Elm::number('start','初始值')->required()->max(999999)->col(16), + Elm::number('end','结束值')->required()->max(999999)->col(16), + ] + ] + ]), + Elm::select('group_data_id','绑定会员卡类型')->options($vipList), + ]; + + $form->setRule($rules); + return $form->setTitle( '添加邀请码')->formData($formData); + } + /** + * Common: 码生成 + * Author: wu-hui + * Time: 2024/04/02 17:22 + * @param $params + * @return int + */ + public function createExchangeCode($params){ + if((int)$params['group_data_id'] <= 0) throw new ValidateException('请选择绑定会员卡类型!'); + // 是否允许生成邀请码 + $isHas = (int)$this->dao->getSearch(['batch_title'=>$params['batch_title']])->value('id'); + if($isHas > 0) throw new ValidateException('批次名称已经存在,请更换名称!'); + // 生成批次唯一编号 + $initial = substr(getFirstCharter($params['batch_title']), 0, 1); + $batchUnique = strtoupper(uniqid($initial));// 批次唯一编号 + // 生成操作 + $insertData = []; + if($params['generation_method'] == 1){ + // 顺序生成 + if($params['start'] <= 0 || $params['end'] <= 0) throw new ValidateException('初始值和结束值必须大于0'); + if($params['start'] >= $params['end']) throw new ValidateException('初始值必须小于结束值'); + for($i = $params['start']; $i <= $params['end']; $i++){ + // 邀请码生成 + $exchangeCode = strtoupper($initial . substr(uniqid(), -8)); + if(!in_array($exchangeCode, array_column($insertData,'exchange_code'))){ + $insertData[] = [ + 'batch_title' => $params['batch_title'], + 'batch_unique' => $batchUnique, + 'exchange_code' => $params['prefix'] . str_pad($i, strlen($params['end']), '0', STR_PAD_LEFT), + 'group_data_id' => $params['group_data_id'], + ]; + } + } + }else{ + // 随机生成 + if($params['create_num'] <= 0) throw new ValidateException('生成数量必须大于0'); + for($i = 0; count($insertData) < $params['create_num']; $i++){ + // 邀请码生成 + $exchangeCode = strtoupper($initial . substr(uniqid(), -8)); + if(!in_array($exchangeCode, array_column($insertData,'exchange_code'))){ + $insertData[] = [ + 'batch_title' => $params['batch_title'], + 'batch_unique' => $batchUnique, + 'exchange_code' => strtoupper($initial . substr(uniqid(), -8)), + 'group_data_id' => $params['group_data_id'], + ]; + } + } + } + + return $this->dao->insertAll($insertData); + } + /** + * Common: 作废表单 + * Author: wu-hui + * Time: 2024/04/02 17:38 + * @return \FormBuilder\Form + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function cancelFormData(){ + $formData = []; + $url = Route::buildUrl('systemUserInviteCodeCancelInfo')->build(); + $form = Elm::createForm($url); + $rules = [ + Elm::number('start_id','开始ID')->required()->appendRule('suffix',[ + 'type' => 'div', + 'style' => ['color' => '#999999'], + 'domProps' => [ + 'innerHTML' => '例:输入 15 则ID大于15 小于等于结束ID的邀请码都会作废', + ] + ]), + Elm::number('end_id','结束ID')->required()->appendRule('suffix',[ + 'type' => 'div', + 'style' => ['color' => '#999999'], + 'domProps' => [ + 'innerHTML' => '例:输入 80 则ID小于等于80 大于开始ID的邀请码都会作废', + ] + ]), + ]; + $form->setRule($rules); + return $form->setTitle( '作废邀请码')->formData($formData); + } + /** + * Common: 作废表单提交 + * Author: wu-hui + * Time: 2024/04/02 17:39 + * @param $params + * @return UserInviteCode + */ + public function cancelExchangeCode($params){ + // 是否允许生成邀请码 + if($params['end_id'] <= 0) throw new ValidateException('结束id必须大于0'); + if($params['end_id'] <= $params['start_id']) throw new ValidateException('结束id必须大于开始id'); + + return UserInviteCode::where('id','>',$params['start_id']) + ->where('id','<=',$params['end_id']) + ->where('status','<>', 2) + ->update([ + 'status' => 3, + ]); + } + /** + * Common: 修改码 + * Author: wu-hui + * Time: 2024/04/02 17:43 + * @param $params + * @return UserInviteCode + */ + public function updateExchangeCode($params){ + if(empty($params['new_exchange_code'])) throw new ValidateException('请输入新邀请码!'); + if(strlen($params['new_exchange_code']) > 10) throw new ValidateException('邀请码长度不能超过10个字符!'); + // 判断:是否存在信息 + $info = $this->getSearchModel(['id'=>$params['id']])->findOrEmpty(); + if((int)($info->id ?? 0) <= 0) throw new ValidateException('邀请码不存在!'); + if((int)($info->status ?? 0) != 0) throw new ValidateException('当前邀请码不允许修改!'); + // 判断:是否已经存在 + $isHas = (int)$this->getSearchModel(['exchange_code'=>$params['new_exchange_code']])->value('id'); + if($isHas > 0) throw new ValidateException('邀请码已经存在!'); + // 执行修改 + return UserInviteCode::where('id',$params['id']) + ->update([ + 'exchange_code' => $params['new_exchange_code'], + ]); + } + + +} diff --git a/app/common/repositories/user/VipExchangeCodeRepository.php b/app/common/repositories/user/VipExchangeCodeRepository.php index 012dcc7..4b248ab 100644 --- a/app/common/repositories/user/VipExchangeCodeRepository.php +++ b/app/common/repositories/user/VipExchangeCodeRepository.php @@ -59,7 +59,7 @@ class VipExchangeCodeRepository extends BaseRepository{ $form = Elm::createForm($url); $rules = [ Elm::input('batch_title','当前批次名称')->required()->col(16), - Elm::radio('type', '生成方式', 0)->options([ + Elm::radio('generation_method', '生成方式', 0)->options([ ['value' => 0, 'label' => '随机生成'], ['value' => 1, 'label' => '顺序生成'], ])->appendRule('suffix',[ @@ -108,7 +108,7 @@ class VipExchangeCodeRepository extends BaseRepository{ $batchUnique = strtoupper(uniqid($initial));// 批次唯一编号 // 生成操作 $insertData = []; - if($params['type'] == 1){ + if($params['generation_method'] == 1){ // 顺序生成 if($params['start'] <= 0 || $params['end'] <= 0) throw new ValidateException('初始值和结束值必须大于0'); if($params['start'] >= $params['end']) throw new ValidateException('初始值必须小于结束值'); diff --git a/app/controller/admin/user/ExchangeCode.php b/app/controller/admin/user/ExchangeCode.php index 5d19062..310180c 100644 --- a/app/controller/admin/user/ExchangeCode.php +++ b/app/controller/admin/user/ExchangeCode.php @@ -40,7 +40,7 @@ class ExchangeCode extends BaseController{ '生成时间:' . date('Y-m-d H:i:s',time()) ]; // $data['header'] = ['批次名称','批次编号','兑换码', '小程序链接']; - $data['header'] = ['批次名称','批次编号','兑换码']; + $data['header'] = ['批次名称','批次编号','兑换码','二维码内容']; $data['filename'] = '兑换码_'.time(); // 处理跳转路径 $data['list'] = array_map(function($item){ @@ -48,7 +48,8 @@ class ExchangeCode extends BaseController{ return [ $item['batch_title'] ?? '', $item['batch_unique'] ?? '', - $item['exchange_code'] + $item['exchange_code'], + $item['qr_code_text'] // $path, ]; }, $data['list']); @@ -89,7 +90,7 @@ class ExchangeCode extends BaseController{ */ public function editInfo(){ $params = $this->request->params([ - ['type', 0], + ['generation_method', 0], 'prefix', ['start', 0], ['end', 0], diff --git a/app/controller/admin/user/UserInviteCode.php b/app/controller/admin/user/UserInviteCode.php new file mode 100644 index 0000000..af3c967 --- /dev/null +++ b/app/controller/admin/user/UserInviteCode.php @@ -0,0 +1,141 @@ +repository = $repository; + } + /** + * Common: 列表信息 + * Author: wu-hui + * Time: 2024/04/02 17:11 + * @return mixed + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getList(){ + [$page, $limit] = $this->getPage(); + $params = $this->request->params(['is_export','batch_unique','status','mer_id','staff_id','group_data_id']); + $params['mer_id'] = $this->request->merId(); + $data = $this->repository->getList((array)$params,(int)$page,(int)$limit); + // 导出数据处理 + if($params['is_export'] == 1){ + // 处理其他导出信息 + $data['title'] = [ + '邀请码', + '生成时间:' . date('Y-m-d H:i:s',time()) + ]; + // $data['header'] = ['批次名称','批次编号','邀请码', '小程序链接']; + $data['header'] = ['批次名称','批次编号','邀请码','二维码内容']; + $data['filename'] = '邀请码_'.time(); + // 处理跳转路径 + $data['list'] = array_map(function($item){ + // $path = '/pages/annex/vip_center/index?ec='.$item['exchange_code']; + return [ + $item['batch_title'] ?? '', + $item['batch_unique'] ?? '', + $item['exchange_code'], + $item['qr_code_text'] + // $path, + ]; + }, $data['list']); + $data['list'] = array_reverse($data['list']); + } + + return app('json')->success($data); + } + /** + * Common: 获取批次列表 + * Author: wu-hui + * Time: 2024/04/02 17:12 + * @return mixed + */ + public function getBatchList(){ + $list = $this->repository->getSearchModel([])->column('batch_unique','batch_title'); + + return app('json')->success($list); + } + /** + * Common: 生成编辑表单 + * Author: wu-hui + * Time: 2024/04/02 17:19 + * @return mixed + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function editForm(){ + $data = $this->repository->getEditFormData(); + + return app('json')->success(formToData($data)); + } + /** + * Common: 编辑提交信息 + * Author: wu-hui + * Time: 2024/04/02 17:29 + * @return mixed + */ + public function editInfo(){ + $params = $this->request->params([ + ['generation_method', 0], + 'prefix', + ['start', 0], + ['end', 0], + 'batch_title', + ['create_num', 0], + ['group_data_id', 0] + ]); + $this->repository->createExchangeCode($params); + + return app('json')->success('添加成功'); + } + /** + * Common: 作废表单 + * Author: wu-hui + * Time: 2024/04/02 17:39 + * @return mixed + * @throws \FormBuilder\Exception\FormBuilderException + */ + public function cancelForm(){ + $data = $this->repository->cancelFormData(); + + return app('json')->success(formToData($data)); + } + /** + * Common: 作废表单提交 + * Author: wu-hui + * Time: 2024/04/02 17:39 + * @return mixed + */ + public function cancelInfo(){ + $params = $this->request->params(['start_id','end_id']); + $this->repository->cancelExchangeCode($params); + + return app('json')->success('作废成功'); + } + /** + * Common: 修改邀请码 + * Author: wu-hui + * Time: 2024/04/02 17:45 + * @return mixed + */ + public function updateCode(){ + $params = $this->request->params(['id','new_exchange_code']); + $this->repository->updateExchangeCode($params); + + return app('json')->success('修改成功'); + } + + +} diff --git a/route/admin/member.php b/route/admin/member.php index 3f2984f..23fb2e6 100644 --- a/route/admin/member.php +++ b/route/admin/member.php @@ -67,14 +67,37 @@ Route::group(function () { Route::post('cancelInfo', 'admin.user.ExchangeCode/cancelInfo')->name('systemUserVipExchangeCodeCancelInfo'); // 修改兑换码 Route::post('updateCode', 'admin.user.ExchangeCode/updateCode')->name('systemUserVipExchangeCodeUpdateCode'); - - - - })->append(['type' => 1])->option([ '_path' => '/user/member/exchangeCode', '_auth' => true, ]); + // 会员卡邀请码 + Route::group('user/inviteCode', function () { + // 兑换码列表 + Route::get('getList', 'admin.user.UserInviteCode/getList')->name('systemUserInviteCodeGetList'); + // 兑换码批次列表 + Route::get('getBatchList', 'admin.user.UserInviteCode/getBatchList')->name('systemUserInviteCodeGetBatchList'); + // 编辑表单 + Route::get('editForm', 'admin.user.UserInviteCode/editForm')->name('systemUserInviteCodeEdit'); + // 提交编辑信息 + Route::post('editInfo', 'admin.user.UserInviteCode/editInfo')->name('systemUserInviteCodeEditInfo'); + // 作废表单 + Route::get('cancelForm', 'admin.user.UserInviteCode/cancelForm')->name('systemUserInviteCodeCancelForm'); + // 提交作废表单 + Route::post('cancelInfo', 'admin.user.UserInviteCode/cancelInfo')->name('systemUserInviteCodeCancelInfo'); + // 修改兑换码 + Route::post('updateCode', 'admin.user.UserInviteCode/updateCode')->name('systemUserInviteCodeUpdateCode'); + })->append(['type' => 1])->option([ + '_path' => '/user/member/inviteCode', + '_auth' => true, + ]); + + + + + + + // 会员订单列表 Route::get('user/svip/order_lst', 'admin.user.Svip/payList')->name('systemUserSvipPayLst')->option([ '_alias' => '列表', @@ -217,8 +240,6 @@ Route::group(function () { ] ]); - - })->middleware(AllowOriginMiddleware::class) ->middleware(AdminTokenMiddleware::class, true) ->middleware(AdminAuthMiddleware::class)