request->get('title', '', 'trim'); $name = $this->request->get('name', '', 'trim'); !empty($title) && $condition['title'] = ['like', "%{$title}%"]; !empty($name) && $condition['name'] = $name; $settingModel = model('Common/Setting'); $settingList = $settingModel->where($condition)->order('id desc')->paginate(20); // 拦截超长配置或特殊白名单配置的展示 $settingList->each(function ($item, $key) { if ($item['name'] == 'game_channel_by_mobild_whitelist' || mb_strlen((string)$item['value']) > 100) { $displayValue = '-'; // 解析白名单配置的JSON数据 if ($item['name'] == 'game_channel_by_mobild_whitelist') { $configData = json_decode($item['value'], true); if ($configData && is_array($configData)) { $displayParts = []; // 游戏显示 if (!empty($configData['game_ids'])) { if ($configData['game_ids'] === 'all') { $displayParts[] = '游戏: 全部'; } else { $gameIds = array_slice(explode(',', $configData['game_ids']), 0, 3); $gameNames = Db::name('cy_game') ->where(['id' => ['in', $gameIds]]) ->column('name'); if (!empty($gameNames)) { $displayParts[] = '游戏: ' . implode('、', $gameNames) . '...'; } } } // 渠道显示 if (!empty($configData['channel_ids'])) { if ($configData['channel_ids'] === 'all') { $displayParts[] = '渠道: 全部'; } else { $channelIds = array_slice(explode(',', $configData['channel_ids']), 0, 3); $channelNames = Db::name('nw_channel') ->where(['id' => ['in', $channelIds]]) ->column('name'); if (!empty($channelNames)) { $displayParts[] = '渠道: ' . implode('、', $channelNames) . '...'; } } } if (!empty($displayParts)) { $displayValue = implode('
', $displayParts); } } } else { // 超长配置,默认截取前100个字符,多的用省略号 $displayValue = mb_substr((string)$item['value'], 0, 100) . '...'; } $item['value'] = $displayValue; } return $item; }); $this->assign('list', $settingList); $this->assign('title', $title); $this->assign('name', $name); $this->assign('page', $settingList->render()); return $this->fetch(); } /** * 新增配置 * @return mixed */ public function add() { if ($this->request->isPost()) { $data = $this->request->param(); // 针对白名单配置单独组装 JSON if (isset($data['name']) && $data['name'] == 'game_channel_by_mobild_whitelist') { $gameIds = isset($data['game_ids']) ? $data['game_ids'] : ''; $channelIds = isset($data['channel_ids']) ? $data['channel_ids'] : ''; $data['value'] = json_encode([ 'game_ids' => $gameIds, 'channel_ids' => $channelIds, 'status' => 1 ], JSON_UNESCAPED_UNICODE); // 删除不在数据库表中的字段 unset($data['game_ids']); unset($data['channel_ids']); // 删除 xm-select 组件可能生成的字段 unset($data['select']); } if (true !== ($res = $this->validate($data, 'Setting'))) { $this->error($res); } $settingModel = model('Common/Setting'); if ($settingModel->where(['name' => input('post.name', '', 'trim')])->find()) { $this->error('配置项已经存在,不能重复添加'); } if ($settingModel->allowField(true)->save($data)) { $this->success('添加成功'); } $this->error($settingModel->getError() ?: '添加失败'); } return $this->fetch(); } /** * 编辑配置 */ public function edit() { $data = $this->checkData(); if ($this->request->isPost()) { $data = $this->request->param(); // 确保 id 字段存在 if (!isset($data['id']) || empty($data['id'])) { $this->error('缺少ID参数'); } // 针对白名单配置单独组装 JSON if (isset($data['name']) && $data['name'] == 'game_channel_by_mobild_whitelist') { $gameIds = isset($data['game_ids']) ? $data['game_ids'] : ''; $channelIds = isset($data['channel_ids']) ? $data['channel_ids'] : ''; $data['value'] = json_encode([ 'game_ids' => $gameIds, 'channel_ids' => $channelIds, ], JSON_UNESCAPED_UNICODE); // 删除不在数据库表中的字段 unset($data['game_ids']); unset($data['channel_ids']); // 删除 xm-select 组件可能生成的字段 unset($data['select']); unset($data['game_select']); unset($data['channel_select']); // 删除所有可能的xm-select生成的字段 foreach ($data as $key => $value) { if (strpos($key, 'select') !== false || strpos($key, 'xm') !== false) { unset($data[$key]); } } } if (true !== ($res = $this->validate($data, 'Setting'))) { $this->error($res); } $settingModel = model('Common/Setting'); if ($settingModel->where(['name' => $data['name'], 'id' => ['<>', $data['id']]])->find()) { $this->error('配置项已经存在,不能重复配置'); } $result = $settingModel->allowField(true)->save($data, ['id' => $data['id']]); if ($result !== false) { $this->success('编辑成功', url('setting/index')); } $this->error('编辑失败或未编辑;' . $settingModel->getError()); } // 如果是白名单配置,单独准备前端联动组件需要的数据 if ($data['name'] == 'game_channel_by_mobild_whitelist') { // 获取游戏数据(按创建时间倒序) $gameList = \think\Db::name('cy_game') ->where(['isdelete' => 0]) ->field('id as value, name') ->order('create_time', 'desc') ->select(); $this->assign('gameList', json_encode($gameList, JSON_UNESCAPED_UNICODE)); // 获取完整渠道树(包含所有层级,用于搜索功能) $tree = \app\common\library\ChannelUtil::getFullChannelTree(); $this->assign('channelTree', json_encode($tree, JSON_UNESCAPED_UNICODE)); // 获取一级渠道列表(用于判断是否一级全选) $channelList = \think\Db::name('nw_channel') ->where(['parent_id' => 0, 'status' => 1]) ->field('id as value, name') ->order('id', 'asc') ->select(); // 解析当前拥有的配置,传给前端用于初始选中 $currentConfig = json_decode($data['value'], true); $gameIds = isset($currentConfig['game_ids']) ? $currentConfig['game_ids'] : ''; $channelIds = isset($currentConfig['channel_ids']) ? $currentConfig['channel_ids'] : ''; $this->assign('gameIds', $gameIds); $this->assign('channelIds', $channelIds); // 获取已选中的渠道的详细信息,用于前台渲染 initValue 标签 $selectedChannels = []; if (!empty($channelIds) && $channelIds !== 'all') { $ids = explode(',', $channelIds); // 判断是否是一级全选模式(所有一级渠道ID都在选中列表中) $level1Ids = array_column($channelList, 'value'); $isLevel1All = !empty(array_diff($level1Ids, array_map('intval', $ids))) === false; if ($isLevel1All) { // 一级全选模式,只返回一级渠道信息 foreach ($channelList as $level1) { $selectedChannels[] = [ 'name' => $level1['name'], 'value' => (int)$level1['value'], 'selected' => true ]; } } else { // 部分选中模式,返回具体选中的渠道信息 $selectedChannelList = \think\Db::name('nw_channel') ->where(['id' => ['in', $ids]]) ->field('id as value, name, parent_id') ->select(); foreach ($selectedChannelList as $sc) { $item = [ 'name' => $sc['name'], 'value' => (int)$sc['value'], 'selected' => true ]; // 检查是否有子节点,如果有则添加 children 属性(用于树形组件识别父节点) $hasChildren = \think\Db::name('nw_channel') ->where(['parent_id' => $sc['value'], 'status' => 1]) ->count() > 0; if ($hasChildren) { $item['children'] = []; } $selectedChannels[] = $item; } } } $this->assign('selectedChannels', json_encode($selectedChannels, JSON_UNESCAPED_UNICODE)); } $this->assign('data', $data); return $this->fetch(); } /** * 删除 */ public function delete() { $data = $this->checkData(); if ($data->delete()) { $this->success('删除成功!'); } $this->error('删除失败'); } /** * 检查礼包信息 * @return array|false|\PDOStatement|string|\think\Model * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ protected function checkData() { $id = $this->request->param('id', 0, 'intval'); $settingModel = model('Common/Setting'); $data = []; if (empty($id) || !($data = $settingModel->find($id))) { $this->error('参数错误,不存在该配置信息'); } return $data; } /** * 平台币说明设置 * */ public function coinInstruction() { $instructionModel = model('Common/CoinInstruction'); $instructionInfo = $instructionModel->find(); //表单提交 if ($this->request->isPost()) { $content = input('post.content'); if ($content == '') { $this->error('平台币劵说明,不能为空'); } if ($instructionInfo) { $instructionModel->allowField(true)->save(['content' => $content], ['id' => $instructionInfo['id']]); $this->success('提交成功'); } else { if ($instructionModel->allowField(true)->save(['content' => $content])) { $this->success('提交成功'); } } $this->error('提交失败'); } $this->assign('data', $instructionInfo); return $this->fetch('coin_instruction'); } /** * 安卓SDK版本配置 * @return mixed */ public function android() { $condition = []; $version = $this->request->get('version', '', 'trim'); !empty($version) && $condition['version'] = ['like', "%{$version}%"]; $sdkModel = model('Common/AndroidSdk'); $configList = $sdkModel ->field(['id', 'version', 'num', 'filename', 'content', 'update_time', 'create_time']) ->where($condition) ->order('create_time', 'desc') ->paginate(10, false, ['query' => $condition]); // dump($configList->toArray()); $this->assign('list', $configList); $this->assign('version', $version); $this->assign('page', $configList->render()); return $this->fetch(); } // 添加安卓sdk public function sdkAdd() { if ($this->request->isPost()) { $data = $this->request->param(); if (true !== ($res = $this->validate($data, 'AndroidSdk.add'))) { $this->error($res); } //filename是完整URL时 if (filter_var($data['filename'], FILTER_VALIDATE_URL)) { //去除掉域名部分 $data['filename'] = str_replace(STATIC_DOMAIN, "", $data['filename']); } $sdkModel = model('Common/AndroidSdk'); if ($sdkModel->allowField(true)->save($data)) { $this->success('添加成功', url('setting/android')); } $this->error($sdkModel->getError() ?: '添加失败'); } return $this->fetch('sdk_add'); } // 修改安卓SDK public function sdkEdit() { $id = $this->request->param('id', 0, 'intval'); $sdkModel = model('Common/AndroidSdk'); $data = []; if (empty($id) || !($data = $sdkModel->find($id))) { $this->error('参数错误,不存在该SDK信息'); } if ($this->request->isPost()) { $data = $this->request->param(); if (true !== ($res = $this->validate($data, 'AndroidSdk.edit'))) { $this->error($res); } //去除掉域名部分 if ($data['filename']) { $data['filename'] = str_replace(STATIC_DOMAIN, "", $data['filename']); } if ($sdkModel->allowField(true)->save($data, ['id' => $data['id']])) { $this->success('编辑成功', url('setting/android')); } $this->error($sdkModel->getError() ?: '编辑失败'); } $this->assign('data', $data); return $this->fetch('sdk_edit'); } // 更新SDK:状态,时间 /* public function sdkUpdate() { $id = $this->request->param('id', 0, 'intval'); $sdkModel = model('Common/AndroidSdk'); if (empty($id) || !($sdkModel->find($id))) { $this->error('参数错误,不存在该SDK信息'); } $data = [ 'status' => 1, 'update_status_time' => request()->time() ]; if (true !== ($res = $this->validate($data, 'AndroidSdk.update'))) { $this->error($res); } if ($sdkModel->allowField(true)->save($data, ['id' => $id])) { $this->success('更新成功', url('setting/android')); } $this->error($sdkModel->getError() ?: '更新失败'); }*/ // 上传文件 public function uploadFile() { $file = request()->file('file'); if (!$file) { $this->error('上传文件不能为空! '); } $fileObject = new FileUpload(); $fileObject->set('allowExt', 'jar'); // 设置允许上传类型 $path = $fileObject->upload($file); if ($path) { $this->success('上传成功', null, ['filename' => $path]); } else { $this->error('上传失败! ' . $fileObject->getError()); }; } /** * 充值预警设置页 * */ public function pay() { $paySettingModel = new PaySetting; $payWarningRuleModel = new PayWarningRule; //配置信息 $settingInfo = $paySettingModel->getPaySetting(); //规则列表 $rule_list = $payWarningRuleModel->getPaySetting(); //外部渠道列表 $channel_list = model('Common/Channel')->getAllByCondition('id,name', ['flag' => 3], 'name asc'); $this->assign('channel_list', $channel_list); $this->assign('rule_list', $rule_list); $this->assign('settingInfo', $settingInfo); $this->assign('whitelist_channels', !empty($settingInfo['whitelist_channel']) ? explode(',', $settingInfo['whitelist_channel']) : []); return $this->fetch(); } /** * 充值预警保存处理 * */ public function payPost() { if ($this->request->isAjax()) { $status = input('post.status'); $whitelist_channel = input('post.whitelist_channel/a'); $emails = input('post.emails/a'); //以下为规则参数 $warning_time = input('post.warning_time/a'); $order_count = input('post.order_count/a'); $min_amount = input('post.min_amount/a'); $max_amount = input('post.max_amount/a'); $is_six = input('post.is_six/a'); $paySettingModel = new PaySetting; $payWarningRuleModel = new PayWarningRule; $validate = new \app\common\library\ValidateExtend(); $result = $this->validate( [ 'status' => input('post.status'), 'emails' => $emails, ], [ ['status', 'require|integer', '请选择功能状态|功能状态必须为整型'], ['emails', 'require', '请填写收件人邮箱'], ] ); if (true !== $result) { $this->error($result); } else { //邮箱格式验证 foreach ($emails as $value) { if (!$validate->is($value, 'email')) { $this->error('收件人邮箱格式不正确'); exit; } } $rule_count = count($warning_time); Db::startTrans(); try { $payWarningRuleModel->where('id<>0')->delete(); //有规则时 if ($rule_count > 0) { $ruleData = []; for ($i = 0; $i < $rule_count; $i++) { $tmp = []; $tmp['warning_time'] = $warning_time[$i]; $tmp['order_count'] = $order_count[$i]; $tmp['min_amount'] = $min_amount[$i]; $tmp['max_amount'] = $max_amount[$i]; $tmp['is_six'] = $is_six[$i]; //规则参数验证 $ruleResult = $this->validate( $tmp, [ ['warning_time', 'require|positiveInteger', '预警时间阈值不能为空|功能状态必须为整型'], ['order_count', 'require|positiveInteger', '连续充值成功订单阈值不能为空|连续充值成功订单阈值必须为整型'], ['min_amount', 'require|positiveInteger', '金额预警最小值不能为空|金额预警最小值必须为整型'], ['max_amount', 'require|positiveInteger|>:min_amount', '金额预警最大值不能为空|金额预警最大值必须为整型|金额预警最大值须大于最小值'], ['is_six', 'require|integer', '请选择是否包括6元|是否包括6元必须为整型'], ] ); if (true !== $ruleResult) { throw new Exception($ruleResult); } $tmp['create_time'] = NOW_TIMESTAMP; $ruleData[] = $tmp; } $payWarningRuleModel->saveAll($ruleData, false); } $settingData = ['status' => $status, 'emails' => implode(";", $emails), 'update_time' => NOW_TIMESTAMP]; $settingData['whitelist_channel'] = !empty($whitelist_channel) ? implode(",", $whitelist_channel) : ''; //保存充值预警配置表 $paySettingModel->save($settingData, ['id' => 1]); Db::commit(); } catch (\Exception $e) { Db::rollback(); $this->error("充值预警设置失败;原因: " . $e->getMessage()); } $this->success('充值预警设置成功'); } } else { $this->error('非法请求'); } } /** * 获取下级渠道数据(用于异步懒加载) */ public function getChannels() { $parentId = $this->request->param('parent_id', 0, 'intval'); $channelList = \think\Db::name('nw_channel') ->where(['parent_id' => $parentId, 'status' => 1]) ->field('id as value, name, level') ->order('id', 'asc') ->select(); $data = []; foreach ($channelList as $v) { // 基于 parent_id 检查是否有启用状态的下层渠道 $hasChildren = \think\Db::name('nw_channel') ->where(['parent_id' => $v['value'], 'status' => 1]) ->count() > 0; $data[] = [ 'name' => $v['name'], 'value' => (int)$v['value'], 'children' => $hasChildren ? [] : null, ]; } return json(['code' => 1, 'data' => $data]); } /** * 搜索渠道(支持远程搜索,用于懒加载树的搜索功能) */ public function searchChannels() { $keyword = $this->request->param('keyword', '', 'trim'); if (empty($keyword)) { return json(['code' => 1, 'data' => []]); } $channelList = Db::name('nw_channel') ->where('name', 'like', "%{$keyword}%") ->where('status', 1) ->field('id as value, name, parent_id') ->order('id', 'asc') ->limit(50) ->select(); $data = []; foreach ($channelList as $v) { $hasChildren = Db::name('nw_channel') ->where(['parent_id' => $v['value'], 'status' => 1]) ->count() > 0; $data[] = [ 'name' => $v['name'], 'value' => (int)$v['value'], 'children' => $hasChildren ? [] : null, ]; } return json(['code' => 1, 'data' => $data]); } }