fix:拖拽排序

This commit is contained in:
dzc committed 2026-01-21 11:32:07 +08:00
1 parent 4496d865a5
commit c8716084e9
8 files changed
+253 -25

No files matched your search

+11
View File
@@ -44,6 +44,17 @@ export function editGroupItem(data: any) {
})
}
/**
* 修改分组排序
*/
export function editGroupSort(data: any) {
return request({
url: '/admin/device/deviceGroup/editGroupSort',
method: 'post',
data: data
})
}
/**
* 添加设施分组子项
*/
@@ -90,7 +90,7 @@
<script setup lang="ts" name="DraggableDeviceGroupDraggable">
import { useMessage } from "/@/hooks/message"
import { getDeviceGroupTree, editGroupItem } from "/@/api/device/deviceGroup"
import { getDeviceGroupTree, editGroupItem, editGroupSort } from "/@/api/device/deviceGroup"
const emit = defineEmits(["getSelectNode"])
@@ -305,6 +305,7 @@ const nodeDragStart = (node: Node, ev: DragEvent) => {
}
// 拖拽成功完成时触发的事件
// dropType为:before、after、inner
const handleNodeDrop = async (draggingNode: any, dropNode: any, dropType: any, ev: DragEvent) => {
const checkedIds = state.checkedTreeNodes.map((item: any) => item.id)
if (checkedIds && checkedIds.length) {
@@ -312,16 +313,57 @@ const handleNodeDrop = async (draggingNode: any, dropNode: any, dropType: any, e
}
const draggingNodeSort = draggingNode.data?.sort ?? 0
const dropNodeSort = dropNode.data?.sort ?? 0
console.log("移动中的sort:", draggingNodeSort, "目标sort:", dropNodeSort, "移动类型:", dropType);
console.log("checkedTreeNodes:", state.checkedTreeNodes);
const leafSelected = (state.checkedTreeNodes || []).filter((n: any) => n && (n.deep === 2 || !n.children || (Array.isArray(n.children) && n.children.length === 0)))
if (leafSelected.length && Array.isArray(state.treeDataList)) {
const selectedSet = new Set<string>(leafSelected.map((n: any) => String(n.id)))
const result: any[] = []
const dragParentId = draggingNode?.data?.parentId
const dragId = String(draggingNode?.data?.id)
const dropId = String(dropNode?.data?.id)
const isAfter = dropType === "after" || dropType === "next"
for (const p of state.treeDataList) {
const chs = Array.isArray(p.children) ? p.children : []
let idOrder: string[] = chs.map((c: any) => String(c.id))
if (String(p.id) === String(dragParentId) && idOrder.length) {
idOrder = idOrder.filter((id) => id !== dragId)
let dropIndex = idOrder.indexOf(dropId)
if (dropIndex < 0) dropIndex = 0
const insertIndex = Math.min(Math.max(dropIndex + (isAfter ? 1 : 0), 0), idOrder.length)
idOrder.splice(insertIndex, 0, dragId)
}
for (const cid of idOrder) {
if (selectedSet.has(cid)) {
const sel = leafSelected.find((s: any) => String(s.id) === cid)
const ch = chs.find((c: any) => String(c.id) === cid)
if (sel && ch && typeof ch.sort !== "undefined") sel.sort = ch.sort
if (sel) result.push(sel)
}
}
}
state.checkedTreeNodes = result
}
console.log("drag后重排checkedTreeNodes:", state.checkedTreeNodes);
const length = state.checkedTreeNodes.length
const list = state.checkedTreeNodes.map((item: any, index: number) => {
return {
id: item.id,
name: item.name,
sort: (length - index) * 10
}
})
console.log("list:", list);
try {
await editGroupItem({
id: draggingNode.data.id,
sort: dropNodeSort + 10
await editGroupSort({
list: list
})
await getTreeData()
if (state.checkedTreeNodes && state.checkedTreeNodes.length) {
// 重写排序
state.checkedTreeNodes = state.checkedTreeNodes.filter((item: any) => item.deep == 2).sort((a: any, b: any) => b.sort - a.sort)
}
emit("getSelectNode", state.curClickedNode, state.checkedTreeNodes, state.switch, buildParentChildCheckedArray())
} catch (error) {
console.log("|拖拽成功完成时触发的事件|,意外的错误", error);
@@ -83,7 +83,7 @@ async function initVideo() {
let { records, total } = data
if (!records || !records.length) records = []
state.total = total
let suitableNum = state.num
let suitableNum = state.currentNum
if (state.total < state.numList[state.numList.length - 1]) {
suitableNum = findSuitableNum(records.length, state.numList);
state.maxCurrentNum = suitableNum
@@ -194,8 +194,14 @@ const getDeviceChannelList = async (codeStr: any) => {
]
}
console.log("replayVideoRef:", replayVideoRef);
let list = []
let deviceCode = state.code
if (_data.playbackGroupChannelCode) {
list = data.map((item: any) => item.channelCode)
deviceCode = null
}
replayVideoRef.value.init(
{ list: [], deviceCode: state.code },
{ list: list, deviceCode: deviceCode },
queryForm,
)
} catch (error: any) {
+3 -1
View File
@@ -108,7 +108,9 @@ const selectObjs = ref([]) as any
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
queryForm: {
excludeBizTypeList: ["3"]
},
pageList: deviceGroupApi.fetchList
})
@@ -37,13 +37,6 @@
</template>
</el-table-column>
</el-table-column>
<el-table-column width="120" prop="groupName" label="默认播放码流">
<template #default="{ row }">
<el-tag v-if="row.deviceChannelStreamType == 1" type="primary">主码流</el-tag>
<el-tag v-else-if="row.deviceChannelStreamType == 2" type="primary">辅码流</el-tag>
<el-tag v-else type="danger">未定义</el-tag>
</template>
</el-table-column>
<el-table-column width="80" prop="groupName" label="排序">
<template #default="{ row }">
{{ row.sort ?? 0 }}
@@ -51,10 +44,6 @@
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button icon="edit-pen" text type="primary" @click="cameraTableFormDialogRef.openDialog
(row.id)">
编辑
</el-button>
<el-button icon="delete" text type="primary" size="mini" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
@@ -81,7 +70,7 @@
</template>
</el-dialog>
<camera-table-form-dialog ref="cameraTableFormDialogRef" @refresh="getDataList" />
<!-- <camera-table-form-dialog ref="cameraTableFormDialogRef" @refresh="getDataList" /> -->
</template>
<script setup lang="ts" name="CameraTableDialog">
@@ -90,7 +79,7 @@ import { useMessage, useMessageBox } from "/@/hooks/message";
import * as deviceGroupApi from "/@/api/device/deviceGroup";
import CameraTableFormDialog from "./camera-table-form-dialog.vue"
// import CameraTableFormDialog from "./camera-table-form-dialog.vue"
// 定义变量内容
const dataFormRef = ref();
@@ -0,0 +1,132 @@
<template>
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible" :close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="120px"
v-loading="loading">
<el-row :gutter="24">
<el-col :span="24" class="mb20">
<el-form-item label="分组名称" prop="name">
<el-input :disabled="form.bizType == '1'" v-model="form.name" placeholder="请输入分组名称" />
</el-form-item>
</el-col>
<el-col v-if="false" :span="24" class="mb20">
<el-form-item label="类型" prop="bizType">
<el-input v-model="form.bizType" placeholder="请输入类型" />
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
<el-form-item label="排序" prop="sort">
<template #label>
<span>排序</span>
<tip content="越大越在前" />
</template>
<el-input-number :min="0" :step="1" v-model="form.sort" placeholder="" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="DeviceGroupDialog">
import { useDict } from '/@/hooks/dict';
import { useMessage } from "/@/hooks/message";
import * as deviceGroupApi from "/@/api/device/deviceGroup";
import { rule } from '/@/utils/validate';
const emit = defineEmits(['refresh']);
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false)
const loading = ref(false)
// 定义字典
const { panel_type } = useDict("panel_type")
// 提交表单数据
const defaultForm = {
id: '',
name: '',
bizType: '3',
panelViewCodes: [],
sort: 10,
}
const form = reactive({ ...defaultForm });
// 定义校验规则
const dataRules = ref({
name: [{ required: true, message: '分组名称不能为空', trigger: 'blur' }],
panelViewCodes: [{ required: true, message: '类型不能为空', trigger: 'change' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
})
// 打开弹窗
const openDialog = (id: string) => {
visible.value = true
form.id = ''
// 重置表单数据
dataFormRef.value?.resetFields();
Object.assign(form, defaultForm)
// 获取deviceGroup信息
if (id) {
form.id = id
getdeviceGroupData(id)
}
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => { });
if (!valid) return false;
try {
loading.value = true;
const _form: any = { ...form }
_form.bizType = '3'
if (_form.panelViewCodes && _form.panelViewCodes.length) {
_form.panelViewCodes = _form.panelViewCodes.join(',')
} else {
_form.panelViewCodes = ""
}
form.id ? await deviceGroupApi.putObj(_form) : await deviceGroupApi.addObj(_form);
useMessage().success(form.id ? '修改成功' : '添加成功');
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
// 初始化表单数据
const getdeviceGroupData = async (id: string) => {
try {
loading.value = true
const { code, data } = await deviceGroupApi.getObj(id)
if (data.panelViewCodes) {
data.panelViewCodes = data.panelViewCodes.split(',')
} else {
data.panelViewCodes = []
}
Object.assign(form, data)
} catch (error) {
console.error("|初始化表单数据|意外的错误:", error);
} finally {
loading.value = false
}
};
// 暴露变量
defineExpose({
openDialog
});
</script>
+47 -1
View File
@@ -29,6 +29,41 @@
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" border :cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle" @selection-change="selectionChangHandle"
@sort-change="sortChangeHandle">
<el-table-column type="selection" width="40" align="center" />
<el-table-column type="index" label="#" width="40" />
<el-table-column prop="name" label="分组名称" />
<el-table-column prop="bizType" label="类型">
<template #default="{ row }">
<dict-tag :options="device_group_type" :value="row.bizType" />
</template>
</el-table-column>
<el-table-column prop="sort" label="排序" />
<el-table-column label="操作" width="210">
<template #default="{ row }">
<div class="flex">
<el-button icon="VideoPlay" text type="primary"
@click="cameraTableDialogRef.openDialog(row.id)">
摄像头
</el-button>
<el-button icon="edit-pen" text type="primary" v-auth="'device_deviceGroup_edit'"
@click="formDialogRef.openDialog(row.id)">
编辑
</el-button>
<el-button v-if="row.bizType != 1" icon="delete" text type="primary"
v-auth="'device_deviceGroup_del'" @click="handleDelete([row.id])">
删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination" />
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
<camera-table-dialog ref="cameraTableDialogRef" @refresh="getDataList(false)" />
</div>
</div>
</template>
@@ -39,6 +74,9 @@ import * as deviceGroupApi from "/@/api/device/deviceGroup";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useDict } from '/@/hooks/dict';
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const CameraTableDialog = defineAsyncComponent(() => import('./camera-table-dialog.vue'));
// 定义查询字典
const { device_group_type, panel_type } = useDict("device_group_type", "panel_type")
// 定义变量内容
@@ -52,7 +90,9 @@ const selectObjs = ref([]) as any
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
queryForm: {
bizType: 3
},
pageList: deviceGroupApi.fetchList
})
@@ -66,6 +106,12 @@ const {
tableStyle
} = useTable(state)
// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
selectObjs.value = objs.map(({ id }) => id);
multiple.value = !objs.length;
};
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件