uni-countdown.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <view class="uni-countdown">
  3. <text v-if="showDay" :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }"
  4. class="uni-countdown__number">{{ d }}</text>
  5. <text v-if="showDay" :style="{ color: splitorColor }" class="uni-countdown__splitor">{{dayText}}</text>
  6. <text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }"
  7. class="uni-countdown__number">{{ h }}</text>
  8. <text :style="{ color: splitorColor }" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
  9. <text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }"
  10. class="uni-countdown__number">{{ i }}</text>
  11. <text :style="{ color: splitorColor }" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
  12. <text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }"
  13. class="uni-countdown__number">{{ s }}</text>
  14. <text v-if="!showColon" :style="{ color: splitorColor }" class="uni-countdown__splitor">{{secondText}}</text>
  15. </view>
  16. </template>
  17. <script>
  18. import {
  19. initVueI18n
  20. } from '@dcloudio/uni-i18n'
  21. import messages from './i18n/index.js'
  22. const { t } = initVueI18n(messages)
  23. /**
  24. * Countdown 倒计时
  25. * @description 倒计时组件
  26. * @tutorial https://ext.dcloud.net.cn/plugin?id=25
  27. * @property {String} backgroundColor 背景色
  28. * @property {String} color 文字颜色
  29. * @property {Number} day 天数
  30. * @property {Number} hour 小时
  31. * @property {Number} minute 分钟
  32. * @property {Number} second 秒
  33. * @property {Number} timestamp 时间戳
  34. * @property {Boolean} showDay = [true|false] 是否显示天数
  35. * @property {Boolean} showColon = [true|false] 是否以冒号为分隔符
  36. * @property {String} splitorColor 分割符号颜色
  37. * @event {Function} timeup 倒计时时间到触发事件
  38. * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
  39. */
  40. export default {
  41. name: 'UniCountdown',
  42. emits:['timeup'],
  43. props: {
  44. showDay: {
  45. type: Boolean,
  46. default: true
  47. },
  48. showColon: {
  49. type: Boolean,
  50. default: true
  51. },
  52. start: {
  53. type: Boolean,
  54. default: true
  55. },
  56. backgroundColor: {
  57. type: String,
  58. default: '#FFFFFF'
  59. },
  60. borderColor: {
  61. type: String,
  62. default: '#000000'
  63. },
  64. color: {
  65. type: String,
  66. default: '#000000'
  67. },
  68. splitorColor: {
  69. type: String,
  70. default: '#000000'
  71. },
  72. day: {
  73. type: Number,
  74. default: 0
  75. },
  76. hour: {
  77. type: Number,
  78. default: 0
  79. },
  80. minute: {
  81. type: Number,
  82. default: 0
  83. },
  84. second: {
  85. type: Number,
  86. default: 0
  87. },
  88. timestamp: {
  89. type: Number,
  90. default: 0
  91. }
  92. },
  93. data() {
  94. return {
  95. timer: null,
  96. syncFlag: false,
  97. d: '00',
  98. h: '00',
  99. i: '00',
  100. s: '00',
  101. leftTime: 0,
  102. seconds: 0
  103. }
  104. },
  105. computed: {
  106. dayText() {
  107. return t("uni-countdown.day")
  108. },
  109. hourText(val) {
  110. return t("uni-countdown.h")
  111. },
  112. minuteText(val) {
  113. return t("uni-countdown.m")
  114. },
  115. secondText(val) {
  116. return t("uni-countdown.s")
  117. },
  118. },
  119. watch: {
  120. day(val) {
  121. this.changeFlag()
  122. },
  123. hour(val) {
  124. this.changeFlag()
  125. },
  126. minute(val) {
  127. this.changeFlag()
  128. },
  129. second(val) {
  130. this.changeFlag()
  131. },
  132. start: {
  133. immediate: true,
  134. handler(newVal, oldVal) {
  135. if (newVal) {
  136. this.startData();
  137. } else {
  138. if (!oldVal) return
  139. clearInterval(this.timer)
  140. }
  141. }
  142. }
  143. },
  144. created: function(e) {
  145. this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
  146. this.countDown()
  147. },
  148. // #ifndef VUE3
  149. destroyed() {
  150. clearInterval(this.timer)
  151. },
  152. // #endif
  153. // #ifdef VUE3
  154. unmounted() {
  155. clearInterval(this.timer)
  156. },
  157. // #endif
  158. methods: {
  159. toSeconds(timestamp, day, hours, minutes, seconds) {
  160. if (timestamp) {
  161. return timestamp - parseInt(new Date().getTime() / 1000, 10)
  162. }
  163. return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
  164. },
  165. timeUp() {
  166. clearInterval(this.timer)
  167. this.$emit('timeup')
  168. },
  169. countDown() {
  170. let seconds = this.seconds
  171. let [day, hour, minute, second] = [0, 0, 0, 0]
  172. if (seconds > 0) {
  173. day = Math.floor(seconds / (60 * 60 * 24))
  174. hour = Math.floor(seconds / (60 * 60)) - (day * 24)
  175. minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
  176. second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
  177. } else {
  178. this.timeUp()
  179. }
  180. if (day < 10) {
  181. day = '0' + day
  182. }
  183. if (hour < 10) {
  184. hour = '0' + hour
  185. }
  186. if (minute < 10) {
  187. minute = '0' + minute
  188. }
  189. if (second < 10) {
  190. second = '0' + second
  191. }
  192. this.d = day
  193. this.h = hour
  194. this.i = minute
  195. this.s = second
  196. },
  197. startData() {
  198. this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
  199. if (this.seconds <= 0) {
  200. return
  201. }
  202. clearInterval(this.timer)
  203. this.countDown()
  204. this.timer = setInterval(() => {
  205. this.seconds--
  206. if (this.seconds < 0) {
  207. this.timeUp()
  208. return
  209. }
  210. this.countDown()
  211. }, 1000)
  212. },
  213. changeFlag() {
  214. if (!this.syncFlag) {
  215. this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
  216. this.startData();
  217. this.syncFlag = true;
  218. }
  219. }
  220. }
  221. }
  222. </script>
  223. <style lang="scss" scoped>
  224. $countdown-height: 48rpx;
  225. $countdown-width: 52rpx;
  226. .uni-countdown {
  227. /* #ifndef APP-NVUE */
  228. display: flex;
  229. /* #endif */
  230. flex-direction: row;
  231. justify-content: flex-start;
  232. padding: 2rpx 0;
  233. }
  234. .uni-countdown__splitor {
  235. /* #ifndef APP-NVUE */
  236. display: flex;
  237. /* #endif */
  238. justify-content: center;
  239. line-height: $countdown-height;
  240. padding: 5rpx;
  241. font-size: $uni-font-size-sm;
  242. }
  243. .uni-countdown__number {
  244. /* #ifndef APP-NVUE */
  245. display: flex;
  246. /* #endif */
  247. justify-content: center;
  248. align-items: center;
  249. width: $countdown-width;
  250. height: $countdown-height;
  251. line-height: $countdown-height;
  252. margin: 5rpx;
  253. text-align: center;
  254. font-size: $uni-font-size-sm;
  255. }
  256. </style>