浏览代码

fix: alert `beforeClose` callback arguments fixed (#5845)

Netfan 3 月之前
父节点
当前提交
ecf518bb02

+ 13 - 3
docs/src/components/common-ui/vben-alert.md

@@ -38,9 +38,16 @@ Alert提供的功能与Modal类似,但只适用于简单应用场景。例如
 /** 预置的图标类型 */
 export type IconType = 'error' | 'info' | 'question' | 'success' | 'warning';
 
+export type BeforeCloseScope = {
+  /** 是否为点击确认按钮触发的关闭 */
+  isConfirm: boolean;
+};
+
 export type AlertProps = {
   /** 关闭前的回调,如果返回false,则终止关闭 */
-  beforeClose?: () => boolean | Promise<boolean | undefined> | undefined;
+  beforeClose?: (
+    scope: BeforeCloseScope,
+  ) => boolean | Promise<boolean | undefined> | undefined;
   /** 边框 */
   bordered?: boolean;
   /** 取消按钮的标题 */
@@ -81,7 +88,7 @@ export function alert(
 
 /**
  * 弹出输入框的函数签名。
- * 参数beforeClose会传入用户当前输入的值
+ * beforeClose的参数会传入用户当前输入的值
  * component指定接受用户输入的组件,默认为Input
  * componentProps 为输入组件设置的属性数据
  * defaultValue 默认的值
@@ -90,7 +97,10 @@ export function alert(
 export async function prompt<T = any>(
   options: Omit<AlertProps, 'beforeClose'> & {
     beforeClose?: (
-      val: T,
+      scope: BeforeCloseScope & {
+        /** 输入组件的当前值 */
+        value: T;
+      },
     ) => boolean | Promise<boolean | undefined> | undefined;
     component?: Component;
     componentProps?: Recordable<any>;

+ 10 - 6
packages/@core/ui-kit/popup-ui/src/alert/AlertBuilder.ts

@@ -2,7 +2,7 @@ import type { Component } from 'vue';
 
 import type { Recordable } from '@vben-core/typings';
 
-import type { AlertProps } from './alert';
+import type { AlertProps, BeforeCloseScope } from './alert';
 
 import { h, ref, render } from 'vue';
 
@@ -131,9 +131,10 @@ export function vbenConfirm(
 
 export async function vbenPrompt<T = any>(
   options: Omit<AlertProps, 'beforeClose'> & {
-    beforeClose?: (
-      val: T,
-    ) => boolean | Promise<boolean | undefined> | undefined;
+    beforeClose?: (scope: {
+      isConfirm: boolean;
+      value: T | undefined;
+    }) => boolean | Promise<boolean | undefined> | undefined;
     component?: Component;
     componentProps?: Recordable<any>;
     defaultValue?: T;
@@ -165,9 +166,12 @@ export async function vbenPrompt<T = any>(
   contents.push(componentRef);
   const props: AlertProps & Recordable<any> = {
     ...delegated,
-    async beforeClose() {
+    async beforeClose(scope: BeforeCloseScope) {
       if (delegated.beforeClose) {
-        return await delegated.beforeClose(modelValue.value);
+        return await delegated.beforeClose({
+          ...scope,
+          value: modelValue.value,
+        });
       }
     },
     content: h(

+ 7 - 1
packages/@core/ui-kit/popup-ui/src/alert/alert.ts

@@ -2,9 +2,15 @@ import type { Component } from 'vue';
 
 export type IconType = 'error' | 'info' | 'question' | 'success' | 'warning';
 
+export type BeforeCloseScope = {
+  isConfirm: boolean;
+};
+
 export type AlertProps = {
   /** 关闭前的回调,如果返回false,则终止关闭 */
-  beforeClose?: () => boolean | Promise<boolean | undefined> | undefined;
+  beforeClose?: (
+    scope: BeforeCloseScope,
+  ) => boolean | Promise<boolean | undefined> | undefined;
   /** 边框 */
   bordered?: boolean;
   /** 取消按钮的标题 */

+ 9 - 8
packages/@core/ui-kit/popup-ui/src/alert/alert.vue

@@ -92,15 +92,17 @@ function handleConfirm() {
   isConfirm.value = true;
   emits('confirm');
 }
+
 function handleCancel() {
-  open.value = false;
+  isConfirm.value = false;
 }
+
 const loading = ref(false);
 async function handleOpenChange(val: boolean) {
   if (!val && props.beforeClose) {
     loading.value = true;
     try {
-      const res = await props.beforeClose();
+      const res = await props.beforeClose({ isConfirm: isConfirm.value });
       if (res !== false) {
         open.value = false;
       }
@@ -141,6 +143,7 @@ async function handleOpenChange(val: boolean) {
                 size="icon"
                 class="rounded-full"
                 :disabled="loading"
+                @click="handleCancel"
               >
                 <X class="text-muted-foreground size-4" />
               </VbenButton>
@@ -154,22 +157,20 @@ async function handleOpenChange(val: boolean) {
           <VbenLoading v-if="loading" :spinning="loading" />
         </AlertDialogDescription>
         <div class="flex justify-end gap-x-2">
-          <AlertDialogCancel
-            v-if="showCancel"
-            @click="handleCancel"
-            :disabled="loading"
-          >
+          <AlertDialogCancel v-if="showCancel" :disabled="loading">
             <component
               :is="components.DefaultButton || VbenButton"
               variant="ghost"
+              @click="handleCancel"
             >
               {{ cancelText || $t('cancel') }}
             </component>
           </AlertDialogCancel>
-          <AlertDialogAction @click="handleConfirm">
+          <AlertDialogAction>
             <component
               :is="components.PrimaryButton || VbenButton"
               :loading="loading"
+              @click="handleConfirm"
             >
               {{ confirmText || $t('confirm') }}
             </component>

+ 4 - 3
playground/src/views/examples/modal/index.vue

@@ -129,7 +129,8 @@ onBeforeUnmount(() => {
 
 function openConfirm() {
   confirm({
-    beforeClose() {
+    beforeClose({ isConfirm }) {
+      if (!isConfirm) return;
       // 这里可以做一些异步操作
       return new Promise((resolve) => {
         setTimeout(() => {
@@ -150,8 +151,8 @@ function openConfirm() {
 
 async function openPrompt() {
   prompt<string>({
-    async beforeClose(val) {
-      if (val === '芝士') {
+    async beforeClose({ isConfirm, value }) {
+      if (isConfirm && value === '芝士') {
         message.error('不能吃芝士');
         return false;
       }