u-alert.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <template>
  2. <up-transition
  3. :mode="transitionMode"
  4. :show="show"
  5. >
  6. <view
  7. class="u-alert"
  8. :class="[`u-alert--${type}--${effect}`]"
  9. @tap.stop="clickHandler"
  10. :style="[addStyle(customStyle)]"
  11. >
  12. <!-- 左侧图标 -->
  13. <view
  14. class="u-alert__icon"
  15. v-if="showIcon"
  16. >
  17. <up-icon
  18. :name="iconName"
  19. size="18"
  20. :color="iconColor"
  21. ></up-icon>
  22. </view>
  23. <!-- 内容区域 -->
  24. <view
  25. class="u-alert__content"
  26. :style="[{
  27. paddingRight: closable ? '20px' : 0
  28. }]"
  29. >
  30. <!-- 标题 -->
  31. <text
  32. class="u-alert__content__title"
  33. v-if="title"
  34. :style="[{
  35. fontSize: addUnit(fontSize),
  36. textAlign: center ? 'center' : 'left'
  37. }]"
  38. :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
  39. >{{ title }}</text>
  40. <!-- 描述信息 -->
  41. <text
  42. class="u-alert__content__desc"
  43. v-if="description"
  44. :style="[{
  45. fontSize: addUnit(fontSize),
  46. textAlign: center ? 'center' : 'left'
  47. }]"
  48. :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
  49. >{{ description }}</text>
  50. </view>
  51. <!-- 关闭按钮 -->
  52. <view
  53. class="u-alert__close"
  54. v-if="closable"
  55. @tap.stop="closeHandler"
  56. >
  57. <slot name="close">
  58. <up-icon
  59. name="close"
  60. :color="iconColor"
  61. size="15"
  62. ></up-icon>
  63. </slot>
  64. </view>
  65. </view>
  66. </up-transition>
  67. </template>
  68. <script>
  69. import { props } from './props';
  70. import { mpMixin } from '../../libs/mixin/mpMixin';
  71. import { mixin } from '../../libs/mixin/mixin';
  72. import { addUnit, addStyle } from '../../libs/function/index';
  73. /**
  74. * Alert 警告提示
  75. * @description 警告提示,展现需要关注的信息。
  76. * @tutorial https://ijry.github.io/uview-plus/components/alertTips.html
  77. *
  78. * @property {String} title 显示的文字
  79. * @property {String} type 使用预设的颜色 (默认 'warning' )
  80. * @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
  81. * @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
  82. * @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
  83. * @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
  84. * @property {Boolean} center 文字是否居中 (默认 false )
  85. * @property {String | Number} fontSize 字体大小 (默认 14 )
  86. * @property {Object} customStyle 定义需要用到的外部样式
  87. * @property {String} transitionMode 过渡动画模式 (默认 'fade' )
  88. * @property {String | Number} duration 自动关闭延时(毫秒),设置为0或负数则不自动关闭 (默认 0 )
  89. * @property {String} icon 自定义图标名称,优先级高于type默认图标
  90. * @property {Boolean} modelValue/v-model 绑定值,控制是否显示 (默认 true )
  91. * @event {Function} click 点击组件时触发
  92. * @event {Function} close 点击关闭按钮时触发
  93. * @event {Function} closed 关闭动画结束时触发
  94. * @example <up-alert :title="title" type = "warning" :closable="closable" :description = "description"></up-alert>
  95. */
  96. export default {
  97. name: 'u-alert',
  98. mixins: [mpMixin, mixin, props],
  99. data() {
  100. return {
  101. // 控制组件显示隐藏
  102. show: true
  103. }
  104. },
  105. computed: {
  106. // 根据不同的主题类型返回对应的图标颜色
  107. iconColor() {
  108. return this.effect === 'light' ? this.type : '#fff'
  109. },
  110. // 不同主题对应不同的图标
  111. iconName() {
  112. // 如果用户自定义了图标,则优先使用自定义图标
  113. if (this.icon) return this.icon;
  114. switch (this.type) {
  115. case 'success':
  116. return 'checkmark-circle-fill';
  117. break;
  118. case 'error':
  119. return 'close-circle-fill';
  120. break;
  121. case 'warning':
  122. return 'error-circle-fill';
  123. break;
  124. case 'info':
  125. return 'info-circle-fill';
  126. break;
  127. case 'primary':
  128. return 'more-circle-fill';
  129. break;
  130. default:
  131. return 'error-circle-fill';
  132. }
  133. }
  134. },
  135. emits: ["click","close", "closed", "update:modelValue"],
  136. watch: {
  137. modelValue: {
  138. handler(newVal) {
  139. this.show = newVal;
  140. },
  141. immediate: true
  142. },
  143. show: {
  144. handler(newVal) {
  145. this.$emit('update:modelValue', newVal);
  146. // 如果是从显示到隐藏,且启用了自动关闭功能
  147. if (!newVal && this.duration > 0) {
  148. this.$emit('closed');
  149. }
  150. }
  151. }
  152. },
  153. mounted() {
  154. // 如果设置了自动关闭时间,则在指定时间后自动关闭
  155. if (this.duration > 0) {
  156. setTimeout(() => {
  157. this.closeHandler();
  158. }, this.duration);
  159. }
  160. },
  161. methods: {
  162. addUnit,
  163. addStyle,
  164. // 点击内容区域触发click事件
  165. clickHandler() {
  166. this.$emit('click')
  167. },
  168. // 点击关闭按钮触发close事件并隐藏组件
  169. closeHandler() {
  170. this.show = false
  171. this.$emit('close');
  172. }
  173. }
  174. }
  175. </script>
  176. <style lang="scss" scoped>
  177. .u-alert {
  178. position: relative;
  179. background-color: $u-primary;
  180. padding: 8px 10px;
  181. @include flex(row);
  182. align-items: center;
  183. border-top-left-radius: 4px;
  184. border-top-right-radius: 4px;
  185. border-bottom-left-radius: 4px;
  186. border-bottom-right-radius: 4px;
  187. &--primary--dark {
  188. background-color: $u-primary;
  189. }
  190. &--primary--light {
  191. background-color: #ecf5ff;
  192. }
  193. &--error--dark {
  194. background-color: $u-error;
  195. }
  196. &--error--light {
  197. background-color: #FEF0F0;
  198. }
  199. &--success--dark {
  200. background-color: $u-success;
  201. }
  202. &--success--light {
  203. background-color: #f5fff0;
  204. }
  205. &--warning--dark {
  206. background-color: $u-warning;
  207. }
  208. &--warning--light {
  209. background-color: #FDF6EC;
  210. }
  211. &--info--dark {
  212. background-color: $u-info;
  213. }
  214. &--info--light {
  215. background-color: #f4f4f5;
  216. }
  217. &__icon {
  218. margin-right: 5px;
  219. }
  220. &__content {
  221. @include flex(column);
  222. flex: 1;
  223. &__title {
  224. color: $u-main-color;
  225. font-size: 14px;
  226. font-weight: bold;
  227. color: #fff;
  228. margin-bottom: 2px;
  229. }
  230. &__desc {
  231. color: $u-main-color;
  232. font-size: 14px;
  233. flex-wrap: wrap;
  234. color: #fff;
  235. }
  236. }
  237. &__title--dark,
  238. &__desc--dark {
  239. color: #FFFFFF;
  240. }
  241. &__text--primary--light,
  242. &__text--primary--light {
  243. color: $u-primary;
  244. }
  245. &__text--success--light,
  246. &__text--success--light {
  247. color: $u-success;
  248. }
  249. &__text--warning--light,
  250. &__text--warning--light {
  251. color: $u-warning;
  252. }
  253. &__text--error--light,
  254. &__text--error--light {
  255. color: $u-error;
  256. }
  257. &__text--info--light,
  258. &__text--info--light {
  259. color: $u-info;
  260. }
  261. &__close {
  262. position: absolute;
  263. top: 11px;
  264. right: 10px;
  265. }
  266. }
  267. </style>