fxdyz
This commit is contained in:
+119
-46
@@ -1,5 +1,6 @@
|
||||
const bridge = window.AstrBotPluginPage;
|
||||
const state = { bindings: [], subscriptions: [], aliases: [], kungfu: [], servers: [], events: {} };
|
||||
const editing = { aliasServer: null, kungfuPzid: null };
|
||||
let toastTimer;
|
||||
|
||||
const byId = (id) => document.getElementById(id);
|
||||
@@ -32,6 +33,42 @@ function emptyRow(columnCount, message) {
|
||||
return row;
|
||||
}
|
||||
|
||||
function aliasText(aliases) {
|
||||
return aliases.length ? aliases.join("、") : "无";
|
||||
}
|
||||
|
||||
function inlineAliasEditor(aliases, label, onSave, onCancel) {
|
||||
const input = document.createElement("input");
|
||||
input.className = "inline-editor";
|
||||
input.value = aliases.join(", ");
|
||||
input.placeholder = "多个别名用逗号分隔";
|
||||
input.setAttribute("aria-label", label);
|
||||
|
||||
const saveButton = button("保存", "", async () => {
|
||||
saveButton.disabled = true;
|
||||
cancelButton.disabled = true;
|
||||
const saved = await onSave(input.value);
|
||||
if (!saved) {
|
||||
saveButton.disabled = false;
|
||||
cancelButton.disabled = false;
|
||||
input.focus();
|
||||
}
|
||||
});
|
||||
const cancelButton = button("取消", "", onCancel);
|
||||
|
||||
input.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
saveButton.click();
|
||||
} else if (event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
cancelButton.click();
|
||||
}
|
||||
});
|
||||
queueMicrotask(() => input.focus());
|
||||
return { input, controls: [saveButton, cancelButton] };
|
||||
}
|
||||
|
||||
function bindingMap() {
|
||||
return new Map(state.bindings.map((item) => [item.session_id, item.server]));
|
||||
}
|
||||
@@ -128,11 +165,22 @@ function renderSubscriptions() {
|
||||
|
||||
function renderAliases() {
|
||||
const body = byId("aliases-body");
|
||||
if (!state.aliases.length) {
|
||||
body.replaceChildren(emptyRow(3, "暂无区服别名配置"));
|
||||
const aliasesByServer = new Map(
|
||||
state.aliases.map((item) => [item.server, item.aliases]),
|
||||
);
|
||||
const servers = [...new Set([
|
||||
...state.servers,
|
||||
...aliasesByServer.keys(),
|
||||
])].sort((left, right) => left.localeCompare(right, "zh-CN"));
|
||||
if (!servers.length) {
|
||||
body.replaceChildren(emptyRow(3, "暂无标准区服数据"));
|
||||
return;
|
||||
}
|
||||
body.replaceChildren(...state.aliases.map((item) => {
|
||||
body.replaceChildren(...servers.map((serverName) => {
|
||||
const item = {
|
||||
server: serverName,
|
||||
aliases: aliasesByServer.get(serverName) || [],
|
||||
};
|
||||
const row = document.createElement("tr");
|
||||
const server = document.createElement("td");
|
||||
const aliases = document.createElement("td");
|
||||
@@ -141,19 +189,40 @@ function renderAliases() {
|
||||
aliases.dataset.label = "别名";
|
||||
actions.dataset.label = "操作";
|
||||
server.textContent = item.server;
|
||||
aliases.textContent = item.aliases.length ? item.aliases.join("、") : "无";
|
||||
aliases.className = "alias-cell";
|
||||
actions.className = "actions";
|
||||
actions.append(
|
||||
button("编辑", "", () => {
|
||||
byId("alias-server").value = item.server;
|
||||
byId("alias-values").value = item.aliases.join(", ");
|
||||
byId("alias-values").focus();
|
||||
}),
|
||||
button("删除", "link-button--danger", async () => {
|
||||
if (!window.confirm(`确认删除 ${item.server} 的全部别名?`)) return;
|
||||
await mutate("aliases/delete", { server: item.server }, "别名已删除");
|
||||
}),
|
||||
);
|
||||
if (editing.aliasServer === item.server) {
|
||||
row.classList.add("is-editing");
|
||||
const editor = inlineAliasEditor(
|
||||
item.aliases,
|
||||
`${item.server}的区服别名`,
|
||||
async (value) => {
|
||||
editing.aliasServer = null;
|
||||
const saved = await mutate(
|
||||
"aliases/save",
|
||||
{ server: item.server, aliases: value },
|
||||
"区服别名已保存",
|
||||
);
|
||||
if (!saved) {
|
||||
editing.aliasServer = item.server;
|
||||
renderAliases();
|
||||
}
|
||||
return saved;
|
||||
},
|
||||
() => {
|
||||
editing.aliasServer = null;
|
||||
renderAliases();
|
||||
},
|
||||
);
|
||||
aliases.append(editor.input);
|
||||
actions.append(...editor.controls);
|
||||
} else {
|
||||
aliases.textContent = aliasText(item.aliases);
|
||||
actions.append(button("编辑", "", () => {
|
||||
editing.aliasServer = item.server;
|
||||
renderAliases();
|
||||
}));
|
||||
}
|
||||
row.append(server, aliases, actions);
|
||||
return row;
|
||||
}));
|
||||
@@ -162,30 +231,53 @@ function renderAliases() {
|
||||
function renderKungfu() {
|
||||
const body = byId("kungfu-body");
|
||||
if (!state.kungfu.length) {
|
||||
body.replaceChildren(emptyRow(4, "暂无心法配置"));
|
||||
body.replaceChildren(emptyRow(3, "暂无心法配置"));
|
||||
return;
|
||||
}
|
||||
body.replaceChildren(...state.kungfu.map((item) => {
|
||||
const row = document.createElement("tr");
|
||||
const pzid = document.createElement("td");
|
||||
const name = document.createElement("td");
|
||||
const aliases = document.createElement("td");
|
||||
const actions = document.createElement("td");
|
||||
pzid.dataset.label = "心法 ID";
|
||||
name.dataset.label = "标准心法名";
|
||||
aliases.dataset.label = "别名";
|
||||
actions.dataset.label = "操作";
|
||||
pzid.textContent = String(item.pzid);
|
||||
name.textContent = item.name;
|
||||
aliases.textContent = item.aliases.length ? item.aliases.join("、") : "无";
|
||||
aliases.className = "alias-cell";
|
||||
actions.className = "actions";
|
||||
actions.append(button("编辑", "", () => {
|
||||
byId("kungfu-pzid").value = String(item.pzid);
|
||||
byId("kungfu-name").value = item.name;
|
||||
byId("kungfu-aliases").value = item.aliases.join(", ");
|
||||
byId("kungfu-aliases").focus();
|
||||
}));
|
||||
row.append(pzid, name, aliases, actions);
|
||||
if (editing.kungfuPzid === item.pzid) {
|
||||
row.classList.add("is-editing");
|
||||
const editor = inlineAliasEditor(
|
||||
item.aliases,
|
||||
`${item.name}的心法别名`,
|
||||
async (value) => {
|
||||
editing.kungfuPzid = null;
|
||||
const saved = await mutate(
|
||||
"kungfu/save",
|
||||
{ pzid: item.pzid, aliases: value },
|
||||
"心法别名已保存",
|
||||
);
|
||||
if (!saved) {
|
||||
editing.kungfuPzid = item.pzid;
|
||||
renderKungfu();
|
||||
}
|
||||
return saved;
|
||||
},
|
||||
() => {
|
||||
editing.kungfuPzid = null;
|
||||
renderKungfu();
|
||||
},
|
||||
);
|
||||
aliases.append(editor.input);
|
||||
actions.append(...editor.controls);
|
||||
} else {
|
||||
aliases.textContent = aliasText(item.aliases);
|
||||
actions.append(button("编辑", "", () => {
|
||||
editing.kungfuPzid = item.pzid;
|
||||
renderKungfu();
|
||||
}));
|
||||
}
|
||||
row.append(name, aliases, actions);
|
||||
return row;
|
||||
}));
|
||||
}
|
||||
@@ -241,25 +333,6 @@ byId("binding-form").addEventListener("submit", async (event) => {
|
||||
if (saved) event.currentTarget.reset();
|
||||
});
|
||||
|
||||
byId("alias-form").addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const saved = await mutate("aliases/save", {
|
||||
server: byId("alias-server").value,
|
||||
aliases: byId("alias-values").value,
|
||||
}, "区服别名已保存");
|
||||
if (saved) event.currentTarget.reset();
|
||||
});
|
||||
|
||||
byId("kungfu-form").addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const saved = await mutate("kungfu/save", {
|
||||
pzid: byId("kungfu-pzid").value,
|
||||
name: byId("kungfu-name").value,
|
||||
aliases: byId("kungfu-aliases").value,
|
||||
}, "心法配置已保存");
|
||||
if (saved) event.currentTarget.reset();
|
||||
});
|
||||
|
||||
byId("refresh").addEventListener("click", async (event) => {
|
||||
const control = event.currentTarget;
|
||||
control.disabled = true;
|
||||
|
||||
@@ -76,17 +76,9 @@
|
||||
</section>
|
||||
|
||||
<section class="panel" id="aliases-panel" role="tabpanel" hidden>
|
||||
<form class="editor editor--aliases" id="alias-form">
|
||||
<label>
|
||||
<span>标准区服名</span>
|
||||
<input id="alias-server" name="server" maxlength="64" list="server-options" placeholder="例如:梦江南" required />
|
||||
</label>
|
||||
<label>
|
||||
<span>别名(多个别名用逗号分隔)</span>
|
||||
<input id="alias-values" name="aliases" placeholder="例如:梦江、梦江南服、MJ" />
|
||||
</label>
|
||||
<button class="button button--primary" type="submit">保存别名</button>
|
||||
</form>
|
||||
<div class="section-intro">
|
||||
<div><h2>区服别名</h2><p>标准区服名称为只读;点击对应行的“编辑”可修改别名。</p></div>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>标准区服名</th><th>别名</th><th class="actions">操作</th></tr></thead>
|
||||
@@ -96,24 +88,12 @@
|
||||
</section>
|
||||
|
||||
<section class="panel" id="kungfu-panel" role="tabpanel" hidden>
|
||||
<form class="editor editor--kungfu" id="kungfu-form">
|
||||
<label>
|
||||
<span>心法 ID(JX3BOX 配装 ID)</span>
|
||||
<input id="kungfu-pzid" name="pzid" type="number" min="1" step="1" placeholder="例如:10014" required />
|
||||
</label>
|
||||
<label>
|
||||
<span>标准心法名</span>
|
||||
<input id="kungfu-name" name="name" maxlength="64" placeholder="例如:紫霞功" required />
|
||||
</label>
|
||||
<label>
|
||||
<span>别名(最多 5 个,用逗号分隔)</span>
|
||||
<input id="kungfu-aliases" name="aliases" placeholder="例如:气纯、紫霞" />
|
||||
</label>
|
||||
<button class="button button--primary" type="submit">保存心法</button>
|
||||
</form>
|
||||
<div class="section-intro">
|
||||
<div><h2>心法别名</h2><p>标准心法名称为只读;点击对应行的“编辑”可修改最多 5 个别名。</p></div>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>心法 ID</th><th>标准心法名</th><th>别名</th><th class="actions">操作</th></tr></thead>
|
||||
<thead><tr><th>标准心法名</th><th>别名</th><th class="actions">操作</th></tr></thead>
|
||||
<tbody id="kungfu-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -59,8 +59,6 @@ h1 { margin: 0; font-size: clamp(26px, 3vw, 36px); line-height: 1.2; letter-spac
|
||||
.panel { margin-top: 18px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; }
|
||||
.panel[hidden] { display: none; }
|
||||
.editor { display: grid; grid-template-columns: minmax(260px, 1.35fr) minmax(210px, 1fr) auto; align-items: end; gap: 16px; padding: 22px; background: var(--surface-subtle); border-bottom: 1px solid var(--border); }
|
||||
.editor--aliases { grid-template-columns: minmax(220px, .8fr) minmax(320px, 1.5fr) auto; }
|
||||
.editor--kungfu { grid-template-columns: minmax(210px, .65fr) minmax(210px, .8fr) minmax(300px, 1.35fr) auto; }
|
||||
label { display: grid; gap: 7px; color: var(--text); font-size: 13px; font-weight: 650; }
|
||||
input { width: 100%; height: 42px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--text); transition: border 160ms ease, box-shadow 160ms ease; }
|
||||
input::placeholder { color: color-mix(in srgb, var(--muted) 76%, transparent); }
|
||||
@@ -73,10 +71,14 @@ th, td { padding: 15px 20px; text-align: center; vertical-align: middle; border-
|
||||
th { background: var(--surface-subtle); color: var(--muted); font-size: 13px; font-weight: 700; }
|
||||
tbody tr:last-child td { border-bottom: 0; }
|
||||
tbody tr:hover { background: color-mix(in srgb, var(--accent-soft) 42%, transparent); }
|
||||
tbody tr.is-editing { background: color-mix(in srgb, var(--accent-soft) 62%, transparent); }
|
||||
.alias-cell { min-width: 320px; }
|
||||
.inline-editor { min-width: 260px; }
|
||||
.actions { white-space: nowrap; }
|
||||
.link-button { padding: 4px 7px; border: 0; border-radius: 5px; background: transparent; color: #3568ae; cursor: pointer; font-weight: 650; }
|
||||
[data-theme="dark"] .link-button { color: #8db9f4; }
|
||||
.link-button:hover { background: color-mix(in srgb, currentColor 10%, transparent); }
|
||||
.link-button:disabled { cursor: wait; opacity: .55; }
|
||||
.link-button--danger { color: var(--danger); }
|
||||
.state { display: inline-flex; align-items: center; gap: 7px; font-weight: 650; }
|
||||
.state::before { width: 8px; height: 8px; border-radius: 50%; background: currentColor; content: ""; }
|
||||
@@ -97,7 +99,7 @@ tbody tr:hover { background: color-mix(in srgb, var(--accent-soft) 42%, transpar
|
||||
.summary__item + .summary__item { border-top: 1px solid var(--border); border-left: 0; }
|
||||
.tabs { gap: 16px; overflow-x: auto; }
|
||||
.tab { flex: 0 0 auto; }
|
||||
.editor, .editor--aliases, .editor--kungfu { grid-template-columns: 1fr; }
|
||||
.editor { grid-template-columns: 1fr; }
|
||||
.table-wrap { overflow: visible; }
|
||||
table, tbody, tr, td { display: block; width: 100%; }
|
||||
thead { display: none; }
|
||||
@@ -106,6 +108,7 @@ tbody tr:hover { background: color-mix(in srgb, var(--accent-soft) 42%, transpar
|
||||
td { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 12px; padding: 8px 16px; border: 0; overflow-wrap: anywhere; }
|
||||
td::before { color: var(--muted); content: attr(data-label); font-size: 12px; font-weight: 700; }
|
||||
td.actions { grid-template-columns: max-content auto auto; align-items: center; width: 100%; white-space: normal; }
|
||||
.alias-cell, .inline-editor { min-width: 0; }
|
||||
td.empty { display: block; padding: 36px 16px; }
|
||||
td.empty::before { content: none; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user