diff --git a/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts b/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts index 87edc1a694b8d03a6e91540add0499e5a5ba0e4c..0fd265013f089d7272b3ad95e2067bde6f6bc969 100644 --- a/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts +++ b/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts @@ -394,7 +394,7 @@ export default { const htmlEventValidateHandler = (e) => { const modelValue = e.target.value; if(messageShowType === MessageShowTypeEnum.popover) { - EventBus.emit("showPopoverErrorMessage", {showPopover: false, message: "", uid: dfcUID} as ShowPopoverErrorMessageEventData); + EventBus.emit("showPopoverErrorMessage", {showPopover: false, message: "", uid: dfcUID, popPosition} as ShowPopoverErrorMessageEventData); } validateFn({validator, modelValue, el, tipEl, isFormTag: false, messageShowType, dfcUID, popPosition}); } diff --git a/packages/devui-vue/devui/form/src/form-control/form-control.tsx b/packages/devui-vue/devui/form/src/form-control/form-control.tsx index 41d2e4af12f061428afa45f9401beee881333baf..55612f3a6f33c8938a83e9de0e87de31caa8e42f 100644 --- a/packages/devui-vue/devui/form/src/form-control/form-control.tsx +++ b/packages/devui-vue/devui/form/src/form-control/form-control.tsx @@ -1,8 +1,8 @@ -import { defineComponent, inject, ref, computed, reactive, onMounted } from 'vue'; +import { defineComponent, inject, ref, computed, reactive, onMounted, Teleport } from 'vue'; import { uniqueId } from 'lodash-es'; import { IForm, formControlProps, formInjectionKey } from '../form-types'; import { ShowPopoverErrorMessageEventData } from '../directive/d-validate-rules' -import { EventBus } from '../util'; +import { EventBus, getElOffset } from '../util'; import Icon from '../../../icon/src/icon'; import Popover from '../../../popover/src/popover'; import './form-control.scss'; @@ -21,10 +21,25 @@ export default defineComponent({ const showPopover = ref(false); const tipMessage = ref(""); const popPosition = ref("bottom"); + let rectInfo: Partial = { + width: 0, + height: 0 + }; + let elOffset = { + left: 0, + top: 0 + } + let popoverLeftPosition = 0 ; + let popoverTopPosition = 0 ; onMounted(() => { + const el = document.getElementById(uid); + elOffset = getElOffset(el); EventBus.on("showPopoverErrorMessage", (data: ShowPopoverErrorMessageEventData) => { if (uid === data.uid) { + rectInfo = el.getBoundingClientRect(); + popoverLeftPosition = popPosition.value === "top" || popPosition.value === "bottom" ? rectInfo.right - (rectInfo.width / 2) : rectInfo.right; + popoverTopPosition = popPosition.value === "top" ? elOffset.top + (rectInfo.height / 2) - rectInfo.height : elOffset.top + (rectInfo.height / 2); showPopover.value = data.showPopover; tipMessage.value = data.message; popPosition.value = data.popPosition as any; // todo: 待popover组件positionType完善类型之后再替换类型 @@ -51,14 +66,20 @@ export default defineComponent({ extraInfo, } = props; return
+ +
+ +
+
-
+
{ctx.slots.default?.()} - { showPopover.value && -
- -
- }
{ (feedbackStatus || ctx.slots.suffixTemplate?.()) && diff --git a/packages/devui-vue/devui/form/src/util/index.ts b/packages/devui-vue/devui/form/src/util/index.ts index a1fac48d3f2b4efc5ba7ed8b34ba04ddb404f1a6..8130e097d2462bb40c788352bd1fab913d7dbe7c 100644 --- a/packages/devui-vue/devui/form/src/util/index.ts +++ b/packages/devui-vue/devui/form/src/util/index.ts @@ -10,3 +10,24 @@ export function hasKey(obj: any, key: string | number | symbol): boolean { if (!isObject(obj)) return false; return Object.prototype.hasOwnProperty.call(obj, key); } + +export function getElOffset(curEl: HTMLElement) { + let totalLeft = 0; + let totalTop = 0; + let par: Partial = curEl.offsetParent; + //首先把自己本身的相加 + totalLeft += curEl.offsetLeft; + totalTop += curEl.offsetTop; + //现在开始一级一级往上查找,只要没有遇到body,把父级参照物的边框和偏移相加 + while (par){ + if (navigator.userAgent.indexOf("MSIE 8.0") === -1){ //不是IE8才进行累加父级参照物的边框 + totalTop += par.clientTop; + totalLeft += par.clientLeft; + } + totalTop += par.offsetTop; + totalLeft += par.offsetLeft; + par = par.offsetParent; + } + return {left: totalLeft, top: totalTop}; +} +