diff --git a/docs/src/en/guide/essentials/server.md b/docs/src/en/guide/essentials/server.md index 95d505c0..67e0b1fd 100644 --- a/docs/src/en/guide/essentials/server.md +++ b/docs/src/en/guide/essentials/server.md @@ -150,8 +150,8 @@ export async function saveUserApi(user: UserInfo) { ```ts import { requestClient } from '#/api/request'; -export async function deleteUserApi(user: UserInfo) { - return requestClient.delete(`/user/${user.id}`, user); +export async function deleteUserApi(userId: number) { + return requestClient.delete(`/user/${userId}`); } ``` diff --git a/docs/src/guide/essentials/server.md b/docs/src/guide/essentials/server.md index 9a494967..cd61d3a5 100644 --- a/docs/src/guide/essentials/server.md +++ b/docs/src/guide/essentials/server.md @@ -180,8 +180,8 @@ export async function saveUserApi(user: UserInfo) { ```ts import { requestClient } from '#/api/request'; -export async function deleteUserApi(user: UserInfo) { - return requestClient.delete(`/user/${user.id}`, user); +export async function deleteUserApi(userId: number) { + return requestClient.delete(`/user/${userId}`); } ``` diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal.vue b/packages/@core/ui-kit/popup-ui/src/modal/modal.vue index e9873ff7..b3fdf3fb 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal.vue +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal.vue @@ -105,10 +105,17 @@ const shouldDraggable = computed( () => draggable.value && !shouldFullscreen.value && header.value, ); +const getAppendTo = computed(() => { + return appendToMain.value + ? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div` + : undefined; +}); + const { dragging, transform } = useModalDraggable( dialogRef, headerRef, shouldDraggable, + getAppendTo, ); const firstOpened = ref(false); @@ -198,11 +205,6 @@ function handleFocusOutside(e: Event) { e.preventDefault(); e.stopPropagation(); } -const getAppendTo = computed(() => { - return appendToMain.value - ? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div` - : undefined; -}); const getForceMount = computed(() => { return !unref(destroyOnClose) && unref(firstOpened); @@ -224,7 +226,8 @@ function handleClosed() { :append-to="getAppendTo" :class=" cn( - 'left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col p-0 sm:rounded-[var(--radius)]', + 'left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col p-0', + shouldFullscreen ? 'sm:rounded-none' : 'sm:rounded-[var(--radius)]', modalClass, { 'border-border border': bordered, diff --git a/packages/@core/ui-kit/popup-ui/src/modal/use-modal-draggable.ts b/packages/@core/ui-kit/popup-ui/src/modal/use-modal-draggable.ts index 47fb9b75..a8a5e405 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/use-modal-draggable.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/use-modal-draggable.ts @@ -12,6 +12,7 @@ export function useModalDraggable( targetRef: Ref, dragRef: Ref, draggable: ComputedRef, + containerSelector?: ComputedRef, ) { const transform = reactive({ offsetX: 0, @@ -29,20 +30,36 @@ export function useModalDraggable( } const targetRect = targetRef.value.getBoundingClientRect(); - const { offsetX, offsetY } = transform; const targetLeft = targetRect.left; const targetTop = targetRect.top; const targetWidth = targetRect.width; const targetHeight = targetRect.height; - const docElement = document.documentElement; - const clientWidth = docElement.clientWidth; - const clientHeight = docElement.clientHeight; - - const minLeft = -targetLeft + offsetX; - const minTop = -targetTop + offsetY; - const maxLeft = clientWidth - targetLeft - targetWidth + offsetX; - const maxTop = clientHeight - targetTop - targetHeight + offsetY; + + let containerRect: DOMRect | null = null; + + if (containerSelector?.value) { + const container = document.querySelector(containerSelector.value); + if (container) { + containerRect = container.getBoundingClientRect(); + } + } + + let maxLeft, maxTop, minLeft, minTop; + if (containerRect) { + minLeft = containerRect.left - targetLeft + offsetX; + maxLeft = containerRect.right - targetLeft - targetWidth + offsetX; + minTop = containerRect.top - targetTop + offsetY; + maxTop = containerRect.bottom - targetTop - targetHeight + offsetY; + } else { + const docElement = document.documentElement; + const clientWidth = docElement.clientWidth; + const clientHeight = docElement.clientHeight; + minLeft = -targetLeft + offsetX; + minTop = -targetTop + offsetY; + maxLeft = clientWidth - targetLeft - targetWidth + offsetX; + maxTop = clientHeight - targetTop - targetHeight + offsetY; + } const onMousemove = (e: MouseEvent) => { let moveX = offsetX + e.clientX - downX; diff --git a/packages/effects/common-ui/src/components/api-component/api-component.vue b/packages/effects/common-ui/src/components/api-component/api-component.vue index a3e72b44..70e86e0e 100644 --- a/packages/effects/common-ui/src/components/api-component/api-component.vue +++ b/packages/effects/common-ui/src/components/api-component/api-component.vue @@ -3,11 +3,11 @@ import type { Component } from 'vue'; import type { AnyPromiseFunction } from '@vben/types'; -import { computed, ref, unref, useAttrs, watch } from 'vue'; +import { computed, nextTick, ref, unref, useAttrs, watch } from 'vue'; import { LoaderCircle } from '@vben/icons'; -import { get, isEqual, isFunction } from '@vben-core/shared/utils'; +import { cloneDeep, get, isEqual, isFunction } from '@vben-core/shared/utils'; import { objectOmit } from '@vueuse/core'; @@ -104,6 +104,8 @@ const refOptions = ref([]); const loading = ref(false); // 首次是否加载过了 const isFirstLoaded = ref(false); +// 标记是否有待处理的请求 +const hasPendingRequest = ref(false); const getOptions = computed(() => { const { labelField, valueField, childrenField, numberToString } = props; @@ -146,18 +148,26 @@ const bindProps = computed(() => { }); async function fetchApi() { - let { api, beforeFetch, afterFetch, params, resultField } = props; + const { api, beforeFetch, afterFetch, resultField } = props; - if (!api || !isFunction(api) || loading.value) { + if (!api || !isFunction(api)) { return; } + + // 如果正在加载,标记有待处理的请求并返回 + if (loading.value) { + hasPendingRequest.value = true; + return; + } + refOptions.value = []; try { loading.value = true; + let finalParams = unref(mergedParams); if (beforeFetch && isFunction(beforeFetch)) { - params = (await beforeFetch(params)) || params; + finalParams = (await beforeFetch(cloneDeep(finalParams))) || finalParams; } - let res = await api(params); + let res = await api(finalParams); if (afterFetch && isFunction(afterFetch)) { res = (await afterFetch(res)) || res; } @@ -177,6 +187,13 @@ async function fetchApi() { isFirstLoaded.value = false; } finally { loading.value = false; + // 如果有待处理的请求,立即触发新的请求 + if (hasPendingRequest.value) { + hasPendingRequest.value = false; + // 使用 nextTick 确保状态更新完成后再触发新请求 + await nextTick(); + fetchApi(); + } } } @@ -190,7 +207,7 @@ async function handleFetchForVisible(visible: boolean) { } } -const params = computed(() => { +const mergedParams = computed(() => { return { ...props.params, ...unref(innerParams), @@ -198,7 +215,7 @@ const params = computed(() => { }); watch( - params, + mergedParams, (value, oldValue) => { if (isEqual(value, oldValue)) { return;