chore: define examples router & add ellipsis comp (#4019)
* chore: define components router * chore: 组件路由放置到演示路由下 * Revert "chore: 组件路由放置到演示路由下" This reverts commit 3c24632ad51f031cf95aafa49183d7c5538098bb. * 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/48/MERGE
parent
de90b07b6f
commit
f1e0278bd8
|
@ -37,7 +37,9 @@
|
|||
"title": "Active Menu Icon",
|
||||
"children": "Children Active Icon"
|
||||
},
|
||||
"fallback": { "title": "Fallback Page" },
|
||||
"fallback": {
|
||||
"title": "Fallback Page"
|
||||
},
|
||||
"features": {
|
||||
"title": "Features",
|
||||
"hideChildrenInMenu": "Hide Menu Children",
|
||||
|
@ -54,6 +56,12 @@
|
|||
"level": "Level Mode",
|
||||
"levelDetail": "Level Mode Detail"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"title": "Examples",
|
||||
"ellipsis": {
|
||||
"title": "EllipsisText"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@
|
|||
"levelDetail": "层级模式详情",
|
||||
"lateralDetail": "平级模式详情"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"title": "示例",
|
||||
"ellipsis": {
|
||||
"title": "文本省略"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -12,6 +12,7 @@ import {
|
|||
|
||||
interface Props {
|
||||
contentClass?: HTMLAttributes['class'];
|
||||
contentStyle?: HTMLAttributes['style'];
|
||||
delayDuration?: number;
|
||||
side: TooltipContentProps['side'];
|
||||
}
|
||||
|
@ -31,6 +32,7 @@ withDefaults(defineProps<Props>(), {
|
|||
<TooltipContent
|
||||
:class="contentClass"
|
||||
:side="side"
|
||||
:style="contentStyle"
|
||||
class="side-content text-popover-foreground bg-popover"
|
||||
>
|
||||
<slot></slot>
|
||||
|
|
|
@ -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