mirror of https://gitee.com/karson/fastadmin.git
优化后台拖拽排序逻辑
parent
fad64c36f0
commit
e2901f3b5e
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
<table id="table" class="table table-bordered table-hover"
|
||||
data-operate-edit="{:$auth->check('auth/rule/edit')}"
|
||||
data-operate-del="{:$auth->check('auth/rule/del')}"
|
||||
data-operate-dragsort="{:$auth->check('auth/rule/dragsort')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('category/edit')}"
|
||||
data-operate-del="{:$auth->check('category/del')}"
|
||||
data-operate-dragsort="{:$auth->check('category/dragsort')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('user/rule/edit')}"
|
||||
data-operate-del="{:$auth->check('user/rule/del')}"
|
||||
data-operate-dragsort="{:$auth->check('user/rule/dragsort')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
//存在对应的类才加载
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
if ($(".export .exporttips").length === 0) {
|
||||
$(".export .dropdown-menu").prepend("<li class='exporttips alert alert-warning-light mb-0 no-border p-2'></li>")
|
||||
}
|
||||
$(".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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue