committed by
GitHub
199 changed files with 3408 additions and 516 deletions
@ -0,0 +1,181 @@ |
|||
<script lang="ts" setup> |
|||
import { h } from 'vue'; |
|||
|
|||
import { Page } from '@vben/common-ui'; |
|||
|
|||
import { ElButton, ElCard, ElCheckbox, ElMessage } from 'element-plus'; |
|||
|
|||
import { useVbenForm } from '#/adapter/form'; |
|||
import { getAllMenusApi } from '#/api'; |
|||
|
|||
const [Form, formApi] = useVbenForm({ |
|||
commonConfig: { |
|||
// 所有表单项 |
|||
componentProps: { |
|||
class: 'w-full', |
|||
}, |
|||
}, |
|||
layout: 'horizontal', |
|||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个 |
|||
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', |
|||
handleSubmit: (values) => { |
|||
ElMessage.success(`表单数据:${JSON.stringify(values)}`); |
|||
}, |
|||
schema: [ |
|||
{ |
|||
// 组件需要在 #/adapter.ts内注册,并加上类型 |
|||
component: 'ApiSelect', |
|||
// 对应组件的参数 |
|||
componentProps: { |
|||
// 菜单接口转options格式 |
|||
afterFetch: (data: { name: string; path: string }[]) => { |
|||
return data.map((item: any) => ({ |
|||
label: item.name, |
|||
value: item.path, |
|||
})); |
|||
}, |
|||
// 菜单接口 |
|||
api: getAllMenusApi, |
|||
}, |
|||
// 字段名 |
|||
fieldName: 'api', |
|||
// 界面显示的label |
|||
label: 'ApiSelect', |
|||
}, |
|||
{ |
|||
component: 'ApiTreeSelect', |
|||
// 对应组件的参数 |
|||
componentProps: { |
|||
// 菜单接口 |
|||
api: getAllMenusApi, |
|||
childrenField: 'children', |
|||
// 菜单接口转options格式 |
|||
labelField: 'name', |
|||
valueField: 'path', |
|||
}, |
|||
// 字段名 |
|||
fieldName: 'apiTree', |
|||
// 界面显示的label |
|||
label: 'ApiTreeSelect', |
|||
}, |
|||
{ |
|||
component: 'Input', |
|||
fieldName: 'string', |
|||
label: 'String', |
|||
}, |
|||
{ |
|||
component: 'InputNumber', |
|||
fieldName: 'number', |
|||
label: 'Number', |
|||
}, |
|||
{ |
|||
component: 'RadioGroup', |
|||
fieldName: 'radio', |
|||
label: 'Radio', |
|||
componentProps: { |
|||
options: [ |
|||
{ value: 'A', label: 'A' }, |
|||
{ value: 'B', label: 'B' }, |
|||
{ value: 'C', label: 'C' }, |
|||
{ value: 'D', label: 'D' }, |
|||
{ value: 'E', label: 'E' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'RadioGroup', |
|||
fieldName: 'radioButton', |
|||
label: 'RadioButton', |
|||
componentProps: { |
|||
isButton: true, |
|||
options: ['A', 'B', 'C', 'D', 'E', 'F'].map((v) => ({ |
|||
value: v, |
|||
label: `选项${v}`, |
|||
})), |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'CheckboxGroup', |
|||
fieldName: 'checkbox', |
|||
label: 'Checkbox', |
|||
componentProps: { |
|||
options: ['A', 'B', 'C'].map((v) => ({ value: v, label: `选项${v}` })), |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'CheckboxGroup', |
|||
fieldName: 'checkbox1', |
|||
label: 'Checkbox1', |
|||
renderComponentContent: () => { |
|||
return { |
|||
default: () => { |
|||
return ['A', 'B', 'C', 'D'].map((v) => |
|||
h(ElCheckbox, { label: v, value: v }), |
|||
); |
|||
}, |
|||
}; |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'CheckboxGroup', |
|||
fieldName: 'checkbotton', |
|||
label: 'CheckBotton', |
|||
componentProps: { |
|||
isButton: true, |
|||
options: [ |
|||
{ value: 'A', label: '选项A' }, |
|||
{ value: 'B', label: '选项B' }, |
|||
{ value: 'C', label: '选项C' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'DatePicker', |
|||
fieldName: 'date', |
|||
label: 'Date', |
|||
}, |
|||
{ |
|||
component: 'Select', |
|||
fieldName: 'select', |
|||
label: 'Select', |
|||
componentProps: { |
|||
filterable: true, |
|||
options: [ |
|||
{ value: 'A', label: '选项A' }, |
|||
{ value: 'B', label: '选项B' }, |
|||
{ value: 'C', label: '选项C' }, |
|||
], |
|||
}, |
|||
}, |
|||
], |
|||
}); |
|||
function setFormValues() { |
|||
formApi.setValues({ |
|||
string: 'string', |
|||
number: 123, |
|||
radio: 'B', |
|||
radioButton: 'C', |
|||
checkbox: ['A', 'C'], |
|||
checkbotton: ['B', 'C'], |
|||
checkbox1: ['A', 'B'], |
|||
date: new Date(), |
|||
select: 'B', |
|||
}); |
|||
} |
|||
</script> |
|||
<template> |
|||
<Page |
|||
description="我们重新包装了CheckboxGroup、RadioGroup、Select,可以通过options属性传入选项属性数组以自动生成选项" |
|||
title="表单演示" |
|||
> |
|||
<ElCard> |
|||
<template #header> |
|||
<div class="flex items-center"> |
|||
<span class="flex-auto">基础表单演示</span> |
|||
<ElButton type="primary" @click="setFormValues">设置表单值</ElButton> |
|||
</div> |
|||
</template> |
|||
<Form /> |
|||
</ElCard> |
|||
</Page> |
|||
</template> |
|||
@ -0,0 +1,143 @@ |
|||
<script lang="ts" setup> |
|||
import { Page } from '@vben/common-ui'; |
|||
|
|||
import { NButton, NCard, useMessage } from 'naive-ui'; |
|||
|
|||
import { useVbenForm } from '#/adapter/form'; |
|||
import { getAllMenusApi } from '#/api'; |
|||
|
|||
const message = useMessage(); |
|||
const [Form, formApi] = useVbenForm({ |
|||
commonConfig: { |
|||
// 所有表单项 |
|||
componentProps: { |
|||
class: 'w-full', |
|||
}, |
|||
}, |
|||
layout: 'horizontal', |
|||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个 |
|||
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', |
|||
handleSubmit: (values) => { |
|||
message.success(`表单数据:${JSON.stringify(values)}`); |
|||
}, |
|||
schema: [ |
|||
{ |
|||
// 组件需要在 #/adapter.ts内注册,并加上类型 |
|||
component: 'ApiSelect', |
|||
// 对应组件的参数 |
|||
componentProps: { |
|||
// 菜单接口转options格式 |
|||
afterFetch: (data: { name: string; path: string }[]) => { |
|||
return data.map((item: any) => ({ |
|||
label: item.name, |
|||
value: item.path, |
|||
})); |
|||
}, |
|||
// 菜单接口 |
|||
api: getAllMenusApi, |
|||
}, |
|||
// 字段名 |
|||
fieldName: 'api', |
|||
// 界面显示的label |
|||
label: 'ApiSelect', |
|||
}, |
|||
{ |
|||
component: 'ApiTreeSelect', |
|||
// 对应组件的参数 |
|||
componentProps: { |
|||
// 菜单接口 |
|||
api: getAllMenusApi, |
|||
childrenField: 'children', |
|||
// 菜单接口转options格式 |
|||
labelField: 'name', |
|||
valueField: 'path', |
|||
}, |
|||
// 字段名 |
|||
fieldName: 'apiTree', |
|||
// 界面显示的label |
|||
label: 'ApiTreeSelect', |
|||
}, |
|||
{ |
|||
component: 'Input', |
|||
fieldName: 'string', |
|||
label: 'String', |
|||
}, |
|||
{ |
|||
component: 'InputNumber', |
|||
fieldName: 'number', |
|||
label: 'Number', |
|||
}, |
|||
{ |
|||
component: 'RadioGroup', |
|||
fieldName: 'radio', |
|||
label: 'Radio', |
|||
componentProps: { |
|||
options: [ |
|||
{ value: 'A', label: 'A' }, |
|||
{ value: 'B', label: 'B' }, |
|||
{ value: 'C', label: 'C' }, |
|||
{ value: 'D', label: 'D' }, |
|||
{ value: 'E', label: 'E' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'RadioGroup', |
|||
fieldName: 'radioButton', |
|||
label: 'RadioButton', |
|||
componentProps: { |
|||
isButton: true, |
|||
class: 'flex flex-wrap', // 如果选项过多,可以添加class来自动折叠 |
|||
options: [ |
|||
{ value: 'A', label: '选项A' }, |
|||
{ value: 'B', label: '选项B' }, |
|||
{ value: 'C', label: '选项C' }, |
|||
{ value: 'D', label: '选项D' }, |
|||
{ value: 'E', label: '选项E' }, |
|||
{ value: 'F', label: '选项F' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'CheckboxGroup', |
|||
fieldName: 'checkbox', |
|||
label: 'Checkbox', |
|||
componentProps: { |
|||
options: [ |
|||
{ value: 'A', label: '选项A' }, |
|||
{ value: 'B', label: '选项B' }, |
|||
{ value: 'C', label: '选项C' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
component: 'DatePicker', |
|||
fieldName: 'date', |
|||
label: 'Date', |
|||
}, |
|||
], |
|||
}); |
|||
function setFormValues() { |
|||
formApi.setValues({ |
|||
string: 'string', |
|||
number: 123, |
|||
radio: 'B', |
|||
radioButton: 'C', |
|||
checkbox: ['A', 'C'], |
|||
date: Date.now(), |
|||
}); |
|||
} |
|||
</script> |
|||
<template> |
|||
<Page |
|||
description="表单适配器重新包装了CheckboxGroup和RadioGroup,可以通过options属性传递选项数据(选项数据将作为子组件的属性)" |
|||
title="表单演示" |
|||
> |
|||
<NCard title="基础表单"> |
|||
<template #header-extra> |
|||
<NButton type="primary" @click="setFormValues">设置表单值</NButton> |
|||
</template> |
|||
<Form /> |
|||
</NCard> |
|||
</Page> |
|||
</template> |
|||
@ -0,0 +1,152 @@ |
|||
--- |
|||
outline: deep |
|||
--- |
|||
|
|||
# Vben ApiComponent Api组件包装器 |
|||
|
|||
框架提供的API“包装器”,它一般不独立使用,主要用于包装其它组件,为目标组件提供自动获取远程数据的能力,但仍然保持了目标组件的原始用法。 |
|||
|
|||
::: info 写在前面 |
|||
|
|||
我们在各个应用的组件适配器中,使用ApiComponent包装了Select、TreeSelect组件,使得这些组件可以自动获取远程数据并生成选项。其它类似的组件(比如Cascader)如有需要也可以参考示例代码自行进行包装。 |
|||
|
|||
::: |
|||
|
|||
## 基础用法 |
|||
|
|||
通过 `component` 传入其它组件的定义,并配置相关的其它属性(主要是一些名称映射)。包装组件将通过`api`获取数据(`beforerFetch`、`afterFetch`将分别在`api`运行前、运行后被调用),使用`resultField`从中提取数组,使用`valueField`、`labelField`等来从数据中提取value和label(如果提供了`childrenField`,会将其作为树形结构递归处理每一级数据),之后将处理好的数据通过`optionsPropName`指定的属性传递给目标组件。 |
|||
|
|||
::: details 包装级联选择器,点击下拉时开始加载远程数据 |
|||
|
|||
```vue |
|||
<script lang="ts" setup> |
|||
import { ApiComponent } from '@vben/common-ui'; |
|||
|
|||
import { Cascader } from 'ant-design-vue'; |
|||
|
|||
const treeData: Record<string, any> = [ |
|||
{ |
|||
label: '浙江', |
|||
value: 'zhejiang', |
|||
children: [ |
|||
{ |
|||
value: 'hangzhou', |
|||
label: '杭州', |
|||
children: [ |
|||
{ |
|||
value: 'xihu', |
|||
label: '西湖', |
|||
}, |
|||
{ |
|||
value: 'sudi', |
|||
label: '苏堤', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
value: 'jiaxing', |
|||
label: '嘉兴', |
|||
children: [ |
|||
{ |
|||
value: 'wuzhen', |
|||
label: '乌镇', |
|||
}, |
|||
{ |
|||
value: 'meihuazhou', |
|||
label: '梅花洲', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
value: 'zhoushan', |
|||
label: '舟山', |
|||
children: [ |
|||
{ |
|||
value: 'putuoshan', |
|||
label: '普陀山', |
|||
}, |
|||
{ |
|||
value: 'taohuadao', |
|||
label: '桃花岛', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
label: '江苏', |
|||
value: 'jiangsu', |
|||
children: [ |
|||
{ |
|||
value: 'nanjing', |
|||
label: '南京', |
|||
children: [ |
|||
{ |
|||
value: 'zhonghuamen', |
|||
label: '中华门', |
|||
}, |
|||
{ |
|||
value: 'zijinshan', |
|||
label: '紫金山', |
|||
}, |
|||
{ |
|||
value: 'yuhuatai', |
|||
label: '雨花台', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
/** |
|||
* 模拟请求接口 |
|||
*/ |
|||
function fetchApi(): Promise<Record<string, any>> { |
|||
return new Promise((resolve) => { |
|||
setTimeout(() => { |
|||
resolve(treeData); |
|||
}, 1000); |
|||
}); |
|||
} |
|||
</script> |
|||
<template> |
|||
<ApiComponent |
|||
:api="fetchApi" |
|||
:component="Cascader" |
|||
:immediate="false" |
|||
children-field="children" |
|||
loading-slot="suffixIcon" |
|||
visible-event="onDropdownVisibleChange" |
|||
/> |
|||
</template> |
|||
``` |
|||
|
|||
::: |
|||
|
|||
## API |
|||
|
|||
### Props |
|||
|
|||
| 属性名 | 描述 | 类型 | 默认值 | |
|||
| --- | --- | --- | --- | |
|||
| component | 欲包装的组件 | `Component` | - | |
|||
| numberToString | 是否将value从数字转为string | `boolean` | `false` | |
|||
| api | 获取数据的函数 | `(arg?: any) => Promise<OptionsItem[] \| Record<string, any>>` | - | |
|||
| params | 传递给api的参数 | `Record<string, any>` | - | |
|||
| resultField | 从api返回的结果中提取options数组的字段名 | `string` | - | |
|||
| labelField | label字段名 | `string` | `label` | |
|||
| childrenField | 子级数据字段名,需要层级数据的组件可用 | `string` | `` | |
|||
| valueField | value字段名 | `string` | `value` | |
|||
| optionsPropName | 组件接收options数据的属性名称 | `string` | `options` | |
|||
| modelPropName | 组件的双向绑定属性名,默认为modelValue。部分组件可能为value | `string` | `modelValue` | |
|||
| immediate | 是否立即调用api | `boolean` | `true` | |
|||
| alwaysLoad | 每次`visibleEvent`事件发生时都重新请求数据 | `boolean` | `false` | |
|||
| beforeFetch | 在api请求之前的回调函数 | `AnyPromiseFunction<any, any>` | - | |
|||
| afterFetch | 在api请求之后的回调函数 | `AnyPromiseFunction<any, any>` | - | |
|||
| options | 直接传入选项数据,也作为api返回空数据时的后备数据 | `OptionsItem[]` | - | |
|||
| visibleEvent | 触发重新请求数据的事件名 | `string` | - | |
|||
| loadingSlot | 组件的插槽名称,用来显示一个"加载中"的图标 | `string` | - | |
|||
|
|||
``` |
|||
|
|||
``` |
|||
@ -0,0 +1,56 @@ |
|||
--- |
|||
outline: deep |
|||
--- |
|||
|
|||
# Vben EllipsisText 省略文本 |
|||
|
|||
框架提供的文本展示组件,可配置超长省略、tooltip提示、展开收起等功能。 |
|||
|
|||
> 如果文档内没有参数说明,可以尝试在在线示例内寻找 |
|||
|
|||
## 基础用法 |
|||
|
|||
通过默认插槽设置文本内容,`maxWidth`属性设置最大宽度。 |
|||
|
|||
<DemoPreview dir="demos/vben-ellipsis-text/line" /> |
|||
|
|||
## 可折叠的文本块 |
|||
|
|||
通过`line`设置折叠后的行数,`expand`属性设置是否支持展开收起。 |
|||
|
|||
<DemoPreview dir="demos/vben-ellipsis-text/expand" /> |
|||
|
|||
## 自定义提示浮层 |
|||
|
|||
通过名为`tooltip`的插槽定制提示信息。 |
|||
|
|||
<DemoPreview dir="demos/vben-ellipsis-text/tooltip" /> |
|||
|
|||
## API |
|||
|
|||
### Props |
|||
|
|||
| 属性名 | 描述 | 类型 | 默认值 | |
|||
| --- | --- | --- | --- | |
|||
| expand | 支持点击展开或收起 | `boolean` | `false` | |
|||
| line | 文本最大行数 | `number` | `1` | |
|||
| maxWidth | 文本区域最大宽度 | `number \| string` | `'100%'` | |
|||
| placement | 提示浮层的位置 | `'bottom'\|'left'\|'right'\|'top'` | `'top'` | |
|||
| tooltip | 启用文本提示 | `boolean` | `true` | |
|||
| tooltipBackgroundColor | 提示文本的背景颜色 | `string` | - | |
|||
| tooltipColor | 提示文本的颜色 | `string` | - | |
|||
| tooltipFontSize | 提示文本的大小 | `string` | - | |
|||
| tooltipMaxWidth | 提示浮层的最大宽度。如不设置则保持与文本宽度一致 | `number` | - | |
|||
| tooltipOverlayStyle | 提示框内容区域样式 | `CSSProperties` | `{ textAlign: 'justify' }` | |
|||
|
|||
### Events |
|||
|
|||
| 事件名 | 描述 | 类型 | |
|||
| ------------ | ------------ | -------------------------- | |
|||
| expandChange | 展开状态改变 | `(isExpand:boolean)=>void` | |
|||
|
|||
### Slots |
|||
|
|||
| 插槽名 | 描述 | |
|||
| ------- | -------------------------------- | |
|||
| tooltip | 启用文本提示时,用来定制提示内容 | |
|||
@ -0,0 +1,44 @@ |
|||
--- |
|||
outline: deep |
|||
--- |
|||
|
|||
# Page 常规页面组件 |
|||
|
|||
提供一个常规页面布局的组件,包括头部、内容区域、底部三个部分。 |
|||
|
|||
::: info 写在前面 |
|||
|
|||
本组件是一个基本布局组件。如果有更多的通用页面布局需求(比如双列布局等),可以根据实际需求自行封装。 |
|||
|
|||
::: |
|||
|
|||
## 基础用法 |
|||
|
|||
将`Page`作为你的业务页面的根组件即可。 |
|||
|
|||
### Props |
|||
|
|||
| 属性名 | 描述 | 类型 | 默认值 | 说明 | |
|||
| --- | --- | --- | --- | --- | |
|||
| title | 页面标题 | `string\|slot` | - | - | |
|||
| description | 页面描述(标题下的内容) | `string\|slot` | - | - | |
|||
| contentClass | 内容区域的class | `string` | - | - | |
|||
| headerClass | 头部区域的class | `string` | - | - | |
|||
| footerClass | 底部区域的class | `string` | - | - | |
|||
| autoContentHeight | 自动调整内容区域的高度 | `boolean` | `false` | - | |
|||
|
|||
::: tip 注意 |
|||
|
|||
如果`title`、`description`、`extra`三者均未提供有效内容(通过`props`或者`slots`均可),则页面头部区域不会渲染。 |
|||
|
|||
::: |
|||
|
|||
### Slots |
|||
|
|||
| 插槽名称 | 描述 | |
|||
| ----------- | ------------ | |
|||
| default | 页面内容 | |
|||
| title | 页面标题 | |
|||
| description | 页面描述 | |
|||
| extra | 页面头部右侧 | |
|||
| footer | 页面底部 | |
|||
@ -0,0 +1,100 @@ |
|||
<script lang="ts" setup> |
|||
import { ApiComponent } from '@vben/common-ui'; |
|||
|
|||
import { Cascader } from 'ant-design-vue'; |
|||
|
|||
const treeData: Record<string, any> = [ |
|||
{ |
|||
label: '浙江', |
|||
value: 'zhejiang', |
|||
children: [ |
|||
{ |
|||
value: 'hangzhou', |
|||
label: '杭州', |
|||
children: [ |
|||
{ |
|||
value: 'xihu', |
|||
label: '西湖', |
|||
}, |
|||
{ |
|||
value: 'sudi', |
|||
label: '苏堤', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
value: 'jiaxing', |
|||
label: '嘉兴', |
|||
children: [ |
|||
{ |
|||
value: 'wuzhen', |
|||
label: '乌镇', |
|||
}, |
|||
{ |
|||
value: 'meihuazhou', |
|||
label: '梅花洲', |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
value: 'zhoushan', |
|||
label: '舟山', |
|||
children: [ |
|||
{ |
|||
value: 'putuoshan', |
|||
label: '普陀山', |
|||
}, |
|||
{ |
|||
value: 'taohuadao', |
|||
label: '桃花岛', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
label: '江苏', |
|||
value: 'jiangsu', |
|||
children: [ |
|||
{ |
|||
value: 'nanjing', |
|||
label: '南京', |
|||
children: [ |
|||
{ |
|||
value: 'zhonghuamen', |
|||
label: '中华门', |
|||
}, |
|||
{ |
|||
value: 'zijinshan', |
|||
label: '紫金山', |
|||
}, |
|||
{ |
|||
value: 'yuhuatai', |
|||
label: '雨花台', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
/** |
|||
* 模拟请求接口 |
|||
*/ |
|||
function fetchApi(): Promise<Record<string, any>> { |
|||
return new Promise((resolve) => { |
|||
setTimeout(() => { |
|||
resolve(treeData); |
|||
}, 1000); |
|||
}); |
|||
} |
|||
</script> |
|||
<template> |
|||
<ApiComponent |
|||
:api="fetchApi" |
|||
:component="Cascader" |
|||
:immediate="false" |
|||
children-field="children" |
|||
loading-slot="suffixIcon" |
|||
visible-event="onDropdownVisibleChange" |
|||
/> |
|||
</template> |
|||
@ -0,0 +1,10 @@ |
|||
<script lang="ts" setup> |
|||
import { EllipsisText } from '@vben/common-ui'; |
|||
|
|||
const text = ` |
|||
Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。 |
|||
`; |
|||
</script> |
|||
<template> |
|||
<EllipsisText :line="3" expand>{{ text }}</EllipsisText> |
|||
</template> |
|||
@ -0,0 +1,10 @@ |
|||
<script lang="ts" setup> |
|||
import { EllipsisText } from '@vben/common-ui'; |
|||
|
|||
const text = ` |
|||
Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。Vben Admin 是一个基于 Vue3.0、Vite、 TypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、多主题配置、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3、vite、ts 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。 |
|||
`; |
|||
</script> |
|||
<template> |
|||
<EllipsisText :max-width="500">{{ text }}</EllipsisText> |
|||
</template> |
|||
@ -0,0 +1,14 @@ |
|||
<script lang="ts" setup> |
|||
import { EllipsisText } from '@vben/common-ui'; |
|||
</script> |
|||
<template> |
|||
<EllipsisText :max-width="240"> |
|||
住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪 |
|||
<template #tooltip> |
|||
<div style="text-align: center"> |
|||
《秦皇岛》<br />住在我心里孤独的<br />孤独的海怪 痛苦之王<br />开始厌倦 |
|||
深海的光 停滞的海浪 |
|||
</div> |
|||
</template> |
|||
</EllipsisText> |
|||
</template> |
|||
@ -1,3 +1,4 @@ |
|||
export { default as MenuBadge } from './components/menu-badge.vue'; |
|||
export * from './components/normal-menu'; |
|||
export { default as Menu } from './menu.vue'; |
|||
export type * from './types'; |
|||
|
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue