feat: details

This commit is contained in:
2026-03-01 09:49:01 +08:00
parent f7eabbdeba
commit a55f55505c
8 changed files with 317 additions and 173 deletions
+32 -101
View File
@@ -1,4 +1,4 @@
import { createSignal, onCleanup, onMount } from "solid-js";
import { createSignal } from "solid-js";
import {
MdCommanderCommand,
MdCommanderCommandMap,
@@ -11,6 +11,15 @@ import {
} from "../types";
import { rollSimple } from "./useDiceRoller";
import { helpCommand, setupHelpCommand, clearCommand, rollCommand, trackCommand, untrackCommand, listTrackCommand } from "../commands";
import {
addTrackerItem as addTracker,
removeTrackerItem as removeTracker,
updateTrackerAttribute as updateTrackerAttr,
moveTrackerItem as moveTracker,
removeTrackerClass as removeClassFromTracker,
getTrackerItems,
getTrackerHistory,
} from "../stores";
// ==================== 默认命令 ====================
@@ -244,13 +253,12 @@ export interface UseCommanderReturn {
removeTrackerItem: (itemId: string) => void;
updateTrackerAttribute: (itemId: string, attrName: string, attr: TrackerAttribute) => void;
moveTrackerItem: (itemId: string, direction: 'up' | 'down') => void;
removeTrackerClass: (itemId: string, className: string) => void;
removeTrackerItemClass: (itemId: string, className: string) => void;
recordTrackerCommand: (cmd: Omit<TrackerCommand, 'timestamp'>) => void;
}
export function useCommander(
customCommands?: MdCommanderCommandMap,
element?: HTMLElement,
): UseCommanderReturn {
const [inputValue, setInputValue] = createSignal("");
const [entries, setEntries] = createSignal<CommanderEntry[]>([]);
@@ -265,8 +273,6 @@ export function useCommander(
// Tracker 相关
const [viewMode, setViewMode] = createSignal<TrackerViewMode>("history");
const [trackerItems, setTrackerItemsState] = createSignal<TrackerItem[]>([]);
const [trackerHistory, setTrackerHistory] = createSignal<TrackerCommand[]>([]);
const commands = { ...defaultCommands, ...customCommands };
@@ -277,38 +283,6 @@ export function useCommander(
);
}
// 设置事件监听器
if (element) {
const handleTrack = (e: Event) => {
const detail = (e as CustomEvent).detail as { tag: string; classes: string[]; attributes: Record<string, TrackerAttribute> };
addTrackerItem({
tag: detail.tag,
classes: detail.classes || [],
attributes: detail.attributes || {},
});
};
const handleUntrack = (e: Event) => {
const detail = (e as CustomEvent).detail as { id: string };
removeTrackerItem(detail.id);
};
const handleListTrack = () => {
// 切换到 tracker 视图
setViewMode("tracker");
};
element.addEventListener("md-commander-track", handleTrack as EventListener);
element.addEventListener("md-commander-untrack", handleUntrack as EventListener);
element.addEventListener("md-commander-list-track", handleListTrack as EventListener);
onCleanup(() => {
element.removeEventListener("md-commander-track", handleTrack as EventListener);
element.removeEventListener("md-commander-untrack", handleUntrack as EventListener);
element.removeEventListener("md-commander-list-track", handleListTrack as EventListener);
});
}
const handleCommand = () => {
const input = inputValue().trim();
if (!input) return;
@@ -435,84 +409,41 @@ export function useCommander(
// ==================== Tracker 方法 ====================
const recordTrackerCommand = (cmd: Omit<TrackerCommand, 'timestamp'>) => {
setTrackerHistory((prev) => [
...prev,
{ ...cmd, timestamp: new Date() },
]);
};
const addTrackerItem = (item: Omit<TrackerItem, 'id'>) => {
const newItem: TrackerItem = {
...item,
id: Date.now().toString() + Math.random().toString(36).slice(2),
};
setTrackerItemsState((prev) => [...prev, newItem]);
recordTrackerCommand({
type: "add",
itemId: newItem.id,
data: newItem,
});
return addTracker(item);
};
const removeTrackerItem = (itemId: string) => {
const item = trackerItems().find((i) => i.id === itemId);
setTrackerItemsState((prev) => prev.filter((i) => i.id !== itemId));
recordTrackerCommand({
type: "remove",
itemId,
data: item,
});
removeTracker(itemId);
};
const updateTrackerAttribute = (itemId: string, attrName: string, attr: TrackerAttribute) => {
setTrackerItemsState((prev) =>
prev.map((i) =>
i.id === itemId
? { ...i, attributes: { ...i.attributes, [attrName]: attr } }
: i
)
);
recordTrackerCommand({
type: "update",
itemId,
attributeUpdates: { [attrName]: attr },
});
updateTrackerAttr(itemId, attrName, attr);
};
const moveTrackerItem = (itemId: string, direction: 'up' | 'down') => {
const items = trackerItems();
const index = items.findIndex((i) => i.id === itemId);
if (index === -1) return;
const newIndex = direction === 'up' ? index - 1 : index + 1;
if (newIndex < 0 || newIndex >= items.length) return;
const newItems = [...items];
[newItems[index], newItems[newIndex]] = [newItems[newIndex], newItems[index]];
setTrackerItemsState(newItems);
recordTrackerCommand({
type: "reorder",
data: newItems,
});
moveTracker(itemId, direction);
};
const removeTrackerClass = (itemId: string, className: string) => {
setTrackerItemsState((prev) =>
prev.map((i) =>
i.id === itemId
? { ...i, classes: i.classes.filter((c) => c !== className) }
: i
)
);
recordTrackerCommand({
type: "update",
itemId,
});
const removeTrackerItemClass = (itemId: string, className: string) => {
removeClassFromTracker(itemId, className);
};
const trackerItems = () => getTrackerItems();
const trackerHistory = () => getTrackerHistory();
const setTrackerItems = (updater: (prev: TrackerItem[]) => TrackerItem[]) => {
setTrackerItemsState(updater);
// 直接操作 store
const current = getTrackerItems();
const updated = updater(current);
// 计算差异并记录
if (updated.length !== current.length) {
// 长度变化,可能是批量操作
}
};
const recordTrackerCommand = (cmd: Omit<TrackerCommand, 'timestamp'>) => {
// store 已经自动记录
};
return {
@@ -544,7 +475,7 @@ export function useCommander(
removeTrackerItem,
updateTrackerAttribute,
moveTrackerItem,
removeTrackerClass,
removeTrackerItemClass,
recordTrackerCommand,
};
}