feat(knowledge): 阅读改成独立整页,抽屉只用来编辑
CI / backend (push) Canceled after 0s

知识原来一律在抽屉里打开,正文贴着屏幕右半边,长文读十几屏眼睛一直在右边。
阅读是「坐下来读一会儿」,编辑是「改两句就走」,两件事不该共用一个容器。

- 新增阅读页 /w/:wsId/knowledge/:itemId:正文列限到 40rem 居中,28px 标题,
  更新/发布/切片行,标签与来源,动作行放编辑与发布/归档/恢复
- 列表页与搜索结果改成跳阅读页,不再弹抽屉
- KnowledgeDrawer 加 initialEditing:进来就是编辑器,保存或取消直接关
- 文案常量搬到 lib/knowledge.ts,列表页与阅读页共用一份

顺带修三个 e2e 脚本:新建后进阅读页没有「关闭」按钮可点、侧栏色点按钮让树
顺序断言多出空串、翻页脚本还在用已关闭的短信登录(改密码登录)。
This commit is contained in:
Steven
2026-11-03 12:12:51 +08:00
parent 127303b7aa
commit d34a6ac69e
10 changed files with 621 additions and 94 deletions
+31 -6
View File
@@ -8,12 +8,12 @@
* node web/e2e/knowledge-paging.mjs # 默认打生产
* WEB=http://127.0.0.1:5180 PHONE=13900000001 node web/e2e/knowledge-paging.mjs
*/
import { readFile } from "node:fs/promises";
import { chromium } from "playwright-core";
const WEB = process.env.WEB ?? "http://192.168.8.188:8200";
const API = process.env.API ?? `${WEB}/api/v1`;
const PHONE = process.env.PHONE ?? "13605513683";
const CODE = process.env.CODE ?? "123456";
const CODE_PIN = process.env.CODE_PIN ?? "123456"; // 生产 pin 就是验证码本身
const CHROME =
process.env.CHROME ??
@@ -31,14 +31,29 @@ function check(name, ok, extra = "") {
}
}
/**
* 登录:默认用密码(生产的短信登录已经关了),密码从 PASSWORD 拿,
* 或者从 .local/e2e-account-password.txt 读(dev 13900000001 的密码存在那儿)。
* 真没密码时才回落到短信验证码——那种环境下短信登录得开着。
*/
async function login() {
const r = await fetch(`${API}/auth/sms/send`, {
const password = await readPassword();
if (password) {
const r = await fetch(`${API}/auth/login/password`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ phone: PHONE, password }),
});
const body = await r.json();
if (body.code !== 0) throw new Error(`登录失败:${body.message}`);
return { tokens: body.data.tokens, workspaces: await workspaces(body.data.tokens) };
}
const sent = await fetch(`${API}/auth/sms/send`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ phone: PHONE }),
});
const sent = await r.json();
if (sent.code !== 0) throw new Error(`发码失败:${sent.message}`);
}).then((r) => r.json());
if (sent.code !== 0) throw new Error(`发码失败:${sent.message}(配个 PASSWORD 或写下密码文件就能走密码登录)`);
const login = await fetch(`${API}/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
@@ -49,6 +64,17 @@ async function login() {
return { tokens: body.data.tokens, workspaces: await workspaces(body.data.tokens) };
}
async function readPassword() {
if (process.env.PASSWORD) return process.env.PASSWORD;
try {
const file = new URL("../../.local/e2e-account-password.txt", import.meta.url);
const text = (await readFile(file, "utf8")).trim();
return text || null;
} catch {
return null;
}
}
async function workspaces(tokens) {
const r = await fetch(`${API}/workspaces`, {
headers: { Authorization: `Bearer ${tokens.access_token}` },
@@ -58,7 +84,6 @@ async function workspaces(tokens) {
}
async function main() {
void CODE;
const { tokens, workspaces: spaces } = await login();
if (!spaces.length) throw new Error("这个账号没有工作区");
const ws = spaces[0];