wd-text.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <template>
  2. <text @click="handleClick" :class="rootClass" :style="rootStyle">
  3. <slot v-if="$slots.prefix || prefix" name="prefix">{{ prefix }}</slot>
  4. <text>{{ formattedText }}</text>
  5. <slot v-if="$slots.suffix || suffix" name="suffix">{{ suffix }}</slot>
  6. </text>
  7. </template>
  8. <script lang="ts">
  9. export default {
  10. name: 'wd-text',
  11. options: {
  12. virtualHost: true,
  13. addGlobalClass: true,
  14. styleIsolation: 'shared'
  15. }
  16. }
  17. </script>
  18. <script lang="ts" setup>
  19. import { computed, ref, watch } from 'vue'
  20. import { isDef, objToStyle } from '../common/util'
  21. import { textProps } from './types'
  22. import dayjs from '../../dayjs'
  23. // 获取组件的 props 和 emit 函数
  24. const props = defineProps(textProps)
  25. const emit = defineEmits(['click'])
  26. // 存储文本类名的响应式变量
  27. const textClass = ref<string>('')
  28. // 监听 props 变化,合并 watch 逻辑
  29. watch(
  30. () => ({
  31. type: props.type,
  32. text: props.text,
  33. mode: props.mode,
  34. color: props.color,
  35. bold: props.bold,
  36. lines: props.lines,
  37. format: props.format
  38. }),
  39. ({ type }) => {
  40. // 验证 type 属性
  41. const types = ['primary', 'error', 'warning', 'success', 'default']
  42. if (type && !types.includes(type)) {
  43. console.error(`type must be one of ${types.toString()}`)
  44. }
  45. computeTextClass()
  46. },
  47. { deep: true, immediate: true }
  48. )
  49. // 计算根元素的类名
  50. const rootClass = computed(() => {
  51. return `wd-text ${props.customClass} ${textClass.value}`
  52. })
  53. // 计算根元素的样式
  54. const rootStyle = computed(() => {
  55. const rootStyle: Record<string, any> = {}
  56. if (props.color) {
  57. rootStyle['color'] = props.color
  58. }
  59. if (props.size) {
  60. rootStyle['font-size'] = `${props.size}`
  61. }
  62. if (props.lineHeight) {
  63. rootStyle['line-height'] = `${props.lineHeight}`
  64. }
  65. if (props.decoration) {
  66. rootStyle['text-decoration'] = `${props.decoration}`
  67. }
  68. return `${objToStyle(rootStyle)}${props.customStyle}`
  69. })
  70. // 计算文本类名的函数
  71. function computeTextClass() {
  72. const { type, color, bold, lines } = props
  73. const textClassList: string[] = []
  74. if (!color) {
  75. textClassList.push(`is-${type}`)
  76. }
  77. if (isDef(lines)) {
  78. textClassList.push(`is-lines-${lines}`)
  79. }
  80. bold && textClassList.push('is-bold')
  81. textClass.value = textClassList.join(' ')
  82. }
  83. // 格式化文本的函数
  84. function formatText(text: string, format: boolean, mode: string): string {
  85. if (format) {
  86. if (mode === 'phone') {
  87. return text.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
  88. } else if (mode === 'name') {
  89. return text.replace(/^(.).*(.)$/, '$1**$2')
  90. } else {
  91. throw new Error('mode must be one of phone or name for encryption')
  92. }
  93. }
  94. return text
  95. }
  96. // 格式化数字的函数
  97. function formatNumber(num: number | string): string {
  98. num = Number(num).toFixed(2)
  99. const x = num.split('.')
  100. let x1 = x[0]
  101. const x2 = x.length > 1 ? '.' + x[1] : ''
  102. const rgx = /(\d+)(\d{3})/
  103. while (rgx.test(x1)) {
  104. x1 = x1.replace(rgx, '$1,$2')
  105. }
  106. return x1 + x2
  107. }
  108. // 计算格式化后的文本
  109. const formattedText = computed(() => {
  110. const { text, mode, format } = props
  111. if (mode === 'date') {
  112. return dayjs(Number(text)).format('YYYY-MM-DD')
  113. }
  114. if (mode === 'price') {
  115. return formatNumber(text)
  116. }
  117. return formatText(`${text}`, format, mode)
  118. })
  119. // 处理点击事件
  120. function handleClick(event: Event) {
  121. emit('click', event)
  122. }
  123. </script>
  124. <style lang="scss" scoped>
  125. @import './index.scss';
  126. </style>