新增钉钉 Stream SDK 依赖,支持无 HTTP 上下文的后台线程显式传入 token 进行审批回调。同时,完善了 MES 审批台账功能,新增审批记录同步、批量发起审批时的门禁与台账写入逻辑,增强了系统的审批流管理能力。
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import { reactive, ref, type Ref } from 'vue';
|
||||
|
||||
const STORAGE_KEY = 'mes_ding_tpl_launch_pos';
|
||||
|
||||
export interface FloatPosition {
|
||||
left: number;
|
||||
top: number;
|
||||
}
|
||||
|
||||
function readAllPositions(): Record<string, FloatPosition> {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}') || {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询条件区域(BasicTable 搜索表单)右侧的默认坐标 */
|
||||
export function calcDefaultPosition(btnWidth: number, btnHeight: number): FloatPosition {
|
||||
const formEl =
|
||||
document.querySelector<HTMLElement>('.jeecg-basic-table-form-container .ant-form') ||
|
||||
document.querySelector<HTMLElement>('.jeecg-basic-table-form-container');
|
||||
if (!formEl) {
|
||||
return {
|
||||
left: Math.max(8, window.innerWidth - btnWidth - 24),
|
||||
top: 100,
|
||||
};
|
||||
}
|
||||
const rect = formEl.getBoundingClientRect();
|
||||
return {
|
||||
left: Math.max(8, rect.right - btnWidth - 12),
|
||||
top: Math.max(8, rect.top + (rect.height - btnHeight) / 2),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 可拖拽悬浮按钮位置:默认对齐查询区右侧,拖拽后按路由持久化。
|
||||
*/
|
||||
export function useDraggablePosition(routePath: Ref<string>) {
|
||||
const pos = reactive<FloatPosition>({ left: 0, top: 0 });
|
||||
const isDragging = ref(false);
|
||||
let moved = false;
|
||||
let pointerId: number | null = null;
|
||||
let startX = 0;
|
||||
let startY = 0;
|
||||
let startLeft = 0;
|
||||
let startTop = 0;
|
||||
let btnWidth = 120;
|
||||
let btnHeight = 36;
|
||||
|
||||
function setButtonSize(width: number, height: number) {
|
||||
btnWidth = width;
|
||||
btnHeight = height;
|
||||
}
|
||||
|
||||
function loadPosition(path: string): boolean {
|
||||
const saved = readAllPositions()[path];
|
||||
if (saved && typeof saved.left === 'number' && typeof saved.top === 'number') {
|
||||
pos.left = saved.left;
|
||||
pos.top = saved.top;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function savePosition(path: string) {
|
||||
const all = readAllPositions();
|
||||
all[path] = { left: pos.left, top: pos.top };
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(all));
|
||||
}
|
||||
|
||||
function applyDefaultPosition() {
|
||||
const p = calcDefaultPosition(btnWidth, btnHeight);
|
||||
pos.left = p.left;
|
||||
pos.top = p.top;
|
||||
}
|
||||
|
||||
function initPosition(path: string, preferDefault = false) {
|
||||
if (!path) return;
|
||||
if (!preferDefault && loadPosition(path)) return;
|
||||
applyDefaultPosition();
|
||||
}
|
||||
|
||||
function clampPosition() {
|
||||
const maxLeft = window.innerWidth - btnWidth - 8;
|
||||
const maxTop = window.innerHeight - btnHeight - 8;
|
||||
pos.left = Math.min(Math.max(8, pos.left), maxLeft);
|
||||
pos.top = Math.min(Math.max(8, pos.top), maxTop);
|
||||
}
|
||||
|
||||
function onPointerMove(e: PointerEvent) {
|
||||
if (pointerId !== e.pointerId) return;
|
||||
const dx = e.clientX - startX;
|
||||
const dy = e.clientY - startY;
|
||||
if (!moved && (Math.abs(dx) > 4 || Math.abs(dy) > 4)) {
|
||||
moved = true;
|
||||
isDragging.value = true;
|
||||
}
|
||||
if (!moved) return;
|
||||
pos.left = startLeft + dx;
|
||||
pos.top = startTop + dy;
|
||||
clampPosition();
|
||||
}
|
||||
|
||||
function endDrag(path: string) {
|
||||
document.removeEventListener('pointermove', onPointerMove);
|
||||
document.removeEventListener('pointerup', onPointerUp);
|
||||
document.removeEventListener('pointercancel', onPointerUp);
|
||||
if (moved && path) {
|
||||
savePosition(path);
|
||||
}
|
||||
pointerId = null;
|
||||
setTimeout(() => {
|
||||
isDragging.value = false;
|
||||
moved = false;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function onPointerUp(e: PointerEvent) {
|
||||
if (pointerId !== e.pointerId) return;
|
||||
endDrag(routePath.value);
|
||||
}
|
||||
|
||||
function onPointerDown(e: PointerEvent, el: HTMLElement | null) {
|
||||
if (e.button !== 0) return;
|
||||
if (el) {
|
||||
const rect = el.getBoundingClientRect();
|
||||
setButtonSize(rect.width, rect.height);
|
||||
}
|
||||
moved = false;
|
||||
isDragging.value = false;
|
||||
pointerId = e.pointerId;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
startLeft = pos.left;
|
||||
startTop = pos.top;
|
||||
(e.currentTarget as HTMLElement)?.setPointerCapture?.(e.pointerId);
|
||||
document.addEventListener('pointermove', onPointerMove);
|
||||
document.addEventListener('pointerup', onPointerUp);
|
||||
document.addEventListener('pointercancel', onPointerUp);
|
||||
}
|
||||
|
||||
function wasDragged() {
|
||||
return moved;
|
||||
}
|
||||
|
||||
return {
|
||||
pos,
|
||||
isDragging,
|
||||
setButtonSize,
|
||||
initPosition,
|
||||
applyDefaultPosition,
|
||||
onPointerDown,
|
||||
wasDragged,
|
||||
clampPosition,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user