mirror of
https://gitee.com/dapppp/ruoyi-plus-vben5.git
synced 2026-03-18 10:38:48 +08:00
refactor(antdv-next): 将message组件调用统一改为window.message
将项目中直接导入的antdv-next的message组件调用改为通过window.message调用,提升代码一致性 移除不再需要的message组件导入 新增api-switch组件用于统一处理状态切换逻辑
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
125
apps/web-antd/src/components/global/api-switch.vue
Normal file
125
apps/web-antd/src/components/global/api-switch.vue
Normal 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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user