diff --git a/application/admin/controller/Ajax.php b/application/admin/controller/Ajax.php index 4fd33e1f..f76caa94 100644 --- a/application/admin/controller/Ajax.php +++ b/application/admin/controller/Ajax.php @@ -50,10 +50,9 @@ class Ajax extends Backend $controllername = $this->request->get('controllername'); $lang = $this->request->get('lang'); if (!$lang || !in_array($lang, config('allow_lang_list')) || !$controllername || !preg_match("/^[a-z0-9_\.]+$/i", $controllername)) { - return jsonp(['errmsg' => '参数错误'], 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]); + return jsonp(['errmsg' => __('Invalid parameters')], 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]); } - $controllername = input("controllername"); $className = Loader::parseClass($this->request->module(), 'controller', $controllername, false); //存在对应的类才加载 @@ -135,66 +134,26 @@ class Ajax extends Backend */ public function weigh() { - //排序的数组 - $ids = $this->request->post("ids"); - //拖动的记录ID - $changeid = $this->request->post("changeid"); - //操作字段 - $field = $this->request->post("field"); - //操作的数据表 - $table = $this->request->post("table"); - if (!Validate::is($table, "alphaDash")) { - $this->error(); + if (!$this->request->isPost()) { + $this->error(__('Invalid request')); } - //主键 - $pk = $this->request->post("pk"); - //排序的方式 - $orderway = strtolower($this->request->post("orderway", "")); - $orderway = $orderway == 'asc' ? 'ASC' : 'DESC'; - $sour = $weighdata = []; - $ids = explode(',', $ids); - $prikey = $pk && preg_match("/^[a-z0-9\-_]+$/i", $pk) ? $pk : (Db::name($table)->getPk() ?: 'id'); - $pid = $this->request->post("pid", ""); - //限制更新的字段 - $field = in_array($field, ['weigh']) ? $field : 'weigh'; - - // 如果设定了pid的值,此时只匹配满足条件的ID,其它忽略 - if ($pid !== '') { - $hasids = []; - $list = Db::name($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pid)->field("{$prikey},pid")->select(); - foreach ($list as $k => $v) { - $hasids[] = $v[$prikey]; - } - $ids = array_values(array_intersect($ids, $hasids)); + $controllername = $this->request->post('controllername'); + if (!$controllername || !preg_match("/^[a-z0-9_\.]+$/i", $controllername)) { + $this->error(__('Invalid parameters')); + } + if (!$this->auth->check(str_replace('.', '/', $controllername) . '/dragsort')) { + $this->error(__('You have no permission')); } - $list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select(); - foreach ($list as $k => $v) { - $sour[] = $v[$prikey]; - $weighdata[$v[$prikey]] = $v[$field]; + $className = Loader::parseClass($this->request->module(), 'controller', $controllername, false); + + if (!class_exists($className)) { + $this->error(__('Invalid parameters')); } - $position = array_search($changeid, $ids); - $desc_id = $sour[$position] ?? end($sour); //移动到目标的ID值,取出所处改变前位置的值 - $sour_id = $changeid; - $weighids = []; - $temp = array_values(array_diff_assoc($ids, $sour)); - foreach ($temp as $m => $n) { - if ($n == $sour_id) { - $offset = $desc_id; - } else { - if ($sour_id == $temp[0]) { - $offset = $temp[$m + 1] ?? $sour_id; - } else { - $offset = $temp[$m - 1] ?? $sour_id; - } - } - if (!isset($weighdata[$offset])) { - continue; - } - $weighids[$n] = $weighdata[$offset]; - Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]); - } - $this->success(); + + // 重设action方法中获取控制器名称 + $this->request->controller($controllername); + return action('admin/' . $controllername . '/dragsort'); } /** @@ -213,21 +172,21 @@ class Ajax extends Backend if ($type == 'content') { break; } - // no break + // no break case 'template': // 模板缓存 rmdirs(TEMP_PATH, false); if ($type == 'template') { break; } - // no break + // no break case 'addons': // 插件缓存 Service::refresh(); if ($type == 'addons') { break; } - // no break + // no break case 'browser': // 浏览器缓存 // 只有生产环境下才修改 @@ -288,8 +247,8 @@ class Ajax extends Backend { $params = $this->request->get("row/a"); if (!empty($params)) { - $province = isset($params['province']) ? $params['province'] : null; - $city = isset($params['city']) ? $params['city'] : null; + $province = $params['province'] ?? null; + $city = $params['city'] ?? null; } else { $province = $this->request->get('province'); $city = $this->request->get('city'); diff --git a/application/admin/controller/auth/Rule.php b/application/admin/controller/auth/Rule.php index 27d98737..fc706fa7 100644 --- a/application/admin/controller/auth/Rule.php +++ b/application/admin/controller/auth/Rule.php @@ -6,6 +6,8 @@ use app\admin\model\AuthRule; use app\common\controller\Backend; use fast\Tree; use think\Cache; +use think\db\Query; +use think\exception\HttpResponseException; /** * 规则管理 @@ -31,7 +33,7 @@ class Rule extends Backend } $this->model = model('AuthRule'); // 必须将结果集转换为数组 - $ruleList = \think\Db::name("auth_rule")->field('type,condition,remark,createtime,updatetime', true)->order('weigh DESC,id ASC')->select(); + $ruleList = \think\Db::name("auth_rule")->field('type,condition,remark,menutype,extend,pinyin,py,createtime,updatetime', true)->order('weigh DESC,id ASC')->select(); foreach ($ruleList as $k => &$v) { $v['title'] = __($v['title']); } @@ -154,4 +156,18 @@ class Rule extends Backend } $this->error(); } + + /** + * 排序 + */ + public function dragsort() + { + + // 注册Hook + \think\Hook::add('admin_dragsort_after', function ($model) { + Cache::rm('__menu__'); + }); + + parent::dragsort(); + } } diff --git a/application/admin/library/traits/Backend.php b/application/admin/library/traits/Backend.php index df96bb36..c8f0119e 100755 --- a/application/admin/library/traits/Backend.php +++ b/application/admin/library/traits/Backend.php @@ -15,7 +15,9 @@ use think\db\exception\ModelNotFoundException; use think\exception\DbException; use think\exception\PDOException; use think\exception\ValidateException; +use think\Hook; use think\response\Json; +use think\Validate; trait Backend { @@ -32,7 +34,7 @@ trait Backend unset($params[$field]); } } - } else if (array_key_exists($this->excludeFields, $params)) { + } elseif (array_key_exists($this->excludeFields, $params)) { unset($params[$this->excludeFields]); } return $params; @@ -341,6 +343,128 @@ trait Backend $this->error(__('No rows were updated')); } + /** + * 排序 + * + * @return void + */ + public function dragsort() + { + $idsString = $this->request->post("ids"); + $changeid = $this->request->post("changeid"); + $field = $this->request->post("field", "weigh"); + $pk = $this->request->post("pk"); + $pid = $this->request->post("pid", ""); + $orderway = $this->request->post("orderway", "desc"); + + // 检测参数是否有效 + if (empty($idsString) || empty($changeid)) { + $this->error(__('Invalid parameters')); + } + + // 验证排序方式 + $orderway = strtolower($orderway); + if (!in_array($orderway, ['asc', 'desc'])) { + $orderway = 'desc'; + } + + // 获取模型表名 + $table = $this->model->getTable(); + + $ids = explode(',', $idsString); + + // 验证changeid是否在ids中 + if (!in_array($changeid, $ids)) { + $this->error(__('Invalid parameters')); + } + + // 允许的排序字段白名单 + $allowedFields = explode(',', $this->dragsortFields); + $field = in_array($field, $allowedFields) ? $field : ''; + + if (!$field) { + $this->error(__('You have no permission')); + } + + // 获取主键 + $prikey = $this->model->getPk(); + + // 开始事务 + Db::startTrans(); + + try { + // 处理pid筛选 + if ($pid !== '') { + $pidValues = explode(',', $pid); // 支持多个pid值 + $validRecords = Db::table($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pidValues)->column($prikey); + + // 只保留有效的ID + $ids = array_values(array_intersect($ids, $validRecords)); + + if (empty($ids)) { + Db::rollback(); + exception(__('No rows were updated')); + } + } + + // 获取当前记录的权重值 + $currentWeights = Db::table($table)->where($prikey, 'in', $ids)->column($field, $prikey); + + // 直接从$currentWeights获取最大和最小权重值 + $minWeight = !empty($currentWeights) ? min($currentWeights) : 1; + $maxWeight = !empty($currentWeights) ? max($currentWeights) : count($ids); + + // 计算权重步长 + $step = 1; + + // 准备批量更新数据 - 直接根据新顺序分配权重 + $updateData = []; + + // 根据排序方式设置初始权重和步长方向 + if ($orderway == 'asc') { + // 升序:从小到大排列 + $newWeight = $minWeight; + $step = abs($step); + } else { + // 降序:从大到小排列 + $newWeight = $maxWeight; + $step = -abs($step); + } + + // 根据新的顺序分配权重值 + foreach ($ids as $index => $id) { + // 计算该记录应有的新权重值 + $expectedWeight = $newWeight; + $newWeight += $step; + + // 如果当前权重与期望权重不同,才需要更新 + if (!isset($currentWeights[$id]) || $currentWeights[$id] != $expectedWeight) { + $updateData[] = [$prikey => $id, $field => $expectedWeight]; + } + } + + // 批量更新 + if (!empty($updateData)) { + + foreach ($updateData as $data) { + Db::table($table)->where($prikey, $data[$prikey])->update([$field => $data[$field]]); + } + } + + // 提交事务 + Db::commit(); + + } catch (\Exception $e) { + // 发生异常时回滚事务 + Db::rollback(); + $this->error(); + } + + Hook::listen("admin_dragsort_after", $this->model); + + $this->success(); + } + /** * 导入 * @@ -391,7 +515,7 @@ trait Backend } //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name - $importHeadType = isset($this->importHeadType) ? $this->importHeadType : 'comment'; + $importHeadType = $this->importHeadType ?? 'comment'; $table = $this->model->getQuery()->getTable(); $database = \think\Config::get('database.database'); diff --git a/application/admin/view/auth/rule/index.html b/application/admin/view/auth/rule/index.html index be73a563..3d6b04e7 100644 --- a/application/admin/view/auth/rule/index.html +++ b/application/admin/view/auth/rule/index.html @@ -25,6 +25,7 @@
diff --git a/application/admin/view/category/index.html b/application/admin/view/category/index.html index 085bb020..9f934cb4 100644 --- a/application/admin/view/category/index.html +++ b/application/admin/view/category/index.html @@ -26,6 +26,7 @@
diff --git a/application/admin/view/user/rule/index.html b/application/admin/view/user/rule/index.html index ff57bad2..7ee5d3b6 100644 --- a/application/admin/view/user/rule/index.html +++ b/application/admin/view/user/rule/index.html @@ -19,6 +19,7 @@
diff --git a/application/index/controller/Ajax.php b/application/index/controller/Ajax.php index 3b73aa35..a97cc91b 100644 --- a/application/index/controller/Ajax.php +++ b/application/index/controller/Ajax.php @@ -38,7 +38,6 @@ class Ajax extends Frontend return jsonp(['errmsg' => '参数错误'], 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]); } - $controllername = input("controllername"); $className = Loader::parseClass($this->request->module(), 'controller', $controllername, false); //存在对应的类才加载 diff --git a/public/assets/js/backend/category.js b/public/assets/js/backend/category.js index 0299bf33..95878b39 100644 --- a/public/assets/js/backend/category.js +++ b/public/assets/js/backend/category.js @@ -10,7 +10,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin edit_url: 'category/edit', del_url: 'category/del', multi_url: 'category/multi', - dragsort_url: 'ajax/weigh', + dragsort_url: 'category/dragsort', table: 'category', } }); diff --git a/public/assets/js/require-table.js b/public/assets/js/require-table.js index 4c98aa66..ecb7aca1 100644 --- a/public/assets/js/require-table.js +++ b/public/assets/js/require-table.js @@ -335,7 +335,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table if ($(".export .exporttips").length === 0) { $(".export .dropdown-menu").prepend("
  • ") } - $(".export .exporttips").html("导出记录:" + (selectedIds.length > 0 ? "选中" : "全部")); + $(".export .exporttips").html("导出记录:" + (selectedIds.length > 0 ? "仅选中" : "全部")); } $(Table.config.disabledbtn, toolbar).toggleClass('disabled', !options.selectedIds.length); @@ -503,8 +503,9 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table pid: pid, field: Table.config.dragsortfield, orderway: options.sortOrder, - table: options.extend.table, - pk: options.pk + table: options.extend.table || '', + pk: options.pk, + controllername: Config.controllername || '' } }; Fast.api.ajax(params, function (data, ret) {