|
|
@@ -1,258 +1,26 @@
|
|
|
<template>
|
|
|
- <view v-if="allowChildNode" :id="id" :class="innerClass" :style="style" @click="onClick">
|
|
|
- <slot>{{ text }}</slot>
|
|
|
- </view>
|
|
|
- <text v-else :id="id" :class="innerClass" :style="style" @click="onClick">
|
|
|
- <!-- #ifdef APP-NVUE -->
|
|
|
- {{ text }}
|
|
|
- <!-- #endif -->
|
|
|
- <!-- #ifndef APP-NVUE -->
|
|
|
- <slot>{{ text ?? '' }}</slot>
|
|
|
- <!-- #endif -->
|
|
|
- </text>
|
|
|
+ <view v-if="(allowChildNode || $slots.default) && !forceNoSlotWhenNestForMp" :id="id" :class="innerClass" :style="style" @click="onClick"><slot>{{ text }}</slot></view>
|
|
|
+ <text v-else :id="id" :class="innerClass" :style="style" @click="onClick">{{ text }}</text>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { computed, getCurrentInstance } from 'vue';
|
|
|
-import { useTheme, type ThemePaddingMargin } from '../theme/ThemeDefine';
|
|
|
-import { RandomUtils } from '@imengyu/imengyu-utils';
|
|
|
-
|
|
|
-export interface TextProps {
|
|
|
- /**
|
|
|
- * 字体颜色。可以是颜色字符串或者在主题中配置的预设名称。
|
|
|
- */
|
|
|
- color?: string,
|
|
|
- /**
|
|
|
- * 是否允许子节点。如果为 true,则使用view包裹。
|
|
|
- * @default false
|
|
|
- */
|
|
|
- allowChildNode?: boolean,
|
|
|
- /**
|
|
|
- * 文字阴影颜色。可以是颜色字符串或者在主题中配置的预设名称。
|
|
|
- */
|
|
|
- shadowColor?: string,
|
|
|
- /**
|
|
|
- * 文字对齐方式。
|
|
|
- */
|
|
|
- textAlign?: 'center'|'left'|'right'|'',
|
|
|
- /**
|
|
|
- * 字体预设。可以是主题中预设的一个名称。
|
|
|
- */
|
|
|
- fontConfig?: string,
|
|
|
- /**
|
|
|
- * 字体大小。可以是实际数值或者在主题中配置的预设名称。
|
|
|
- */
|
|
|
- fontSize?: string|number,
|
|
|
- /**
|
|
|
- * 字体名称。
|
|
|
- */
|
|
|
- fontFamily?: string,
|
|
|
- /**
|
|
|
- * 字体样式。
|
|
|
- */
|
|
|
- fontStyle?: string,
|
|
|
- /**
|
|
|
- * 字体粗细。
|
|
|
- */
|
|
|
- fontWeight?: string|number,
|
|
|
- /**
|
|
|
- * 是否是粗体
|
|
|
- */
|
|
|
- bold?: boolean,
|
|
|
- /**
|
|
|
- * 是否是斜体
|
|
|
- */
|
|
|
- italic?: boolean,
|
|
|
- /**
|
|
|
- * 是否加下划线
|
|
|
- */
|
|
|
- underline?: boolean,
|
|
|
- /**
|
|
|
- * 是否加删除线
|
|
|
- */
|
|
|
- lineThrough?: boolean,
|
|
|
- /**
|
|
|
- * 是否有阴影。
|
|
|
- */
|
|
|
- shadow?: boolean,
|
|
|
- /**
|
|
|
- * 背景颜色。可以是颜色字符串或者在主题中配置的预设名称。
|
|
|
- */
|
|
|
- backgroundColor?: string,
|
|
|
- /**
|
|
|
- * 是否可以选择
|
|
|
- */
|
|
|
- selectable?: boolean,
|
|
|
- /**
|
|
|
- * word-break
|
|
|
- * @default undefined
|
|
|
- */
|
|
|
- wordBreak?: 'normal'|'break-all'|'keep-all'|'break-word'|undefined;
|
|
|
- /**
|
|
|
- * 是否允许换行
|
|
|
- * @default true
|
|
|
- */
|
|
|
- wrap?: boolean,
|
|
|
- /**
|
|
|
- * 行数限制
|
|
|
- */
|
|
|
- lines?: number,
|
|
|
- margin?: number|string|number[]|ThemePaddingMargin,
|
|
|
- padding?: number|string|number[]|ThemePaddingMargin,
|
|
|
- innerStyle?: object,
|
|
|
- innerClass?: object|string,
|
|
|
- /**
|
|
|
- * 最大宽度
|
|
|
- */
|
|
|
- maxWidth?: number|string,
|
|
|
-
|
|
|
- /**
|
|
|
- * 自动工具文字长短设置大小,在 autoSize 为 true 时有效。
|
|
|
- *
|
|
|
- * 这个是一个小功能,目的是为了在某些情况下(例如金额显示),容器宽度一定但是文字长短不定,
|
|
|
- * 此时需要自动缩放大小,文字越长,字号越小。
|
|
|
- *
|
|
|
- * 计算公式是 (1 - (text.length - minLen) / (maxLen - minLen)) * (maxSize - minSize) + minSize
|
|
|
- */
|
|
|
- autoSize?: {
|
|
|
- /**
|
|
|
- * 小程序无法获取模板内容,需要额外提供字符串
|
|
|
- */
|
|
|
- text?: string,
|
|
|
- /**
|
|
|
- * 最长文字长度,用于自动大小公式计算
|
|
|
- */
|
|
|
- maxLen: number;
|
|
|
- /**
|
|
|
- * 最短文字长度,如果输入文字长度小于这个值,则不会进行自动缩放
|
|
|
- */
|
|
|
- minLen: number;
|
|
|
- /**
|
|
|
- * 最大文字字号,用于自动大小公式计算
|
|
|
- */
|
|
|
- maxSize: number;
|
|
|
- /**
|
|
|
- * 最小文字字号,用于自动大小公式计算
|
|
|
- */
|
|
|
- minSize: number;
|
|
|
- },
|
|
|
- text?: string|number,
|
|
|
- /**
|
|
|
- * 是否可以点击
|
|
|
- */
|
|
|
- touchable?: boolean,
|
|
|
-}
|
|
|
+import { useText, type TextProps } from './Text';
|
|
|
|
|
|
/**
|
|
|
* 组件说明:文字封装,支持点击事件,颜色,阴影。
|
|
|
*/
|
|
|
const props = withDefaults(defineProps<TextProps>(), {
|
|
|
shadowColor: '#000',
|
|
|
- bold: false,
|
|
|
- italic: false,
|
|
|
- underline: false,
|
|
|
- lineThrough: false,
|
|
|
- shadow: false,
|
|
|
- touchable: false,
|
|
|
wrap: true,
|
|
|
});
|
|
|
-const emit = defineEmits([ 'click' ])
|
|
|
-
|
|
|
-const id = `text-${RandomUtils.genNonDuplicateID(12)}`;
|
|
|
-const instance = getCurrentInstance();
|
|
|
-const { resolveThemeColor, resolveThemeSize, getText } = useTheme();
|
|
|
-
|
|
|
-function getAutoSize() {
|
|
|
- //自动缩放大小,文字越长,字号越小
|
|
|
- const autoSizeOption = props.autoSize;
|
|
|
- if (autoSizeOption) {
|
|
|
- const text = '' + autoSizeOption.text;
|
|
|
- if (text.length < autoSizeOption.minLen)
|
|
|
- return props.fontSize;
|
|
|
- return (1 - (text.length - autoSizeOption.minLen) / (autoSizeOption.maxLen - autoSizeOption.minLen))
|
|
|
- * (autoSizeOption.maxSize - autoSizeOption.minSize) + autoSizeOption.minSize;
|
|
|
- }
|
|
|
-}
|
|
|
-function onClick(e: any) {
|
|
|
- if (props.touchable) {
|
|
|
- emit("click", e)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const style = computed(() => {
|
|
|
- const o : Record<string, any> = {
|
|
|
- }
|
|
|
- const style = props.fontConfig ? getText(props.fontConfig) : undefined;
|
|
|
- const color = props.color ?? style?.color as string;
|
|
|
- const backgroundColor = props.backgroundColor ?? style?.backgroundColor as string;
|
|
|
- const fontSize = props.fontSize ?? style?.fontSize as string;
|
|
|
- const fontWeight = props.fontWeight ?? style?.fontWeight as string;
|
|
|
- const fontFamily = props.fontFamily ?? style?.fontFamily as string;
|
|
|
- const fontStyle = props.fontStyle ?? style?.fontStyle as string;
|
|
|
-
|
|
|
- if (color) o.color = resolveThemeColor(color, "text");
|
|
|
- if (backgroundColor) o.background = resolveThemeColor(backgroundColor);
|
|
|
- if (fontSize) o.fontSize = resolveThemeSize(fontSize);
|
|
|
- if (fontWeight) o.fontWeight = fontWeight;
|
|
|
- if (fontStyle) o.fontStyle = fontStyle;
|
|
|
- if (!props.wrap) o.whiteSpace = 'nowrap';
|
|
|
+const emit = defineEmits([ 'click' ]);
|
|
|
|
|
|
- if (fontFamily) o.fontFamily = fontFamily;
|
|
|
- if (props.textAlign) {
|
|
|
- o.textAlign = props.textAlign;
|
|
|
- }
|
|
|
- if (props.selectable) o.userSelect = props.selectable;
|
|
|
- if (props.lines) {
|
|
|
- o.display = '-webkit-box';
|
|
|
- o['-webkit-line-clamp'] = props.lines;
|
|
|
- o['-webkit-box-orient'] = 'vertical';
|
|
|
- o.overflow = 'hidden';
|
|
|
- o.textOverflow = 'ellipsis';
|
|
|
- }
|
|
|
- if (props.bold)
|
|
|
- o.fontWeight = 'bold';
|
|
|
- if (props.italic)
|
|
|
- o.fontStyle = 'italic';
|
|
|
- if ((props.underline || props.lineThrough) && !o.textDecoration)
|
|
|
- o.textDecoration = '';
|
|
|
- if (props.underline)
|
|
|
- o.textDecoration += ' underline';
|
|
|
- if (props.lineThrough)
|
|
|
- o.textDecoration += ' line-through';
|
|
|
- if (props.maxWidth)
|
|
|
- o.maxWidth = resolveThemeSize(props.maxWidth);
|
|
|
- if (props.wordBreak)
|
|
|
- o.wordBreak = props.wordBreak;
|
|
|
-
|
|
|
- if (props.shadow && props.shadowColor) {
|
|
|
- o.textShadow = '1px 1px 2px ' + resolveThemeColor(props.shadowColor, 'text');
|
|
|
- }
|
|
|
- if (props.autoSize) {
|
|
|
- const s = getAutoSize();
|
|
|
- if (s)
|
|
|
- o.fontSize = s + 'rpx';
|
|
|
- }
|
|
|
-
|
|
|
- const rs = {
|
|
|
- ...o,
|
|
|
- ...props.innerStyle
|
|
|
- };
|
|
|
- return rs;
|
|
|
-})
|
|
|
-
|
|
|
-async function measureTextWidth() {
|
|
|
- return await new Promise<number>((resolve) => {
|
|
|
- uni.createSelectorQuery()
|
|
|
- // #ifdef MP
|
|
|
- .in(instance)
|
|
|
- // #endif
|
|
|
- .select(`#${id}`)
|
|
|
- .boundingClientRect((data) => {
|
|
|
- resolve((data as UniApp.NodeInfo)?.width ?? 0)
|
|
|
- })
|
|
|
- .exec();
|
|
|
- })
|
|
|
-}
|
|
|
+const {
|
|
|
+ id,
|
|
|
+ style,
|
|
|
+ measureTextWidth,
|
|
|
+ onClick,
|
|
|
+} = useText(props, emit);
|
|
|
|
|
|
defineExpose({
|
|
|
measureTextWidth,
|
|
|
@@ -263,12 +31,4 @@ defineOptions({
|
|
|
styleIsolation: "shared",
|
|
|
},
|
|
|
});
|
|
|
-
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss">
|
|
|
-.nana-text-can-press {
|
|
|
- cursor: pointer;
|
|
|
- opacity: 0.8;
|
|
|
-}
|
|
|
-</style>
|
|
|
+</script>
|