[渠道管理]

This commit is contained in:
2026-04-15 10:19:41 +08:00
parent 7b002c9410
commit 8cc28096c4
11 changed files with 595 additions and 343 deletions

View File

@@ -0,0 +1,347 @@
<?php
namespace app\admin\controller;
use Throwable;
use app\common\controller\Backend;
use support\think\Db;
use support\Response;
use Webman\Http\Request as WebmanRequest;
/**
* 渠道管理
*/
class Channel extends Backend
{
/**
* Channel模型对象
* @var object|null
* @phpstan-var \app\common\model\Channel|null
*/
protected ?object $model = null;
protected array|string $preExcludeFields = ['id', 'user_count', 'profit_amount', 'create_time', 'update_time'];
protected array $withJoinTable = ['adminGroup', 'admin'];
protected string|array $quickSearchField = ['id', 'code', 'name'];
private array $currentChannelIds = [];
protected function initController(WebmanRequest $request): ?Response
{
$this->model = new \app\common\model\Channel();
$this->currentChannelIds = $this->getCurrentChannelIds();
return null;
}
/**
* 渠道-管理员树(父级=渠道,子级=管理员,仅可选择子级)
*/
public function adminTree(WebmanRequest $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) return $response;
$query = Db::name('channel')
->field(['id', 'name', 'admin_group_id'])
->order('id', 'asc');
if (!$this->auth->isSuperAdmin()) {
$query = $query->where('id', 'in', $this->currentChannelIds ?: [0]);
}
$channels = $query->select()->toArray();
$groupChildrenCache = [];
$getGroupChildren = function ($groupId) use (&$getGroupChildren, &$groupChildrenCache) {
if ($groupId === null || $groupId === '') return [];
if (array_key_exists($groupId, $groupChildrenCache)) return $groupChildrenCache[$groupId];
$children = Db::name('admin_group')
->where('pid', $groupId)
->where('status', 1)
->column('id');
$all = [];
foreach ($children as $cid) {
$all[] = $cid;
foreach ($getGroupChildren($cid) as $cc) {
$all[] = $cc;
}
}
$groupChildrenCache[$groupId] = $all;
return $all;
};
$tree = [];
foreach ($channels as $ch) {
$groupId = $ch['admin_group_id'] ?? null;
$groupIds = [];
if ($groupId !== null && $groupId !== '') {
$groupIds[] = $groupId;
foreach ($getGroupChildren($groupId) as $gid) {
$groupIds[] = $gid;
}
}
$adminIds = [];
if ($groupIds) {
$adminIds = Db::name('admin_group_access')
->where('group_id', 'in', array_unique($groupIds))
->column('uid');
}
$adminIds = array_values(array_unique($adminIds));
$admins = [];
if ($adminIds) {
$admins = Db::name('admin')
->field(['id', 'username'])
->where('id', 'in', $adminIds)
->order('id', 'asc')
->select()
->toArray();
}
$children = [];
foreach ($admins as $a) {
$children[] = [
'value' => (string) $a['id'],
'label' => $a['username'],
'channel_id' => $ch['id'],
'is_leaf' => true,
];
}
$tree[] = [
'value' => 'channel_' . $ch['id'],
'label' => $ch['name'],
'disabled' => true,
'children' => $children,
];
}
return $this->success('', [
'list' => $tree,
]);
}
/**
* 添加重写管理员只选顶级组admin_group_id 后端自动写入)
* @throws Throwable
*/
protected function _add(): Response
{
if ($this->request && $this->request->method() === 'POST') {
$data = $this->request->post();
if (!$data) {
return $this->error(__('Parameter %s can not be empty', ['']));
}
$data = $this->applyInputFilter($data);
$data = $this->excludeFields($data);
$data = $this->normalizeAgentModeFields($data);
unset($data['invite_code']);
$adminId = $data['admin_id'] ?? null;
if ($adminId === null || $adminId === '') {
return $this->error(__('Parameter %s can not be empty', ['admin_id']));
}
if (array_key_exists('admin_group_id', $data)) {
unset($data['admin_group_id']);
}
$topGroupId = Db::name('admin_group_access')
->alias('aga')
->join('admin_group ag', 'aga.group_id = ag.id')
->where('aga.uid', $adminId)
->where('ag.pid', 0)
->value('ag.id');
if ($topGroupId === null || $topGroupId === '') {
return $this->error(__('Record not found'));
}
$data['admin_group_id'] = $topGroupId;
if (!$this->auth->isSuperAdmin()) {
$data['top_admin_id'] = $this->auth->id;
$data['admin_id'] = $this->auth->id;
}
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$data[$this->dataLimitField] = $this->auth->id;
}
$result = false;
$this->model->startTrans();
try {
if ($this->modelValidate) {
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
if (class_exists($validate)) {
$validate = new $validate();
if ($this->modelSceneValidate) {
$validate->scene('add');
}
$validate->check($data);
}
}
$result = $this->model->save($data);
$this->model->commit();
} catch (Throwable $e) {
$this->model->rollback();
return $this->error($e->getMessage());
}
if ($result !== false) {
return $this->success(__('Added successfully'));
}
return $this->error(__('No rows were added'));
}
return $this->error(__('Parameter error'));
}
/**
* 编辑重写管理员只选顶级组admin_group_id 后端自动写入)
* @throws Throwable
*/
protected function _edit(): Response
{
$pk = $this->model->getPk();
$id = $this->request ? ($this->request->post($pk) ?? $this->request->get($pk)) : null;
$row = $this->model->find($id);
if (!$row) {
return $this->error(__('Record not found'));
}
if (!$this->auth->isSuperAdmin() && !in_array($row['id'], $this->currentChannelIds, true)) {
return $this->error(__('You have no permission'));
}
$dataLimitAdminIds = $this->getDataLimitAdminIds();
if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
return $this->error(__('You have no permission'));
}
if ($this->request && $this->request->method() === 'POST') {
$data = $this->request->post();
if (!$data) {
return $this->error(__('Parameter %s can not be empty', ['']));
}
$data = $this->applyInputFilter($data);
$data = $this->excludeFields($data);
$data = $this->normalizeAgentModeFields($data);
unset($data['invite_code']);
if (array_key_exists('admin_group_id', $data)) {
unset($data['admin_group_id']);
}
$nextAdminId = array_key_exists('admin_id', $data) ? $data['admin_id'] : ($row['admin_id'] ?? null);
if ($nextAdminId !== null && $nextAdminId !== '') {
$topGroupId = Db::name('admin_group_access')
->alias('aga')
->join('admin_group ag', 'aga.group_id = ag.id')
->where('aga.uid', $nextAdminId)
->where('ag.pid', 0)
->value('ag.id');
if ($topGroupId === null || $topGroupId === '') {
return $this->error(__('Record not found'));
}
$data['admin_group_id'] = $topGroupId;
}
if (!$this->auth->isSuperAdmin()) {
$data['top_admin_id'] = $this->auth->id;
$data['admin_id'] = $this->auth->id;
}
$result = false;
$this->model->startTrans();
try {
if ($this->modelValidate) {
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
if (class_exists($validate)) {
$validate = new $validate();
if ($this->modelSceneValidate) {
$validate->scene('edit');
}
$data[$pk] = $row[$pk];
$validate->check($data);
}
}
$result = $row->save($data);
$this->model->commit();
} catch (Throwable $e) {
$this->model->rollback();
return $this->error($e->getMessage());
}
if ($result !== false) {
return $this->success(__('Update successful'));
}
return $this->error(__('No rows updated'));
}
return $this->success('', [
'row' => $row
]);
}
/**
* 查看
* @throws Throwable
*/
protected function _index(): Response
{
if ($this->request && $this->request->get('select')) {
return $this->select($this->request);
}
list($where, $alias, $limit, $order) = $this->queryBuilder();
if (!$this->auth->isSuperAdmin()) {
$where[] = [$alias['channel'] . '.id', 'in', $this->currentChannelIds ?: [0]];
}
$res = $this->model
->withJoin($this->withJoinTable, $this->withJoinType)
->with($this->withJoinTable)
->visible(['adminGroup' => ['name'], 'admin' => ['username']])
->alias($alias)
->where($where)
->order($order)
->paginate($limit);
return $this->success('', [
'list' => $res->items(),
'total' => $res->total(),
'remark' => get_route_remark(),
]);
}
private function getCurrentChannelIds(): array
{
if ($this->auth->isSuperAdmin()) {
return Db::name('channel')->column('id');
}
$admin = Db::name('admin')
->field(['id', 'channel_id'])
->where('id', $this->auth->id)
->find();
$ids = [];
if ($admin && !empty($admin['channel_id'])) {
$ids[] = $admin['channel_id'];
}
$owned = Db::name('channel')->where('top_admin_id', $this->auth->id)->column('id');
$created = Db::name('channel')->where('admin_id', $this->auth->id)->column('id');
return array_values(array_unique(array_merge($ids, $owned, $created)));
}
private function normalizeAgentModeFields(array $data): array
{
$mode = $data['agent_mode'] ?? null;
if ($mode === 'turnover') {
$data['affiliate_share_rate'] = null;
$data['affiliate_fee_rate'] = null;
$data['carryover_balance'] = 0;
return $data;
}
if ($mode === 'affiliate') {
$data['turnover_share_rate'] = null;
}
return $data;
}
}