Pre Merge pull request !16 from 玲娜贝er/dev

This commit is contained in:
玲娜贝er 2025-02-07 06:45:28 +00:00 committed by Gitee
commit cd86a4438c
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
21 changed files with 115 additions and 39 deletions

View File

@ -1,3 +1,10 @@
# 1.2.1
# BUG FIXES
- 客户端管理 错误的status disabled
- modal/drawer升级后zIndex(2000)会遮挡Tinymce的下拉框zIndex(1300)
# 1.2.0
**REFACTOR**

View File

@ -1,6 +1,6 @@
{
"name": "@vben/web-antd",
"version": "1.2.0",
"version": "1.2.1",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@ -345,7 +345,7 @@ function handleDone(name: string, url: string) {
v-if="!initOptions.inline && init"
v-model="modelValue"
:init="initOptions"
:style="{ visibility: 'hidden' }"
:style="{ visibility: 'hidden', zIndex: 3000 }"
:tinymce-script-src="tinymceScriptSrc"
license-key="gpl"
/>
@ -353,6 +353,17 @@ function handleDone(name: string, url: string) {
</div>
</template>
<style lang="scss">
/***
由于modal/drawer的zIndex升级后为2000
这里会造成遮挡 修改为更高的zIndex
*/
.tox.tox-silver-sink.tox-tinymce-aux {
/** 该样式默认为1300的zIndex */
z-index: 2025;
}
</style>
<style lang="scss" scoped>
/**
隐藏右上角upgrade按钮

View File

@ -3,6 +3,7 @@ import type { RouteRecordRaw } from 'vue-router';
import { mergeRouteModules, traverseTreeValues } from '@vben/utils';
import { coreRoutes, fallbackNotFoundRoute } from './core';
import { workflowIframeRoutes } from './workflow-iframe';
const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
eager: true,
@ -26,11 +27,14 @@ const externalRoutes: RouteRecordRaw[] = [];
const routes: RouteRecordRaw[] = [
...coreRoutes,
...externalRoutes,
...workflowIframeRoutes,
fallbackNotFoundRoute,
];
/** 基本路由(登录, 第三方登录, 注册等) + workflowIframe路由不需要拦截 */
const basicRoutes = [...coreRoutes, ...workflowIframeRoutes];
/** 基本路由列表,这些路由不需要进入权限拦截 */
const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name);
const coreRouteNames = traverseTreeValues(basicRoutes, (route) => route.name);
/** 有权限校验的路由列表,包含动态路由和静态路由 */
const accessRoutes = [...dynamicRoutes, ...staticRoutes];

View File

@ -60,6 +60,9 @@ const localRoutes: RouteRecordStringComponent[] = [
name: 'WorkflowDesigner',
path: '/workflow/designer',
},
/**
* iframe路由 ./workflow-iframe.ts
*/
{
component: 'workflow/leave/leave-form',
meta: {
@ -71,18 +74,6 @@ const localRoutes: RouteRecordStringComponent[] = [
name: 'WorkflowLeaveIndex',
path: '/workflow/leaveEdit/index',
},
// 这里是iframe使用的 去掉外层的BasicLayout
{
component: 'workflow/leave/leave-form',
meta: {
title: '请假申请',
hideInMenu: true,
// 不使用基础布局(仅在顶级生效)
noBasicLayout: true,
},
name: 'WorkflowLeaveInner',
path: '/workflow/leaveEdit/index/iframe',
},
];
/**

View File

@ -0,0 +1,18 @@
import type { RouteRecordRaw } from '@vben/types';
/**
* workflow表单的iframe内嵌路由
* 😅
*/
export const workflowIframeRoutes: RouteRecordRaw[] = [
// 这里是iframe使用的 去掉外层的BasicLayout
{
name: 'WorkflowLeaveInner',
path: '/workflow/leaveEdit/index/iframe',
component: () => import('#/views/workflow/leave/leave-form.vue'),
meta: {
hideInTab: true,
title: '请假申请',
},
},
];

View File

@ -1,3 +1,6 @@
<template>
<iframe class="size-full" src="http://localhost:9090/applications"></iframe>
<iframe
class="size-full"
src="http://localhost:9090/admin/applications"
></iframe>
</template>

View File

@ -55,6 +55,14 @@ function setupForm(update: boolean) {
]);
}
// Schema
const getStatusSchema = (disabled: boolean) => [
{
componentProps: { disabled },
fieldName: 'status',
},
];
const [BasicDrawer, drawerApi] = useVbenDrawer({
onCancel: handleCancel,
onConfirm: handleConfirm,
@ -70,15 +78,11 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({
if (isUpdate.value && id) {
const record = await clientInfo(id);
// id1
formApi.updateSchema([
{
componentProps: {
disabled: record.id === 1,
},
fieldName: 'status',
},
]);
formApi.updateSchema(getStatusSchema(record.id === 1));
await formApi.setValues(record);
} else {
// :
formApi.updateSchema(getStatusSchema(false));
}
drawerApi.drawerLoading(false);
},

View File

@ -30,6 +30,7 @@ const [BasicForm, formApi] = useVbenForm({
const [BasicModal, modalApi] = useVbenModal({
fullscreenButton: false,
closeOnClickModal: false,
onCancel: handleCancel,
onConfirm: handleConfirm,
onOpenChange: async (isOpen) => {
@ -72,7 +73,7 @@ async function handleCancel() {
</script>
<template>
<BasicModal :fullscreen-button="true" :title="title" class="w-[800px]">
<BasicModal :title="title" class="w-[800px]">
<BasicForm />
</BasicModal>
</template>

View File

@ -182,13 +182,6 @@ const cardSize = computed(() => {
<style lang="scss">
html:has(#leave-form) {
/**
去除 '菜单加载中' 主要是iframe内嵌使用
*/
.ant-message-notice-content:has(.ant-message-loading) {
display: none;
}
/**
去除顶部进度条样式
*/

View File

@ -347,7 +347,7 @@ export interface ActionButtonOptions {
/** 是否显示 */
show?: boolean;
/** 按钮文本 */
text?: string;
content?: string;
/** 任意属性 */
[key: string]: any;
}

View File

@ -80,6 +80,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
"enable": true,
"height": 38,
"keepAlive": true,
"maxCount": 0,
"middleClickToClose": false,
"persist": true,
"showIcon": true,

View File

@ -80,6 +80,7 @@ const defaultPreferences: Preferences = {
enable: true,
height: 38,
keepAlive: true,
maxCount: 0,
middleClickToClose: false,
persist: true,
showIcon: true,

View File

@ -168,6 +168,8 @@ interface TabbarPreferences {
height: number;
/** 开启标签页缓存功能 */
keepAlive: boolean;
/** 限制最大数量 */
maxCount: number;
/** 是否点击中键时关闭标签 */
middleClickToClose: boolean;
/** 是否持久化标签 */

View File

@ -5,6 +5,7 @@ import { computed } from 'vue';
import { $t } from '@vben/locales';
import NumberFieldItem from '../number-field-item.vue';
import SelectItem from '../select-item.vue';
import SwitchItem from '../switch-item.vue';
@ -22,6 +23,7 @@ const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
const tabbarStyleType = defineModel<string>('tabbarStyleType');
const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
const tabbarMaxCount = defineModel<number>('tabbarMaxCount');
const tabbarMiddleClickToClose = defineModel<boolean>(
'tabbarMiddleClickToClose',
);
@ -54,6 +56,16 @@ const styleItems = computed((): SelectOption[] => [
<SwitchItem v-model="tabbarPersist" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.persist') }}
</SwitchItem>
<NumberFieldItem
v-model="tabbarMaxCount"
:disabled="!tabbarEnable"
:max="30"
:min="0"
:step="5"
:tip="$t('preferences.tabbar.maxCountTip')"
>
{{ $t('preferences.tabbar.maxCount') }}
</NumberFieldItem>
<SwitchItem v-model="tabbarDraggable" :disabled="!tabbarEnable">
{{ $t('preferences.tabbar.draggable') }}
</SwitchItem>

View File

@ -1,7 +1,10 @@
<script setup lang="ts">
import type { SelectOption } from '@vben/types';
import { useSlots } from 'vue';
import { CircleHelp } from '@vben/icons';
import {
NumberField,
NumberFieldContent,
@ -10,7 +13,6 @@ import {
NumberFieldInput,
VbenTooltip,
} from '@vben-core/shadcn-ui';
import { useSlots } from 'vue';
defineOptions({
name: 'PreferenceSelectItem',
@ -21,10 +23,12 @@ withDefaults(
disabled?: boolean;
items?: SelectOption[];
placeholder?: string;
tip?: string;
}>(),
{
disabled: false,
placeholder: '',
tip: '',
items: () => [],
},
);
@ -45,11 +49,17 @@ const slots = useSlots();
<span class="flex items-center text-sm">
<slot></slot>
<VbenTooltip v-if="slots.tip" side="bottom">
<VbenTooltip v-if="slots.tip || tip" side="bottom">
<template #trigger>
<CircleHelp class="ml-1 size-3 cursor-help" />
</template>
<slot name="tip"></slot>
<slot name="tip">
<template v-if="tip">
<p v-for="(line, index) in tip.split('\n')" :key="index">
{{ line }}
</p>
</template>
</slot>
</VbenTooltip>
</span>

View File

@ -116,6 +116,7 @@ const tabbarPersist = defineModel<boolean>('tabbarPersist');
const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
const tabbarStyleType = defineModel<string>('tabbarStyleType');
const tabbarMaxCount = defineModel<number>('tabbarMaxCount');
const tabbarMiddleClickToClose = defineModel<boolean>(
'tabbarMiddleClickToClose',
);
@ -365,6 +366,7 @@ async function handleReset() {
v-model:tabbar-show-more="tabbarShowMore"
v-model:tabbar-style-type="tabbarStyleType"
v-model:tabbar-wheelable="tabbarWheelable"
v-model:tabbar-max-count="tabbarMaxCount"
v-model:tabbar-middle-click-to-close="tabbarMiddleClickToClose"
/>
</Block>

View File

@ -62,6 +62,8 @@
"showMore": "Show More Button",
"showMaximize": "Show Maximize Button",
"persist": "Persist Tabs",
"maxCount": "Max Count of Tabs",
"maxCountTip": "When the number of tabs exceeds the maximum,\nthe oldest tab will be closed.\n Set to 0 to disable count checking.",
"draggable": "Enable Draggable Sort",
"wheelable": "Support Mouse Wheel",
"middleClickClose": "Close Tab when Mouse Middle Button Click",

View File

@ -62,6 +62,8 @@
"showMore": "显示更多按钮",
"showMaximize": "显示最大化按钮",
"persist": "持久化标签页",
"maxCount": "最大标签数",
"maxCountTip": "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制",
"draggable": "启动拖拽排序",
"wheelable": "启用纵向滚轮响应",
"middleClickClose": "点击鼠标中键关闭标签页",

View File

@ -20,6 +20,7 @@
}
},
"dependencies": {
"@vben-core/preferences": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"pinia": "catalog:",

View File

@ -1,13 +1,17 @@
import type { TabDefinition } from '@vben-core/typings';
import type { Router, RouteRecordNormalized } from 'vue-router';
import type { TabDefinition } from '@vben-core/typings';
import { toRaw } from 'vue';
import { preferences } from '@vben-core/preferences';
import {
openRouteInNewWindow,
startProgress,
stopProgress,
} from '@vben-core/shared/utils';
import { acceptHMRUpdate, defineStore } from 'pinia';
import { toRaw } from 'vue';
interface TabbarState {
/**
@ -104,6 +108,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
});
if (tabIndex === -1) {
const maxCount = preferences.tabbar.maxCount;
// 获取动态路由打开数,超过 0 即代表需要控制打开数
const maxNumOfOpenTab = (routeTab?.meta?.maxNumOfOpenTab ??
-1) as number;
@ -119,8 +124,14 @@ export const useTabbarStore = defineStore('core-tabbar', {
(item) => item.name === routeTab.name,
);
index !== -1 && this.tabs.splice(index, 1);
} else if (maxCount > 0 && this.tabs.length >= maxCount) {
// 关闭第一个
const index = this.tabs.findIndex(
(item) =>
!Reflect.has(item.meta, 'affixTab') || !item.meta.affixTab,
);
index !== -1 && this.tabs.splice(index, 1);
}
this.tabs.push(tab);
} else {
// 页面已经存在,不重复添加选项卡,只更新选项卡参数