文件
fenleixinxi/application/admin/controller/auth/Rule.php
MiAn cb12bf5fc8 feat: 新增地址选择插件及订阅消息等多项功能优化
- 新增地址选择插件,支持地图位置选择并返回地址和经纬度
- 新增微信订阅消息发送功能,支持审核结果、提现通知等场景
- 新增订单支付状态查询、提现收款人姓名保存等接口
- 新增服务区域管理,支持按省市区划分并同步到信息发布
- 新增资金流水和营收报表导出功能
- 新增可用优惠券查询、订单退款拆分处理等功能
- 优化后台角标显示、首页数据统计、UI配置下发等
- 修复订单支付并发问题、地区管理逻辑等
2026-10-22 17:14:56 +08:00

269 行
8.5 KiB
PHP
可执行文件

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace app\admin\controller\auth;
use app\admin\model\AuthRule;
use app\common\controller\Backend;
use fast\Tree;
use think\Cache;
/**
* 规则管理
*
* @icon fa fa-list
* @remark 左侧菜单与权限节点都在这里维护;修改后左侧导航自动刷新,删除菜单会连同其子级一起删除
*/
class Rule extends Backend
{
/**
* @var \app\admin\model\AuthRule
*/
protected $model = null;
protected $rulelist = [];
protected $multiFields = 'ismenu,status';
public function _initialize()
{
parent::_initialize();
if (!$this->auth->isSuperAdmin()) {
$this->error(__('Access is allowed only to the super management group'));
}
$this->model = model('AuthRule');
// 必须将结果集转换为数组
$ruleList = \think\Db::name("auth_rule")->field('type,condition,remark,createtime,updatetime', true)->order('weigh DESC,id ASC')->select();
foreach ($ruleList as $k => &$v) {
$v['title'] = __($v['title']);
}
unset($v);
Tree::instance()->init($ruleList)->icon = ['&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;&nbsp;&nbsp;&nbsp;'];
$this->rulelist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title');
$ruledata = [0 => __('None')];
foreach ($this->rulelist as $k => &$v) {
if (!$v['ismenu']) {
continue;
}
$ruledata[$v['id']] = $v['title'];
unset($v['spacer']);
}
unset($v);
$this->view->assign('ruledata', $ruledata);
$this->view->assign("menutypeList", $this->model->getMenutypeList());
}
/**
* 查看
*/
public function index()
{
if ($this->request->isAjax()) {
$list = $this->assignSeq($this->filterRuleList($this->rulelist));
$total = count($list);
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
/**
* 按筛选条件过滤规则树
*
* 支持:仅菜单 / 仅权限节点 / 全部、状态、关键词(标题或规则名)。
* 命中节点的父级会一并保留,避免树形层级断裂。
*
* @param array $list
* @return array
*/
protected function filterRuleList(array $list)
{
$type = (string)$this->request->request('rule_filter', 'menu');
$status = (string)$this->request->request('rule_status', '');
$keyword = trim((string)$this->request->request('rule_keyword', ''));
$type = in_array($type, ['menu', 'node', 'all'], true) ? $type : 'all';
$status = in_array($status, ['normal', 'hidden'], true) ? $status : '';
if ($type === 'all' && $status === '' && $keyword === '') {
return $list;
}
$byId = [];
foreach ($list as $row) {
$byId[(int)$row['id']] = $row;
}
$keep = [];
foreach ($list as $row) {
$match = true;
if ($type === 'menu' && !$row['ismenu']) {
$match = false;
}
if ($type === 'node' && $row['ismenu']) {
$match = false;
}
if ($status !== '' && $row['status'] !== $status) {
$match = false;
}
if ($keyword !== '' && stripos($row['title'], $keyword) === false && stripos($row['name'], $keyword) === false) {
$match = false;
}
if (!$match) {
continue;
}
// 保留命中节点的所有父级
$id = (int)$row['id'];
$guard = 0;
while ($id && isset($byId[$id]) && $guard++ < 20) {
$keep[$id] = true;
$id = (int)$byId[$id]['pid'];
}
}
$result = [];
foreach ($list as $row) {
if (isset($keep[(int)$row['id']])) {
$result[] = $row;
}
}
return $result;
}
/**
* 生成层级序号:1、1.1、1.2、2、2.1……
*
* 树形列表默认会隐藏子行,若按行号显示序号会出现 1/7/28 这类跳号;
* 这里按父子层级编号,展开/收起都稳定可读。
*
* @param array $list
* @return array
*/
protected function assignSeq(array $list)
{
$byId = [];
foreach ($list as $row) {
$byId[(int)$row['id']] = $row;
}
$seqById = [];
$counters = [];
foreach ($list as &$row) {
$depth = 0;
$pid = (int)$row['pid'];
$guard = 0;
while ($pid && isset($byId[$pid]) && $guard++ < 20) {
$depth++;
$pid = (int)$byId[$pid]['pid'];
}
$counters[$depth] = isset($counters[$depth]) ? $counters[$depth] + 1 : 1;
if ($depth === 0) {
$seq = (string)$counters[$depth];
} else {
$parentSeq = isset($seqById[(int)$row['pid']]) ? $seqById[(int)$row['pid']] : '';
$seq = ($parentSeq !== '' ? $parentSeq . '.' : '') . $counters[$depth];
}
// 进入新分支后,重置更深的层级计数
for ($i = $depth + 1; $i <= 10; $i++) {
unset($counters[$i]);
}
$row['seq'] = $seq;
$seqById[(int)$row['id']] = $seq;
}
unset($row);
return $list;
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost()) {
$this->token();
$params = $this->request->post("row/a", [], 'strip_tags');
if ($params) {
if (!$params['ismenu'] && !$params['pid']) {
$this->error(__('The non-menu rule must have parent'));
}
$result = $this->model->validate()->save($params);
if ($result === false) {
$this->error($this->model->getError());
}
$this->success();
}
$this->error();
}
return $this->view->fetch();
}
/**
* 编辑
*/
public function edit($ids = null)
{
$row = $this->model->get(['id' => $ids]);
if (!$row) {
$this->error(__('No Results were found'));
}
if ($this->request->isPost()) {
$this->token();
$params = $this->request->post("row/a", [], 'strip_tags');
if ($params) {
if (!$params['ismenu'] && !$params['pid']) {
$this->error(__('The non-menu rule must have parent'));
}
if ($params['pid'] == $row['id']) {
$this->error(__('Can not change the parent to self'));
}
if ($params['pid'] != $row['pid']) {
$childrenIds = Tree::instance()->init(collection(AuthRule::select())->toArray())->getChildrenIds($row['id']);
if (in_array($params['pid'], $childrenIds)) {
$this->error(__('Can not change the parent to child'));
}
}
$params = $this->preExcludePrimaryKey($params);
//这里需要针对name做唯一验证
$ruleValidate = \think\Loader::validate('AuthRule');
$ruleValidate->rule([
'name' => 'require|unique:AuthRule,name,' . $row->id,
]);
$result = $row->validate()->save($params);
if ($result === false) {
$this->error($row->getError());
}
$this->success();
}
$this->error();
}
$this->view->assign("row", $row);
return $this->view->fetch();
}
/**
* 删除
*/
public function del($ids = "")
{
if (!$this->request->isPost()) {
$this->error(__("Invalid parameters"));
}
$ids = $ids ? $ids : $this->request->post("ids");
if ($ids) {
$delIds = [];
foreach (explode(',', $ids) as $k => $v) {
$delIds = array_merge($delIds, Tree::instance()->getChildrenIds($v, true));
}
$delIds = array_unique($delIds);
$count = $this->model->where('id', 'in', $delIds)->delete();
if ($count) {
Cache::rm('__menu__');
$this->success();
}
}
$this->error();
}
}