wip(menu): perf menu

This commit is contained in:
vben
2020-12-15 00:13:23 +08:00
parent ec7efcf0f0
commit a65ad9edd5
80 changed files with 1338 additions and 972 deletions

View File

@@ -2,9 +2,7 @@ import { withInstall } from '../util';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import AppLogo from './src/AppLogo.vue';
export const AppLocalePicker = createAsyncComponent(() => import('./src/AppLocalePicker.vue'), {
loading: true,
});
export const AppLocalePicker = createAsyncComponent(() => import('./src/AppLocalePicker.vue'));
export const AppProvider = createAsyncComponent(() => import('./src/AppProvider.vue'));
export const AppSearch = createAsyncComponent(() => import('./src/search/AppSearch.vue'), {
loading: true,

View File

@@ -11,8 +11,8 @@
:overlayClassName="`${prefixCls}-overlay`"
>
<span :class="prefixCls">
<GlobalOutlined :class="`${prefixCls}__icon`" />
<span v-if="showText">{{ getLangText }}</span>
<Icon icon="cil:language" />
<span v-if="showText" :class="`${prefixCls}__text`">{{ getLangText }}</span>
</span>
</Dropdown>
</template>
@@ -30,9 +30,10 @@
import { propTypes } from '/@/utils/propTypes';
import { useDesign } from '/@/hooks/web/useDesign';
import Icon from '/@/components/Icon';
export default defineComponent({
name: 'AppLocalPicker',
components: { GlobalOutlined, Dropdown },
components: { GlobalOutlined, Dropdown, Icon },
props: {
// Whether to display text
showText: propTypes.bool.def(true),
@@ -88,8 +89,8 @@
align-items: center;
cursor: pointer;
&__icon {
margin-right: 4px;
&__text {
margin-left: 6px;
}
}
</style>

View File

@@ -87,7 +87,7 @@
}
&__title {
font-size: 18px;
font-size: 16px;
font-weight: 700;
opacity: 0;
transition: all 0.5s;

View File

@@ -3,11 +3,13 @@
</template>
<script lang="ts">
import type { PropType } from 'vue';
import { defineComponent, toRefs } from 'vue';
import { defineComponent, toRefs, ref } from 'vue';
import { createAppProviderContext } from './useAppContext';
import designSetting from '/@/settings/designSetting';
import { createBreakpointListen } from '/@/hooks/event/useBreakpoint';
export default defineComponent({
name: 'AppProvider',
inheritAttrs: false,
@@ -18,8 +20,17 @@
},
},
setup(props) {
const isMobileRef = ref(false);
createBreakpointListen(({ screenMap, sizeEnum, width }) => {
const lgWidth = screenMap.get(sizeEnum.LG);
if (lgWidth) {
isMobileRef.value = width.value - 1 < lgWidth;
}
});
const { prefixCls } = toRefs(props);
createAppProviderContext({ prefixCls });
createAppProviderContext({ prefixCls, isMobile: isMobileRef });
return {};
},
});

View File

@@ -50,6 +50,6 @@
@prefix-cls: ~'@{namespace}-app-search';
.@{prefix-cls} {
padding: 0 10px;
padding: 2px;
}
</style>

View File

@@ -3,6 +3,8 @@ import { createContext, useContext } from '/@/hooks/core/useContext';
export interface AppProviderContextProps {
prefixCls: Ref<string>;
isMobile: Ref<boolean>;
}
const key: InjectionKey<AppProviderContextProps> = Symbol();

View File

@@ -77,7 +77,7 @@ export default defineComponent({
onMounted(update);
return () => (
<div ref={elRef} class={[attrs.class, 'app-iconify anticon']} style={unref(wrapStyleRef)} />
<span ref={elRef} class={[attrs.class, 'app-iconify anticon']} style={unref(wrapStyleRef)} />
);
},
});

View File

@@ -1,79 +1,62 @@
<template>
<slot name="header" v-if="!getIsHorizontal" />
<ScrollContainer :class="`${prefixCls}-wrapper`" :style="getWrapperStyle">
<Menu
:selectedKeys="selectedKeys"
:defaultSelectedKeys="defaultSelectedKeys"
:mode="mode"
:openKeys="getOpenKeys"
:inlineIndent="inlineIndent"
:theme="theme"
@openChange="handleOpenChange"
:class="getMenuClass"
@click="handleMenuClick"
:subMenuOpenDelay="0.2"
v-bind="getInlineCollapseOptions"
>
<template v-for="item in items" :key="item.path">
<BasicSubMenuItem
:item="item"
:theme="theme"
:level="1"
:appendClass="appendClass"
:parentPath="currentParentPath"
:showTitle="showTitle"
:isHorizontal="isHorizontal"
/>
</template>
</Menu>
</ScrollContainer>
<Menu
:selectedKeys="selectedKeys"
:defaultSelectedKeys="defaultSelectedKeys"
:mode="mode"
:openKeys="getOpenKeys"
:inlineIndent="inlineIndent"
:theme="theme"
@openChange="handleOpenChange"
:class="getMenuClass"
@click="handleMenuClick"
:subMenuOpenDelay="0.2"
v-bind="getInlineCollapseOptions"
>
<template v-for="item in items" :key="item.path">
<BasicSubMenuItem
:item="item"
:theme="theme"
:level="1"
:showTitle="showTitle"
:isHorizontal="isHorizontal"
/>
</template>
</Menu>
</template>
<script lang="ts">
import type { MenuState } from './types';
import {
computed,
defineComponent,
unref,
reactive,
watch,
toRefs,
ref,
CSSProperties,
} from 'vue';
import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue';
import { Menu } from 'ant-design-vue';
import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
import { ScrollContainer } from '/@/components/Container';
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { appStore } from '/@/store/modules/app';
import { useOpenKeys } from './useOpenKeys';
import { useRouter } from 'vue-router';
import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
import { isFunction } from '/@/utils/is';
import { getCurrentParentPath } from '/@/router/menus';
import { basicProps } from './props';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { REDIRECT_NAME } from '/@/router/constant';
import { tabStore } from '/@/store/modules/tab';
import { useDesign } from '/@/hooks/web/useDesign';
import { getCurrentParentPath } from '/@/router/menus';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
export default defineComponent({
name: 'BasicMenu',
components: {
Menu,
ScrollContainer,
BasicSubMenuItem,
// BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
},
props: basicProps,
emits: ['menuClick'],
setup(props, { emit }) {
const currentParentPath = ref('');
const isClickGo = ref(false);
const menuState = reactive<MenuState>({
@@ -97,18 +80,24 @@
accordion
);
const getMenuClass = computed(() => {
const getIsTopMenu = computed(() => {
const { type, mode } = props;
return (
(type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
(props.isHorizontal && unref(getSplit))
);
});
const getMenuClass = computed(() => {
return [
prefixCls,
`justify-${unref(getTopMenuAlign)}`,
{
[`${prefixCls}--hide-title`]: !unref(showTitle),
[`${prefixCls}--collapsed-show-title`]: props.collapsedShowTitle,
[`${prefixCls}__second`]:
!props.isHorizontal && appStore.getProjectConfig.menuSetting.split,
[`${prefixCls}__sidebar-hor`]:
type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL,
[`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
[`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
},
];
});
@@ -125,23 +114,10 @@
return inlineCollapseOptions;
});
const getWrapperStyle = computed(
(): CSSProperties => {
return {
height: `calc(100% - ${props.showLogo ? '48px' : '0px'})`,
overflowY: 'hidden',
};
}
);
watch(
() => tabStore.getCurrentTab,
() => {
if (unref(currentRoute).name === REDIRECT_NAME) return;
handleMenuChange();
unref(getSplit) && getParentPath();
}
);
listenerLastChangeTab((route) => {
if (route.name === REDIRECT_NAME) return;
handleMenuChange(route);
}, false);
watch(
() => props.items,
@@ -153,16 +129,6 @@
}
);
getParentPath();
async function getParentPath() {
const { appendClass } = props;
if (!appendClass) return '';
const parentPath = await getCurrentParentPath(unref(currentRoute).path);
currentParentPath.value = parentPath;
}
async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
const { beforeClickFn } = props;
if (beforeClickFn && isFunction(beforeClickFn)) {
@@ -176,28 +142,31 @@
menuState.selectedKeys = [key];
}
function handleMenuChange() {
async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
if (unref(isClickGo)) {
isClickGo.value = false;
return;
}
const path = unref(currentRoute).path;
const path = (route || unref(currentRoute)).path;
if (props.mode !== MenuModeEnum.HORIZONTAL) {
setOpenKeys(path);
}
menuState.selectedKeys = [path];
if (unref(getIsTopMenu)) {
const parentPath = await getCurrentParentPath(path);
menuState.selectedKeys = [parentPath];
} else {
menuState.selectedKeys = [path];
}
}
return {
prefixCls,
getIsHorizontal,
getWrapperStyle,
handleMenuClick,
getInlineCollapseOptions,
getMenuClass,
handleOpenChange,
getOpenKeys,
currentParentPath,
showTitle,
...toRefs(menuState),
};

View File

@@ -1,96 +0,0 @@
import type { Menu as MenuType } from '/@/router/types';
import type { PropType } from 'vue';
import { computed, unref } from 'vue';
import { defineComponent } from 'vue';
import Icon from '/@/components/Icon/index';
import { useI18n } from '/@/hooks/web/useI18n';
import { useDesign } from '/@/hooks/web/useDesign';
const { t } = useI18n();
export default defineComponent({
name: 'MenuContent',
props: {
item: {
type: Object as PropType<MenuType>,
default: null,
},
showTitle: {
type: Boolean as PropType<boolean>,
default: true,
},
level: {
type: Number as PropType<number>,
default: 0,
},
isHorizontal: {
type: Boolean as PropType<boolean>,
default: true,
},
},
setup(props) {
const { prefixCls } = useDesign('basic-menu');
const getI18nName = computed(() => t(props.item?.name));
const getTagClass = computed(() => {
const { item } = props;
const { tag = {} } = item || {};
const { dot, type = 'error' } = tag;
return [
`${prefixCls}__tag`,
type,
{
dot,
},
];
});
const getNameClass = computed(() => {
const { showTitle } = props;
return { [`${prefixCls}--show-title`]: showTitle, [`${prefixCls}__name`]: !showTitle };
});
/**
* @description: 渲染图标
*/
function renderIcon(icon?: string) {
return icon ? <Icon icon={icon} size={18} class="menu-item-icon" /> : null;
}
function renderTag() {
const { item, showTitle, isHorizontal } = props;
if (!item || showTitle || isHorizontal) return null;
const { tag } = item;
if (!tag) return null;
const { dot, content } = tag;
if (!dot && !content) return null;
return <span class={unref(getTagClass)}>{dot ? '' : content}</span>;
}
return () => {
const { item } = props;
if (!item) {
return null;
}
const { icon } = item;
const name = unref(getI18nName);
return (
<span class={`${prefixCls}__content-wrapper`}>
{renderIcon(icon)}
{
<span class={unref(getNameClass)}>
{name}
{renderTag()}
</span>
}
</span>
);
};
},
});

View File

@@ -1,6 +1,6 @@
<template>
<MenuItem :class="getLevelClass">
<MenuContent v-bind="$props" :item="item" />
<MenuItemContent v-bind="$props" :item="item" />
</MenuItem>
</template>
<script lang="ts">
@@ -9,25 +9,18 @@
import { useDesign } from '/@/hooks/web/useDesign';
import { itemProps } from '../props';
import MenuContent from '../MenuContent';
import MenuItemContent from './MenuItemContent.vue';
export default defineComponent({
name: 'BasicMenuItem',
components: { MenuItem: Menu.Item, MenuContent },
components: { MenuItem: Menu.Item, MenuItemContent },
props: itemProps,
setup(props) {
const { prefixCls } = useDesign('basic-menu-item');
const getLevelClass = computed(() => {
const { appendClass, level, item, parentPath, theme } = props;
const isAppendActiveCls = appendClass && level === 1 && item.path === parentPath;
const { level, theme } = props;
const levelCls = [
`${prefixCls}__level${level}`,
theme,
{
'top-active-menu': isAppendActiveCls,
},
];
const levelCls = [`${prefixCls}__level${level}`, theme];
return levelCls;
});
return {

View File

@@ -2,7 +2,7 @@
<BasicMenuItem v-if="!menuHasChildren(item)" v-bind="$props" />
<SubMenu v-else :class="[`${prefixCls}__level${level}`, theme]">
<template #title>
<MenuContent v-bind="$props" :item="item" />
<MenuItemContent v-bind="$props" :item="item" />
</template>
<!-- <template #expandIcon="{ key }">
<ExpandIcon :key="key" />
@@ -21,17 +21,17 @@
import { useDesign } from '/@/hooks/web/useDesign';
import { itemProps } from '../props';
import BasicMenuItem from './BasicMenuItem.vue';
import MenuContent from '../MenuContent';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import MenuItemContent from './MenuItemContent.vue';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export default defineComponent({
name: 'BasicSubMenuItem',
isSubMenu: true,
components: {
BasicMenuItem,
SubMenu: Menu.SubMenu,
MenuItem: Menu.Item,
MenuContent,
MenuItemContent,
// ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
},
props: itemProps,

View File

@@ -0,0 +1,41 @@
<template>
<span :class="`${prefixCls}-wrapper`">
<Icon v-if="getIcon" :icon="getIcon" :size="18" :class="`${prefixCls}-wrapper__icon`" />
<span :class="getNameClass">
{{ getI18nName }}
<MenuItemTag v-bind="$props" />
</span>
</span>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
import Icon from '/@/components/Icon/index';
import { useI18n } from '/@/hooks/web/useI18n';
import { useDesign } from '/@/hooks/web/useDesign';
import { contentProps } from '../props';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
const { t } = useI18n();
export default defineComponent({
name: 'MenuItemContent',
components: { Icon, MenuItemTag: createAsyncComponent(() => import('./MenuItemTag.vue')) },
props: contentProps,
setup(props) {
const { prefixCls } = useDesign('basic-menu-item-content');
const getI18nName = computed(() => t(props.item?.name));
const getIcon = computed(() => props.item?.icon);
const getNameClass = computed(() => {
const { showTitle } = props;
return { [`${prefixCls}--show-title`]: showTitle, [`${prefixCls}__name`]: !showTitle };
});
return {
prefixCls,
getNameClass,
getI18nName,
getIcon,
};
},
});
</script>

View File

@@ -0,0 +1,56 @@
<template>
<span :class="getTagClass" v-if="getShowTag">{{ getContent }}</span>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { contentProps } from '../props';
export default defineComponent({
name: 'MenuItemTag',
props: contentProps,
setup(props) {
const { prefixCls } = useDesign('basic-menu-item-tag');
const getShowTag = computed(() => {
const { item, showTitle, isHorizontal } = props;
if (!item || showTitle || isHorizontal) return false;
const { tag } = item;
if (!tag) return false;
const { dot, content } = tag;
if (!dot && !content) return false;
return true;
});
const getContent = computed(() => {
if (!getShowTag.value) return '';
const { item } = props;
const { tag } = item;
const { dot, content } = tag!;
return dot ? '' : content;
});
const getTagClass = computed(() => {
const { item } = props;
const { tag = {} } = item || {};
const { dot, type = 'error' } = tag;
return [
prefixCls,
[`${prefixCls}--${type}`],
{
[`${prefixCls}--dot`]: dot,
},
];
});
return {
prefixCls,
getTagClass,
getShowTag,
getContent,
};
},
});
</script>

View File

@@ -1,6 +1,8 @@
@import (reference) '../../../design/index.less';
@basic-menu-prefix-cls: ~'@{namespace}-basic-menu';
@basic-menu-content-prefix-cls: ~'@{namespace}-basic-menu-item-content';
@basic-menu-tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag';
.active-style() {
color: @white;
@@ -41,7 +43,7 @@
// }
// collapsed show title start
&--show-title {
.@{basic-menu-content-prefix-cls}--show-title {
max-width: unset !important;
opacity: 1 !important;
}
@@ -78,104 +80,34 @@
& > li > .ant-menu-submenu-title {
line-height: 24px;
}
.@{basic-menu-prefix-cls}__content-wrapper {
.@{basic-menu-content-prefix-cls}-wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.@{basic-menu-prefix-cls}--show-title {
.@{basic-menu-content-prefix-cls}--show-title {
line-height: 30px;
}
}
}
.@{basic-menu-content-prefix-cls}-wrapper {
width: 100%;
&__icon {
vertical-align: text-top;
}
}
.ant-menu-item {
transition: unset;
}
// scrollbar -s tart
// &-wrapper {
/* 滚动槽 */
// &::-webkit-scrollbar {
// width: 5px;
// height: 5px;
// }
// &::-webkit-scrollbar-track {
// background: rgba(0, 0, 0, 0);
// }
// &::-webkit-scrollbar-thumb {
// background: rgba(255, 255, 255, 0.2);
// border-radius: 3px;
// box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
// }
// ::-webkit-scrollbar-thumb:hover {
// background: @border-color-dark;
// }
// }
// scrollbar end
&-item__level1.light {
&.top-active-menu {
top: 0 !important;
}
&.top-active-menu:not(.ant-menu-item-selected) {
color: @primary-color;
border-bottom: 3px solid @primary-color;
}
}
&__sidebar-hor {
// overflow: hidden;
&.ant-menu-horizontal {
display: flex;
border: 0;
align-items: center;
.@{basic-menu-prefix-cls}-item__level1 {
margin-right: 2px;
}
&.ant-menu-light {
.ant-menu-item {
&.@{basic-menu-prefix-cls}-item__level1 {
height: @header-height;
line-height: @header-height;
}
}
.ant-menu-submenu:hover,
.ant-menu-item-open,
.ant-menu-submenu-open,
.ant-menu-item-selected,
.ant-menu-submenu-selected,
.ant-menu-item:hover,
.ant-menu-item-active,
.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-submenu-active,
.ant-menu-submenu-title:hover {
color: @primary-color !important;
border-bottom: 3px solid @primary-color;
}
.ant-menu-submenu {
&:hover {
border-bottom: 3px solid @primary-color;
}
&.ant-menu-selected,
&.ant-menu-submenu-selected {
border-bottom: 3px solid @primary-color;
}
}
}
&.ant-menu-dark {
background: transparent;
@@ -204,12 +136,6 @@
.@{basic-menu-prefix-cls}-item__level1 {
background: transparent;
&.top-active-menu {
color: @white;
background: @top-menu-active-bg-color;
border-radius: 2px 2px 0 0;
}
&.ant-menu-item-selected,
&.ant-menu-submenu-selected {
background: @top-menu-active-bg-color !important;
@@ -292,7 +218,7 @@
}
&.ant-menu-light:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
overflow: hidden;
// overflow: hidden;
border-right: none;
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
@@ -301,26 +227,32 @@
}
}
// 激活的子菜单样式
.ant-menu-item.ant-menu-item-selected {
position: relative;
}
&.@{basic-menu-prefix-cls}__second.ant-menu-inline-collapsed:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
// Reset menu item row height
.ant-menu-item,
.ant-menu-sub.ant-menu-inline > .ant-menu-item,
.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
.@{basic-menu-prefix-cls}-item__level1 {
display: flex;
height: @app-menu-item-height * 1.4;
padding: 6px 0 !important;
margin: 0;
font-size: 12px;
line-height: @app-menu-item-height;
align-items: center;
text-align: center;
> div {
padding: 6px 0 !important;
font-size: 12px;
}
.@{basic-menu-content-prefix-cls}__name {
display: inline-block;
width: 50%;
overflow: hidden;
}
}
}
.@{basic-menu-prefix-cls}__tag {
.@{basic-menu-tag-prefix-cls} {
position: absolute;
top: calc(50% - 8px);
right: 30px;
@@ -332,7 +264,7 @@
color: #fff;
border-radius: 2px;
&.dot {
&--dot {
top: calc(50% - 4px);
width: 8px;
height: 8px;
@@ -340,19 +272,19 @@
border-radius: 50%;
}
&.primary {
&--primary {
background: @primary-color;
}
&.error {
&--error {
background: @error-color;
}
&.success {
&--success {
background: @success-color;
}
&.warn {
&--warn {
background: @warning-color;
}
}
@@ -362,10 +294,6 @@
transition: unset;
}
// .ant-menu-submenu-arrow {
// transition: all 0.15s ease 0s;
// }
.ant-menu-inline.ant-menu-sub {
box-shadow: unset !important;
transition: unset;
@@ -384,10 +312,10 @@
// collapsed show title end
.ant-menu-item,
.ant-menu-submenu-title {
> .@{basic-menu-prefix-cls}__name {
> .@{basic-menu-content-prefix-cls}__name {
width: 100%;
.@{basic-menu-prefix-cls}__tag {
.@{basic-menu-tag-prefix-cls} {
float: right;
margin-top: @app-menu-item-height / 2;
transform: translate(0%, -50%);

View File

@@ -9,7 +9,6 @@ export const basicProps = {
type: Array as PropType<Menu[]>,
default: () => [],
},
appendClass: propTypes.bool,
collapsedShowTitle: propTypes.bool,
@@ -42,8 +41,16 @@ export const itemProps = {
},
level: propTypes.number,
theme: propTypes.oneOf(['dark', 'light']),
appendClass: propTypes.bool,
parentPath: propTypes.string,
showTitle: propTypes.bool,
isHorizontal: propTypes.bool,
};
export const contentProps = {
item: {
type: Object as PropType<Menu>,
default: null,
},
showTitle: propTypes.bool.def(true),
level: propTypes.number.def(0),
isHorizontal: propTypes.bool.def(true),
};

View File

@@ -42,6 +42,8 @@ export function useOpenKeys(
if (unref(mode) === MenuModeEnum.HORIZONTAL || !unref(accordion)) {
menuState.openKeys = openKeys;
} else {
// const menuList = toRaw(menus.value);
// getAllParentPath(menuList, path);
const rootSubMenuKeys: string[] = [];
for (const { children, path } of unref(menus)) {
if (children && children.length > 0) {

View File

@@ -22,11 +22,13 @@
});
</script>
<style lang="less" scoped>
@import (reference) '../../../design/index.less';
.app-footer {
position: fixed;
right: 0;
bottom: 0;
z-index: 99;
z-index: @page-footer-z-index;
display: flex;
width: 100%;
align-items: center;

View File

@@ -6,7 +6,7 @@
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
z-index: @preview-comp-z-index;
background: rgba(0, 0, 0, 0.5);
user-select: none;

View File

@@ -55,7 +55,6 @@
import { checkFileType, checkImgType, getBase64WithFile } from './helper';
import { buildUUID } from '/@/utils/uuid';
import { createImgPreview } from '/@/components/Preview/index';
import { uploadApi } from '/@/api/sys/upload';
import { isFunction } from '/@/utils/is';
import { warn } from '/@/utils/log';
import FileList from './FileList';
@@ -176,7 +175,7 @@
}
try {
item.status = UploadResultStatus.UPLOADING;
const { data } = await uploadApi(
const { data } = await props.api?.(
{
...(props.uploadParams || {}),
file: item.file,