Clarify Hint pack save behavior

Keep manual editing while making save the only user action and applying changes immediately without a separate publish workflow.
This commit is contained in:
Rocky
2026-08-21 15:37:13 +08:00
parent 454ba8ddc5
commit b25f5ae6e9
8 changed files with 32 additions and 10 deletions
+1
View File
@@ -17,6 +17,7 @@ export type AdminAuditAction =
| "CONTENT_SKILL_ENABLED"
| "CONTENT_SKILL_DISABLED"
| "CONTENT_HINT_PACK_PUBLISHED"
| "CONTENT_HINT_PACK_SAVED"
| "CONTENT_HINT_FEED_SETTINGS_UPDATED"
| "CONTENT_HINT_FEED_GENERATED";
@@ -113,7 +113,7 @@ export function ContentPage() {
const saved = await adminApi.updateContentHintPack(locale, payload);
setHintVersion(saved.version);
setHintText(formatHintPack(saved));
toast.success(`${locale} Hint pack 已发布`);
toast.success(`${locale} Hint pack 已保存并生效`);
} catch (requestError) {
toast.error(errorMessage(requestError, "Hint pack 保存失败"));
} finally {
@@ -129,7 +129,7 @@ export function ContentPage() {
<PageHeader
eyebrow="Official Content"
title="内容管理"
description="维护客户端官方 Skill、AI Hint 自动生成与 zh/en 手动发布包。所有变更都会写入审计。"
description="维护客户端官方 Skill、AI Hint 自动生成与 zh/en 内容。所有变更都会写入审计。"
actions={
canEdit ? (
<Button onClick={() => setEditingSkill("new")}>
@@ -221,7 +221,7 @@ export function ContentPage() {
AI Hint packs
</h2>
<p className="mt-1 text-sm text-muted">
JSON AIHintPack version
AIHintPack version
</p>
</div>
<Card className="overflow-hidden">
@@ -263,7 +263,7 @@ export function ContentPage() {
{canEdit ? (
<div className="mt-4 flex justify-end">
<Button loading={hintSaving} onClick={() => void saveHint()}>
</Button>
</div>
) : null}
@@ -239,7 +239,7 @@ export function HintAutoSection({ canEdit }: HintAutoSectionProps) {
<p className="text-xs text-muted">
TopHub API Key
JSON
JSON
</p>
{canEdit ? (
+20 -1
View File
@@ -26,7 +26,7 @@ describe("内容管理", () => {
expect(screen.queryByRole("button", { name: "新增 Skill" })).toBeNull();
const editor = await screen.findByLabelText("zh JSON");
expect(editor).toHaveProperty("readOnly", true);
expect(screen.queryByRole("button", { name: "保存并立即发布" })).toBeNull();
expect(screen.queryByRole("button", { name: "保存" })).toBeNull();
expect(screen.queryByRole("button", { name: "立即生成" })).toBeNull();
expect(screen.queryByRole("button", { name: "保存生成设置" })).toBeNull();
});
@@ -90,6 +90,25 @@ describe("内容管理", () => {
await waitFor(() => expect(regenerate).toHaveBeenCalledOnce());
});
it("SUPER_ADMIN 可编辑并保存当前生效的 Hint pack", async () => {
mockSession("SUPER_ADMIN");
mockContent();
const save = vi.spyOn(adminApi, "updateContentHintPack").mockResolvedValue({
locale: "zh",
generatedAt: "2026-08-21T06:00:00Z",
intervalHours: 12,
version: 3,
cards: [],
});
window.location.hash = "#/content";
render(<App />);
await userEvent.click(await screen.findByRole("button", { name: "保存" }));
await waitFor(() => expect(save).toHaveBeenCalledOnce());
expect(await screen.findByText("version 3")).toBeTruthy();
});
});
function mockSession(role: AdminRole) {
+1 -1
View File
@@ -34,7 +34,7 @@ The migrated generator runs independently inside OSGAccountServer and publishes:
## Rollback
Disable `HINT_FEED_ENABLED` to stop scheduled generation. Published packs remain
available from MySQL and manual publishing remains available. No rollback step
available from MySQL and manual editing/saving remains available. No rollback step
depends on or modifies `key.osglab.com`.
Provider credentials such as `TOPHUB_API_KEY` stay in environment-backed secret
+3 -2
View File
@@ -808,7 +808,7 @@ paths:
security:
- adminMtls: []
adminSession: []
summary: Immediately publish a locale Hint pack and increment its version
summary: Save and immediately apply edits to a locale Hint pack
parameters:
- $ref: "#/components/parameters/HintLocale"
- $ref: "#/components/parameters/AdminCsrf"
@@ -819,7 +819,7 @@ paths:
schema: { $ref: "#/components/schemas/UpdateAIHintPackRequest" }
responses:
"200":
description: Published pack
description: Saved active pack
content:
application/json:
schema: { $ref: "#/components/schemas/AdminAIHintPack" }
@@ -1249,6 +1249,7 @@ paths:
- CONTENT_SKILL_ENABLED
- CONTENT_SKILL_DISABLED
- CONTENT_HINT_PACK_PUBLISHED
- CONTENT_HINT_PACK_SAVED
- CONTENT_HINT_FEED_SETTINGS_UPDATED
- CONTENT_HINT_FEED_GENERATED
- name: result
@@ -116,6 +116,7 @@ enum class AdminAuditAction {
CONTENT_SKILL_ENABLED,
CONTENT_SKILL_DISABLED,
CONTENT_HINT_PACK_PUBLISHED,
CONTENT_HINT_PACK_SAVED,
CONTENT_HINT_FEED_SETTINGS_UPDATED,
CONTENT_HINT_FEED_GENERATED,
}
@@ -215,7 +215,7 @@ class ContentService(
now,
audit(
actor,
AdminAuditAction.CONTENT_HINT_PACK_PUBLISHED,
AdminAuditAction.CONTENT_HINT_PACK_SAVED,
"OFFICIAL_HINT_PACK",
locale,
requestId,