mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-01-23 17:50:25 +08:00
chore(deps): 升级最新依赖 (#3743)
* chore: update deps * fix: eslint * chore: update deps * fix: typecheck
This commit is contained in:
parent
302e2125ba
commit
87541da27c
@ -32,17 +32,17 @@
|
||||
"stub": "pnpm unbuild --stub"
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8.4.35",
|
||||
"postcss": "^8.4.38",
|
||||
"postcss-html": "^1.6.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"prettier": "^3.2.5",
|
||||
"stylelint": "^16.2.1",
|
||||
"stylelint": "^16.3.1",
|
||||
"stylelint-config-property-sort-order-smacss": "^10.0.0",
|
||||
"stylelint-config-recommended-scss": "^14.0.0",
|
||||
"stylelint-config-recommended-vue": "^1.5.0",
|
||||
"stylelint-config-standard": "^36.0.0",
|
||||
"stylelint-config-standard-scss": "^13.0.0",
|
||||
"stylelint-config-standard-scss": "^13.1.0",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"stylelint-prettier": "^5.0.0"
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
"node-server.json"
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/node": "^20.11.19",
|
||||
"vite": "^5.1.3"
|
||||
"@types/node": "^20.12.7",
|
||||
"vite": "^5.2.9"
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"vite": "^5.1.3"
|
||||
"vite": "^5.2.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
@ -41,16 +41,16 @@
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"ant-design-vue": "^4.1.2",
|
||||
"dayjs": "^1.11.10",
|
||||
"dotenv": "^16.4.4",
|
||||
"dotenv": "^16.4.5",
|
||||
"fs-extra": "^11.2.0",
|
||||
"less": "^4.2.0",
|
||||
"picocolors": "^1.0.0",
|
||||
"pkg-types": "^1.0.3",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.71.0",
|
||||
"unocss": "0.58.5",
|
||||
"sass": "^1.75.0",
|
||||
"unocss": "0.59.4",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-dts": "^3.7.2",
|
||||
"vite-plugin-dts": "^3.8.3",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-purge-icons": "^0.10.0",
|
||||
|
62
package.json
62
package.json
@ -70,51 +70,51 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@iconify/iconify": "^3.1.1",
|
||||
"@logicflow/core": "^1.2.22",
|
||||
"@logicflow/extension": "^1.2.22",
|
||||
"@logicflow/core": "^1.2.26",
|
||||
"@logicflow/extension": "^1.2.26",
|
||||
"@vben/hooks": "workspace:*",
|
||||
"@vue/shared": "^3.4.19",
|
||||
"@vueuse/core": "^10.7.2",
|
||||
"@vue/shared": "^3.4.23",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"ant-design-vue": "^4.1.2",
|
||||
"axios": "^1.6.7",
|
||||
"axios": "^1.6.8",
|
||||
"codemirror": "^5.65.16",
|
||||
"cropperjs": "^1.6.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.4.3",
|
||||
"echarts": "^5.5.0",
|
||||
"exceljs": "^4.4.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.1",
|
||||
"path-to-regexp": "^6.2.2",
|
||||
"pinia": "2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"print-js": "^1.6.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"qs": "^6.11.2",
|
||||
"qs": "^6.12.1",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"showdown": "^2.1.0",
|
||||
"sortablejs": "^1.15.2",
|
||||
"tinymce": "^5.10.9",
|
||||
"unocss": "^0.58.5",
|
||||
"vditor": "^3.9.9",
|
||||
"vue": "^3.4.19",
|
||||
"vue-i18n": "^9.9.1",
|
||||
"vue-json-pretty": "^2.3.0",
|
||||
"vue-router": "^4.2.5",
|
||||
"unocss": "^0.59.4",
|
||||
"vditor": "^3.10.4",
|
||||
"vue": "^3.4.23",
|
||||
"vue-i18n": "^9.13.0",
|
||||
"vue-json-pretty": "^2.4.0",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue-types": "^5.1.1",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vxe-table": "^4.5.18",
|
||||
"vxe-table": "^4.5.22",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.1",
|
||||
"xe-utils": "^3.5.20",
|
||||
"xe-utils": "^3.5.24",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^18.6.1",
|
||||
"@commitlint/config-conventional": "^18.6.2",
|
||||
"@iconify/json": "^2.2.183",
|
||||
"@commitlint/cli": "^19.2.2",
|
||||
"@commitlint/config-conventional": "^19.2.2",
|
||||
"@iconify/json": "^2.2.202",
|
||||
"@purge-icons/generated": "^0.10.0",
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
@ -122,7 +122,7 @@
|
||||
"@types/mockjs": "^1.0.10",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@types/qs": "^6.9.11",
|
||||
"@types/qs": "^6.9.15",
|
||||
"@types/showdown": "^2.0.6",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@vben/eslint-config": "workspace:*",
|
||||
@ -130,25 +130,25 @@
|
||||
"@vben/ts-config": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vben/vite-config": "workspace:*",
|
||||
"@vue/compiler-sfc": "^3.4.19",
|
||||
"@vue/test-utils": "^2.4.4",
|
||||
"@vue/compiler-sfc": "^3.4.23",
|
||||
"@vue/test-utils": "^2.4.5",
|
||||
"cross-env": "^7.0.3",
|
||||
"cz-git": "^1.8.0",
|
||||
"czg": "^1.8.0",
|
||||
"cz-git": "^1.9.1",
|
||||
"czg": "^1.9.1",
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "15.2.2",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-packagejson": "^2.4.11",
|
||||
"prettier-plugin-packagejson": "^2.5.0",
|
||||
"rimraf": "^5.0.5",
|
||||
"turbo": "^1.12.4",
|
||||
"typescript": "^5.3.3",
|
||||
"turbo": "^1.13.2",
|
||||
"typescript": "^5.4.5",
|
||||
"unbuild": "^2.0.0",
|
||||
"vite": "^5.1.3",
|
||||
"vite": "^5.2.9",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-vue-inspector": "^4.0.2",
|
||||
"vue-tsc": "^1.8.27"
|
||||
"vite-plugin-vue-inspector": "^5.0.0",
|
||||
"vue-tsc": "^2.0.13"
|
||||
},
|
||||
"packageManager": "pnpm@9.0.2",
|
||||
"packageManager": "pnpm@9.0.4",
|
||||
"engines": {
|
||||
"node": ">=18.12.0",
|
||||
"pnpm": ">=9.0.2"
|
||||
|
@ -30,9 +30,9 @@
|
||||
"lint": "pnpm eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^10.7.2",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"vue": "^3.4.19"
|
||||
"vue": "^3.4.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vben/types": "workspace:*"
|
||||
|
16889
pnpm-lock.yaml
generated
16889
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -66,7 +66,11 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref, emit: A
|
||||
const ret: SearchResult[] = [];
|
||||
filterMenu.forEach((item) => {
|
||||
const { name, path, icon, children, hideMenu, meta } = item;
|
||||
if (!hideMenu && reg.test(name?.toLowerCase()) && (!children?.length || meta?.hideChildrenInMenu)) {
|
||||
if (
|
||||
!hideMenu &&
|
||||
reg.test(name?.toLowerCase()) &&
|
||||
(!children?.length || meta?.hideChildrenInMenu)
|
||||
) {
|
||||
ret.push({
|
||||
name: parent?.name ? `${parent.name} > ${name}` : name,
|
||||
path,
|
||||
|
@ -46,7 +46,7 @@
|
||||
type: Array,
|
||||
},
|
||||
api: {
|
||||
type: Function as PropType<(arg?: any) => Promise<Option[] | Recordable<any>>> ,
|
||||
type: Function as PropType<(arg?: any) => Promise<Option[] | Recordable<any>>>,
|
||||
default: null,
|
||||
},
|
||||
numberToString: propTypes.bool,
|
||||
|
@ -25,7 +25,7 @@
|
||||
const props = defineProps({
|
||||
value: { type: Array as PropType<Array<string>> },
|
||||
api: {
|
||||
type: Function as PropType<(arg) => Promise<TransferItem[] | Recordable<any>>> ,
|
||||
type: Function as PropType<(arg) => Promise<TransferItem[] | Recordable<any>>>,
|
||||
default: null,
|
||||
},
|
||||
params: { type: Object },
|
||||
|
@ -194,7 +194,7 @@ export function useTableScroll(
|
||||
let modalElIterator: HTMLElement = tableEl.parentElement!;
|
||||
let modalIsFullscreen = false;
|
||||
while (modalElIterator !== document.body) {
|
||||
if(!modalElIterator) break;
|
||||
if (!modalElIterator) break;
|
||||
if (modalElIterator.classList.contains('ant-modal')) {
|
||||
modalEl = modalElIterator;
|
||||
modalWrapEl = modalEl.parentElement;
|
||||
|
@ -34,8 +34,8 @@
|
||||
@register="registerPreviewModal"
|
||||
@list-change="handlePreviewChange"
|
||||
@delete="handlePreviewDelete"
|
||||
v-bind:preview-columns="props.previewColumns"
|
||||
v-bind:before-preview-data="props.beforePreviewData"
|
||||
:preview-columns="props.previewColumns"
|
||||
:before-preview-data="props.beforePreviewData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -53,8 +53,10 @@
|
||||
return () => {
|
||||
const { columns, actionColumn, dataSource } = props;
|
||||
let columnList: FileBasicColumn[];
|
||||
columnList = (actionColumn ? [...columns, actionColumn] : [...columns]) as FileBasicColumn[];
|
||||
|
||||
columnList = (
|
||||
actionColumn ? [...columns, actionColumn] : [...columns]
|
||||
) as FileBasicColumn[];
|
||||
|
||||
return (
|
||||
// x scrollbar
|
||||
<div class="overflow-x-auto">
|
||||
|
@ -26,24 +26,23 @@
|
||||
|
||||
const emit = defineEmits(['list-change', 'register', 'delete']);
|
||||
|
||||
let columns : BasicColumn[] | FileBasicColumn[] = createPreviewColumns();
|
||||
let actionColumn :any;
|
||||
let columns: BasicColumn[] | FileBasicColumn[] = createPreviewColumns();
|
||||
let actionColumn: any;
|
||||
|
||||
const [register] = useModalInner();
|
||||
const { t } = useI18n();
|
||||
|
||||
const fileListRef = ref<PreviewFileItem[] | Array<any>>([]);
|
||||
watch(
|
||||
watch(
|
||||
() => props.previewColumns,
|
||||
() => {
|
||||
if (props.previewColumns.length) {
|
||||
columns = props.previewColumns;
|
||||
actionColumn = null
|
||||
}else{
|
||||
columns=createPreviewColumns();
|
||||
actionColumn = createPreviewActionColumn({ handleRemove, handleDownload })
|
||||
};
|
||||
|
||||
actionColumn = null;
|
||||
} else {
|
||||
columns = createPreviewColumns();
|
||||
actionColumn = createPreviewActionColumn({ handleRemove, handleDownload });
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
@ -52,17 +51,17 @@
|
||||
() => props.value,
|
||||
(value) => {
|
||||
if (!isArray(value)) value = [];
|
||||
if(props.beforePreviewData){
|
||||
value = props.beforePreviewData(value) as any
|
||||
fileListRef.value = value
|
||||
return
|
||||
if (props.beforePreviewData) {
|
||||
value = props.beforePreviewData(value) as any;
|
||||
fileListRef.value = value;
|
||||
return;
|
||||
}
|
||||
fileListRef.value = value
|
||||
.filter((item) => !!item)
|
||||
.map((item) => {
|
||||
if(typeof item!="string"){
|
||||
console.error("return value should be string")
|
||||
return
|
||||
if (typeof item != 'string') {
|
||||
console.error('return value should be string');
|
||||
return;
|
||||
}
|
||||
return {
|
||||
url: item,
|
||||
|
@ -16,17 +16,17 @@ type SortableOptions = Merge<
|
||||
>;
|
||||
|
||||
export const previewType = {
|
||||
previewColumns:{
|
||||
type: Array as (PropType<BasicColumn[] | FileBasicColumn[]>),
|
||||
previewColumns: {
|
||||
type: Array as PropType<BasicColumn[] | FileBasicColumn[]>,
|
||||
default: [],
|
||||
required: false,
|
||||
},
|
||||
beforePreviewData:{
|
||||
type: Function as PropType<(arg:string[])=>Recordable<any>>,
|
||||
beforePreviewData: {
|
||||
type: Function as PropType<(arg: string[]) => Recordable<any>>,
|
||||
default: null,
|
||||
required: false,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
type ListType = 'text' | 'picture' | 'picture-card';
|
||||
|
||||
@ -90,7 +90,7 @@ export const basicProps = {
|
||||
|
||||
export const uploadContainerProps = {
|
||||
value: {
|
||||
type: Array as (PropType<string[]>),
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
...basicProps,
|
||||
@ -102,7 +102,7 @@ export const uploadContainerProps = {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
...previewType
|
||||
...previewType,
|
||||
};
|
||||
|
||||
export const previewProps = {
|
||||
@ -110,12 +110,12 @@ export const previewProps = {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
...previewType
|
||||
...previewType,
|
||||
};
|
||||
|
||||
export const fileListProps = {
|
||||
columns: {
|
||||
type: Array as (PropType<BasicColumn[] | FileBasicColumn[]> ),
|
||||
type: Array as PropType<BasicColumn[] | FileBasicColumn[]>,
|
||||
default: null,
|
||||
},
|
||||
actionColumn: {
|
||||
|
@ -1,26 +1,45 @@
|
||||
<template>
|
||||
<div :class="[prefixCls, `${prefixCls}--${theme}`]">
|
||||
<a-breadcrumb :routes="routes">
|
||||
<template #itemRender="{ route, routes: routesMatched, paths }">
|
||||
<Icon :icon="getIcon(route)" v-if="getShowBreadCrumbIcon && getIcon(route)" />
|
||||
<span v-if="!hasRedirect(routesMatched, route)">
|
||||
{{ t(route.meta.title || route.name) }}
|
||||
</span>
|
||||
<router-link v-else to="" @click="handleClick(route, paths, $event as Event)">
|
||||
{{ t(route.meta.title || route.name) }}
|
||||
</router-link>
|
||||
<Breadcrumb>
|
||||
<template v-for="routeItem in routes" :key="routeItem.name">
|
||||
<BreadcrumbItem>
|
||||
<Icon :icon="getIcon(routeItem)" v-if="getShowBreadCrumbIcon && getIcon(routeItem)" />
|
||||
<span v-if="!hasRedirect(routes, routeItem)">
|
||||
{{ t((routeItem.meta.title || routeItem.name) as string) }}
|
||||
</span>
|
||||
<router-link v-else to="" @click="handleClick(routeItem)">
|
||||
{{ t((routeItem.meta.title || routeItem.name) as string) }}
|
||||
</router-link>
|
||||
<template v-if="routeItem.children" #overlay>
|
||||
<Menu>
|
||||
<template v-for="childItem in routeItem.children" :key="childItem.name">
|
||||
<MenuItem>
|
||||
<Icon
|
||||
:icon="getIcon(childItem)"
|
||||
v-if="getShowBreadCrumbIcon && getIcon(childItem)"
|
||||
/>
|
||||
<span v-if="!hasRedirect(routes, childItem)">
|
||||
{{ t((childItem.meta?.title || childItem.name) as string) }}
|
||||
</span>
|
||||
<router-link v-else to="" @click="handleClick(childItem)">
|
||||
{{ t((childItem.meta?.title || childItem.name) as string) }}
|
||||
</router-link>
|
||||
</MenuItem>
|
||||
</template>
|
||||
</Menu>
|
||||
</template>
|
||||
</BreadcrumbItem>
|
||||
</template>
|
||||
</a-breadcrumb>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import type { RouteLocationMatched } from 'vue-router';
|
||||
import { useRouter } from 'vue-router';
|
||||
import type { Menu } from '@/router/types';
|
||||
|
||||
import { defineComponent, ref, watchEffect } from 'vue';
|
||||
import { ref, watchEffect } from 'vue';
|
||||
|
||||
import { Breadcrumb } from 'ant-design-vue';
|
||||
import { Breadcrumb, BreadcrumbItem, Menu, MenuItem } from 'ant-design-vue';
|
||||
import Icon from '@/components/Icon/Icon.vue';
|
||||
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
@ -36,121 +55,114 @@
|
||||
import { REDIRECT_NAME } from '@/router/constant';
|
||||
import { getAllParentPath } from '@/router/helper/menuHelper';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutBreadcrumb',
|
||||
components: { Icon, [Breadcrumb.name]: Breadcrumb },
|
||||
props: {
|
||||
theme: propTypes.oneOf(['dark', 'light']),
|
||||
},
|
||||
setup() {
|
||||
const routes = ref<RouteLocationMatched[]>([]);
|
||||
const { currentRoute } = useRouter();
|
||||
const { prefixCls } = useDesign('layout-breadcrumb');
|
||||
const { getShowBreadCrumbIcon } = useRootSetting();
|
||||
const go = useGo();
|
||||
defineOptions({ name: 'LayoutBreadcrumb' });
|
||||
|
||||
const { t } = useI18n();
|
||||
watchEffect(async () => {
|
||||
if (currentRoute.value.name === REDIRECT_NAME) return;
|
||||
const menus = await getMenus();
|
||||
|
||||
const routeMatched = currentRoute.value.matched;
|
||||
const cur = routeMatched?.[routeMatched.length - 1];
|
||||
let path = currentRoute.value.path;
|
||||
|
||||
if (cur && cur?.meta?.currentActiveMenu) {
|
||||
path = cur.meta.currentActiveMenu as string;
|
||||
}
|
||||
|
||||
const parent = getAllParentPath(menus, path);
|
||||
const filterMenus = menus.filter((item) => item.path === parent[0]);
|
||||
const matched = getMatched(filterMenus, parent) as any;
|
||||
|
||||
if (!matched || matched.length === 0){
|
||||
routes.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const breadcrumbList = filterItem(matched);
|
||||
|
||||
if (currentRoute.value.meta?.currentActiveMenu) {
|
||||
breadcrumbList.push({
|
||||
...currentRoute.value,
|
||||
name: currentRoute.value.meta?.title || currentRoute.value.name,
|
||||
} as unknown as RouteLocationMatched);
|
||||
}
|
||||
routes.value = breadcrumbList;
|
||||
});
|
||||
|
||||
function getMatched(menus: Menu[], parent: string[]) {
|
||||
const metched: Menu[] = [];
|
||||
menus.forEach((item) => {
|
||||
if (parent.includes(item.path)) {
|
||||
metched.push({
|
||||
...item,
|
||||
name: item.meta?.title || item.name,
|
||||
});
|
||||
}
|
||||
if (item.children?.length) {
|
||||
metched.push(...getMatched(item.children, parent));
|
||||
}
|
||||
});
|
||||
return metched;
|
||||
}
|
||||
|
||||
function filterItem(list: RouteLocationMatched[]) {
|
||||
return filter(list, (item) => {
|
||||
const { meta, name } = item;
|
||||
if (!meta) {
|
||||
return !!name;
|
||||
}
|
||||
const { title, hideBreadcrumb, hideMenu } = meta;
|
||||
if (!title || hideBreadcrumb || hideMenu) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).filter((item) => !item.meta?.hideBreadcrumb);
|
||||
}
|
||||
|
||||
function handleClick(route: RouteLocationMatched, paths: string[], e: Event) {
|
||||
e?.preventDefault();
|
||||
const { children, redirect, meta } = route;
|
||||
|
||||
if (children?.length && !redirect) {
|
||||
e?.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (meta?.carryParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (redirect && isString(redirect)) {
|
||||
go(redirect);
|
||||
} else {
|
||||
let goPath = '';
|
||||
if (paths.length === 1) {
|
||||
goPath = paths[0];
|
||||
} else {
|
||||
const ps = paths.slice(1);
|
||||
const lastPath = ps.pop() || '';
|
||||
goPath = `${lastPath}`;
|
||||
}
|
||||
goPath = /^\//.test(goPath) ? goPath : `/${goPath}`;
|
||||
go(goPath);
|
||||
}
|
||||
}
|
||||
|
||||
function hasRedirect(routes: RouteLocationMatched[], route: RouteLocationMatched) {
|
||||
return routes.indexOf(route) !== routes.length - 1;
|
||||
}
|
||||
|
||||
function getIcon(route) {
|
||||
return route.icon || route.meta?.icon;
|
||||
}
|
||||
|
||||
return { routes, t, prefixCls, getIcon, getShowBreadCrumbIcon, handleClick, hasRedirect };
|
||||
},
|
||||
defineProps({
|
||||
theme: propTypes.oneOf(['dark', 'light']),
|
||||
});
|
||||
|
||||
const routes = ref<RouteLocationMatched[]>([]);
|
||||
const { currentRoute } = useRouter();
|
||||
const { prefixCls } = useDesign('layout-breadcrumb');
|
||||
const { getShowBreadCrumbIcon } = useRootSetting();
|
||||
const go = useGo();
|
||||
|
||||
const { t } = useI18n();
|
||||
watchEffect(async () => {
|
||||
if (currentRoute.value.name === REDIRECT_NAME) return;
|
||||
const menus = await getMenus();
|
||||
|
||||
const routeMatched = currentRoute.value.matched;
|
||||
const cur = routeMatched?.[routeMatched.length - 1];
|
||||
let path = currentRoute.value.path;
|
||||
|
||||
if (cur && cur?.meta?.currentActiveMenu) {
|
||||
path = cur.meta.currentActiveMenu as string;
|
||||
}
|
||||
|
||||
const parent = getAllParentPath(menus, path);
|
||||
const filterMenus = menus.filter((item) => item.path === parent[0]);
|
||||
const matched = getMatched(filterMenus, parent) as any;
|
||||
|
||||
if (!matched || matched.length === 0) {
|
||||
routes.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const breadcrumbList = filterItem(matched);
|
||||
|
||||
if (currentRoute.value.meta?.currentActiveMenu) {
|
||||
breadcrumbList.push({
|
||||
...currentRoute.value,
|
||||
name: currentRoute.value.meta?.title || currentRoute.value.name,
|
||||
} as unknown as RouteLocationMatched);
|
||||
}
|
||||
routes.value = breadcrumbList;
|
||||
});
|
||||
|
||||
function getMatched(menus, parent: string[]) {
|
||||
const matched: any[] = [];
|
||||
menus.forEach((item) => {
|
||||
if (parent.includes(item.path)) {
|
||||
matched.push({
|
||||
...item,
|
||||
name: item.meta?.title || item.name,
|
||||
});
|
||||
}
|
||||
if (item.children?.length) {
|
||||
matched.push(...getMatched(item.children, parent));
|
||||
}
|
||||
});
|
||||
return matched;
|
||||
}
|
||||
|
||||
function filterItem(list: RouteLocationMatched[]) {
|
||||
return filter(list, (item) => {
|
||||
const { meta, name } = item;
|
||||
if (!meta) {
|
||||
return !!name;
|
||||
}
|
||||
const { title, hideBreadcrumb, hideMenu } = meta;
|
||||
if (!title || hideBreadcrumb || hideMenu) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).filter((item) => !item.meta?.hideBreadcrumb);
|
||||
}
|
||||
|
||||
function handleClick(route) {
|
||||
console.log(route);
|
||||
const { children, redirect, meta } = route;
|
||||
|
||||
if (children?.length && !redirect) {
|
||||
return;
|
||||
}
|
||||
if (meta?.carryParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (redirect && isString(redirect)) {
|
||||
go(redirect);
|
||||
} else {
|
||||
let goPath = '';
|
||||
if (route.path) {
|
||||
goPath = route.path;
|
||||
} else {
|
||||
const lastPath = '';
|
||||
goPath = `${lastPath}`;
|
||||
}
|
||||
goPath = /^\//.test(goPath) ? goPath : `/${goPath}`;
|
||||
go(goPath);
|
||||
}
|
||||
}
|
||||
|
||||
function hasRedirect(routes, route) {
|
||||
return routes.indexOf(route) !== routes.length - 1;
|
||||
}
|
||||
|
||||
function getIcon(route) {
|
||||
return route.icon || route.meta?.icon;
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
@prefix-cls: ~'@{namespace}-layout-breadcrumb';
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
<Alert message="嵌入表单,自定义预览内容" />
|
||||
<BasicForm @register="registerPreview" class="my-5" />
|
||||
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@ -27,9 +26,9 @@
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
import { BasicForm, FormSchema, useForm } from '@/components/Form';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import { Alert,Button } from 'ant-design-vue';
|
||||
import { Alert, Button } from 'ant-design-vue';
|
||||
import { uploadApi } from '@/api/sys/upload';
|
||||
import { createVNode } from "vue"
|
||||
import { createVNode } from 'vue';
|
||||
|
||||
const schemasValiate: FormSchema[] = [
|
||||
{
|
||||
@ -40,16 +39,17 @@
|
||||
componentProps: {
|
||||
api: uploadApi,
|
||||
},
|
||||
},{
|
||||
},
|
||||
{
|
||||
field: 'field2',
|
||||
component: "ImageUpload",
|
||||
component: 'ImageUpload',
|
||||
label: '字段2(ImageUpload)',
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
componentProps: {
|
||||
api: uploadApi,
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
const schemasCustom: FormSchema[] = [
|
||||
@ -58,41 +58,41 @@
|
||||
component: 'Upload',
|
||||
label: '字段3',
|
||||
componentProps: {
|
||||
resultField:"data3.url",
|
||||
api: (file,progress)=>{
|
||||
return new Promise((resolve)=>{
|
||||
uploadApi(file,progress).then((uploadApiResponse)=>{
|
||||
resultField: 'data3.url',
|
||||
api: (file, progress) => {
|
||||
return new Promise((resolve) => {
|
||||
uploadApi(file, progress).then((uploadApiResponse) => {
|
||||
resolve({
|
||||
code:200,
|
||||
data3:{
|
||||
url:uploadApiResponse.data.url
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
code: 200,
|
||||
data3: {
|
||||
url: uploadApiResponse.data.url,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'field4',
|
||||
component: "ImageUpload",
|
||||
component: 'ImageUpload',
|
||||
label: '字段4(ImageUpload)',
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
componentProps: {
|
||||
resultField:"data4.url",
|
||||
api: (file,progress)=>{
|
||||
return new Promise((resolve)=>{
|
||||
uploadApi(file,progress).then((uploadApiResponse)=>{
|
||||
resultField: 'data4.url',
|
||||
api: (file, progress) => {
|
||||
return new Promise((resolve) => {
|
||||
uploadApi(file, progress).then((uploadApiResponse) => {
|
||||
resolve({
|
||||
code:200,
|
||||
data4:{
|
||||
url:uploadApiResponse.data.url
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
code: 200,
|
||||
data4: {
|
||||
url: uploadApiResponse.data.url,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -103,117 +103,124 @@
|
||||
component: 'Upload',
|
||||
label: '字段5',
|
||||
componentProps: {
|
||||
previewColumns:[{
|
||||
title:"url5",
|
||||
dataIndex:"url5"
|
||||
},{
|
||||
title:"type5",
|
||||
dataIndex:"type5"
|
||||
},{
|
||||
title:"name5",
|
||||
dataIndex:"name5"
|
||||
},
|
||||
{
|
||||
title:"operation",
|
||||
dataIndex:"",
|
||||
customRender: ({ record })=>{
|
||||
return createVNode(Button,{
|
||||
onclick:()=>{
|
||||
console.log(record)
|
||||
createMessage.success(`请到控制台查看该行输出结果`);
|
||||
previewColumns: [
|
||||
{
|
||||
title: 'url5',
|
||||
dataIndex: 'url5',
|
||||
},
|
||||
{
|
||||
title: 'type5',
|
||||
dataIndex: 'type5',
|
||||
},
|
||||
{
|
||||
title: 'name5',
|
||||
dataIndex: 'name5',
|
||||
},
|
||||
{
|
||||
title: 'operation',
|
||||
dataIndex: '',
|
||||
customRender: ({ record }) => {
|
||||
return createVNode(
|
||||
Button,
|
||||
{
|
||||
onclick: () => {
|
||||
console.log(record);
|
||||
createMessage.success(`请到控制台查看该行输出结果`);
|
||||
},
|
||||
},
|
||||
'点我',
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
beforePreviewData: (arg) => {
|
||||
let data = arg
|
||||
.filter((item) => !!item)
|
||||
.map((item) => {
|
||||
if (typeof item !== 'string') {
|
||||
console.error('return value should be string');
|
||||
return;
|
||||
}
|
||||
},"点我")
|
||||
}
|
||||
return {
|
||||
url5: item,
|
||||
type5: item.split('.').pop() || '',
|
||||
name5: item.split('/').pop() || '',
|
||||
};
|
||||
});
|
||||
return data;
|
||||
},
|
||||
],
|
||||
beforePreviewData:(arg)=>{
|
||||
let data = arg.filter((item) => !!item).map((item) => {
|
||||
if(typeof item !== "string"){
|
||||
console.error("return value should be string")
|
||||
return
|
||||
}
|
||||
return {
|
||||
url5: item,
|
||||
type5: item.split('.').pop() || '',
|
||||
name5: item.split('/').pop() || '',
|
||||
};
|
||||
})
|
||||
return data
|
||||
},
|
||||
resultField:"data5.url",
|
||||
api: (file,progress)=>{
|
||||
return new Promise((resolve)=>{
|
||||
uploadApi(file,progress).then((uploadApiResponse)=>{
|
||||
resultField: 'data5.url',
|
||||
api: (file, progress) => {
|
||||
return new Promise((resolve) => {
|
||||
uploadApi(file, progress).then((uploadApiResponse) => {
|
||||
resolve({
|
||||
code:200,
|
||||
data5:{
|
||||
url:uploadApiResponse.data.url
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
code: 200,
|
||||
data5: {
|
||||
url: uploadApiResponse.data.url,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
function handleChange(list: string[]) {
|
||||
createMessage.success(`已上传文件${JSON.stringify(list)}`);
|
||||
}
|
||||
const [registerValiate,{getFieldsValue:getFieldsValueValiate,validate}] = useForm({
|
||||
const [registerValiate, { getFieldsValue: getFieldsValueValiate, validate }] = useForm({
|
||||
labelWidth: 160,
|
||||
schemas:schemasValiate,
|
||||
schemas: schemasValiate,
|
||||
actionColOptions: {
|
||||
span: 18,
|
||||
},
|
||||
submitFunc:()=>{
|
||||
return new Promise((resolve)=>{
|
||||
validate().then((e)=>{
|
||||
resolve()
|
||||
console.log(getFieldsValueValiate())
|
||||
createMessage.success(`请到控制台查看结果`);
|
||||
}).catch(()=>{
|
||||
createMessage.error(`请输入必填项`);
|
||||
})
|
||||
})
|
||||
}
|
||||
submitFunc: () => {
|
||||
return new Promise((resolve) => {
|
||||
validate()
|
||||
.then((_e) => {
|
||||
resolve();
|
||||
console.log(getFieldsValueValiate());
|
||||
createMessage.success(`请到控制台查看结果`);
|
||||
})
|
||||
.catch(() => {
|
||||
createMessage.error(`请输入必填项`);
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// resultFields 字段示例
|
||||
const [registerCustom,{getFieldsValue:getFieldsValueCustom}] = useForm({
|
||||
const [registerCustom, { getFieldsValue: getFieldsValueCustom }] = useForm({
|
||||
labelWidth: 160,
|
||||
schemas:schemasCustom,
|
||||
schemas: schemasCustom,
|
||||
actionColOptions: {
|
||||
span: 18,
|
||||
},
|
||||
submitFunc:()=>{
|
||||
return new Promise((resolve)=>{
|
||||
console.log(getFieldsValueCustom())
|
||||
resolve()
|
||||
submitFunc: () => {
|
||||
return new Promise((resolve) => {
|
||||
console.log(getFieldsValueCustom());
|
||||
resolve();
|
||||
createMessage.success(`请到控制台查看结果`);
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// registerPreview
|
||||
const [registerPreview,{getFieldsValue:getFieldsValuePreview}] = useForm({
|
||||
const [registerPreview, { getFieldsValue: getFieldsValuePreview }] = useForm({
|
||||
labelWidth: 160,
|
||||
schemas:schemasPreview,
|
||||
schemas: schemasPreview,
|
||||
actionColOptions: {
|
||||
span: 18,
|
||||
},
|
||||
submitFunc:()=>{
|
||||
return new Promise((resolve)=>{
|
||||
console.log(getFieldsValuePreview())
|
||||
resolve()
|
||||
submitFunc: () => {
|
||||
return new Promise((resolve) => {
|
||||
console.log(getFieldsValuePreview());
|
||||
resolve();
|
||||
createMessage.success(`请到控制台查看结果`);
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
@ -30,8 +30,8 @@
|
||||
const { setWatermark: setWatermark2 } = useWatermark();
|
||||
const { setWatermark: setWatermark3 } = useWatermark(app, {
|
||||
fontColor: 'red',
|
||||
fontSize:12,
|
||||
rotate:30
|
||||
fontSize: 12,
|
||||
rotate: 30,
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
Loading…
Reference in New Issue
Block a user