NoticeBar.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <template>
  2. <Touchable
  3. touchable
  4. direction="row"
  5. :flexGrow="0"
  6. :flexShrink="0"
  7. :innerStyle="{
  8. ...themeStyles.view.value,
  9. backgroundColor: themeContext.resolveThemeColor(backgroundColor),
  10. }"
  11. @click="emit('click')"
  12. >
  13. <slot name="leftIcon">
  14. <Icon
  15. :innerStyle="themeStyles.icon.value"
  16. :color="textColor"
  17. :icon="icon"
  18. v-bind="iconProps"
  19. />
  20. </slot>
  21. <view v-if="scroll" :style="themeStyles.contentView.value">
  22. <HorizontalScrollText :innerStyle="textStyleFinal" :scrollDuration="scrollDuration" :text="content" />
  23. </view>
  24. <Text v-else :lines="wrap ? undefined : 1" :innerStyle="textStyleFinal" :text="content" />
  25. <slot name="rightIcon" />
  26. <IconButton
  27. v-if="closeable"
  28. icon="close"
  29. :innerStyle="themeStyles.icon.value"
  30. :color="textColor"
  31. @click="emit('close')"
  32. />
  33. </Touchable>
  34. </template>
  35. <script setup lang="ts">
  36. import { computed } from 'vue';
  37. import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
  38. import { DynamicSize, DynamicSize2 } from '../theme/ThemeTools';
  39. import type { IconProps } from '../basic/Icon.vue';
  40. import Icon from '../basic/Icon.vue';
  41. import IconButton from '../basic/IconButton.vue';
  42. import Text from '../basic/Text.vue';
  43. import HorizontalScrollText from '../typography/HorizontalScrollText.vue';
  44. import Touchable from '../feedback/Touchable.vue';
  45. export interface NoticeBarProps {
  46. /**
  47. * 左边的图标, 可以传入图片
  48. */
  49. icon?: string|undefined;
  50. /**
  51. * 图标或者图片的自定义样式
  52. */
  53. iconStyle?: ViewStyle;
  54. /**
  55. * 图标额外属性
  56. */
  57. iconProps?: IconProps;
  58. /**
  59. * 内容
  60. */
  61. content?: string;
  62. /**
  63. * 文字的自定义样式
  64. */
  65. textStyle?: TextStyle;
  66. /**
  67. * 背景颜色
  68. * @default light.warning
  69. */
  70. backgroundColor?: string;
  71. /**
  72. * 文字颜色
  73. * @default text.warning
  74. */
  75. textColor?: string;
  76. /**
  77. * 是否滚动播放
  78. * @default true
  79. */
  80. scroll?: boolean;
  81. /**
  82. * 滚动动画时长(毫秒)
  83. * @default 100000
  84. */
  85. scrollDuration?: number;
  86. /**
  87. * 文字是否换行,仅在非滚动播放时生效
  88. * @default false
  89. */
  90. wrap?: boolean;
  91. /**
  92. * 是否显示关闭按钮。用户点击后会触发 `close` 事件,请自行处理 NoticeBar 的显示与否。
  93. * @default false
  94. */
  95. closeable?: boolean;
  96. }
  97. const themeContext = useTheme();
  98. const emit = defineEmits([ 'close', 'click' ]);
  99. const props = withDefaults(defineProps<NoticeBarProps>(), {
  100. icon: 'notification',
  101. backgroundColor: () => propGetThemeVar('NoticeBarBackgroundColor', 'background.warning'),
  102. textColor: () => propGetThemeVar('NoticeBarTextColor', 'text.warning'),
  103. scroll: true,
  104. scrollDuration: () => propGetThemeVar('NoticeBarScrollDuration', 100000),
  105. wrap: false,
  106. closeable: false,
  107. });
  108. const textStyleFinal = computed(() => ({
  109. width: 'auto',
  110. height: 'auto',
  111. flex: 1,
  112. color: themeContext.resolveThemeColor(props.textColor),
  113. ...props.textStyle,
  114. } as TextStyle));
  115. const themeStyles = themeContext.useThemeStyles({
  116. view: {
  117. display: 'flex',
  118. position: 'relative',
  119. padding: DynamicSize2('NoticeBarPaddingVertical', 'NoticeBarPaddingHorizontal', 12, 20),
  120. justifyContent: 'space-between',
  121. alignContent: 'center',
  122. },
  123. icon: {
  124. marginRight: DynamicSize('NoticeBarIconMarginRight', 10),
  125. },
  126. contentView: {
  127. flex: 1,
  128. overflow: 'hidden',
  129. },
  130. });
  131. </script>