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:
@@ -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 ? (
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user