From 4b28ede0add31f776ffce57b54e93274d215b8cb Mon Sep 17 00:00:00 2001
From: schangxiang@126.com <schangxiang@126.com>
Date: 周二, 06 5月 2025 06:39:36 +0800
Subject: [PATCH] 22
---
HIAWms/web/src/components/vue3-context-menu/ContextMenuUtils.ts | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 158 insertions(+), 0 deletions(-)
diff --git a/HIAWms/web/src/components/vue3-context-menu/ContextMenuUtils.ts b/HIAWms/web/src/components/vue3-context-menu/ContextMenuUtils.ts
new file mode 100644
index 0000000..14c27a9
--- /dev/null
+++ b/HIAWms/web/src/components/vue3-context-menu/ContextMenuUtils.ts
@@ -0,0 +1,158 @@
+import { defineComponent, toRefs } from "vue";
+import type { VNode } from "vue";
+import type { MenuOptions } from "./ContextMenuDefine";
+import { MenuConstOptions } from "./ContextMenuDefine";
+
+/**
+ * Get absolute y position of HTMLElement
+ * @param e Element
+ * @param stopNode Specify the node for recursive termination, default to body
+ * @returns
+ */
+export function getTop(e: HTMLElement, stopNode?: HTMLElement): number {
+ let offset = e.offsetTop;
+ if (e.offsetParent != null && e.offsetParent != stopNode) {
+ offset -= e.offsetParent.scrollTop;
+ offset += getTop(e.offsetParent as HTMLElement, stopNode);
+ }
+ return offset;
+}
+/**
+ * Get absolute x position of HTMLElement
+ * @param e Element
+ * @param stopNode Specify the node for recursive termination, default to body
+ * @returns
+ */
+export function getLeft(e: HTMLElement, stopNode?: HTMLElement): number {
+ let offset = e.offsetLeft;
+ if (e.offsetParent != null && e.offsetParent != stopNode) {
+ offset -= e.offsetParent.scrollLeft;
+ offset += getLeft(e.offsetParent as HTMLElement, stopNode);
+ }
+ return offset;
+}
+
+/**
+ * If your `body` element is in a scaled state (e.g. `transform: scale(0.5)`),
+ * this may lead to the wrong position of the menu display.
+ * You can use this function to transform the menu display position:
+ *
+ * ```ts
+ *
+ import ContextMenu from '@imengyu/vue3-context-menu'
+
+ function onContextMenu(e: MouseEvent) {
+ const scaledPosition = ContextMenu.transformMenuPosition(e.target as HTMLElement, e.offsetX, e.offsetY);
+ //Full code of menuData is in `/examples/views/InScaledBody.vue`
+ menuData.x = scaledPosition.x;
+ menuData.y = scaledPosition.y;
+ //show menu
+ ContextMenu.showContextMenu(menuData);
+ }
+ * ```
+ * @param e Current click element
+ * @param offsetX MouseEvent.offsetX
+ * @param offsetY MouseEvent.offsetY
+ */
+export function transformMenuPosition(
+ e: HTMLElement,
+ offsetX: number,
+ offsetY: number,
+ container?: HTMLElement
+): {
+ x: number;
+ y: number;
+} {
+ return {
+ x: getLeft(e, container) + offsetX,
+ y: getTop(e, container) + offsetY,
+ };
+}
+
+const DEFAULT_CONTAINER_ID = "mx-menu-default-container";
+const GEN_CONTAINER_ID = "mx-menu-container-";
+let containerId = 0;
+
+export function removeContainer(container: HTMLElement): void {
+ container.parentNode?.removeChild(container);
+}
+export function genContainer(options: MenuOptions): {
+ eleId: string;
+ container: HTMLElement;
+ isNew: boolean;
+} {
+ const { getContainer, zIndex } = options;
+
+ if (getContainer) {
+ const container =
+ typeof getContainer === "function" ? getContainer() : getContainer;
+ if (container) {
+ let eleId = container.getAttribute("id");
+ if (!eleId) {
+ eleId = GEN_CONTAINER_ID + containerId++;
+ container.setAttribute("id", eleId);
+ }
+ return {
+ eleId,
+ container,
+ isNew: false,
+ };
+ }
+ }
+
+ let container = document.getElementById(DEFAULT_CONTAINER_ID);
+ if (!container) {
+ container = document.createElement("div");
+ container.setAttribute("id", DEFAULT_CONTAINER_ID);
+ container.setAttribute(
+ "class",
+ "mx-menu-ghost-host information_full_screen"
+ );
+ document.body.appendChild(container);
+ }
+ container.style.zIndex =
+ zIndex?.toString() || MenuConstOptions.defaultZindex.toString();
+ return {
+ eleId: DEFAULT_CONTAINER_ID,
+ container,
+ isNew: true,
+ };
+}
+
+/**
+ * Number to px string
+ * @param value
+ * @returns
+ */
+export function solveNumberOrStringSize(value: string | number): string {
+ return typeof value === "number" ? `${value}px` : value;
+}
+
+/**
+ * Render a VNode
+ */
+export const VNodeRender = defineComponent({
+ props: {
+ /**
+ * Can be VNode or (data: unknown) => VNode
+ */
+ vnode: {
+ type: null,
+ },
+ /**
+ * If vnode is a callback, this data will be passed to the callback first parameter.
+ * @default null
+ */
+ data: {
+ type: null,
+ default: null,
+ },
+ },
+ setup(props) {
+ const { vnode, data } = toRefs(props);
+ return () =>
+ typeof vnode.value === "function"
+ ? (vnode.value as unknown as (data: unknown) => VNode)(data.value)
+ : (vnode.value as unknown as VNode);
+ },
+});
--
Gitblit v1.9.3