feat(console): 媒体拖拽改槽位制——预设落位+边界死区(±12%行高)防乱跳,仅决定性越过才提交一次、其他行FLIP让位(260ms缓出)
This commit is contained in:
@@ -18087,6 +18087,7 @@ function ConsolePane() {
|
||||
};
|
||||
const dragRowRef = (0, import_react.useRef)(null);
|
||||
const dragFlipRef = (0, import_react.useRef)(null);
|
||||
const lastTargetRef = (0, import_react.useRef)(-1);
|
||||
const [dragRowId, setDragRowId] = (0, import_react.useState)(null);
|
||||
(0, import_react.useLayoutEffect)(() => {
|
||||
const first = dragFlipRef.current;
|
||||
@@ -18099,7 +18100,7 @@ function ConsolePane() {
|
||||
const r = el.getBoundingClientRect();
|
||||
const dx = f.x - r.left;
|
||||
const dy = f.y - r.top;
|
||||
if (dx || dy) el.animate([{ transform: "translate(" + dx + "px," + dy + "px)" }, { transform: "none" }], { duration: 160, easing: "cubic-bezier(.22,.61,.36,1)" });
|
||||
if (dx || dy) el.animate([{ transform: "translate(" + dx + "px," + dy + "px)" }, { transform: "none" }], { duration: 260, easing: "cubic-bezier(.25,.6,.3,1)" });
|
||||
});
|
||||
}, [photoList]);
|
||||
const onHandleDown = (id, e) => {
|
||||
@@ -18107,29 +18108,34 @@ function ConsolePane() {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dragRowRef.current = id;
|
||||
lastTargetRef.current = photoList.findIndex((x) => x.id === id);
|
||||
setDragRowId(id);
|
||||
const onMove = (ev) => {
|
||||
if (dragRowRef.current !== id) return;
|
||||
const rows = Array.from(document.querySelectorAll(".dsh-wt_photoRow"));
|
||||
if (rows.length === 0) return;
|
||||
const first = rows[0].getBoundingClientRect();
|
||||
const h = first.height;
|
||||
const rel = (ev.clientY - first.top) / h;
|
||||
let t = Math.max(0, Math.min(rows.length - 1, Math.floor(rel + 0.5)));
|
||||
const frac = rel - Math.floor(rel);
|
||||
if (Math.abs(frac - 0.5) < 0.12) t = lastTargetRef.current;
|
||||
if (t === lastTargetRef.current) return;
|
||||
const from = photoList.findIndex((x) => x.id === id);
|
||||
if (from < 0) return;
|
||||
const rects = /* @__PURE__ */ new Map();
|
||||
rows.forEach((el) => {
|
||||
const k = el.dataset.rid ?? "";
|
||||
const r = el.getBoundingClientRect();
|
||||
rects.set(k, { x: r.left, y: r.top });
|
||||
});
|
||||
let target = 0;
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const r = rows[i].getBoundingClientRect();
|
||||
if (ev.clientY > r.top + r.height / 2) target = i + 1;
|
||||
}
|
||||
const from = photoList.findIndex((x) => x.id === id);
|
||||
if (from < 0) return;
|
||||
const next = [...photoList];
|
||||
const moved = next.splice(from, 1)[0];
|
||||
const to = Math.max(0, Math.min(target > from ? target - 1 : target, next.length));
|
||||
const to = Math.max(0, Math.min(t, next.length));
|
||||
next.splice(to, 0, moved);
|
||||
dragFlipRef.current = rects;
|
||||
setPhotoList(next);
|
||||
lastTargetRef.current = t;
|
||||
};
|
||||
const onUp = () => {
|
||||
dragRowRef.current = null;
|
||||
|
||||
@@ -1575,8 +1575,9 @@ function ConsolePane() {
|
||||
/** 抓手拖拽排序:按住抓手上下移动 → 行实时重排,松手持久化 */
|
||||
const dragRowRef = useRef<string | null>(null)
|
||||
const dragFlipRef = useRef<Map<string, { x: number; y: number }> | null>(null)
|
||||
const lastTargetRef = useRef<number>(-1)
|
||||
const [dragRowId, setDragRowId] = useState<string | null>(null)
|
||||
// FLIP:重排后旧位置 → 新位置的平滑滑动(160ms 缓动)
|
||||
// FLIP:落位提交后,其他行从旧位置平滑让位(260ms 缓出)
|
||||
useLayoutEffect(() => {
|
||||
const first = dragFlipRef.current
|
||||
if (!first) return
|
||||
@@ -1588,7 +1589,7 @@ function ConsolePane() {
|
||||
const r = el.getBoundingClientRect()
|
||||
const dx = f.x - r.left
|
||||
const dy = f.y - r.top
|
||||
if (dx || dy) el.animate([{ transform: 'translate(' + dx + 'px,' + dy + 'px)' }, { transform: 'none' }], { duration: 160, easing: 'cubic-bezier(.22,.61,.36,1)' })
|
||||
if (dx || dy) el.animate([{ transform: 'translate(' + dx + 'px,' + dy + 'px)' }, { transform: 'none' }], { duration: 260, easing: 'cubic-bezier(.25,.6,.3,1)' })
|
||||
})
|
||||
}, [photoList])
|
||||
const onHandleDown = (id: string, e: { button: number; preventDefault: () => void; stopPropagation: () => void }) => {
|
||||
@@ -1596,26 +1597,31 @@ function ConsolePane() {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
dragRowRef.current = id
|
||||
lastTargetRef.current = photoList.findIndex((x) => x.id === id)
|
||||
setDragRowId(id)
|
||||
const onMove = (ev: PointerEvent) => {
|
||||
if (dragRowRef.current !== id) return
|
||||
const rows = Array.from(document.querySelectorAll<HTMLElement>('.dsh-wt_photoRow'))
|
||||
// 收集当前(重排前)位置用于 FLIP
|
||||
const rects = new Map<string, { x: number; y: number }>()
|
||||
rows.forEach((el) => { const k = el.dataset.rid ?? ''; const r = el.getBoundingClientRect(); rects.set(k, { x: r.left, y: r.top }) })
|
||||
let target = 0
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const r = rows[i].getBoundingClientRect()
|
||||
if (ev.clientY > r.top + r.height / 2) target = i + 1
|
||||
}
|
||||
if (rows.length === 0) return
|
||||
// 槽位制:按固定行高算最近槽位;边界 ±0.12 行高为死区,未决定性越过前不切换
|
||||
const first = rows[0].getBoundingClientRect()
|
||||
const h = first.height
|
||||
const rel = (ev.clientY - first.top) / h
|
||||
let t = Math.max(0, Math.min(rows.length - 1, Math.floor(rel + 0.5)))
|
||||
const frac = rel - Math.floor(rel)
|
||||
if (Math.abs(frac - 0.5) < 0.12) t = lastTargetRef.current
|
||||
if (t === lastTargetRef.current) return
|
||||
const from = photoList.findIndex((x) => x.id === id)
|
||||
if (from < 0) return
|
||||
const rects = new Map<string, { x: number; y: number }>()
|
||||
rows.forEach((el) => { const k = el.dataset.rid ?? ''; const r = el.getBoundingClientRect(); rects.set(k, { x: r.left, y: r.top }) })
|
||||
const next = [...photoList]
|
||||
const moved = next.splice(from, 1)[0]
|
||||
const to = Math.max(0, Math.min(target > from ? target - 1 : target, next.length))
|
||||
const to = Math.max(0, Math.min(t, next.length))
|
||||
next.splice(to, 0, moved)
|
||||
dragFlipRef.current = rects
|
||||
setPhotoList(next)
|
||||
lastTargetRef.current = t
|
||||
}
|
||||
const onUp = () => {
|
||||
dragRowRef.current = null
|
||||
|
||||
Reference in New Issue
Block a user