bf415c6a0eb55de22448cb185688d4b0d181e8306c9e3a2002221649c470618b5ac6c8f4507d53e242344495a2dfa34fcfcd4d076c549356efd8e3bccffb6a 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <template>
  2. <div class="el-statistic">
  3. <div class="head" v-if="title||$slots.title">
  4. <slot name="title">
  5. <span class="title">
  6. {{ title }}
  7. </span>
  8. </slot>
  9. </div>
  10. <div class="con">
  11. <span class="prefix" v-if="prefix||$slots.prefix">
  12. <slot name="prefix" >
  13. {{ prefix }}
  14. </slot>
  15. </span>
  16. <span class="number" :style="valueStyle">
  17. <slot name="formatter"> {{ disposeValue }}</slot>
  18. </span>
  19. <span class="suffix" v-if="suffix||$slots.suffix">
  20. <slot name="suffix">
  21. {{ suffix }}
  22. </slot>
  23. </span>
  24. </div>
  25. </div>
  26. </template>
  27. <script>
  28. import { isNumber, chain, multiply, padStart, reduce} from 'element-ui/src/utils/lodash';
  29. export default {
  30. name: 'ElStatistic',
  31. data() {
  32. return {
  33. disposeValue: '',
  34. timeTask: null,
  35. REFRESH_INTERVAL: 1000 / 30
  36. };
  37. },
  38. props: {
  39. decimalSeparator: {
  40. type: String,
  41. default: '.'
  42. },
  43. groupSeparator: {
  44. type: String,
  45. default: ''
  46. },
  47. precision: {
  48. type: Number,
  49. default: null
  50. },
  51. value: {
  52. type: [String, Number, Date],
  53. default: ''
  54. },
  55. prefix: {
  56. type: String,
  57. default: ''
  58. },
  59. suffix: {
  60. type: String,
  61. default: ''
  62. },
  63. title: {
  64. type: [String, Number],
  65. default: ''
  66. },
  67. timeIndices: {
  68. type: Boolean,
  69. default: false
  70. },
  71. valueStyle: {
  72. type: Object,
  73. default: function() {
  74. return {};
  75. }
  76. },
  77. format: {
  78. type: String,
  79. default: 'HH:mm:ss:SSS'
  80. },
  81. rate: {
  82. type: Number,
  83. default: 1000
  84. }
  85. },
  86. created() {
  87. this.branch();
  88. },
  89. watch: {
  90. value: function() {
  91. this.branch();
  92. },
  93. groupSeparator() {
  94. this.dispose();
  95. },
  96. mulriple() {
  97. this.dispose();
  98. }
  99. },
  100. methods: {
  101. branch() {
  102. let { timeIndices, countDown, dispose} = this;
  103. if (timeIndices) {
  104. countDown(this.value.valueOf() || this.value);
  105. } else {
  106. dispose();
  107. }
  108. },
  109. magnification(num, mulriple = 1000, groupSeparator = ',') {
  110. // magnification factor
  111. const level = String(mulriple).length ;
  112. return num.replace(new RegExp(`(\\d)(?=(\\d{${level - 1}})+$)`, 'g'), `$1${groupSeparator}`);
  113. },
  114. dispose() {
  115. let { value, rate, groupSeparator } = this;
  116. if (!isNumber(value)) return false;
  117. if (this.precision) {
  118. value = value.toFixed(this.precision);
  119. }
  120. let [integer, decimal] = String(value).split('.');
  121. // 1000 multiplying power
  122. if (groupSeparator) {
  123. integer = this.magnification(integer, rate, groupSeparator);
  124. }
  125. let result = `${integer}${decimal ? this.decimalSeparator + decimal : ''}`;
  126. this.disposeValue = result;
  127. return result;
  128. },
  129. diffDate(minuend, subtrahend) {
  130. return Math.max(minuend - subtrahend, 0);
  131. },
  132. suspend(isStop) {
  133. if (isStop) {
  134. if (this.timeTask) {
  135. clearInterval(this.timeTask);
  136. this.timeTask = null;
  137. }
  138. } else {
  139. this.branch();
  140. }
  141. return this.disposeValue;
  142. },
  143. formatTimeStr: function(time) {
  144. let {format} = this;
  145. const escapeRegex = /\[[^\]]*]/g;
  146. const keepList = (format.match(escapeRegex) || []).map(str => str.slice(1, -1));
  147. const timeUnits = [
  148. ['Y', 1000 * 60 * 60 * 24 * 365], // years
  149. ['M', 1000 * 60 * 60 * 24 * 30], // months
  150. ['D', 1000 * 60 * 60 * 24], // days
  151. ['H', 1000 * 60 * 60], // hours
  152. ['m', 1000 * 60], // minutes
  153. ['s', 1000], // seconds
  154. ['S', 1] // million seconds
  155. ];
  156. let formatText = reduce(
  157. timeUnits,
  158. (con, item) => {
  159. const name = item[0];
  160. return con.replace(new RegExp(`${name}+`, 'g'), (match) => {
  161. let sum = chain(time).divide(item[1]).floor(0).value();
  162. time -= multiply(sum, item[1]);
  163. return padStart(String(sum), String(match).length, 0);
  164. });
  165. },
  166. format
  167. );
  168. let index = 0;
  169. return formatText.replace(escapeRegex, () => {
  170. const match = keepList[index];
  171. index += 1;
  172. return match;
  173. });
  174. },
  175. stopTime(time) {
  176. let result = true; // stop
  177. if (time) {
  178. this.$emit('change', time);
  179. result = false;
  180. } else {
  181. result = true;
  182. this.suspend(true);
  183. this.$emit('finish', true);
  184. }
  185. return result;
  186. },
  187. countDown(timeVlaue) {
  188. let {REFRESH_INTERVAL, timeTask, diffDate, formatTimeStr, stopTime, suspend } = this;
  189. if (timeTask) return;
  190. let than = this;
  191. this.timeTask = setInterval(()=> {
  192. let diffTiem = diffDate(timeVlaue, Date.now());
  193. than.disposeValue = formatTimeStr(diffTiem);
  194. stopTime(diffTiem);
  195. }, REFRESH_INTERVAL);
  196. this.$once('hook:beforeDestroy', () => {
  197. suspend(true);
  198. });
  199. }
  200. }
  201. };
  202. </script>