Browse Source
* chore: define components router
* chore: 组件路由放置到演示路由下
* Revert "chore: 组件路由放置到演示路由下"
This reverts commit 3c24632ad5.
* chore: typo
* chore: 增加密码强度组件
* chore: 国际化密码强度的菜单
* chore(@vben/web-antd): 迁移文本省略组件
* chore: typo
* chore: 组件命名方式遵从packages
* chore: Optimize the onExpand function
* chore: update css
* chore(@vben/web-antd): optimize the getPosition function
* chore: add ellipsis-text in comm-ui
* chore: 文本省略组件迁移至common-ui
* feat(@vben/common-ui): Tooltip的tip支持style传参
* chore: 优化组件渲染
* chore: 使用css module解决样式冲突
* chore: update props
* chore: 优化css
* chore: rm unuse attr
---------
Co-authored-by: Li Kui <90845831+likui628@users.noreply.github.com>
pull/4096/head
committed by
GitHub
9 changed files with 237 additions and 1 deletions
@ -0,0 +1,30 @@ |
|||
import type { RouteRecordRaw } from 'vue-router'; |
|||
|
|||
import { BasicLayout } from '#/layouts'; |
|||
import { $t } from '#/locales'; |
|||
|
|||
const routes: RouteRecordRaw[] = [ |
|||
{ |
|||
component: BasicLayout, |
|||
meta: { |
|||
icon: 'ion:layers-outline', |
|||
keepAlive: true, |
|||
order: 1000, |
|||
title: $t('page.examples.title'), |
|||
}, |
|||
name: 'Examples', |
|||
path: '/examples', |
|||
children: [ |
|||
{ |
|||
name: 'EllipsisDemo', |
|||
path: '/examples/ellipsis', |
|||
component: () => import('#/views/examples/ellipsis/index.vue'), |
|||
meta: { |
|||
title: $t('page.examples.ellipsis.title'), |
|||
}, |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
|
|||
export default routes; |
|||
@ -0,0 +1,2 @@ |
|||
export const longText: string = |
|||
'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 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。'; |
|||
@ -0,0 +1,42 @@ |
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
|
|||
import { EllipsisText } from '@vben/common-ui'; |
|||
|
|||
import { Collapse, CollapsePanel } from 'ant-design-vue'; |
|||
|
|||
import { longText } from './data'; |
|||
|
|||
const text = ref(longText); |
|||
const activeKey = ref(['1', '2', '3', '4']); |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="card-box p-5"> |
|||
<h1 class="mb-5 text-xl font-semibold">文本省略示例</h1> |
|||
<div> |
|||
<Collapse v-model:activeKey="activeKey"> |
|||
<CollapsePanel key="1" header="Ellipsis 基本使用"> |
|||
<EllipsisText :max-width="240">{{ text }}</EllipsisText> |
|||
</CollapsePanel> |
|||
<CollapsePanel key="2" header="Ellipsis 多行省略"> |
|||
<EllipsisText :line="2">{{ text }}</EllipsisText> |
|||
</CollapsePanel> |
|||
<CollapsePanel key="3" header="Ellipsis 点击展开"> |
|||
<EllipsisText :line="3" expand>{{ text }}</EllipsisText> |
|||
</CollapsePanel> |
|||
<CollapsePanel key="4" header="Ellipsis 定制 Tooltip 内容"> |
|||
<EllipsisText :max-width="240"> |
|||
住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪 |
|||
<template #tooltip> |
|||
<div style="text-align: center"> |
|||
《秦皇岛》<br />住在我心里孤独的<br />孤独的海怪 痛苦之王<br />开始厌倦 |
|||
深海的光 停滞的海浪 |
|||
</div> |
|||
</template> |
|||
</EllipsisText> |
|||
</CollapsePanel> |
|||
</Collapse> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
@ -0,0 +1,144 @@ |
|||
<script setup lang="ts"> |
|||
import { computed, type CSSProperties, nextTick, ref, watchEffect } from 'vue'; |
|||
|
|||
import { VbenTooltip } from '@vben-core/shadcn-ui'; |
|||
|
|||
interface Props { |
|||
/** |
|||
* 是否启用点击文本展开全部 |
|||
* @default false |
|||
*/ |
|||
expand?: boolean; |
|||
/** |
|||
* 文本最大行数 |
|||
* @default 1 |
|||
*/ |
|||
line?: number; |
|||
/** |
|||
* 文本最大宽度 |
|||
* @default '100%' |
|||
*/ |
|||
maxWidth?: number | string; |
|||
/** |
|||
* 提示框位置 |
|||
* @default 'top' |
|||
*/ |
|||
placement: 'bottom' | 'left' | 'right' | 'top'; |
|||
/** |
|||
* 是否启用文本提示框 |
|||
* @default true |
|||
*/ |
|||
tooltip?: boolean; |
|||
/** |
|||
* 提示框背景颜色,优先级高于 overlayStyle |
|||
*/ |
|||
tooltipBackgroundColor?: string; |
|||
/** |
|||
* 提示文本字体颜色,优先级高于 overlayStyle |
|||
*/ |
|||
tooltipColor?: string; |
|||
/** |
|||
* 提示文本字体大小,单位px,优先级高于 overlayStyle |
|||
*/ |
|||
tooltipFontSize?: number; |
|||
/** |
|||
* 提示框内容最大宽度,单位px,默认不设置时,提示文本内容自动与展示文本宽度保持一致 |
|||
*/ |
|||
tooltipMaxWidth?: number; |
|||
/** |
|||
* 提示框内容区域样式 |
|||
* @default { textAlign: 'justify' } |
|||
*/ |
|||
tooltipOverlayStyle?: CSSProperties; // 提示框内容区域样式 |
|||
} |
|||
const props = withDefaults(defineProps<Props>(), { |
|||
expand: false, |
|||
line: 1, |
|||
maxWidth: '100%', |
|||
placement: 'top', |
|||
tooltip: true, |
|||
tooltipBackgroundColor: '', |
|||
tooltipColor: '', |
|||
tooltipFontSize: 14, |
|||
tooltipMaxWidth: undefined, |
|||
tooltipOverlayStyle: () => ({ textAlign: 'justify' }), |
|||
}); |
|||
const emit = defineEmits<{ expandChange: [boolean] }>(); |
|||
|
|||
const textMaxWidth = computed(() => { |
|||
if (typeof props.maxWidth === 'number') { |
|||
return `${props.maxWidth}px`; |
|||
} |
|||
return props.maxWidth; |
|||
}); |
|||
const showTooltip = ref(false); |
|||
const ellipsis = ref(); |
|||
const defaultTooltipMaxWidth = ref(); |
|||
watchEffect(() => { |
|||
showTooltip.value = props.tooltip; |
|||
}); |
|||
watchEffect( |
|||
() => { |
|||
if (props.tooltip && ellipsis.value) { |
|||
defaultTooltipMaxWidth.value = |
|||
props.tooltipMaxWidth ?? ellipsis.value.offsetWidth + 24; |
|||
} |
|||
}, |
|||
{ flush: 'post' }, |
|||
); |
|||
function onExpand() { |
|||
const { style } = ellipsis.value; |
|||
const isExpanded = !style['-webkit-line-clamp']; |
|||
if (props.tooltip) { |
|||
showTooltip.value = !isExpanded; |
|||
} |
|||
|
|||
nextTick(() => { |
|||
style['-webkit-line-clamp'] = isExpanded ? props.line : ''; |
|||
}); |
|||
|
|||
emit('expandChange', !isExpanded); |
|||
} |
|||
</script> |
|||
<template> |
|||
<VbenTooltip |
|||
:content-style="{ |
|||
...tooltipOverlayStyle, |
|||
maxWidth: `${defaultTooltipMaxWidth}px`, |
|||
fontSize: `${tooltipFontSize}px`, |
|||
color: tooltipColor, |
|||
backgroundColor: tooltipBackgroundColor, |
|||
}" |
|||
:disabled="!showTooltip" |
|||
:overlay-style="tooltipOverlayStyle" |
|||
:side="placement" |
|||
> |
|||
<slot name="tooltip"> |
|||
<slot></slot> |
|||
</slot> |
|||
|
|||
<template #trigger> |
|||
<div |
|||
ref="ellipsis" |
|||
:class="{ |
|||
'!cursor-pointer': expand, |
|||
['inline-block truncate']: line === 1, |
|||
[$style.ellipsisMultiLine]: line > 1, |
|||
}" |
|||
:style="`-webkit-line-clamp: ${line}; max-width: ${textMaxWidth};`" |
|||
class="cursor-text overflow-hidden" |
|||
@click="expand ? onExpand() : () => false" |
|||
v-bind="$attrs" |
|||
> |
|||
<slot></slot> |
|||
</div> |
|||
</template> |
|||
</VbenTooltip> |
|||
</template> |
|||
|
|||
<style module> |
|||
.ellipsisMultiLine { |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
} |
|||
</style> |
|||
@ -0,0 +1 @@ |
|||
export { default as EllipsisText } from './ellipsis-text.vue'; |
|||
@ -1,5 +1,6 @@ |
|||
export * from './about'; |
|||
export * from './authentication'; |
|||
export * from './dashboard'; |
|||
export * from './ellipsis-text'; |
|||
export * from './fallback'; |
|||
export { useToast } from '@vben-core/shadcn-ui'; |
|||
|
|||
Loading…
Reference in new issue