iter(g95): 统计数值支持倒计时模式
This commit is contained in:
@@ -1,7 +1,17 @@
|
||||
import { effect, h } from '@ui-arch/frame';
|
||||
import { effect, h, signal } from '@ui-arch/frame';
|
||||
import type { StatisticProps } from './types.js';
|
||||
|
||||
/*** 统计数值:标题 + 大号数字 + 前后缀 + 环比趋势,数值变化时 rAF 滚动过渡(400ms,easeOutCubic) ***/
|
||||
/*** 剩余毫秒 → DD 天 HH:MM:SS(不足一天省略天数,保持等宽跳动不抖动) ***/
|
||||
function fmtLeft(ms: number): string {
|
||||
const total = Math.floor(ms / 1000);
|
||||
const d = Math.floor(total / 86400);
|
||||
const hh = String(Math.floor((total % 86400) / 3600)).padStart(2, '0');
|
||||
const mm = String(Math.floor((total % 3600) / 60)).padStart(2, '0');
|
||||
const ss = String(total % 60).padStart(2, '0');
|
||||
return d > 0 ? `${d} 天 ${hh}:${mm}:${ss}` : `${hh}:${mm}:${ss}`;
|
||||
}
|
||||
|
||||
/*** 统计数值:标题 + 大号数字 + 前后缀 + 环比趋势;数值滚动过渡,传 countdown 则改为每秒倒计时 ***/
|
||||
export function statistic(props: StatisticProps): HTMLElement {
|
||||
// —— 状态集中声明 ——
|
||||
const precision = props.precision ?? 0; // 小数位
|
||||
@@ -36,6 +46,17 @@ export function statistic(props: StatisticProps): HTMLElement {
|
||||
props.trend ? h('span', { class: `ua-stat-trend is-${props.trend}` }, props.trend === 'up' ? '▲' : '▼') : null);
|
||||
const view = h('div', { class: 'ua-stat' }, props.title ? h('div', { class: 'ua-stat-title' }, props.title) : null, row);
|
||||
|
||||
effect(() => roll(props.value())); // 信号变化即滚动到新值(首跑做入场动画)
|
||||
const target = props.countdown;
|
||||
if (target) {
|
||||
const left = signal(Math.max(0, target - Date.now())); // 剩余毫秒
|
||||
const timer = window.setInterval(() => {
|
||||
const ms = Math.max(0, target - Date.now());
|
||||
left(ms);
|
||||
if (!ms || !view.isConnected) window.clearInterval(timer); // 到点或已卸载即停表,不留常驻定时器
|
||||
}, 1000);
|
||||
effect(() => { num.textContent = fmtLeft(left()); }); // 倒计时模式不走滚动动画,每秒直落
|
||||
} else if (props.value) {
|
||||
effect(() => roll(props.value!())); // 信号变化即滚动到新值(首跑做入场动画)
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -419,7 +419,8 @@ export interface DescriptionsProps {
|
||||
/*** 统计数值入参 ***/
|
||||
export interface StatisticProps {
|
||||
title?: string; // 指标名;缺省不渲染标题行
|
||||
value: Signal<number>; // 数值信号:变化时滚动过渡到新值(首跑即入场动画)
|
||||
value?: Signal<number>; // 数值信号:变化时滚动过渡到新值(首跑即入场动画);倒计时模式可不传
|
||||
countdown?: number; // 目标时间戳(毫秒):传了即倒计时模式,每秒显示 DD 天 HH:MM:SS,忽略 value
|
||||
precision?: number; // 小数位;缺省 0
|
||||
prefix?: string; // 数字前缀(如 ¥);缺省不渲染
|
||||
suffix?: string; // 数字后缀(如 元 / %);缺省不渲染
|
||||
|
||||
@@ -1824,7 +1824,12 @@
|
||||
"n": "value",
|
||||
"t": "Signal<number>",
|
||||
"r": 1,
|
||||
"d": "数值信号:变化时从当前显示值滚动到新值,首跑即入场动画"
|
||||
"d": "数值信号:变化时滚动过渡到新值;倒计时模式可不传"
|
||||
},
|
||||
{
|
||||
"n": "countdown",
|
||||
"t": "number",
|
||||
"d": "目标时间戳(毫秒):传了即倒计时模式,每秒显示 DD 天 HH:MM:SS,忽略 value"
|
||||
},
|
||||
{
|
||||
"n": "precision",
|
||||
@@ -1855,7 +1860,8 @@
|
||||
"precision 控制小数位,千分位由 toLocaleString 自动加,不要自己拼格式化",
|
||||
"trend 只表达方向与颜色(涨红跌绿),数值本身与环比幅度仍由调用方组织",
|
||||
"多条指标并排时用 descriptions 或 flex 容器排列,本组件不自带网格",
|
||||
"用户开启「减弱动效」时组件直接落终值,无需调用方判断"
|
||||
"用户开启「减弱动效」时组件直接落终值,无需调用方判断",
|
||||
"做倒计时(活动剩余时间等)传 countdown: 目标时间戳,组件每秒刷新并在到点/卸载时自动停表"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user