tauri-android-demo/src/ui.ts
2026-07-07 17:53:20 +08:00

86 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 能力演示卡片的定义结构
* - title: 卡片标题
* - desc: 能力说明
* - actions: 该卡片下的操作按钮列表
*/
export interface DemoAction {
/** 按钮文字 */
label: string;
/** 是否使用次要样式(灰色按钮) */
secondary?: boolean;
/** 点击后执行的处理函数,返回要展示的文本 */
run: (ctx: DemoContext) => Promise<string> | string;
}
/** 卡片定义 */
export interface DemoCard {
/** 卡片唯一 id用于关联输出区域 */
id: string;
/** 卡片标题 */
title: string;
/** 卡片说明文字 */
desc: string;
/** 是否需要一个文本输入框 */
input?: { placeholder: string; default?: string };
/** 操作按钮 */
actions: DemoAction[];
}
/** 传递给操作函数的上下文,可读取输入框内容 */
export interface DemoContext {
/** 获取当前卡片输入框的值(不存在时返回空字符串) */
getInput: () => string;
}
/**
* 渲染单个能力卡片到指定容器
* @param container 卡片挂载的父节点
* @param card 卡片定义
* 注意事项:按钮点击时会自动捕获异常并以红色输出错误信息,避免未处理的 Promise 报错。
*/
export function renderCard(container: HTMLElement, card: DemoCard): void {
const el = document.createElement("section");
el.className = "card";
const inputHtml = card.input
? `<div class="row" style="margin-bottom:10px">
<input type="text" id="input-${card.id}" placeholder="${card.input.placeholder}" value="${card.input.default ?? ""}" />
</div>`
: "";
el.innerHTML = `
<h2>${card.title}</h2>
<p class="desc">${card.desc}</p>
${inputHtml}
<div class="row" id="actions-${card.id}"></div>
<div class="output" id="out-${card.id}">—</div>
`;
container.appendChild(el);
const out = el.querySelector<HTMLDivElement>(`#out-${card.id}`)!;
const actionsRow = el.querySelector<HTMLDivElement>(`#actions-${card.id}`)!;
const ctx: DemoContext = {
getInput: () =>
el.querySelector<HTMLInputElement>(`#input-${card.id}`)?.value ?? "",
};
for (const action of card.actions) {
const btn = document.createElement("button");
btn.textContent = action.label;
if (action.secondary) btn.classList.add("secondary");
btn.addEventListener("click", async () => {
out.className = "output";
out.textContent = "执行中…";
try {
out.textContent = await action.run(ctx);
out.classList.add("ok");
} catch (err) {
out.textContent = `出错:${err instanceof Error ? err.message : String(err)}`;
out.classList.add("err");
}
});
actionsRow.appendChild(btn);
}
}