Countdown.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { createVNode as _createVNode, resolveDirective as _resolveDirective } from "vue";
  4. import { defineComponent, onBeforeUnmount, onMounted, onUpdated, ref } from 'vue';
  5. import omit from '../_util/omit';
  6. import initDefaultProps from '../_util/props-util/initDefaultProps';
  7. import { someType } from '../_util/type';
  8. import Statistic, { statisticProps } from './Statistic';
  9. import { formatCountdown as formatCD } from './utils';
  10. const REFRESH_INTERVAL = 1000 / 30;
  11. function getTime(value) {
  12. return new Date(value).getTime();
  13. }
  14. export const countdownProps = () => {
  15. return _extends(_extends({}, statisticProps()), {
  16. value: someType([Number, String, Object]),
  17. format: String,
  18. onFinish: Function,
  19. onChange: Function
  20. });
  21. };
  22. export default defineComponent({
  23. compatConfig: {
  24. MODE: 3
  25. },
  26. name: 'AStatisticCountdown',
  27. props: initDefaultProps(countdownProps(), {
  28. format: 'HH:mm:ss'
  29. }),
  30. // emits: ['finish', 'change'],
  31. setup(props, _ref) {
  32. let {
  33. emit,
  34. slots
  35. } = _ref;
  36. const countdownId = ref();
  37. const statistic = ref();
  38. const syncTimer = () => {
  39. const {
  40. value
  41. } = props;
  42. const timestamp = getTime(value);
  43. if (timestamp >= Date.now()) {
  44. startTimer();
  45. } else {
  46. stopTimer();
  47. }
  48. };
  49. const startTimer = () => {
  50. if (countdownId.value) return;
  51. const timestamp = getTime(props.value);
  52. countdownId.value = setInterval(() => {
  53. statistic.value.$forceUpdate();
  54. if (timestamp > Date.now()) {
  55. emit('change', timestamp - Date.now());
  56. }
  57. syncTimer();
  58. }, REFRESH_INTERVAL);
  59. };
  60. const stopTimer = () => {
  61. const {
  62. value
  63. } = props;
  64. if (countdownId.value) {
  65. clearInterval(countdownId.value);
  66. countdownId.value = undefined;
  67. const timestamp = getTime(value);
  68. if (timestamp < Date.now()) {
  69. emit('finish');
  70. }
  71. }
  72. };
  73. const formatCountdown = _ref2 => {
  74. let {
  75. value,
  76. config
  77. } = _ref2;
  78. const {
  79. format
  80. } = props;
  81. return formatCD(value, _extends(_extends({}, config), {
  82. format
  83. }));
  84. };
  85. const valueRenderHtml = node => node;
  86. onMounted(() => {
  87. syncTimer();
  88. });
  89. onUpdated(() => {
  90. syncTimer();
  91. });
  92. onBeforeUnmount(() => {
  93. stopTimer();
  94. });
  95. return () => {
  96. const value = props.value;
  97. return _createVNode(Statistic, _objectSpread({
  98. "ref": statistic
  99. }, _extends(_extends({}, omit(props, ['onFinish', 'onChange'])), {
  100. value,
  101. valueRender: valueRenderHtml,
  102. formatter: formatCountdown
  103. })), slots);
  104. };
  105. }
  106. });