update: 弹窗表单数据更改关闭时的提示框(可能最终不会加入) 测试页面: 参数管理

This commit is contained in:
dap 2025-04-05 13:33:15 +08:00
parent b4d038e22f
commit 26587ac09a
3 changed files with 135 additions and 6 deletions

View File

@ -26,11 +26,15 @@
- TableSwitch组件重构
- 管理员租户切换不再返回首页 直接刷新当前页(除特殊页面外会回到首页)
- 租户切换Select增加loading
- modalLoading/drawerLoading改为调用内部的lock/unlock方法
- ~~modalLoading/drawerLoading改为调用内部的lock/unlock方法~~ 有待商榷暂时按老版本逻辑不变
- 登录验证码 增加loading
- DictEnum使用const代替enum
- TinyMCE组件重构 移除冗余代码/功能 增加loading
**ALPHA功能**
- 弹窗表单数据更改关闭时的提示框(可能最终不会加入) 测试页面: 参数管理
**BUG FIX**
- 重新登录 字典会unknown的情况[详细分析](https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IBY27D)

View File

@ -0,0 +1,117 @@
import type { ExtendedFormApi } from '@vben/common-ui';
import type { MaybePromise } from '@vben/types';
import { ref } from 'vue';
import { $t } from '@vben/locales';
import { Modal } from 'ant-design-vue';
import { isFunction } from 'lodash-es';
interface BeforeCloseDiffProps {
/**
*
* @returns Promise<string>
*/
initializedGetter: () => MaybePromise<string>;
/**
*
* @returns Promise<string>
*/
currentGetter: () => MaybePromise<string>;
/**
*
* @param init
* @param current
* @returns boolean
*/
compare?: (init: string, current: string) => boolean;
}
/**
* @deprecated api变动/
* @param props props
* @returns hook
*
* 待解决问题: 网速慢情况直接关闭
* 使api.lock会导致在报错情况无法关闭(finally)
*/
export function useBeforeCloseDiff(props: BeforeCloseDiffProps) {
const { initializedGetter, currentGetter, compare } = props;
const initialized = ref<string>('');
const isInitialized = ref(false);
const isSubmitted = ref(false);
async function updateInitialized(data?: string) {
initialized.value = data || (await initializedGetter());
isInitialized.value = true;
}
function setSubmitted() {
isSubmitted.value = true;
}
async function onBeforeClose(): Promise<boolean> {
// 如果还未初始化,直接允许关闭
if (!isInitialized.value) {
return true;
}
// 如果已经提交过,直接允许关闭
if (isSubmitted.value) {
// 重置状态
isSubmitted.value = false;
return true;
}
try {
const current = await currentGetter();
if (isFunction(compare) && compare(initialized.value, current)) {
return true;
} else {
// 如果数据没有变化,直接允许关闭
if (current === initialized.value) {
return true;
}
}
// 数据有变化,显示确认对话框
return new Promise<boolean>((resolve) => {
Modal.confirm({
title: $t('pages.common.tip'),
content: $t('您有未保存的更改,确认要退出吗?'),
centered: true,
okButtonProps: { danger: true },
cancelText: $t('common.cancel'),
okText: $t('common.confirm'),
onOk: () => {
resolve(true);
isInitialized.value = false;
},
onCancel: () => resolve(false),
});
});
} catch (error) {
console.error('Failed to compare data:', error);
return true;
}
}
return {
onBeforeClose,
updateInitialized,
setSubmitted,
};
}
/**
* useVbenForm使用的
* @param formApi
* @returns getter
*/
export function defaultFormValueGetter(formApi: ExtendedFormApi) {
return async () => {
const v = await formApi.getValues();
return JSON.stringify(v);
};
}

View File

@ -7,6 +7,7 @@ import { cloneDeep } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { configAdd, configInfo, configUpdate } from '#/api/system/config';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
import { modalSchema } from './data';
@ -25,9 +26,15 @@ const [BasicForm, formApi] = useVbenForm({
showDefaultActions: false,
});
const { onBeforeClose, updateInitialized, setSubmitted } = useBeforeCloseDiff({
initializedGetter: defaultFormValueGetter(formApi),
currentGetter: defaultFormValueGetter(formApi),
});
const [BasicModal, modalApi] = useVbenModal({
fullscreenButton: false,
onCancel: handleCancel,
onBeforeClose,
onClosed: handleClosed,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
if (!isOpen) {
@ -42,6 +49,7 @@ const [BasicModal, modalApi] = useVbenModal({
const record = await configInfo(id);
await formApi.setValues(record);
}
await updateInitialized();
modalApi.modalLoading(false);
},
@ -56,8 +64,9 @@ async function handleConfirm() {
}
const data = cloneDeep(await formApi.getValues());
await (isUpdate.value ? configUpdate(data) : configAdd(data));
setSubmitted();
emit('reload');
await handleCancel();
modalApi.close();
} catch (error) {
console.error(error);
} finally {
@ -65,14 +74,13 @@ async function handleConfirm() {
}
}
async function handleCancel() {
modalApi.close();
async function handleClosed() {
await formApi.resetForm();
}
</script>
<template>
<BasicModal :close-on-click-modal="false" :title="title" class="w-[550px]">
<BasicModal :title="title" class="w-[550px]">
<BasicForm />
</BasicModal>
</template>