refactor(antdv-next): 将message组件调用统一改为window.message

将项目中直接导入的antdv-next的message组件调用改为通过window.message调用,提升代码一致性
移除不再需要的message组件导入
新增api-switch组件用于统一处理状态切换逻辑
This commit is contained in:
dap
2026-01-15 09:35:54 +08:00
parent 2312f438ac
commit ee1b37c787
23 changed files with 211 additions and 90 deletions

View File

@@ -8,8 +8,6 @@ import { computed, ref, unref, watch, watchEffect } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t as t } from '@vben/locales';
import { message } from 'antdv-next';
import cropperModal from './cropper-modal.vue';
defineOptions({ name: 'CropperAvatar' });
@@ -74,7 +72,7 @@ watch(
function handleUploadSuccess({ data, source }: any) {
sourceValue.value = source;
emit('change', { data, source });
message.success(t('component.cropper.uploadSuccess'));
window.message.success(t('component.cropper.uploadSuccess'));
}
const closeModal = () => modalApi.close();

View File

@@ -8,7 +8,7 @@ import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t as t } from '@vben/locales';
import { Avatar, message, Space, Tooltip, Upload } from 'antdv-next';
import { Avatar, Space, Tooltip, Upload } from 'antdv-next';
import { isFunction } from 'lodash-es';
import { dataURLtoBlob } from '#/utils/file/base64Conver';
@@ -102,7 +102,7 @@ async function handleOk() {
const uploadApi = props.uploadApi;
if (uploadApi && isFunction(uploadApi)) {
if (!previewSource.value) {
message.warn('未选择图片');
window.message.warning('未选择图片');
return;
}
const blob = dataURLtoBlob(previewSource.value);

View File

@@ -0,0 +1,125 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { $t } from '@vben/locales';
import { Modal, Switch } from 'antdv-next';
import { isFunction } from 'lodash-es';
interface Props {
/**
* 选中的文本
* @default i18n 启用
*/
checkedText?: string;
/**
* 未选中的文本
* @default i18n 禁用
*/
unCheckedText?: string;
disabled?: boolean;
/**
* 需要自己在内部处理更新的逻辑 因为status已经双向绑定了 可以直接获取
*/
api: (checked: boolean) => PromiseLike<void>;
/**
* 更新前是否弹窗确认
* @default false
*/
confirm?: boolean;
/**
* 对应的提示内容
* @param checked 选中的值(更新后的值)
* @default string '确认要更新状态吗?'
*/
confirmText?: (checked: boolean) => string;
}
const props = withDefaults(defineProps<Props>(), {
checkedText: undefined,
unCheckedText: undefined,
confirm: false,
confirmText: undefined,
});
const emit = defineEmits<{ reload: [] }>();
// 修改为computed 支持语言切换
const checkedTextComputed = computed(() => {
return props.checkedText ?? $t('pages.common.enable');
});
const unCheckedTextComputed = computed(() => {
return props.unCheckedText ?? $t('pages.common.disable');
});
const currentChecked = defineModel<boolean>('value', {
default: false,
});
const loading = ref(false);
function confirmUpdate(checked: boolean, lastStatus: boolean) {
const content = isFunction(props.confirmText)
? props.confirmText(checked)
: `确认要更新状态吗?`;
Modal.confirm({
title: '提示',
content,
centered: true,
onOk: async () => {
try {
loading.value = true;
const { api } = props;
isFunction(api) && (await api(checked));
emit('reload');
} catch {
currentChecked.value = lastStatus;
} finally {
loading.value = false;
}
},
onCancel: () => {
currentChecked.value = lastStatus;
},
});
}
async function handleChange(checked: boolean, e: Event) {
// 阻止事件冒泡 否则会跟行选中冲突
e.stopPropagation();
// 原本的状态
const lastStatus = !checked;
// 切换状态
currentChecked.value = checked;
const { api } = props;
try {
loading.value = true;
if (props.confirm) {
confirmUpdate(checked, lastStatus);
return;
}
isFunction(api) && (await api(checked));
emit('reload');
} catch {
currentChecked.value = lastStatus;
} finally {
loading.value = false;
}
}
</script>
<template>
<Switch
v-bind="$attrs"
:loading="loading"
:disabled="disabled"
:checked="currentChecked"
:checked-children="checkedTextComputed"
:un-checked-children="unCheckedTextComputed"
@change="handleChange"
/>
</template>

View File

@@ -12,7 +12,7 @@ import { useTabs } from '@vben/hooks';
import { $t } from '@vben/locales';
import { getPopupContainer } from '@vben/utils';
import { message, Select, Spin } from 'antdv-next';
import { Select, Spin } from 'antdv-next';
import { storeToRefs } from 'pinia';
import { tenantDynamicClear, tenantDynamicToggle } from '#/api/system/tenant';
@@ -90,7 +90,7 @@ const onSelected: SelectProps['onSelect'] = async (
// 关闭之前的message 只保留一条
messageInstance.value?.();
messageInstance.value = message.success(
messageInstance.value = window.message.success(
`${$t('component.tenantToggle.switch')} ${option.companyName}`,
);
@@ -111,7 +111,9 @@ async function onDeselect() {
await tenantDynamicClear();
// 关闭之前的message 只保留一条
messageInstance.value?.();
messageInstance.value = message.success($t('component.tenantToggle.reset'));
messageInstance.value = window.message.success(
$t('component.tenantToggle.reset'),
);
lastSelected.value = '';
close(false);

View File

@@ -9,7 +9,7 @@ import { ref, toRefs, watch } from 'vue';
import { $t } from '@vben/locales';
import { UploadOutlined } from '@ant-design/icons-vue';
import { message, Upload } from 'antdv-next';
import { Upload } from 'antdv-next';
import { isArray, isFunction, isObject, isString } from 'lodash-es';
import { uploadApi } from '#/api';
@@ -129,14 +129,14 @@ const beforeUpload = async (file: File) => {
const { maxSize, accept } = props;
const isAct = await checkFileType(file, accept);
if (!isAct) {
message.error($t('component.upload.acceptUpload', [accept]));
window.message.error($t('component.upload.acceptUpload', [accept]));
isActMsg.value = false;
// 防止弹出多个错误提示
setTimeout(() => (isActMsg.value = true), 1000);
}
const isLt = file.size / 1024 / 1024 > maxSize;
if (isLt) {
message.error($t('component.upload.maxSizeMultiple', [maxSize]));
window.message.error($t('component.upload.maxSizeMultiple', [maxSize]));
isLtMsg.value = false;
// 防止弹出多个错误提示
setTimeout(() => (isLtMsg.value = true), 1000);
@@ -165,7 +165,7 @@ async function customRequest(info: UploadRequestOption<any>) {
* 内部的逻辑由requestClient.upload处理 这里不用判断业务状态码 不符合会自动reject
*/
info.onSuccess!(res);
message.success($t('component.upload.uploadSuccess'));
window.message.success($t('component.upload.uploadSuccess'));
// 获取
const value = getValue();
isInnerOperate.value = true;
@@ -218,9 +218,9 @@ function getValue() {
</div>
<div v-if="showDescription" class="mt-2 flex flex-wrap items-center">
请上传不超过
<div class="text-primary mx-1 font-bold">{{ maxSize }}MB</div>
<div class="mx-1 font-bold text-primary">{{ maxSize }}MB</div>
<div class="text-primary mx-1 font-bold">{{ accept.join('/') }}</div>
<div class="mx-1 font-bold text-primary">{{ accept.join('/') }}</div>
格式文件
</div>
</Upload>

View File

@@ -9,7 +9,7 @@ import { ref, toRefs, watch } from 'vue';
import { $t } from '@vben/locales';
import { PlusOutlined } from '@ant-design/icons-vue';
import { message, Modal, Upload } from 'antdv-next';
import { Modal, Upload } from 'antdv-next';
import { isArray, isFunction, isObject, isString, uniqueId } from 'lodash-es';
import { uploadApi } from '#/api';
@@ -30,7 +30,7 @@ const props = withDefaults(
api?: UploadApi;
disabled?: boolean;
helpText?: string;
// eslint-disable-next-line no-use-before-define
listType?: ListType;
// 最大数量的文件Infinity不限制
maxNumber?: number;
@@ -189,14 +189,14 @@ const beforeUpload = async (file: File) => {
const { maxSize, accept } = props;
const isAct = await checkImageFileType(file, accept);
if (!isAct) {
message.error($t('component.upload.acceptUpload', [accept]));
window.message.error($t('component.upload.acceptUpload', [accept]));
isActMsg.value = false;
// 防止弹出多个错误提示
setTimeout(() => (isActMsg.value = true), 1000);
}
const isLt = file.size / 1024 / 1024 > maxSize;
if (isLt) {
message.error($t('component.upload.maxSizeMultiple', [maxSize]));
window.message.error($t('component.upload.maxSizeMultiple', [maxSize]));
isLtMsg.value = false;
// 防止弹出多个错误提示
setTimeout(() => (isLtMsg.value = true), 1000);
@@ -225,7 +225,7 @@ async function customRequest(info: UploadRequestOption<any>) {
* 内部的逻辑由requestClient.upload处理 这里不用判断业务状态码 不符合会自动reject
*/
info.onSuccess!(res);
message.success($t('component.upload.uploadSuccess'));
window.message.success($t('component.upload.uploadSuccess'));
// 获取
const value = getValue();
isInnerOperate.value = true;
@@ -294,9 +294,9 @@ function getValue() {
class="mt-2 flex flex-wrap items-center text-[14px]"
>
请上传不超过
<div class="text-primary mx-1 font-bold">{{ maxSize }}MB</div>
<div class="mx-1 font-bold text-primary">{{ maxSize }}MB</div>
<div class="text-primary mx-1 font-bold">{{ accept.join('/') }}</div>
<div class="mx-1 font-bold text-primary">{{ accept.join('/') }}</div>
格式文件
</div>
<Modal

View File

@@ -22,7 +22,7 @@ import { computed, onUnmounted, ref, watch } from 'vue';
import { $t } from '@vben/locales';
import { message, Modal } from 'antdv-next';
import { Modal } from 'antdv-next';
import { isFunction, isString } from 'lodash-es';
import { ossInfo } from '#/api/system/oss';
@@ -270,7 +270,7 @@ export function useUpload(
function beforeUpload(file: FileType) {
const isLtMax = file.size / 1024 / 1024 < props.maxSize!;
if (!isLtMax) {
message.error($t('component.upload.maxSize', [props.maxSize]));
window.message.error($t('component.upload.maxSize', [props.maxSize]));
return false;
}
// 大坑 Safari不支持file-type库 去除文件类型的校验
@@ -301,7 +301,7 @@ export function useUpload(
});
info.onSuccess!(res);
if (props.showSuccessMsg) {
message.success($t('component.upload.uploadSuccess'));
window.message.success($t('component.upload.uploadSuccess'));
}
emit('success', info.file as RcFile, res);
} catch (error: any) {