UNPKG

@zhsz/cool-design-dv

Version:

265 lines (264 loc) 7.84 kB
import { defineComponent, useAttrs, ref, computed, watch, onMounted, onBeforeUnmount, openBlock, createElementBlock, mergeProps, unref, renderSlot, createTextVNode, toDisplayString, createCommentVNode, createElementVNode, normalizeClass, createBlock } from "vue"; import "./baseNumber.css"; import { Icon } from "@iconify/vue"; import { CountUp } from "countup.js"; import { isObject } from "lodash-es"; const _hoisted_1 = { key: 0, class: "my-number__prefix" }; const _hoisted_2 = { key: 1, class: "my-number__suffix" }; const __default__ = defineComponent({ name: "baseNumber" }); const _sfc_main = /* @__PURE__ */ defineComponent({ ...__default__, props: { // 数字 value: [Number, String], // 默认值 defaultValue: { type: [Number, String], default: 0 }, // CountUp配置参数对象 countUp: { type: [Boolean, Object] }, // 趋势 trend: { type: String, validator(val) { return ["up", "down", "-"].includes(val); } }, // 精度,保留几位小数 precision: { type: Number, default: 0 }, // 分隔符 separator: { type: String, default: "," }, // 前缀 prefix: { type: String }, // 后缀 suffix: String, // 按百分比计算显示 percentage: Boolean, // 颜色类型 type: { type: String, default: "", validator(val) { return ["", "primary", "success", "warning", "danger", "info"].includes( val ); } }, // 前缀 和 后缀采用下标显示 sup: Boolean }, emits: ["complete"], setup(__props, { emit: __emit }) { const props = __props; const defaultCountUp = { auto: true, // 是否自动开始计数,默认为自动开始 startVal: 0, // 计数初始值,不限正负数,默认值为0 decimalPlaces: 0, // 计数器数值精度。默认值为0 duration: 2, // 计数器动画持续时间,即计数器从开始到结束的时间,单位为秒,默认值为2秒 useEasing: true, // 是否显示渐入渐出效果。默认值为显示 useGrouping: true, // 计数器是否采用带格式的值,如10,000和10000两种格式(分隔符用separator来定义),默认值为使用 separator: "," // 分隔值的符号,默认值为‘,’(英文逗号) }; const $attrs = useAttrs(); const $emit = __emit; const counter = ref(); const container = ref(); const displayValue = computed(() => { if (!isNumber(props.value)) { return props.defaultValue ? getPercent(props.defaultValue) : ""; } if (props.percentage) { return getPercent(props.value); } return format(props.value || "", props.precision, props.separator); }); const trendClasses = computed(() => { if (!props.trend) return; if (props.trend === "-") { return "is-default"; } return `is-${props.trend}`; }); const classes = computed(() => { return { "my-number": true, "is-pointer": $attrs.onClick, [`is-${props.type}`]: !!props.type }; }); computed(() => { return { "my-number__sup": !!props.sup }; }); const countUpOptions = computed(() => { if (props.countUp === true) { return { ...defaultCountUp, separator: props.separator, decimalPlaces: props.precision }; } if (isObject(props.countUp)) { return { ...defaultCountUp, ...props.countUp, separator: props.separator, decimalPlaces: props.precision }; } return null; }); function init() { var _a; setCountUp(); if ((_a = countUpOptions.value) == null ? void 0 : _a.auto) { start(); } } function setCountUp() { if (counter.value) { counter.value = null; } if (countUpOptions.value === null) return; counter.value = new CountUp( container.value, Number(props.value), countUpOptions.value ); } function start() { reset(); counter.value && counter.value.start(onComplete); } function reset() { counter.value && counter.value.reset(); } function update(num) { if (num) { counter.value && counter.value.update(num); } else { counter.value && counter.value.update(props.value); } } function onComplete() { $emit("complete"); } function isNumber(n) { const val = Number.parseFloat(String(n)); return !Number.isNaN(val) && Number.isFinite(val); } function getPercent(val) { return props.percentage ? `${(Number.parseFloat(String(val)) * 100).toFixed(props.precision)}%` : val; } function format(val, n, separator) { const s = Number.parseFloat(String(val).replace(/[^\d.-]/g, "")).toFixed(n) + ""; const l = s.split(".")[0].split("").reverse(); const r = s.split(".")[1]; let t = ""; for (let i = 0; i < l.length; i++) { t += l[i] + ((i + 1) % 3 === 0 && i + 1 !== l.length ? `${separator}` : ""); } return t.split("").reverse().join("") + (r ? `.${r}` : ""); } watch( () => props.value, (val) => { update(val); } ); watch( () => countUpOptions.value, () => { if (!countUpOptions.value) { return; } init(); } ); onMounted(() => { if (countUpOptions.value) { init(); } }); onBeforeUnmount(() => { counter.value = null; }); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", mergeProps({ class: classes.value }, unref($attrs)), [ __props.prefix || _ctx.$slots.prefix ? (openBlock(), createElementBlock("span", _hoisted_1, [ renderSlot(_ctx.$slots, "prefix", {}, () => [ createTextVNode(toDisplayString(__props.prefix), 1) ]) ])) : createCommentVNode("", true), createElementVNode("span", { class: "my-number__value", ref_key: "container", ref: container }, [ renderSlot(_ctx.$slots, "default", { value: __props.value, displayValue: displayValue.value }, () => [ createTextVNode(toDisplayString(displayValue.value), 1) ]) ], 512), __props.suffix || _ctx.$slots.suffix ? (openBlock(), createElementBlock("span", _hoisted_2, [ renderSlot(_ctx.$slots, "suffix", {}, () => [ createTextVNode(toDisplayString(__props.suffix), 1) ]) ])) : createCommentVNode("", true), __props.trend || _ctx.$slots.trend ? (openBlock(), createElementBlock("span", { key: 2, class: normalizeClass(["my-number__trend", trendClasses.value]) }, [ renderSlot(_ctx.$slots, "trend", { trend: __props.trend }, () => [ __props.trend === "up" ? (openBlock(), createBlock(unref(Icon), { key: 0, icon: "icon-park-outline:arrow-up" })) : createCommentVNode("", true), __props.trend === "down" ? (openBlock(), createBlock(unref(Icon), { key: 1, icon: "icon-park-outline:arrow-down" })) : createCommentVNode("", true), __props.trend === "-" ? (openBlock(), createBlock(unref(Icon), { key: 2, icon: "icon-park-outline:minus" })) : createCommentVNode("", true) ]) ], 2)) : createCommentVNode("", true) ], 16); }; } }); export { _sfc_main as default };