Pre Merge pull request !16 from 玲娜贝er/dev
This commit is contained in:
commit
cd86a4438c
@ -1,3 +1,10 @@
|
||||
# 1.2.1
|
||||
|
||||
# BUG FIXES
|
||||
|
||||
- 客户端管理 错误的status disabled
|
||||
- modal/drawer升级后zIndex(2000)会遮挡Tinymce的下拉框zIndex(1300)
|
||||
|
||||
# 1.2.0
|
||||
|
||||
**REFACTOR**
|
||||
|
@ -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": {
|
||||
|
@ -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按钮
|
||||
|
@ -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];
|
||||
|
@ -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',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
18
apps/web-antd/src/router/routes/workflow-iframe.ts
Normal file
18
apps/web-antd/src/router/routes/workflow-iframe.ts
Normal 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: '请假申请',
|
||||
},
|
||||
},
|
||||
];
|
@ -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>
|
||||
|
@ -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);
|
||||
// 不能禁用id为1的记录
|
||||
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);
|
||||
},
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
去除顶部进度条样式
|
||||
*/
|
||||
|
@ -347,7 +347,7 @@ export interface ActionButtonOptions {
|
||||
/** 是否显示 */
|
||||
show?: boolean;
|
||||
/** 按钮文本 */
|
||||
text?: string;
|
||||
content?: string;
|
||||
/** 任意属性 */
|
||||
[key: string]: any;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -80,6 +80,7 @@ const defaultPreferences: Preferences = {
|
||||
enable: true,
|
||||
height: 38,
|
||||
keepAlive: true,
|
||||
maxCount: 0,
|
||||
middleClickToClose: false,
|
||||
persist: true,
|
||||
showIcon: true,
|
||||
|
@ -168,6 +168,8 @@ interface TabbarPreferences {
|
||||
height: number;
|
||||
/** 开启标签页缓存功能 */
|
||||
keepAlive: boolean;
|
||||
/** 限制最大数量 */
|
||||
maxCount: number;
|
||||
/** 是否点击中键时关闭标签 */
|
||||
middleClickToClose: boolean;
|
||||
/** 是否持久化标签 */
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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",
|
||||
|
@ -62,6 +62,8 @@
|
||||
"showMore": "显示更多按钮",
|
||||
"showMaximize": "显示最大化按钮",
|
||||
"persist": "持久化标签页",
|
||||
"maxCount": "最大标签数",
|
||||
"maxCountTip": "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制",
|
||||
"draggable": "启动拖拽排序",
|
||||
"wheelable": "启用纵向滚轮响应",
|
||||
"middleClickClose": "点击鼠标中键关闭标签页",
|
||||
|
@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@vben-core/preferences": "workspace:*",
|
||||
"@vben-core/shared": "workspace:*",
|
||||
"@vben-core/typings": "workspace:*",
|
||||
"pinia": "catalog:",
|
||||
|
@ -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 {
|
||||
// 页面已经存在,不重复添加选项卡,只更新选项卡参数
|
||||
|
Loading…
Reference in New Issue
Block a user