mirror of
https://gitee.com/wonderful-code/buildadmin
synced 2024-11-21 22:55:36 +00:00
feat:表格拖拽排序api
This commit is contained in:
parent
66f81332b3
commit
6f201d8e43
@ -1,17 +1,18 @@
|
||||
<?php
|
||||
return [
|
||||
'Username' => 'User Name',
|
||||
'Password' => 'Password',
|
||||
'Captcha' => 'Captcha',
|
||||
'CaptchaId' => 'Captcha Id',
|
||||
'Please enter the correct verification code' => 'Please enter the correct verification code!',
|
||||
'Parameter %s can not be empty' => 'Parameter %s can not be empty',
|
||||
'Record not found' => 'Record not found',
|
||||
'No rows were added' => 'No rows were added',
|
||||
'No rows were deleted' => 'No rows were deleted',
|
||||
'No rows updated' => 'No rows updated',
|
||||
'Update successful' => 'Update successful!',
|
||||
'Added successfully' => 'Added successfully!',
|
||||
'Deleted successfully' => 'Deleted successfully!',
|
||||
'Parameter error' => 'Parameter error!',
|
||||
'Username' => 'User Name',
|
||||
'Password' => 'Password',
|
||||
'Captcha' => 'Captcha',
|
||||
'CaptchaId' => 'Captcha Id',
|
||||
'Please enter the correct verification code' => 'Please enter the correct verification code!',
|
||||
'Parameter %s can not be empty' => 'Parameter %s can not be empty',
|
||||
'Record not found' => 'Record not found',
|
||||
'No rows were added' => 'No rows were added',
|
||||
'No rows were deleted' => 'No rows were deleted',
|
||||
'No rows updated' => 'No rows updated',
|
||||
'Update successful' => 'Update successful!',
|
||||
'Added successfully' => 'Added successfully!',
|
||||
'Deleted successfully' => 'Deleted successfully!',
|
||||
'Parameter error' => 'Parameter error!',
|
||||
'Invalid collation because the weights of the two targets are equal' => 'Invalid collation because the weights of the two targets are equal',
|
||||
];
|
@ -1,17 +1,18 @@
|
||||
<?php
|
||||
return [
|
||||
'Username' => '用户名',
|
||||
'Password' => '密码',
|
||||
'Captcha' => '验证码',
|
||||
'CaptchaId' => '验证码ID',
|
||||
'Please enter the correct verification code' => '请输入正确的验证码!',
|
||||
'Parameter %s can not be empty' => '参数%s不能为空',
|
||||
'Record not found' => '记录未找到',
|
||||
'No rows were added' => '未添加任何行',
|
||||
'No rows were deleted' => '未删除任何行',
|
||||
'No rows updated' => '未更新任何行',
|
||||
'Update successful' => '更新成功!',
|
||||
'Added successfully' => '添加成功!',
|
||||
'Deleted successfully' => '删除成功!',
|
||||
'Parameter error' => '参数错误!',
|
||||
'Username' => '用户名',
|
||||
'Password' => '密码',
|
||||
'Captcha' => '验证码',
|
||||
'CaptchaId' => '验证码ID',
|
||||
'Please enter the correct verification code' => '请输入正确的验证码!',
|
||||
'Parameter %s can not be empty' => '参数%s不能为空',
|
||||
'Record not found' => '记录未找到',
|
||||
'No rows were added' => '未添加任何行',
|
||||
'No rows were deleted' => '未删除任何行',
|
||||
'No rows updated' => '未更新任何行',
|
||||
'Update successful' => '更新成功!',
|
||||
'Added successfully' => '添加成功!',
|
||||
'Deleted successfully' => '删除成功!',
|
||||
'Parameter error' => '参数错误!',
|
||||
'Invalid collation because the weights of the two targets are equal' => '无效排序整理,因为两个目标权重是相等的',
|
||||
];
|
@ -3,6 +3,7 @@
|
||||
namespace app\admin\library\traits;
|
||||
|
||||
use Exception;
|
||||
use think\facade\Config;
|
||||
use think\facade\Db;
|
||||
use think\db\exception\PDOException;
|
||||
use think\exception\ValidateException;
|
||||
@ -12,7 +13,7 @@ trait Backend
|
||||
protected function excludeFields($params)
|
||||
{
|
||||
if (!is_array($this->preExcludeFields)) {
|
||||
$this->preExcludeFields = explode(',', $this->preExcludeFields);
|
||||
$this->preExcludeFields = explode(',', (string)$this->preExcludeFields);
|
||||
}
|
||||
|
||||
foreach ($this->preExcludeFields as $field) {
|
||||
@ -132,4 +133,39 @@ trait Backend
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
}
|
||||
|
||||
public function sortable($id, $targetId)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
$target = $this->model->find($targetId);
|
||||
|
||||
if (!$row || !$target) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
if ($row[$this->weighField] == $target[$this->weighField]) {
|
||||
$autoSortEqWeight = is_null($this->autoSortEqWeight) ? Config::get('buildadmin.auto_sort_eq_weight') : $this->autoSortEqWeight;
|
||||
if (!$autoSortEqWeight) {
|
||||
$this->error(__('Invalid collation because the weights of the two targets are equal'));
|
||||
}
|
||||
|
||||
// 自动重新整理排序
|
||||
$all = $this->model->select();
|
||||
foreach ($all as $item) {
|
||||
$item[$this->weighField] = $item[$this->model->getPk()];
|
||||
$item->save();
|
||||
}
|
||||
unset($all);
|
||||
// 重新获取
|
||||
$row = $this->model->find($id);
|
||||
$target = $this->model->find($targetId);
|
||||
}
|
||||
|
||||
$ebak = $target[$this->weighField];
|
||||
$target[$this->weighField] = $row[$this->weighField];
|
||||
$row[$this->weighField] = $ebak;
|
||||
$row->save();
|
||||
$target->save();
|
||||
|
||||
$this->success('');
|
||||
}
|
||||
}
|
@ -19,6 +19,18 @@ class Backend extends Api
|
||||
|
||||
protected $model = null;
|
||||
|
||||
/**
|
||||
* 权重(排序)字段
|
||||
*/
|
||||
protected $weighField = 'weigh';
|
||||
|
||||
/**
|
||||
* 表格拖拽排序时,两个权重相等则自动重新整理
|
||||
* config/buildadmin.php文件中的auto_sort_eq_weight为默认值
|
||||
* null=取默认值,false=关,true=开
|
||||
*/
|
||||
protected $autoSortEqWeight = null;
|
||||
|
||||
/**
|
||||
* 快速搜索字段
|
||||
*/
|
||||
|
@ -9,6 +9,8 @@ return [
|
||||
'admin_login_captcha' => true,
|
||||
// 管理员登录失败可重试次数,false则无限
|
||||
'admin_login_retry' => 10,
|
||||
// 表格拖拽排序时,两个权重相等则自动重新整理;控制器类中也有此项(作为单控制器自定义配置)
|
||||
'auto_sort_eq_weight' => false,
|
||||
// 允许执行的命令
|
||||
'allowed_commands' => [
|
||||
'ping-baidu' => 'ping baidu.com',
|
||||
|
@ -5,6 +5,7 @@ export const actionUrl = new Map([
|
||||
['add', controllerUrl + 'add'],
|
||||
['edit', controllerUrl + 'edit'],
|
||||
['del', controllerUrl + 'del'],
|
||||
['sortable', controllerUrl + 'sortable'],
|
||||
])
|
||||
|
||||
export function index(loading: boolean, keyword: string = '') {
|
||||
@ -58,3 +59,19 @@ export function postData(action: string, data: anyObj) {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export function sortableApi(id: number, targetId: number) {
|
||||
return createAxios(
|
||||
{
|
||||
url: actionUrl.get('sortable'),
|
||||
method: 'post',
|
||||
data: {
|
||||
id: id,
|
||||
targetId: targetId,
|
||||
},
|
||||
},
|
||||
{
|
||||
showSuccessMessage: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="table-header">
|
||||
<el-tooltip v-if="props.buttons.includes('refresh')" content="刷新" placement="top">
|
||||
<el-button v-blur @click="onAction('refresh')" color="#40485b" class="table-header-operate" type="info">
|
||||
<el-button v-blur @click="onAction('refresh', { loading: true })" color="#40485b" class="table-header-operate" type="info">
|
||||
<Icon name="fa fa-refresh" />
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
@ -100,3 +100,27 @@ const padStart = (str: string, maxLength: number, fillString: string = ' ') => {
|
||||
}
|
||||
return fillString.slice(0, fillLength) + str
|
||||
}
|
||||
|
||||
/**
|
||||
* 将带children的数组降维,然后寻找index所在的行
|
||||
*/
|
||||
export const findIndexRow = (data: TableRow[], findIdx: number, keyIndex: number | TableRow = -1): number | TableRow => {
|
||||
for (const key in data) {
|
||||
if (typeof keyIndex == 'number') {
|
||||
keyIndex++
|
||||
}
|
||||
|
||||
if (keyIndex == findIdx) {
|
||||
return data[key]
|
||||
}
|
||||
|
||||
if (data[key].children) {
|
||||
keyIndex = findIndexRow(data[key].children!, findIdx, keyIndex)
|
||||
if (typeof keyIndex != 'number') {
|
||||
return keyIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keyIndex
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ function createAxios(axiosConfig: AxiosRequestConfig, options: Options = {}, loa
|
||||
return Promise.reject(response.data)
|
||||
} else if (options.showSuccessMessage && response.data && response.data.code == 1) {
|
||||
ElNotification({
|
||||
title: response.data.msg ? response.data.msg : '操作成功',
|
||||
message: response.data.msg ? response.data.msg : '操作成功',
|
||||
type: 'success',
|
||||
})
|
||||
}
|
||||
|
@ -124,8 +124,8 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, onUnmounted, onMounted } from 'vue'
|
||||
import { actionUrl, index, edit, del, postData } from '/@/api/backend/auth/Menu'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import { actionUrl, index, edit, del, postData, sortableApi } from '/@/api/backend/auth/Menu'
|
||||
import { defaultOptButtons, findIndexRow } from '/@/components/table'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import IconSelector from '/@/components/icon/selector.vue'
|
||||
@ -134,6 +134,7 @@ import useCurrentInstance from '/@/utils/useCurrentInstance'
|
||||
import Sortable from 'sortablejs'
|
||||
import { getArrayKey } from '/@/utils/common'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElNotification } from 'element-plus'
|
||||
|
||||
const { t } = useI18n()
|
||||
const { proxy } = useCurrentInstance()
|
||||
@ -153,6 +154,8 @@ const table: {
|
||||
dblClickNotEditColumn: (string | undefined)[]
|
||||
// 列数据
|
||||
column: TableColumn[]
|
||||
// 拖动排序限位字段:例如拖动行pid=1,那么拖动目的行pid也需要为1
|
||||
dragSortLimitField: string
|
||||
} = reactive({
|
||||
pk: 'id',
|
||||
data: [],
|
||||
@ -182,6 +185,7 @@ const table: {
|
||||
buttons: defaultOptButtons(),
|
||||
},
|
||||
],
|
||||
dragSortLimitField: 'pid',
|
||||
})
|
||||
/* 表格状态-e */
|
||||
|
||||
@ -314,7 +318,8 @@ const onAction = (type: string, data: anyObj) => {
|
||||
[
|
||||
'refresh',
|
||||
() => {
|
||||
getIndex(true)
|
||||
table.data = []
|
||||
getIndex(data.loading ? true : false)
|
||||
},
|
||||
],
|
||||
[
|
||||
@ -379,7 +384,21 @@ const dragSort = () => {
|
||||
for (const key in table.column[buttonsKey].buttons) {
|
||||
table.column[buttonsKey].buttons![key as any].disabledTip = false
|
||||
}
|
||||
console.log(evt)
|
||||
// 找到对应行id
|
||||
let moveRow = findIndexRow(table.data, evt.oldIndex!) as TableRow
|
||||
let replaceRow = findIndexRow(table.data, evt.newIndex!) as TableRow
|
||||
if (moveRow[table.dragSortLimitField] != replaceRow[table.dragSortLimitField]) {
|
||||
onAction('refresh', {})
|
||||
ElNotification({
|
||||
type: 'error',
|
||||
message: '移动位置超出了可移动范围!',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
sortableApi(moveRow.id, replaceRow.id).then((res) => {
|
||||
onAction('refresh', {})
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user