NoticeBar.vue 3.4 KB

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