Merge branch 'main' into fix
This commit is contained in:
@@ -17,6 +17,7 @@ import type { BaseFormComponentType } from '@vben/common-ui';
|
|||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
computed,
|
||||||
defineAsyncComponent,
|
defineAsyncComponent,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
h,
|
h,
|
||||||
@@ -383,12 +384,17 @@ const withPreviewUpload = () => {
|
|||||||
attrs?.fileList || attrs?.['file-list'] || [],
|
attrs?.fileList || attrs?.['file-list'] || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const maxSize = computed(() => attrs?.maxSize ?? attrs?.['max-size']);
|
||||||
|
const aspectRatio = computed(
|
||||||
|
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
|
||||||
|
);
|
||||||
|
|
||||||
const handleBeforeUpload = async (
|
const handleBeforeUpload = async (
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
originFileList: Array<File>,
|
originFileList: Array<File>,
|
||||||
) => {
|
) => {
|
||||||
if (attrs.maxSize && (file.size || 0) / 1024 / 1024 > attrs.maxSize) {
|
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
||||||
message.error($t('ui.formRules.sizeLimit', [attrs.maxSize]));
|
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
||||||
file.status = 'removed';
|
file.status = 'removed';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -401,7 +407,7 @@ const withPreviewUpload = () => {
|
|||||||
) {
|
) {
|
||||||
file.status = 'removed';
|
file.status = 'removed';
|
||||||
// antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取
|
// antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取
|
||||||
const blob = await cropImage(originFileList[0], attrs.aspectRatio);
|
const blob = await cropImage(originFileList[0], aspectRatio.value);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
return reject(new Error($t('ui.crop.errorTip')));
|
return reject(new Error($t('ui.crop.errorTip')));
|
||||||
|
|||||||
@@ -41,6 +41,18 @@ export function getElementVisibleRect(
|
|||||||
const left = Math.max(rect.left, 0);
|
const left = Math.max(rect.left, 0);
|
||||||
const right = Math.min(rect.right, viewWidth);
|
const right = Math.min(rect.right, viewWidth);
|
||||||
|
|
||||||
|
// 如果元素完全不可见,则返回一个空的矩形
|
||||||
|
if (top >= viewHeight || bottom <= 0 || left >= viewWidth || right <= 0) {
|
||||||
|
return {
|
||||||
|
bottom: 0,
|
||||||
|
height: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bottom,
|
bottom,
|
||||||
height: Math.max(0, bottom - top),
|
height: Math.max(0, bottom - top),
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
|
|||||||
// 不能用 Object.assign,会丢失 api 的原型函数
|
// 不能用 Object.assign,会丢失 api 的原型函数
|
||||||
Object.setPrototypeOf(extendedApi, api);
|
Object.setPrototypeOf(extendedApi, api);
|
||||||
},
|
},
|
||||||
|
consumed: false,
|
||||||
options,
|
options,
|
||||||
async reCreateModal() {
|
async reCreateModal() {
|
||||||
isModalReady.value = false;
|
isModalReady.value = false;
|
||||||
@@ -73,7 +74,13 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
|
|||||||
return [Modal, extendedApi as ExtendedModalApi] as const;
|
return [Modal, extendedApi as ExtendedModalApi] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
const injectData = inject<any>(USER_MODAL_INJECT_KEY, {});
|
let injectData = inject<any>(USER_MODAL_INJECT_KEY, {});
|
||||||
|
// 这个数据已经被使用了,说明这个弹窗是嵌套的弹窗,不应该merge上层的配置
|
||||||
|
if (injectData.consumed) {
|
||||||
|
injectData = {};
|
||||||
|
} else {
|
||||||
|
injectData.consumed = true;
|
||||||
|
}
|
||||||
|
|
||||||
const mergedOptions = {
|
const mergedOptions = {
|
||||||
...DEFAULT_MODAL_PROPS,
|
...DEFAULT_MODAL_PROPS,
|
||||||
|
|||||||
@@ -32,19 +32,19 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
// const startTime = ref(0);
|
// const startTime = ref(0);
|
||||||
const showSpinner = ref(false);
|
const showSpinner = ref(false);
|
||||||
const renderSpinner = ref(false);
|
const renderSpinner = ref(false);
|
||||||
const timer = ref<ReturnType<typeof setTimeout>>();
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.spinning,
|
() => props.spinning,
|
||||||
(show) => {
|
(show) => {
|
||||||
if (!show) {
|
if (!show) {
|
||||||
showSpinner.value = false;
|
showSpinner.value = false;
|
||||||
clearTimeout(timer.value);
|
timer && clearTimeout(timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// startTime.value = performance.now();
|
// startTime.value = performance.now();
|
||||||
timer.value = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
// const loadingTime = performance.now() - startTime.value;
|
// const loadingTime = performance.now() - startTime.value;
|
||||||
|
|
||||||
showSpinner.value = true;
|
showSpinner.value = true;
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ function useEcharts(chartRef: Ref<EchartsUIType>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
useTimeoutFn(() => {
|
useTimeoutFn(() => {
|
||||||
if (!chartInstance) {
|
if (!chartInstance || chartInstance?.getDom() !== el) {
|
||||||
|
chartInstance?.dispose();
|
||||||
const instance = initCharts();
|
const instance = initCharts();
|
||||||
if (!instance) return;
|
if (!instance) return;
|
||||||
}
|
}
|
||||||
@@ -104,6 +105,36 @@ function useEcharts(chartRef: Ref<EchartsUIType>) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateDate = (
|
||||||
|
option: EChartsOption,
|
||||||
|
notMerge = false, // false = 合并(保留动画),true = 完全替换
|
||||||
|
lazyUpdate = false, // true 时不立即重绘,适合短时间内多次调用
|
||||||
|
): Promise<echarts.ECharts | null> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (!chartInstance) {
|
||||||
|
// 还没初始化 → 当作首次渲染
|
||||||
|
renderEcharts(option).then(resolve);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并你原有的全局配置(比如 backgroundColor)
|
||||||
|
const finalOption = {
|
||||||
|
...option,
|
||||||
|
...getOptions.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
chartInstance.setOption(finalOption, {
|
||||||
|
notMerge,
|
||||||
|
lazyUpdate,
|
||||||
|
// silent: true, // 如果追求极致性能可开启(关闭所有事件)
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(chartInstance);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
const el = getChartEl();
|
const el = getChartEl();
|
||||||
if (isElHidden(el)) {
|
if (isElHidden(el)) {
|
||||||
@@ -139,6 +170,7 @@ function useEcharts(chartRef: Ref<EchartsUIType>) {
|
|||||||
return {
|
return {
|
||||||
renderEcharts,
|
renderEcharts,
|
||||||
resize,
|
resize,
|
||||||
|
updateDate,
|
||||||
getChartInstance: () => chartInstance,
|
getChartInstance: () => chartInstance,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import type { BaseFormComponentType } from '@vben/common-ui';
|
|||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
computed,
|
||||||
defineAsyncComponent,
|
defineAsyncComponent,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
h,
|
h,
|
||||||
@@ -383,12 +384,17 @@ const withPreviewUpload = () => {
|
|||||||
attrs?.fileList || attrs?.['file-list'] || [],
|
attrs?.fileList || attrs?.['file-list'] || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const maxSize = computed(() => attrs?.maxSize ?? attrs?.['max-size']);
|
||||||
|
const aspectRatio = computed(
|
||||||
|
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
|
||||||
|
);
|
||||||
|
|
||||||
const handleBeforeUpload = async (
|
const handleBeforeUpload = async (
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
originFileList: Array<File>,
|
originFileList: Array<File>,
|
||||||
) => {
|
) => {
|
||||||
if (attrs.maxSize && (file.size || 0) / 1024 / 1024 > attrs.maxSize) {
|
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
||||||
message.error($t('ui.formRules.sizeLimit', [attrs.maxSize]));
|
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
||||||
file.status = 'removed';
|
file.status = 'removed';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -401,7 +407,7 @@ const withPreviewUpload = () => {
|
|||||||
) {
|
) {
|
||||||
file.status = 'removed';
|
file.status = 'removed';
|
||||||
// antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取
|
// antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取
|
||||||
const blob = await cropImage(originFileList[0], attrs.aspectRatio);
|
const blob = await cropImage(originFileList[0], aspectRatio.value);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
return reject(new Error($t('ui.crop.errorTip')));
|
return reject(new Error($t('ui.crop.errorTip')));
|
||||||
|
|||||||
@@ -78,15 +78,22 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isLoggingOut = ref(false); // 正在 logout 标识, 防止 /logout 死循环.
|
||||||
|
|
||||||
async function logout(redirect: boolean = true) {
|
async function logout(redirect: boolean = true) {
|
||||||
|
if (isLoggingOut.value) return; // 正在登出中, 说明已进入循环, 直接返回.
|
||||||
|
isLoggingOut.value = true; // 设置 标识
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await logoutApi();
|
await logoutApi();
|
||||||
} catch {
|
} catch {
|
||||||
// 不做任何处理
|
// 不做任何处理
|
||||||
}
|
} finally {
|
||||||
|
isLoggingOut.value = false; // 重置 标识
|
||||||
|
|
||||||
resetAllStores();
|
resetAllStores();
|
||||||
accessStore.setLoginExpired(false);
|
accessStore.setLoginExpired(false);
|
||||||
|
}
|
||||||
|
|
||||||
// 回登录页带上当前路由地址
|
// 回登录页带上当前路由地址
|
||||||
await router.replace({
|
await router.replace({
|
||||||
|
|||||||
Reference in New Issue
Block a user