Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into antdv-next

This commit is contained in:
dap
2026-02-09 16:26:26 +08:00
128 changed files with 4183 additions and 68 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/design",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -16,13 +16,13 @@
html {
@apply text-foreground bg-background font-sans;
scroll-behavior: smooth;
font-size: var(--font-size-base, 16px);
font-variation-settings: normal;
font-synthesis-weight: none;
line-height: 1.15;
text-size-adjust: 100%;
scroll-behavior: smooth;
text-rendering: optimizelegibility;
text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
/* -webkit-font-smoothing: antialiased;

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/icons",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/shared",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -19,6 +19,8 @@ export const VBEN_LOGO_URL =
*/
export const VBEN_PREVIEW_URL = 'https://www.vben.pro';
export const VBEN_ANTDV_NEXT_PREVIEW_URL = 'https://antdv-next.vben.pro';
export const VBEN_ELE_PREVIEW_URL = 'https://ele.vben.pro';
export const VBEN_NAIVE_PREVIEW_URL = 'https://naive.vben.pro';

View File

@@ -0,0 +1,107 @@
import { beforeEach, describe, expect, it } from 'vitest';
import { createStack, Stack } from '../stack';
describe('stack', () => {
let stack: Stack<number>;
beforeEach(() => {
stack = new Stack<number>();
});
it('push & size should work', () => {
stack.push(1, 2);
expect(stack.size).toBe(2);
});
it('peek should return top element without removing it', () => {
stack.push(1, 2);
expect(stack.peek()).toBe(2);
expect(stack.size).toBe(2);
});
it('pop should remove and return top element', () => {
stack.push(1, 2);
expect(stack.pop()).toBe(2);
expect(stack.size).toBe(1);
expect(stack.peek()).toBe(1);
});
it('pop on empty stack should return undefined', () => {
expect(stack.pop()).toBeUndefined();
expect(stack.peek()).toBeUndefined();
});
it('clear should remove all elements', () => {
stack.push(1, 2);
stack.clear();
expect(stack.size).toBe(0);
expect(stack.peek()).toBeUndefined();
});
it('toArray should return a shallow copy', () => {
stack.push(1, 2);
const arr = stack.toArray();
arr.push(3);
expect(stack.size).toBe(2);
expect(stack.toArray()).toEqual([1, 2]);
});
it('dedup should remove existing item before push', () => {
stack.push(1, 2, 1);
expect(stack.toArray()).toEqual([2, 1]);
expect(stack.size).toBe(2);
});
it('dedup = false should allow duplicate items', () => {
const s = new Stack<number>(false);
s.push(1, 1, 1);
expect(s.toArray()).toEqual([1, 1, 1]);
expect(s.size).toBe(3);
});
it('remove should delete all matching items', () => {
stack.push(1, 2, 1);
stack.remove(1);
expect(stack.toArray()).toEqual([2]);
expect(stack.size).toBe(1);
});
it('maxSize should limit stack capacity', () => {
const s = new Stack<number>(true, 3);
s.push(1, 2, 3, 4);
expect(s.toArray()).toEqual([2, 3, 4]);
expect(s.size).toBe(3);
});
it('dedup + maxSize should work together', () => {
const s = new Stack<number>(true, 3);
s.push(1, 2, 3, 2); // 去重并重新入栈
expect(s.toArray()).toEqual([1, 3, 2]);
expect(s.size).toBe(3);
});
it('createStack should create a stack instance', () => {
const s = createStack<number>(true, 2);
s.push(1, 2, 3);
expect(s.toArray()).toEqual([2, 3]);
});
});

View File

@@ -8,6 +8,7 @@ export * from './letter';
export * from './merge';
export * from './nprogress';
export * from './resources';
export * from './stack';
export * from './state-handler';
export * from './to';
export * from './tree';

View File

@@ -0,0 +1,103 @@
/**
* @zh_CN 栈数据结构
*/
export class Stack<T> {
/**
* @zh_CN 栈内元素数量
*/
get size() {
return this.items.length;
}
/**
* @zh_CN 是否去重
*/
private readonly dedup: boolean;
/**
* @zh_CN 栈内元素
*/
private items: T[] = [];
/**
* @zh_CN 栈的最大容量
*/
private readonly maxSize?: number;
constructor(dedup = true, maxSize?: number) {
this.maxSize = maxSize;
this.dedup = dedup;
}
/**
* @zh_CN 清空栈内元素
*/
clear() {
this.items.length = 0;
}
/**
* @zh_CN 查看栈顶元素
* @returns 栈顶元素
*/
peek(): T | undefined {
return this.items[this.items.length - 1];
}
/**
* @zh_CN 出栈
* @returns 栈顶元素
*/
pop(): T | undefined {
return this.items.pop();
}
/**
* @zh_CN 入栈
* @param items 要入栈的元素
*/
push(...items: T[]) {
items.forEach((item) => {
// 去重
if (this.dedup) {
const index = this.items.indexOf(item);
if (index !== -1) {
this.items.splice(index, 1);
}
}
this.items.push(item);
if (this.maxSize && this.items.length > this.maxSize) {
this.items.splice(0, this.items.length - this.maxSize);
}
});
}
/**
* @zh_CN 移除栈内元素
* @param itemList 要移除的元素列表
*/
remove(...itemList: T[]) {
this.items = this.items.filter((i) => !itemList.includes(i));
}
/**
* @zh_CN 保留栈内元素
* @param itemList 要保留的元素列表
*/
retain(itemList: T[]) {
this.items = this.items.filter((i) => itemList.includes(i));
}
/**
* @zh_CN 转换为数组
* @returns 栈内元素数组
*/
toArray(): T[] {
return [...this.items];
}
}
/**
* @zh_CN 创建一个栈实例
* @param dedup 是否去重
* @param maxSize 栈的最大容量
* @returns 栈实例
*/
export const createStack = <T>(dedup = true, maxSize?: number) =>
new Stack<T>(dedup, maxSize);

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/typings",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/composables",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -105,6 +105,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
"showMaximize": true,
"showMore": true,
"styleType": "chrome",
"visitHistory": true,
"wheelable": true,
},
"theme": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/preferences",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -106,6 +106,7 @@ const defaultPreferences: Preferences = {
showMaximize: true,
showMore: true,
styleType: 'chrome',
visitHistory: true,
wheelable: true,
},
theme: {

View File

@@ -224,6 +224,8 @@ interface TabbarPreferences {
showMore: boolean;
/** 标签页风格 */
styleType: TabsStyleType;
/** 是否开启访问历史记录 */
visitHistory: boolean;
/** 是否开启鼠标滚轮响应 */
wheelable: boolean;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/form-ui",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/layout-ui",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/menu-ui",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/popup-ui",
"version": "5.2.1",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/shadcn-ui",
"version": "5.5.9",
"version": "5.6.0",
"#main": "./dist/index.mjs",
"#module": "./dist/index.mjs",
"homepage": "https://github.com/vbenjs/vue-vben-admin",

View File

@@ -33,5 +33,16 @@ const modelValue = useVModel(props, 'modelValue', emits, {
<style lang="scss" scoped>
input {
--ring: var(--primary);
&::-ms-reveal,
&::-ms-clear {
display: none;
}
&::-webkit-credentials-auto-fill-button,
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button {
display: none;
}
}
</style>

View File

@@ -65,16 +65,24 @@ const modelValue = defineModel<Arrayable<number | string>>();
const expanded = ref<Array<number | string>>(props.defaultExpandedKeys ?? []);
const treeValue = ref();
let lastTreeData: any = null;
onMounted(() => {
watchEffect(() => {
flattenData.value = flatten(props.treeData, props.childrenField);
updateTreeValue();
if (
props.defaultExpandedLevel !== undefined &&
props.defaultExpandedLevel > 0
)
expandToLevel(props.defaultExpandedLevel);
// 只在 treeData 变化时执行展开
const currentTreeData = JSON.stringify(props.treeData);
if (lastTreeData !== currentTreeData) {
lastTreeData = currentTreeData;
if (
props.defaultExpandedLevel !== undefined &&
props.defaultExpandedLevel > 0
) {
expandToLevel(props.defaultExpandedLevel);
}
}
});
});
@@ -87,9 +95,11 @@ function getItemByValue(value: number | string) {
function updateTreeValue() {
const val = modelValue.value;
if (val === undefined) {
treeValue.value = undefined;
} else {
if (Array.isArray(val)) {
treeValue.value = props.multiple ? [] : undefined;
} else if (Array.isArray(val)) {
if (val.length === 0) {
treeValue.value = [];
} else {
const filteredValues = val.filter((v) => {
const item = getItemByValue(v);
return item && !get(item, props.disabledField);
@@ -99,14 +109,14 @@ function updateTreeValue() {
if (filteredValues.length !== val.length) {
modelValue.value = filteredValues;
}
}
} else {
const item = getItemByValue(val);
if (item && !get(item, props.disabledField)) {
treeValue.value = item;
} else {
const item = getItemByValue(val);
if (item && !get(item, props.disabledField)) {
treeValue.value = item;
} else {
treeValue.value = undefined;
modelValue.value = undefined;
}
treeValue.value = props.multiple ? [] : undefined;
modelValue.value = props.multiple ? [] : undefined;
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vben-core/tabs-ui",
"version": "5.5.9",
"version": "5.6.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {