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 * from './components/normal-menu'; |
||||
export { default as Menu } from './menu.vue'; |
export { default as Menu } from './menu.vue'; |
||||
export type * from './types'; |
export type * from './types'; |
||||
|
|||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue