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');
|
$controllername = $this->request->get('controllername');
|
||||||
$lang = $this->request->get('lang');
|
$lang = $this->request->get('lang');
|
||||||
if (!$lang || !in_array($lang, config('allow_lang_list')) || !$controllername || !preg_match("/^[a-z0-9_\.]+$/i", $controllername)) {
|
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);
|
$className = Loader::parseClass($this->request->module(), 'controller', $controllername, false);
|
||||||
|
|
||||||
//存在对应的类才加载
|
//存在对应的类才加载
|
||||||
|
|
@ -135,66 +134,26 @@ class Ajax extends Backend
|
||||||
*/
|
*/
|
||||||
public function weigh()
|
public function weigh()
|
||||||
{
|
{
|
||||||
//排序的数组
|
if (!$this->request->isPost()) {
|
||||||
$ids = $this->request->post("ids");
|
$this->error(__('Invalid request'));
|
||||||
//拖动的记录ID
|
|
||||||
$changeid = $this->request->post("changeid");
|
|
||||||
//操作字段
|
|
||||||
$field = $this->request->post("field");
|
|
||||||
//操作的数据表
|
|
||||||
$table = $this->request->post("table");
|
|
||||||
if (!Validate::is($table, "alphaDash")) {
|
|
||||||
$this->error();
|
|
||||||
}
|
}
|
||||||
//主键
|
$controllername = $this->request->post('controllername');
|
||||||
$pk = $this->request->post("pk");
|
if (!$controllername || !preg_match("/^[a-z0-9_\.]+$/i", $controllername)) {
|
||||||
//排序的方式
|
$this->error(__('Invalid parameters'));
|
||||||
$orderway = strtolower($this->request->post("orderway", ""));
|
}
|
||||||
$orderway = $orderway == 'asc' ? 'ASC' : 'DESC';
|
if (!$this->auth->check(str_replace('.', '/', $controllername) . '/dragsort')) {
|
||||||
$sour = $weighdata = [];
|
$this->error(__('You have no permission'));
|
||||||
$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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select();
|
$className = Loader::parseClass($this->request->module(), 'controller', $controllername, false);
|
||||||
foreach ($list as $k => $v) {
|
|
||||||
$sour[] = $v[$prikey];
|
if (!class_exists($className)) {
|
||||||
$weighdata[$v[$prikey]] = $v[$field];
|
$this->error(__('Invalid parameters'));
|
||||||
}
|
}
|
||||||
$position = array_search($changeid, $ids);
|
|
||||||
$desc_id = $sour[$position] ?? end($sour); //移动到目标的ID值,取出所处改变前位置的值
|
// 重设action方法中获取控制器名称
|
||||||
$sour_id = $changeid;
|
$this->request->controller($controllername);
|
||||||
$weighids = [];
|
return action('admin/' . $controllername . '/dragsort');
|
||||||
$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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -213,21 +172,21 @@ class Ajax extends Backend
|
||||||
if ($type == 'content') {
|
if ($type == 'content') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// no break
|
// no break
|
||||||
case 'template':
|
case 'template':
|
||||||
// 模板缓存
|
// 模板缓存
|
||||||
rmdirs(TEMP_PATH, false);
|
rmdirs(TEMP_PATH, false);
|
||||||
if ($type == 'template') {
|
if ($type == 'template') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// no break
|
// no break
|
||||||
case 'addons':
|
case 'addons':
|
||||||
// 插件缓存
|
// 插件缓存
|
||||||
Service::refresh();
|
Service::refresh();
|
||||||
if ($type == 'addons') {
|
if ($type == 'addons') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// no break
|
// no break
|
||||||
case 'browser':
|
case 'browser':
|
||||||
// 浏览器缓存
|
// 浏览器缓存
|
||||||
// 只有生产环境下才修改
|
// 只有生产环境下才修改
|
||||||
|
|
@ -288,8 +247,8 @@ class Ajax extends Backend
|
||||||
{
|
{
|
||||||
$params = $this->request->get("row/a");
|
$params = $this->request->get("row/a");
|
||||||
if (!empty($params)) {
|
if (!empty($params)) {
|
||||||
$province = isset($params['province']) ? $params['province'] : null;
|
$province = $params['province'] ?? null;
|
||||||
$city = isset($params['city']) ? $params['city'] : null;
|
$city = $params['city'] ?? null;
|
||||||
} else {
|
} else {
|
||||||
$province = $this->request->get('province');
|
$province = $this->request->get('province');
|
||||||
$city = $this->request->get('city');
|
$city = $this->request->get('city');
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ use app\admin\model\AuthRule;
|
||||||
use app\common\controller\Backend;
|
use app\common\controller\Backend;
|
||||||
use fast\Tree;
|
use fast\Tree;
|
||||||
use think\Cache;
|
use think\Cache;
|
||||||
|
use think\db\Query;
|
||||||
|
use think\exception\HttpResponseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则管理
|
* 规则管理
|
||||||
|
|
@ -31,7 +33,7 @@ class Rule extends Backend
|
||||||
}
|
}
|
||||||
$this->model = model('AuthRule');
|
$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) {
|
foreach ($ruleList as $k => &$v) {
|
||||||
$v['title'] = __($v['title']);
|
$v['title'] = __($v['title']);
|
||||||
}
|
}
|
||||||
|
|
@ -154,4 +156,18 @@ class Rule extends Backend
|
||||||
}
|
}
|
||||||
$this->error();
|
$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\DbException;
|
||||||
use think\exception\PDOException;
|
use think\exception\PDOException;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
|
use think\Hook;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
trait Backend
|
trait Backend
|
||||||
{
|
{
|
||||||
|
|
@ -32,7 +34,7 @@ trait Backend
|
||||||
unset($params[$field]);
|
unset($params[$field]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (array_key_exists($this->excludeFields, $params)) {
|
} elseif (array_key_exists($this->excludeFields, $params)) {
|
||||||
unset($params[$this->excludeFields]);
|
unset($params[$this->excludeFields]);
|
||||||
}
|
}
|
||||||
return $params;
|
return $params;
|
||||||
|
|
@ -341,6 +343,128 @@ trait Backend
|
||||||
$this->error(__('No rows were updated'));
|
$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
|
//导入文件首行类型,默认是注释,如果需要使用字段名称请使用name
|
||||||
$importHeadType = isset($this->importHeadType) ? $this->importHeadType : 'comment';
|
$importHeadType = $this->importHeadType ?? 'comment';
|
||||||
|
|
||||||
$table = $this->model->getQuery()->getTable();
|
$table = $this->model->getQuery()->getTable();
|
||||||
$database = \think\Config::get('database.database');
|
$database = \think\Config::get('database.database');
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
<table id="table" class="table table-bordered table-hover"
|
<table id="table" class="table table-bordered table-hover"
|
||||||
data-operate-edit="{:$auth->check('auth/rule/edit')}"
|
data-operate-edit="{:$auth->check('auth/rule/edit')}"
|
||||||
data-operate-del="{:$auth->check('auth/rule/del')}"
|
data-operate-del="{:$auth->check('auth/rule/del')}"
|
||||||
|
data-operate-dragsort="{:$auth->check('auth/rule/dragsort')}"
|
||||||
width="100%">
|
width="100%">
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||||
data-operate-edit="{:$auth->check('category/edit')}"
|
data-operate-edit="{:$auth->check('category/edit')}"
|
||||||
data-operate-del="{:$auth->check('category/del')}"
|
data-operate-del="{:$auth->check('category/del')}"
|
||||||
|
data-operate-dragsort="{:$auth->check('category/dragsort')}"
|
||||||
width="100%">
|
width="100%">
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||||
data-operate-edit="{:$auth->check('user/rule/edit')}"
|
data-operate-edit="{:$auth->check('user/rule/edit')}"
|
||||||
data-operate-del="{:$auth->check('user/rule/del')}"
|
data-operate-del="{:$auth->check('user/rule/del')}"
|
||||||
|
data-operate-dragsort="{:$auth->check('user/rule/dragsort')}"
|
||||||
width="100%">
|
width="100%">
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ class Ajax extends Frontend
|
||||||
return jsonp(['errmsg' => '参数错误'], 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);
|
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);
|
$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',
|
edit_url: 'category/edit',
|
||||||
del_url: 'category/del',
|
del_url: 'category/del',
|
||||||
multi_url: 'category/multi',
|
multi_url: 'category/multi',
|
||||||
dragsort_url: 'ajax/weigh',
|
dragsort_url: 'category/dragsort',
|
||||||
table: 'category',
|
table: 'category',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
if ($(".export .exporttips").length === 0) {
|
if ($(".export .exporttips").length === 0) {
|
||||||
$(".export .dropdown-menu").prepend("<li class='exporttips alert alert-warning-light mb-0 no-border p-2'></li>")
|
$(".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);
|
$(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,
|
pid: pid,
|
||||||
field: Table.config.dragsortfield,
|
field: Table.config.dragsortfield,
|
||||||
orderway: options.sortOrder,
|
orderway: options.sortOrder,
|
||||||
table: options.extend.table,
|
table: options.extend.table || '',
|
||||||
pk: options.pk
|
pk: options.pk,
|
||||||
|
controllername: Config.controllername || ''
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Fast.api.ajax(params, function (data, ret) {
|
Fast.api.ajax(params, function (data, ret) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue