Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin
This commit is contained in:
commit
14d9bf2d73
16
.github/labeler.yml
vendored
16
.github/labeler.yml
vendored
@ -1,16 +0,0 @@
|
|||||||
# Add 'feature' label to any PR where the head branch name starts with `feature` or has a `feature` section in the name
|
|
||||||
feature:
|
|
||||||
- head-branch: ["^feat", "feat"]
|
|
||||||
|
|
||||||
bug:
|
|
||||||
- head-branch: ["^fix", "fix"]
|
|
||||||
|
|
||||||
chore:
|
|
||||||
- head-branch: ["^chore", "chore"]
|
|
||||||
|
|
||||||
perf:
|
|
||||||
- head-branch: ["^perf", "perf"]
|
|
||||||
|
|
||||||
documentation:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ["**/*.md", "docs/**"]
|
|
22
.github/workflows/labeler.yml
vendored
22
.github/workflows/labeler.yml
vendored
@ -1,22 +0,0 @@
|
|||||||
name: PR Labeler
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, edited, synchronize]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
label:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Label PR based on title or file changes
|
|
||||||
uses: actions/labeler@v5
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
configuration-path: .github/labeler.yml
|
|
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@ -9,7 +9,7 @@
|
|||||||
"url": "http://localhost:5555",
|
"url": "http://localhost:5555",
|
||||||
"env": { "NODE_ENV": "development" },
|
"env": { "NODE_ENV": "development" },
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"webRoot": "${workspaceFolder}/playground/src"
|
"webRoot": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
@ -18,7 +18,7 @@
|
|||||||
"url": "http://localhost:5666",
|
"url": "http://localhost:5666",
|
||||||
"env": { "NODE_ENV": "development" },
|
"env": { "NODE_ENV": "development" },
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"webRoot": "${workspaceFolder}/apps/web-antd/src"
|
"webRoot": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
@ -27,7 +27,7 @@
|
|||||||
"url": "http://localhost:5777",
|
"url": "http://localhost:5777",
|
||||||
"env": { "NODE_ENV": "development" },
|
"env": { "NODE_ENV": "development" },
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"webRoot": "${workspaceFolder}/apps/web-ele/src"
|
"webRoot": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"url": "http://localhost:5888",
|
"url": "http://localhost:5888",
|
||||||
"env": { "NODE_ENV": "development" },
|
"env": { "NODE_ENV": "development" },
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"webRoot": "${workspaceFolder}/apps/web-naive/src"
|
"webRoot": "${workspaceFolder}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,11 @@ const trendItems: WorkbenchTrendItem[] = [
|
|||||||
<WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" />
|
<WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full lg:w-2/5">
|
<div class="w-full lg:w-2/5">
|
||||||
<WorkbenchQuickNav :items="quickNavItems" title="快捷导航" />
|
<WorkbenchQuickNav
|
||||||
|
:items="quickNavItems"
|
||||||
|
class="mt-5 lg:mt-0"
|
||||||
|
title="快捷导航"
|
||||||
|
/>
|
||||||
<WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" />
|
<WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" />
|
||||||
<AnalysisChartCard class="mt-5" title="访问来源">
|
<AnalysisChartCard class="mt-5" title="访问来源">
|
||||||
<AnalyticsVisitsSource />
|
<AnalyticsVisitsSource />
|
||||||
|
@ -36,7 +36,7 @@ You can check the list below to understand all the available variables.
|
|||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
|
|
||||||
/* Main area background color */
|
/* Main area background color */
|
||||||
--background-deep: 210 11.11% 96.47%;
|
--background-deep: 216 20.11% 95.47%;
|
||||||
--foreground: 210 6% 21%;
|
--foreground: 210 6% 21%;
|
||||||
|
|
||||||
/* Background color for <Card /> */
|
/* Background color for <Card /> */
|
||||||
@ -111,7 +111,7 @@ You can check the list below to understand all the available variables.
|
|||||||
|
|
||||||
/* menu */
|
/* menu */
|
||||||
--sidebar: 0 0% 100%;
|
--sidebar: 0 0% 100%;
|
||||||
--sidebar-deep: 210 11.11% 96.47%;
|
--sidebar-deep: 216 20.11% 95.47%;
|
||||||
--menu: var(--sidebar);
|
--menu: var(--sidebar);
|
||||||
|
|
||||||
/* header */
|
/* header */
|
||||||
@ -330,7 +330,7 @@ type BuiltinThemeType =
|
|||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
|
|
||||||
/* Main area background color */
|
/* Main area background color */
|
||||||
--background-deep: 210 11.11% 96.47%;
|
--background-deep: 216 20.11% 95.47%;
|
||||||
--foreground: 222 84% 5%;
|
--foreground: 222 84% 5%;
|
||||||
|
|
||||||
/* Background color for <Card /> */
|
/* Background color for <Card /> */
|
||||||
|
@ -36,7 +36,7 @@ css 变量内的颜色,必须使用 `hsl` 格式,如 `0 0% 100%`,不需要
|
|||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
|
|
||||||
/* 主体区域背景色 */
|
/* 主体区域背景色 */
|
||||||
--background-deep: 210 11.11% 96.47%;
|
--background-deep: 216 20.11% 95.47%;
|
||||||
--foreground: 210 6% 21%;
|
--foreground: 210 6% 21%;
|
||||||
|
|
||||||
/* Background color for <Card /> */
|
/* Background color for <Card /> */
|
||||||
@ -111,7 +111,7 @@ css 变量内的颜色,必须使用 `hsl` 格式,如 `0 0% 100%`,不需要
|
|||||||
|
|
||||||
/* menu */
|
/* menu */
|
||||||
--sidebar: 0 0% 100%;
|
--sidebar: 0 0% 100%;
|
||||||
--sidebar-deep: 210 11.11% 96.47%;
|
--sidebar-deep: 216 20.11% 95.47%;
|
||||||
--menu: var(--sidebar);
|
--menu: var(--sidebar);
|
||||||
|
|
||||||
/* header */
|
/* header */
|
||||||
@ -330,7 +330,7 @@ type BuiltinThemeType =
|
|||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
|
|
||||||
/* 主体区域背景色 */
|
/* 主体区域背景色 */
|
||||||
--background-deep: 210 11.11% 96.47%;
|
--background-deep: 216 20.11% 95.47%;
|
||||||
--foreground: 222 84% 5%;
|
--foreground: 222 84% 5%;
|
||||||
|
|
||||||
/* Background color for <Card /> */
|
/* Background color for <Card /> */
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eslint-config-turbo": "^2.1.0",
|
"eslint-config-turbo": "^2.1.0",
|
||||||
"eslint-plugin-command": "^0.2.3",
|
"eslint-plugin-command": "^0.2.3",
|
||||||
"eslint-plugin-import-x": "^4.1.0"
|
"eslint-plugin-import-x": "^4.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.9.1",
|
"@eslint/js": "^9.9.1",
|
||||||
|
@ -36,18 +36,18 @@
|
|||||||
"nitropack": "^2.9.7",
|
"nitropack": "^2.9.7",
|
||||||
"resolve.exports": "^2.0.2",
|
"resolve.exports": "^2.0.2",
|
||||||
"vite-plugin-lib-inject-css": "^2.1.1",
|
"vite-plugin-lib-inject-css": "^2.1.1",
|
||||||
"vite-plugin-pwa": "^0.20.1",
|
"vite-plugin-pwa": "^0.20.2",
|
||||||
"vite-plugin-vue-devtools": "^7.3.9"
|
"vite-plugin-vue-devtools": "^7.3.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/archiver": "^6.0.2",
|
"@types/archiver": "^6.0.2",
|
||||||
"@types/html-minifier-terser": "^7.0.2",
|
"@types/html-minifier-terser": "^7.0.2",
|
||||||
"@vben/node-utils": "workspace:*",
|
"@vben/node-utils": "workspace:*",
|
||||||
"@vitejs/plugin-vue": "^5.1.2",
|
"@vitejs/plugin-vue": "^5.1.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"rollup": "^4.21.1",
|
"rollup": "^4.21.2",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"sass": "^1.77.8",
|
"sass": "^1.77.8",
|
||||||
"vite": "^5.4.2",
|
"vite": "^5.4.2",
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
"@vben/turbo-run": "workspace:*",
|
"@vben/turbo-run": "workspace:*",
|
||||||
"@vben/vite-config": "workspace:*",
|
"@vben/vite-config": "workspace:*",
|
||||||
"@vben/vsh": "workspace:*",
|
"@vben/vsh": "workspace:*",
|
||||||
"@vitejs/plugin-vue": "^5.1.2",
|
"@vitejs/plugin-vue": "^5.1.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
@ -93,7 +93,7 @@
|
|||||||
"vite": "^5.4.2",
|
"vite": "^5.4.2",
|
||||||
"vitest": "^2.0.5",
|
"vitest": "^2.0.5",
|
||||||
"vue": "^3.4.38",
|
"vue": "^3.4.38",
|
||||||
"vue-tsc": "^2.0.29"
|
"vue-tsc": "^2.1.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20",
|
"node": ">=20",
|
||||||
|
@ -136,7 +136,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-box {
|
.card-box {
|
||||||
@apply bg-card text-card-foreground border-border rounded-xl border shadow;
|
@apply bg-card text-card-foreground border-border rounded-xl border;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
|
|
||||||
/* 主体区域背景色 */
|
/* 主体区域背景色 */
|
||||||
--background-deep: 210 11.11% 96.47%;
|
--background-deep: 216 20.11% 95.47%;
|
||||||
--foreground: 210 6% 21%;
|
--foreground: 210 6% 21%;
|
||||||
|
|
||||||
/* Background color for <Card /> */
|
/* Background color for <Card /> */
|
||||||
@ -77,7 +77,7 @@
|
|||||||
/* ============= custom ============= */
|
/* ============= custom ============= */
|
||||||
|
|
||||||
/* 遮罩颜色 */
|
/* 遮罩颜色 */
|
||||||
--overlay: 0 0% 0% / 30%;
|
--overlay: 0 0% 0% / 45%;
|
||||||
|
|
||||||
/* 基本文字大小 */
|
/* 基本文字大小 */
|
||||||
--font-size-base: 16px;
|
--font-size-base: 16px;
|
||||||
|
@ -70,12 +70,12 @@ const defaultPreferences: Preferences = {
|
|||||||
expandOnHover: true,
|
expandOnHover: true,
|
||||||
extraCollapse: true,
|
extraCollapse: true,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
width: 230,
|
width: 224,
|
||||||
},
|
},
|
||||||
tabbar: {
|
tabbar: {
|
||||||
dragable: true,
|
dragable: true,
|
||||||
enable: true,
|
enable: true,
|
||||||
height: 36,
|
height: 38,
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
persist: true,
|
persist: true,
|
||||||
showIcon: true,
|
showIcon: true,
|
||||||
|
@ -50,7 +50,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
sidebarWidth: 180,
|
sidebarWidth: 180,
|
||||||
sideCollapseWidth: 60,
|
sideCollapseWidth: 60,
|
||||||
tabbarEnable: true,
|
tabbarEnable: true,
|
||||||
tabbarHeight: 36,
|
tabbarHeight: 40,
|
||||||
zIndex: 200,
|
zIndex: 200,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ function pointerDownOutside(e: Event) {
|
|||||||
{
|
{
|
||||||
'left-0 top-0 size-full max-h-full !translate-x-0 !translate-y-0':
|
'left-0 top-0 size-full max-h-full !translate-x-0 !translate-y-0':
|
||||||
shouldFullscreen,
|
shouldFullscreen,
|
||||||
'top-1/2 -translate-y-1/2': centered && !shouldFullscreen,
|
'top-1/2 !-translate-y-1/2': centered && !shouldFullscreen,
|
||||||
'duration-300': !dragging,
|
'duration-300': !dragging,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -28,12 +28,12 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const text = computed(() => {
|
const text = computed(() => {
|
||||||
return props.alt.slice(0, 2).toUpperCase();
|
return props.alt.slice(-2).toUpperCase();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="props.class" class="relative flex-shrink-0">
|
<div :class="props.class" class="relative flex flex-shrink-0 items-center">
|
||||||
<Avatar :class="props.class" class="size-full">
|
<Avatar :class="props.class" class="size-full">
|
||||||
<AvatarImage :alt="alt" :src="src" />
|
<AvatarImage :alt="alt" :src="src" />
|
||||||
<AvatarFallback>{{ text }}</AvatarFallback>
|
<AvatarFallback>{{ text }}</AvatarFallback>
|
||||||
|
@ -32,7 +32,7 @@ const { handleClick, visible } = useBackTop(props);
|
|||||||
<VbenButton
|
<VbenButton
|
||||||
v-if="visible"
|
v-if="visible"
|
||||||
:style="backTopStyle"
|
:style="backTopStyle"
|
||||||
class="dark:bg-accent dark:hover:bg-heavy bg-background hover:bg-heavy data shadow-float fixed bottom-10 z-[1000] h-10 w-10 rounded-full duration-500"
|
class="dark:bg-accent dark:hover:bg-heavy bg-background hover:bg-heavy data shadow-float fixed bottom-10 z-[1000] size-10 rounded-full duration-500"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="icon"
|
variant="icon"
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IBreadcrumb } from './types';
|
import type { BreadcrumbProps } from './types';
|
||||||
|
|
||||||
import { VbenIcon } from '../icon';
|
import { VbenIcon } from '../icon';
|
||||||
|
|
||||||
interface Props {
|
interface Props extends BreadcrumbProps {}
|
||||||
breadcrumbs: IBreadcrumb[];
|
|
||||||
showIcon?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({ name: 'Breadcrumb' });
|
defineOptions({ name: 'Breadcrumb' });
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { BreadcrumbProps } from './types';
|
||||||
|
|
||||||
|
import { useForwardPropsEmits } from 'radix-vue';
|
||||||
|
|
||||||
|
import Breadcrumb from './breadcrumb.vue';
|
||||||
|
import BreadcrumbBackground from './breadcrumb-background.vue';
|
||||||
|
|
||||||
|
interface Props extends BreadcrumbProps {
|
||||||
|
class?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {});
|
||||||
|
|
||||||
|
const emit = defineEmits<{ select: [string] }>();
|
||||||
|
|
||||||
|
const forward = useForwardPropsEmits(props, emit);
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Breadcrumb v-if="styleType === 'normal'" v-bind="forward" />
|
||||||
|
<BreadcrumbBackground v-if="styleType === 'background'" v-bind="forward" />
|
||||||
|
</template>
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IBreadcrumb } from './types';
|
import type { BreadcrumbProps } from './types';
|
||||||
|
|
||||||
import { ChevronDown } from '@vben-core/icons';
|
import { ChevronDown } from '@vben-core/icons';
|
||||||
|
|
||||||
@ -19,10 +19,7 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '../ui/dropdown-menu';
|
} from '../ui/dropdown-menu';
|
||||||
|
|
||||||
interface Props {
|
interface Props extends BreadcrumbProps {}
|
||||||
breadcrumbs: IBreadcrumb[];
|
|
||||||
showIcon?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({ name: 'Breadcrumb' });
|
defineOptions({ name: 'Breadcrumb' });
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
export { default as VbenBreadcrumb } from './breadcrumb.vue';
|
export { default as VbenBreadcrumbView } from './breadcrumb-view.vue';
|
||||||
export { default as VbenBackgroundBreadcrumb } from './breadcrumb-background.vue';
|
|
||||||
|
|
||||||
export type * from './types';
|
export type * from './types';
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
import type { BreadcrumbStyleType } from '@vben-core/typings';
|
||||||
|
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
|
|
||||||
interface IBreadcrumb {
|
export interface IBreadcrumb {
|
||||||
icon?: Component | string;
|
icon?: Component | string;
|
||||||
isHome?: boolean;
|
isHome?: boolean;
|
||||||
items?: IBreadcrumb[];
|
items?: IBreadcrumb[];
|
||||||
@ -8,4 +10,8 @@ interface IBreadcrumb {
|
|||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { IBreadcrumb };
|
export interface BreadcrumbProps {
|
||||||
|
breadcrumbs: IBreadcrumb[];
|
||||||
|
showIcon?: boolean;
|
||||||
|
styleType?: BreadcrumbStyleType;
|
||||||
|
}
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { VbenAvatar } from '../avatar';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* 是否收起文本
|
* @zh_CN 是否收起文本
|
||||||
*/
|
*/
|
||||||
collapsed?: boolean;
|
collapsed?: boolean;
|
||||||
/**
|
/**
|
||||||
* Logo 跳转地址
|
* @zh_CN Logo 跳转地址
|
||||||
*/
|
*/
|
||||||
href?: string;
|
href?: string;
|
||||||
/**
|
/**
|
||||||
* Logo 图片大小
|
* @zh_CN Logo 图片大小
|
||||||
*/
|
*/
|
||||||
logoSize?: number;
|
logoSize?: number;
|
||||||
/**
|
/**
|
||||||
* Logo 图标
|
* @zh_CN Logo 图标
|
||||||
*/
|
*/
|
||||||
src?: string;
|
src?: string;
|
||||||
/**
|
/**
|
||||||
* Logo 文本
|
* @zh_CN Logo 文本
|
||||||
*/
|
*/
|
||||||
text: string;
|
text: string;
|
||||||
/**
|
/**
|
||||||
* Logo 主题
|
* @zh_CN Logo 主题
|
||||||
*/
|
*/
|
||||||
theme?: string;
|
theme?: string;
|
||||||
}
|
}
|
||||||
@ -44,16 +46,18 @@ withDefaults(defineProps<Props>(), {
|
|||||||
<a
|
<a
|
||||||
:class="$attrs.class"
|
:class="$attrs.class"
|
||||||
:href="href"
|
:href="href"
|
||||||
class="flex h-full items-center gap-2 overflow-hidden px-3 text-lg font-semibold leading-normal transition-all duration-500"
|
class="flex h-full items-center gap-2 overflow-hidden px-3 text-lg leading-normal transition-all duration-500"
|
||||||
>
|
>
|
||||||
<img
|
<VbenAvatar
|
||||||
v-if="src"
|
v-if="src"
|
||||||
:alt="text"
|
:alt="text"
|
||||||
:src="src"
|
:src="src"
|
||||||
:width="logoSize"
|
class="relative w-8 rounded-none bg-transparent"
|
||||||
class="relative rounded-none bg-transparent"
|
|
||||||
/>
|
/>
|
||||||
<span v-if="!collapsed" class="text-foreground truncate text-nowrap">
|
<span
|
||||||
|
v-if="!collapsed"
|
||||||
|
class="text-foreground truncate text-nowrap font-semibold"
|
||||||
|
>
|
||||||
{{ text }}
|
{{ text }}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -12,7 +12,7 @@ const props = defineProps<{
|
|||||||
<div
|
<div
|
||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
'bg-card text-card-foreground border-border rounded-xl border shadow-sm',
|
'bg-card text-card-foreground border-border rounded-xl border',
|
||||||
props.class,
|
props.class,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -60,9 +60,9 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
ref="contentRef"
|
ref="contentRef"
|
||||||
:class="contentClass"
|
:class="contentClass"
|
||||||
:style="style"
|
:style="style"
|
||||||
class="tabs-chrome !flex h-full w-max pr-6"
|
class="tabs-chrome !flex h-full w-max overflow-y-hidden pr-6"
|
||||||
>
|
>
|
||||||
<TransitionGroup name="slide-right">
|
<TransitionGroup name="slide-down">
|
||||||
<div
|
<div
|
||||||
v-for="(tab, i) in tabsView"
|
v-for="(tab, i) in tabsView"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
@ -84,14 +84,14 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
<!-- divider -->
|
<!-- divider -->
|
||||||
<div
|
<div
|
||||||
v-if="i !== 0 && tab.key !== active"
|
v-if="i !== 0 && tab.key !== active"
|
||||||
class="tabs-chrome__divider bg-foreground/50 absolute left-[var(--gap)] top-1/2 z-0 h-4 w-[1px] translate-y-[-50%] transition-all"
|
class="tabs-chrome__divider bg-border absolute left-[var(--gap)] top-1/2 z-0 h-4 w-[1px] translate-y-[-50%] transition-all"
|
||||||
></div>
|
></div>
|
||||||
<!-- background -->
|
<!-- background -->
|
||||||
<div
|
<div
|
||||||
class="tabs-chrome__background absolute z-[-1] size-full px-[calc(var(--gap)-1px)] py-0 transition-opacity duration-150"
|
class="tabs-chrome__background absolute z-[-1] size-full px-[calc(var(--gap)-1px)] py-0 transition-opacity duration-150"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="tabs-chrome__background-content group-[.is-active]:bg-heavy dark:group-[.is-active]:bg-accent h-full rounded-tl-[var(--gap)] rounded-tr-[var(--gap)] duration-150"
|
class="tabs-chrome__background-content group-[.is-active]:bg-primary/15 dark:group-[.is-active]:bg-accent h-full rounded-tl-[var(--gap)] rounded-tr-[var(--gap)] duration-150"
|
||||||
></div>
|
></div>
|
||||||
<svg
|
<svg
|
||||||
class="tabs-chrome__background-before group-[.is-active]:fill-primary/15 dark:group-[.is-active]:fill-accent absolute bottom-0 left-[-1px] fill-transparent transition-all duration-150"
|
class="tabs-chrome__background-before group-[.is-active]:fill-primary/15 dark:group-[.is-active]:fill-accent absolute bottom-0 left-[-1px] fill-transparent transition-all duration-150"
|
||||||
@ -128,7 +128,7 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
|
|
||||||
<!-- tab-item-main -->
|
<!-- tab-item-main -->
|
||||||
<div
|
<div
|
||||||
class="tabs-chrome__item-main group-[.is-active]:text-accent-foreground dark:group-[.is-active]:text-accent-foreground text-accent-foreground z-[2] mx-[calc(var(--gap)*2)] my-0 flex h-full items-center overflow-hidden rounded-tl-[5px] rounded-tr-[5px] pl-2 pr-4 duration-150"
|
class="tabs-chrome__item-main group-[.is-active]:text-primary dark:group-[.is-active]:text-accent-foreground text-accent-foreground z-[2] mx-[calc(var(--gap)*2)] my-0 flex h-full items-center overflow-hidden rounded-tl-[5px] rounded-tr-[5px] pl-2 pr-4 duration-150"
|
||||||
>
|
>
|
||||||
<VbenIcon
|
<VbenIcon
|
||||||
v-if="showIcon"
|
v-if="showIcon"
|
||||||
@ -168,7 +168,7 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
@apply pb-[2px];
|
@apply pb-[2px];
|
||||||
|
|
||||||
&-content {
|
&-content {
|
||||||
@apply bg-accent-hover mx-[2px] rounded-md;
|
@apply bg-accent mx-[2px] rounded-md;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,15 @@ const active = defineModel<string>('active');
|
|||||||
const typeWithClass = computed(() => {
|
const typeWithClass = computed(() => {
|
||||||
const typeClasses: Record<string, { content: string }> = {
|
const typeClasses: Record<string, { content: string }> = {
|
||||||
brisk: {
|
brisk: {
|
||||||
content: `h-full after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-full after:h-[1.5px] after:bg-primary after:scale-x-0 after:transition-[transform] after:ease-out after:duration-300 hover:after:scale-x-100 after:origin-left [&.is-active]:after:scale-x-100 border-l border-border`,
|
content: `h-full after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-full after:h-[1.5px] after:bg-primary after:scale-x-0 after:transition-[transform] after:ease-out after:duration-300 hover:after:scale-x-100 after:origin-left [&.is-active]:after:scale-x-100 [&:not(:first-child)]:border-l last:border-r last:border-r border-border`,
|
||||||
},
|
},
|
||||||
card: {
|
card: {
|
||||||
content:
|
content:
|
||||||
'h-[calc(100%-6px)] rounded-md ml-2 border border-border transition-all',
|
'h-[calc(100%-6px)] rounded-md ml-2 border border-border transition-all',
|
||||||
},
|
},
|
||||||
plain: {
|
plain: {
|
||||||
content: 'h-full border-l border-border',
|
content:
|
||||||
|
'h-full [&:not(:first-child)]:border-l last:border-r border-border',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,9 +64,9 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="contentClass"
|
:class="contentClass"
|
||||||
class="relative !flex h-full w-max items-center pr-6"
|
class="relative !flex h-full w-max items-center overflow-y-hidden pr-6"
|
||||||
>
|
>
|
||||||
<TransitionGroup name="slide-right">
|
<TransitionGroup name="slide-down">
|
||||||
<div
|
<div
|
||||||
v-for="(tab, i) in tabsView"
|
v-for="(tab, i) in tabsView"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
|
@ -23,7 +23,7 @@ const defaultValue = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="card-box w-full px-4 pb-5 pt-3 shadow">
|
<div class="card-box w-full px-4 pb-5 pt-3">
|
||||||
<Tabs :default-value="defaultValue">
|
<Tabs :default-value="defaultValue">
|
||||||
<TabsList>
|
<TabsList>
|
||||||
<template v-for="tab in tabs" :key="tab.label">
|
<template v-for="tab in tabs" :key="tab.label">
|
||||||
|
@ -27,6 +27,6 @@
|
|||||||
"@vben/utils": "workspace:*",
|
"@vben/utils": "workspace:*",
|
||||||
"vue": "^3.4.38",
|
"vue": "^3.4.38",
|
||||||
"vue-router": "^4.4.3",
|
"vue-router": "^4.4.3",
|
||||||
"watermark-js-plus": "^1.5.3"
|
"watermark-js-plus": "^1.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ const logoSource = computed(() => preferences.logo.source);
|
|||||||
<!-- 左侧认证面板 -->
|
<!-- 左侧认证面板 -->
|
||||||
<AuthenticationFormView
|
<AuthenticationFormView
|
||||||
v-if="authPanelLeft"
|
v-if="authPanelLeft"
|
||||||
class="min-h-full w-2/5"
|
class="min-h-full w-2/5 flex-1"
|
||||||
transition-name="slide-left"
|
transition-name="slide-left"
|
||||||
>
|
>
|
||||||
<template v-if="toolbar" #toolbar>
|
<template v-if="toolbar" #toolbar>
|
||||||
|
@ -6,7 +6,7 @@ import { computed } from 'vue';
|
|||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import { VbenBackgroundBreadcrumb, VbenBreadcrumb } from '@vben-core/shadcn-ui';
|
import { VbenBreadcrumbView } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
hideWhenOnlyOne?: boolean;
|
hideWhenOnlyOne?: boolean;
|
||||||
@ -62,17 +62,10 @@ function handleSelect(path: string) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VbenBreadcrumb
|
<VbenBreadcrumbView
|
||||||
v-if="type === 'normal'"
|
|
||||||
:breadcrumbs="breadcrumbs"
|
|
||||||
:show-icon="showIcon"
|
|
||||||
class="ml-2"
|
|
||||||
@select="handleSelect"
|
|
||||||
/>
|
|
||||||
<VbenBackgroundBreadcrumb
|
|
||||||
v-if="type === 'background'"
|
|
||||||
:breadcrumbs="breadcrumbs"
|
:breadcrumbs="breadcrumbs"
|
||||||
:show-icon="showIcon"
|
:show-icon="showIcon"
|
||||||
|
:style-type="type"
|
||||||
class="ml-2"
|
class="ml-2"
|
||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
/>
|
/>
|
||||||
|
@ -61,7 +61,7 @@ async function checkForUpdates() {
|
|||||||
}
|
}
|
||||||
function handleNotice(versionTag: string) {
|
function handleNotice(versionTag: string) {
|
||||||
const { dismiss } = toast({
|
const { dismiss } = toast({
|
||||||
action: h('div', [
|
action: h('div', { class: 'inline-flex items-center' }, [
|
||||||
h(
|
h(
|
||||||
ToastAction,
|
ToastAction,
|
||||||
{
|
{
|
||||||
@ -76,7 +76,8 @@ function handleNotice(versionTag: string) {
|
|||||||
ToastAction,
|
ToastAction,
|
||||||
{
|
{
|
||||||
altText: $t('common.refresh'),
|
altText: $t('common.refresh'),
|
||||||
class: 'bg-primary hover:bg-primary-hover mx-1',
|
class:
|
||||||
|
'bg-primary text-primary-foreground hover:bg-primary-hover mx-1',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
lastVersionTag.value = versionTag;
|
lastVersionTag.value = versionTag;
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
@ -94,7 +95,7 @@ function handleNotice(versionTag: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
// 每5分钟检查一次
|
// 每 checkUpdatesInterval(默认值为1) 分钟检查一次
|
||||||
timer.value = setInterval(
|
timer.value = setInterval(
|
||||||
checkForUpdates,
|
checkForUpdates,
|
||||||
props.checkUpdatesInterval * 60 * 1000,
|
props.checkUpdatesInterval * 60 * 1000,
|
||||||
|
@ -87,7 +87,7 @@ export const errorMessageResponseInterceptor = (
|
|||||||
errMsg = $t('fallback.http.requestTimeout');
|
errMsg = $t('fallback.http.requestTimeout');
|
||||||
}
|
}
|
||||||
if (errMsg) {
|
if (errMsg) {
|
||||||
makeErrorMessage?.(errMsg);
|
makeErrorMessage?.(errMsg, error);
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ export const errorMessageResponseInterceptor = (
|
|||||||
errorMessage = $t('fallback.http.internalServerError');
|
errorMessage = $t('fallback.http.internalServerError');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
makeErrorMessage?.(errorMessage);
|
makeErrorMessage?.(errorMessage, error);
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,7 @@ interface ResponseInterceptorConfig<T = any> {
|
|||||||
rejected?: (error: any) => any;
|
rejected?: (error: any) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MakeErrorMessageFn = (message: string) => void;
|
type MakeErrorMessageFn = (message: string, error: any) => void;
|
||||||
|
|
||||||
interface HttpResponse<T = any> {
|
interface HttpResponse<T = any> {
|
||||||
code: number;
|
code: number;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"@vben-core/shared": "workspace:*",
|
"@vben-core/shared": "workspace:*",
|
||||||
"@vben-core/typings": "workspace:*",
|
"@vben-core/typings": "workspace:*",
|
||||||
"pinia": "2.2.2",
|
"pinia": "2.2.2",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"pinia-plugin-persistedstate": "^3.2.3",
|
||||||
"vue": "^3.4.38",
|
"vue": "^3.4.38",
|
||||||
"vue-router": "^4.4.3"
|
"vue-router": "^4.4.3"
|
||||||
}
|
}
|
||||||
|
593
pnpm-lock.yaml
593
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user