pi-skill-evolve 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -29,21 +29,6 @@ export const RANGE_LABEL: Record<RangeKey, string> = {
|
|
|
29
29
|
/** 状态下拉的可选值:既有 run 终态,也有待处理页自己的两种(running / stale) */
|
|
30
30
|
export const STATUS_OPTIONS = ["running", "stale", "reviewed", "applied", "rejected", "failed", "analyzed"] as const;
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* 状态下拉的中文标签(用户 2026-11-08:「这里的下拉应该是中文」)。
|
|
34
|
-
* 值仍然是状态机原文(URL 与过滤逻辑不变),只改给人看的那一侧;
|
|
35
|
-
* 与徽章文案保持同一套词——同一个概念全站只能有一个中文名。
|
|
36
|
-
*/
|
|
37
|
-
export const STATUS_LABEL: Record<(typeof STATUS_OPTIONS)[number], string> = {
|
|
38
|
-
running: "复盘中",
|
|
39
|
-
stale: "卡死",
|
|
40
|
-
reviewed: "待入队",
|
|
41
|
-
applied: "已采纳",
|
|
42
|
-
rejected: "已拒绝",
|
|
43
|
-
failed: "失败",
|
|
44
|
-
analyzed: "待评审",
|
|
45
|
-
};
|
|
46
|
-
|
|
47
32
|
export interface ListFilter {
|
|
48
33
|
skill: string;
|
|
49
34
|
/** 空串 = 全部 */
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
telemetryOffWhileEnabled,
|
|
22
22
|
} from "../flags.ts";
|
|
23
23
|
import type { WebView } from "./data.ts";
|
|
24
|
-
import { RANGE_KEYS, RANGE_LABEL,
|
|
24
|
+
import { RANGE_KEYS, RANGE_LABEL, type ListFilter, type ViewPage } from "./filter.ts";
|
|
25
25
|
import { listHref, type ListExtras } from "./list-query.ts";
|
|
26
26
|
import { escapeHtml, formatStamp, formatTimeSeconds } from "./text.ts";
|
|
27
27
|
import type { WebControls } from "./activity.ts";
|
|
@@ -106,16 +106,7 @@ ${run}</div>
|
|
|
106
106
|
${warn}${backlog}`;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
/**
|
|
110
|
-
function statusSelect(current: string): string {
|
|
111
|
-
const options = [`<option value="">全部状态</option>`];
|
|
112
|
-
for (const status of STATUS_OPTIONS) {
|
|
113
|
-
// value 仍是状态机原文(过滤逻辑不变),只把展示换中文
|
|
114
|
-
options.push(`<option value="${status}"${status === current ? " selected" : ""}>${STATUS_LABEL[status]}</option>`);
|
|
115
|
-
}
|
|
116
|
-
return options.join("");
|
|
117
|
-
}
|
|
118
|
-
|
|
109
|
+
/** 时间下拉:只有「看多久内」需要人手动换,状态与技能已在 tab 与技能页面各自解决了 */
|
|
119
110
|
function rangeSelect(current: string): string {
|
|
120
111
|
return RANGE_KEYS.map(
|
|
121
112
|
(key) => `<option value="${key}"${key === current ? " selected" : ""}>${RANGE_LABEL[key]}</option>`,
|
|
@@ -123,16 +114,16 @@ function rangeSelect(current: string): string {
|
|
|
123
114
|
}
|
|
124
115
|
|
|
125
116
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
117
|
+
* 筛选表单:只留「时间」一个条件。
|
|
118
|
+
* 技能:每个列表页的行里已经有技能列,技能页可以按技能点进来,再摆一个模糊搜索框没人知道该填什么;
|
|
119
|
+
* 状态:顶部 tab 本身就是按状态分的(待处理 / 待审批 / 已采纳 / 已处理 / 复盘报告),重复选毫无意义。
|
|
120
|
+
* 两个参数(skill / status)仍由 `parseListQuery` 支持,旧链接与代码内部跳转不会断,只是不再出输入框。
|
|
128
121
|
*/
|
|
129
122
|
export function renderFilterForm(view: WebView, filter: ListFilter, extras: ListExtras): string {
|
|
130
123
|
const keep = extraInputs(extras);
|
|
131
124
|
return `<form class="filter" method="get">
|
|
132
125
|
<input type="hidden" name="view" value="${view}">
|
|
133
|
-
${keep}<label
|
|
134
|
-
<label>状态 <select name="status">${statusSelect(filter.status)}</select></label>
|
|
135
|
-
<label>时间 <select name="range">${rangeSelect(filter.range)}</select></label>
|
|
126
|
+
${keep}<label>时间 <select name="range">${rangeSelect(filter.range)}</select></label>
|
|
136
127
|
<button type="submit">筛选</button>
|
|
137
128
|
<a class="btn" href="${escapeHtml(listHref(view, filter, 1, extras))}">重置</a>
|
|
138
129
|
</form>`;
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 筛选栏的验收测试(用户 2026-11-08:「这个搜索框的技能和状态不用了吧, 技能不知道用来搜索什么,
|
|
3
|
+
* 状态应该在顶部 tab 包含了吧」)。
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* 口径:
|
|
6
|
+
* 1. 表单**只剩「时间」**一个条件——技能看不出该填什么、状态与顶部 tab 重复,两个都撤掉;
|
|
7
|
+
* 2. 撤掉的是**输入控件**,不是参数:`?skill=` / `?status=` 仍由 `parseListQuery` 解析,
|
|
8
|
+
* 技能页点进来、旧书签、代码内部跳转都不会断;
|
|
9
|
+
* 3. 表单仍是 GET + 保留 `view`,否则一提交就跳出当前页。
|
|
9
10
|
*
|
|
10
11
|
* 纪律:纯字符串断言,不碰文件系统、不起服务。
|
|
11
12
|
*/
|
|
12
13
|
import { test } from "node:test";
|
|
13
14
|
import assert from "node:assert/strict";
|
|
14
15
|
|
|
15
|
-
import { parseListQuery
|
|
16
|
+
import { parseListQuery } from "../lib/web/filter.ts";
|
|
16
17
|
import { renderFilterForm } from "../lib/web/render-controls.ts";
|
|
17
18
|
|
|
18
19
|
const FILTER = parseListQuery(new URLSearchParams(""));
|
|
@@ -22,36 +23,38 @@ function form(): string {
|
|
|
22
23
|
return renderFilterForm("pending", FILTER, EXTRAS);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
test("
|
|
26
|
+
test("筛选栏不再有技能输入框与状态下拉", () => {
|
|
26
27
|
const html = form();
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
assert.ok(!html.includes('name="skill"'), "技能搜索框已撤掉");
|
|
29
|
+
assert.ok(!html.includes('name="status"'), "状态下拉已撤掉(顶部 tab 就是状态)");
|
|
30
|
+
assert.ok(!html.includes("全部状态"));
|
|
31
|
+
assert.ok(!html.includes("全部技能"));
|
|
31
32
|
});
|
|
32
33
|
|
|
33
|
-
test("
|
|
34
|
+
test("时间筛选还在,且三个档位齐全", () => {
|
|
34
35
|
const html = form();
|
|
35
|
-
|
|
36
|
-
for (const
|
|
37
|
-
assert.ok(
|
|
36
|
+
assert.ok(html.includes('name="range"'));
|
|
37
|
+
for (const label of ["最近 7 天", "最近 30 天", "全部时间"]) {
|
|
38
|
+
assert.ok(html.includes(`>${label}<`), `缺时间档位:${label}`);
|
|
38
39
|
}
|
|
39
40
|
});
|
|
40
41
|
|
|
41
|
-
test("
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
test("表单仍是 GET,且保留 view", () => {
|
|
43
|
+
const html = form();
|
|
44
|
+
assert.ok(html.includes('method="get"'));
|
|
45
|
+
assert.ok(html.includes('<input type="hidden" name="view" value="pending">'));
|
|
44
46
|
});
|
|
45
47
|
|
|
46
|
-
test("
|
|
47
|
-
const
|
|
48
|
-
assert.
|
|
49
|
-
assert.
|
|
50
|
-
assert.
|
|
48
|
+
test("参数没被删:URL 里的 skill / status 仍然生效", () => {
|
|
49
|
+
const parsed = parseListQuery(new URLSearchParams("skill=deploy-test&status=stale&range=30d"));
|
|
50
|
+
assert.equal(parsed.skill, "deploy-test");
|
|
51
|
+
assert.equal(parsed.status, "stale");
|
|
52
|
+
assert.equal(parsed.range, "30d");
|
|
51
53
|
});
|
|
52
54
|
|
|
53
|
-
test("
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
assert.ok(html.includes('
|
|
55
|
+
test("技能页跳过来的链接照旧能带 skill 参数(只是不再有输入框)", () => {
|
|
56
|
+
const parsed = parseListQuery(new URLSearchParams("skill=ui-verify"));
|
|
57
|
+
const html = renderFilterForm("reports", parsed, EXTRAS);
|
|
58
|
+
assert.ok(!html.includes('name="skill"'));
|
|
59
|
+
assert.equal(parsed.skill, "ui-verify", "筛选逻辑要能吃到链接里的技能");
|
|
57
60
|
});
|