refactor: format

This commit is contained in:
hypercross 2026-02-26 09:08:05 +08:00
parent cc22b89226
commit 0a2c756213
1 changed files with 46 additions and 46 deletions

View File

@ -1,5 +1,5 @@
import { customElement, noShadowDOM } from 'solid-element'; import { customElement, noShadowDOM } from "solid-element";
import { createSignal, onMount } from 'solid-js'; import { createSignal, onMount } from "solid-js";
interface RollResult { interface RollResult {
total: number; total: number;
@ -7,11 +7,6 @@ interface RollResult {
detail: string; detail: string;
} }
interface DiceOperator {
pattern: RegExp;
handler: (match: RegExpMatchArray, rolls: number[]) => { value: number; rolls: number[]; detail: string };
}
function rollDice(formula: string): RollResult { function rollDice(formula: string): RollResult {
const allRolls: number[] = []; const allRolls: number[] = [];
let total = 0; let total = 0;
@ -19,18 +14,21 @@ function rollDice(formula: string): RollResult {
// 解析骰子公式,支持 + 和 - 运算符 // 解析骰子公式,支持 + 和 - 运算符
// 先按 + 和 - 分割,但保留运算符 // 先按 + 和 - 分割,但保留运算符
const tokens = formula.split(/([+-])/).map(t => t.trim()).filter(t => t.length > 0); const tokens = formula
.split(/([+-])/)
.map((t) => t.trim())
.filter((t) => t.length > 0);
let sign = 1; let sign = 1;
for (let i = 0; i < tokens.length; i++) { for (let i = 0; i < tokens.length; i++) {
const token = tokens[i]; const token = tokens[i];
if (token === '+') { if (token === "+") {
sign = 1; sign = 1;
continue; continue;
} }
if (token === '-') { if (token === "-") {
sign = -1; sign = -1;
continue; continue;
} }
@ -69,7 +67,7 @@ function rollDice(formula: string): RollResult {
const match = processedToken.match(/^(\d+)?d(\d+)$/i); const match = processedToken.match(/^(\d+)?d(\d+)$/i);
if (match) { if (match) {
const count = parseInt(match[1] || '1'); const count = parseInt(match[1] || "1");
const sides = parseInt(match[2]); const sides = parseInt(match[2]);
const rolls: number[] = []; const rolls: number[] = [];
@ -102,13 +100,15 @@ function rollDice(formula: string): RollResult {
const partTotal = processedRolls.reduce((a, b) => a + b, 0); const partTotal = processedRolls.reduce((a, b) => a + b, 0);
total += sign * partTotal; total += sign * partTotal;
allRolls.push(...processedRolls); allRolls.push(...processedRolls);
details.push(`${detail}=[${processedRolls.join(',')}]${sign < 0 ? ' (负)' : ''}`); details.push(
`${detail}=[${processedRolls.join(",")}]${sign < 0 ? " (负)" : ""}`,
);
} else { } else {
// 处理固定数字 // 处理固定数字
const num = parseInt(token); const num = parseInt(token);
if (!isNaN(num)) { if (!isNaN(num)) {
total += sign * num; total += sign * num;
details.push(`${num}${sign < 0 ? ' (负)' : ''}`); details.push(`${num}${sign < 0 ? " (负)" : ""}`);
} }
} }
} }
@ -116,36 +116,32 @@ function rollDice(formula: string): RollResult {
return { return {
total, total,
rolls: allRolls, rolls: allRolls,
detail: details.join(' + ') detail: details.join(" + "),
}; };
} }
// 生成唯一 ID
let diceCounter = 0;
function generateDiceId(): string {
return `dice-${Date.now()}-${diceCounter++}`;
}
// 从 URL 参数获取骰子结果 // 从 URL 参数获取骰子结果
function getDiceResultFromUrl(key: string): number | null { function getDiceResultFromUrl(key: string): number | null {
if (typeof window === 'undefined') return null; if (typeof window === "undefined") return null;
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const value = params.get(`dice-${key}`); const value = params.get(`dice-${key}`);
return value ? parseInt(value) : null; return value ? parseInt(value) : null;
} }
customElement('md-dice', { key: '' }, (props, { element }) => { // TODO:使用history.pushState
function setDiceResultToUrl(key: string, value: number) {}
customElement("md-dice", { key: "" }, (props, { element }) => {
noShadowDOM(); noShadowDOM();
const [result, setResult] = createSignal<number | null>(null); const [result, setResult] = createSignal<number | null>(null);
const [isRolled, setIsRolled] = createSignal(false); const [isRolled, setIsRolled] = createSignal(false);
const [rollDetail, setRollDetail] = createSignal<string>(''); const [rollDetail, setRollDetail] = createSignal<string>("");
const [diceId] = createSignal(generateDiceId());
// 从 element 的 textContent 获取骰子公式 // 从 element 的 textContent 获取骰子公式
const formula = element?.textContent?.trim() || ''; const formula = element?.textContent?.trim() || "";
// 使用的 key如果没有提供则使用生成的 ID // 使用的 key如果没有提供则使用生成的 ID
const effectiveKey = () => props.key || diceId(); const effectiveKey = () => props.key;
onMount(() => { onMount(() => {
// 初始化时检查 URL 参数 // 初始化时检查 URL 参数
@ -164,13 +160,15 @@ customElement('md-dice', { key: '' }, (props, { element }) => {
setResult(rollResult.total); setResult(rollResult.total);
setRollDetail(rollResult.detail); setRollDetail(rollResult.detail);
setIsRolled(true); setIsRolled(true);
// TODO:保存结果到url
}; };
const handleTextClick = () => { const handleTextClick = () => {
// 点击文本:总是重置为公式 // 点击文本:总是重置为公式
setResult(null); setResult(null);
setIsRolled(false); setIsRolled(false);
setRollDetail(''); setRollDetail("");
// TODO:从url中移除结果
}; };
const displayText = () => (isRolled() ? `${result()}` : formula); const displayText = () => (isRolled() ? `${result()}` : formula);
@ -178,24 +176,26 @@ customElement('md-dice', { key: '' }, (props, { element }) => {
return ( return (
<span class="inline-flex items-center gap-1"> <span class="inline-flex items-center gap-1">
<a <a
href={effectiveKey() && isRolled() ? `?dice-${effectiveKey()}=${result()}` : '#'}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
handleRoll(); handleRoll();
}} }}
class="text-blue-600 hover:text-blue-800 cursor-pointer" class="text-blue-600 hover:text-blue-800 cursor-pointer"
title={rollDetail() || '掷骰子'} title={rollDetail() || "掷骰子"}
> >
🎲 🎲
</a> </a>
<span <span
onClick={handleTextClick} onClick={handleTextClick}
class={isRolled() ? 'cursor-pointer text-gray-700 hover:text-gray-900' : 'text-gray-600'} class={
title={isRolled() ? '点击重置为公式' : formula} isRolled()
? "cursor-pointer text-gray-700 hover:text-gray-900"
: "text-gray-600"
}
title={isRolled() ? "点击重置为公式" : formula}
> >
{displayText()} {displayText()}
</span> </span>
</span> </span>
); );
}); });