feat: 增加宁德时代的图表
This commit is contained in:
@@ -46,16 +46,23 @@ export function createAppShell(root, { onReload }) {
|
||||
const layout = element('div', 'app-layout');
|
||||
const companyNav = element('aside', 'sidebar company-sidebar');
|
||||
const content = element('main', 'content');
|
||||
// tab 栏与参数行共处一个 sticky 容器:参数行是独立的一行(不是 tab 栏的一部分),
|
||||
// 但要和 tab 栏一起钉在顶部。若让两行各自 sticky,参数行就得设「tab 栏高度」的 top
|
||||
// 偏移,而 tab 栏会换行、窄屏还会横向滚动,高度并不固定;绑在一个容器里天然不会错位。
|
||||
const tabHeader = element('div', 'tab-header');
|
||||
const tabs = element('nav', 'tabs');
|
||||
const params = element('div', 'tab-controls');
|
||||
params.hidden = true;
|
||||
tabHeader.append(tabs, params);
|
||||
const cards = element('div', 'cards');
|
||||
content.append(tabs, cards);
|
||||
content.append(tabHeader, cards);
|
||||
const chartNav = element('aside', 'sidebar chart-sidebar');
|
||||
layout.append(companyNav, content, chartNav);
|
||||
const cartBar = element('div', 'cart-bar');
|
||||
cartBar.hidden = true;
|
||||
root.append(layout, reloadButton, cartBar);
|
||||
|
||||
return { companyNav, tabs, cards, chartNav, cartBar };
|
||||
return { companyNav, tabs, params, cards, chartNav, cartBar };
|
||||
}
|
||||
|
||||
export function renderCompanies(container, companies, activeCompanyId, onSelect) {
|
||||
@@ -82,6 +89,70 @@ export function renderTabs(container, tabs, activeTabId, onSelect) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* tab 级数值参数控件(目前只有「现价」)—— 由 manifest 的 tab.controls 声明。
|
||||
*
|
||||
* 位置:页面里独立的一行,钉在 tab 栏正下方(见 createAppShell 的 .tab-header)。
|
||||
* 不塞进 tab 栏:它是改数据口径的输入,混在导航按钮里容易被当成 tab 误点。
|
||||
*
|
||||
* 回调约定:onChange(id, rawValue) 返回 false 表示这次输入不合法(越界/非数字),
|
||||
* 输入框标红示意,图表保持原样 —— 校验规则属于控制层,壳层不重复实现。
|
||||
*/
|
||||
export function renderTabControls(container, controls, values, onChange) {
|
||||
// 容器是常驻的,每次整屏重渲染都要清空;否则 resize(200ms 防抖)会叠出多行控件
|
||||
container.replaceChildren();
|
||||
container.hidden = !controls?.length;
|
||||
if (!controls?.length) return;
|
||||
controls.forEach((control) => {
|
||||
const field = element('label', 'param-field');
|
||||
if (control.hint) field.title = control.hint;
|
||||
field.append(element('span', 'param-label', control.label));
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.className = 'param-input';
|
||||
input.type = 'number';
|
||||
input.inputMode = 'decimal';
|
||||
input.step = String(control.step ?? 1);
|
||||
input.min = String(control.min);
|
||||
input.max = String(control.max);
|
||||
input.value = String(values?.[control.id] ?? control.value);
|
||||
input.setAttribute('aria-label', `${control.label}${control.unit ?? ''}`);
|
||||
field.append(input, element('span', 'param-unit', control.unit ?? ''));
|
||||
|
||||
// 合法区间常驻显示:输入越界时它变红,用户不必猜上下限
|
||||
field.append(element('span', 'param-range', `${control.min}–${control.max}`));
|
||||
|
||||
const reset = button('重置', {
|
||||
className: 'param-reset',
|
||||
onClick: () => {
|
||||
input.value = String(control.value);
|
||||
input.dataset.invalid = 'false';
|
||||
// 值已回到默认,按钮自己进入禁用态(不等下一次 input 事件,否则点完还亮着)
|
||||
reset.disabled = true;
|
||||
onChange?.(control.id, input.value, { immediate: true });
|
||||
input.focus();
|
||||
},
|
||||
});
|
||||
reset.title = `回到默认值 ${control.value}`;
|
||||
|
||||
const apply = (immediate = false) => {
|
||||
const ok = onChange?.(control.id, input.value, { immediate }) !== false;
|
||||
input.dataset.invalid = String(!ok);
|
||||
reset.disabled = input.value === String(control.value);
|
||||
};
|
||||
input.addEventListener('input', () => apply());
|
||||
// 回车立即生效,不等防抖(防抖只针对连续输入)
|
||||
input.addEventListener('keydown', (event) => {
|
||||
if (event.key !== 'Enter') return;
|
||||
event.preventDefault();
|
||||
apply(true);
|
||||
});
|
||||
reset.disabled = input.value === String(control.value);
|
||||
|
||||
container.append(field, reset);
|
||||
});
|
||||
}
|
||||
|
||||
export function renderCards(container, charts, activeViews, { onExport, isCarted, onToggleCart, onSelectView }) {
|
||||
container.replaceChildren();
|
||||
if (!charts.length) {
|
||||
|
||||
Reference in New Issue
Block a user