- D前端: lib/api/messages.ts(patchMessage/deleteMessage,兼容裸DTO与{message}) + MessageActions.tsx(仅user消息; 单击/右键/450ms长按开Miuix玻璃菜单; 编辑弹窗预填+字数→乐观updateMessageById→patchMessage→失败回滚; 删除确认→deleteMessage→removeMessageById; 乐观气泡禁用) + chat.tsx挂载 + Icon加edit/trash/more
- 日志前端: types(AdminLogLine time:string|number) + adminSystem.adminObservabilityLogs + Observability.tsx 后端分级tail(level筛选chip注明'该级及以上'+等宽行HH:mm:ss.SSS·level着色·source·msg+30s刷新) 下半保留WS回显
- Docs/api-client §6a/§4.2 修正: PATCH /messages/{id} 实际返回 {data:<DTO>} 非 {data:{message}}(前端已双向兼容,避免误导Android)
- 前端 build 绿(167 modules); SSR冒烟11 checks
- 遗留: 未实机登录; 菜单absolute理论上边缘可裁切(可改portal)
37 lines
1.7 KiB
TypeScript
37 lines
1.7 KiB
TypeScript
import type { MessageDto } from "./sessions";
|
|
import { request } from "./core";
|
|
|
|
/**
|
|
* Single-message mutations (design/16 §4.2 D3, Docs/api-client.md §6a/6b).
|
|
* Both succeed against the persisted row and broadcast the change over the WS
|
|
* hub (`message_edited` / `message_deleted`), so other clients converge without
|
|
* a re-fetch; the caller's REST response is only the acknowledgement.
|
|
*/
|
|
|
|
/** The gateway answers PATCH with `{data: <updated message DTO>}` (see
|
|
* gateway/history_write.go `writeJSON(w, 200, toHistoryMessage(msg))` and
|
|
* history_write_broadcast_test.go, which decodes `data` straight into the DTO).
|
|
* Docs/api-client.md §6a writes that envelope as `{data:{message}}`; the optional
|
|
* `message` field keeps this call working either way, so a plain DTO is never
|
|
* mistaken for an empty result (which would blank the bubble). */
|
|
type PatchMessageEnvelope = MessageDto & { message?: MessageDto };
|
|
|
|
/** PATCH /api/v1/messages/{id} — replace one message's `content`. The backend
|
|
* validates non-empty `≤4000` runes (400) and existence (404), and only ever
|
|
* changes `content`; role / timestamps / platform are preserved. */
|
|
export async function patchMessage(id: string, content: string): Promise<MessageDto> {
|
|
const res = await request<PatchMessageEnvelope>(
|
|
`/messages/${encodeURIComponent(id)}`,
|
|
{ method: "PATCH", body: JSON.stringify({ content }) }
|
|
);
|
|
return res.message ?? res;
|
|
}
|
|
|
|
/** DELETE /api/v1/messages/{id} — remove one message (404 when already gone).
|
|
* The response echoes the deleted id, so a caller can assert what it removed. */
|
|
export function deleteMessage(id: string): Promise<{ deleted: string }> {
|
|
return request<{ deleted: string }>(`/messages/${encodeURIComponent(id)}`, {
|
|
method: "DELETE",
|
|
});
|
|
}
|