@hupan56/wlkj 3.1.7 → 3.1.8
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.
- package/package.json +1 -1
- package/templates/qoder/scripts/domain/report/status_snapshot.py +19 -10
- package/templates/qoder/scripts/domain/requirement/archive_prd.py +5 -39
- package/templates/qoder/scripts/foundation/integrations/zentao_client.py +28 -5
- package/templates/qoder/skills/design-import/figma-workflow.md +81 -81
- package/templates/qoder/skills/prototype-generator/SKILL.md +43 -43
- package/templates/qoder/skills/wl-commit/SKILL.md +14 -2
package/package.json
CHANGED
|
@@ -141,16 +141,25 @@ def snapshot(repo=None):
|
|
|
141
141
|
data["index_age_days"] = _index_freshness(meta)
|
|
142
142
|
|
|
143
143
|
# 3. EVA 评估历史 (健康度趋势)
|
|
144
|
-
data
|
|
145
|
-
|
|
144
|
+
# ⚠ 真实路径是 data/learning/eval-history.jsonl (旧版写 .qoder/learning/ 是历史 bug,
|
|
145
|
+
# eval_prd.py/learn.py 早改了, 这里要对齐 EVAL_HISTORY_PATH, 否则 /wl-status 永远 null)。
|
|
146
|
+
try:
|
|
147
|
+
from foundation.core.paths import EVAL_HISTORY_PATH
|
|
148
|
+
eval_path = str(EVAL_HISTORY_PATH)
|
|
149
|
+
except Exception:
|
|
150
|
+
eval_path = os.path.join(repo, "data", "learning", "eval-history.jsonl")
|
|
151
|
+
data["eval_history"] = _read_jsonl_tail(eval_path, n=10)
|
|
146
152
|
|
|
147
|
-
# 4. 学习反馈
|
|
148
|
-
data["feedback_count"] =
|
|
149
|
-
|
|
150
|
-
if os.path.
|
|
153
|
+
# 4. 学习反馈 (扫所有成员的 journal/feedback.jsonl, learn.py 写这里)
|
|
154
|
+
data["feedback_count"] = 0
|
|
155
|
+
members_dir = os.path.join(repo, "workspace", "members")
|
|
156
|
+
if os.path.isdir(members_dir):
|
|
151
157
|
try:
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
for m in os.listdir(members_dir):
|
|
159
|
+
fb = os.path.join(members_dir, m, "journal", "feedback.jsonl")
|
|
160
|
+
if os.path.isfile(fb):
|
|
161
|
+
with open(fb, encoding="utf-8") as f:
|
|
162
|
+
data["feedback_count"] += sum(1 for _ in f)
|
|
154
163
|
except Exception:
|
|
155
164
|
pass
|
|
156
165
|
|
|
@@ -172,8 +181,8 @@ def snapshot(repo=None):
|
|
|
172
181
|
# 8. 任务目录结构
|
|
173
182
|
data["tasks_dir"] = _list_dir(os.path.join(qd, "workspace", "tasks"))
|
|
174
183
|
|
|
175
|
-
# 9. 学习模式
|
|
176
|
-
data["patterns"] = _list_dir(os.path.join(
|
|
184
|
+
# 9. 学习模式 (data/learning/patterns/, 非 .qoder/learning/)
|
|
185
|
+
data["patterns"] = _list_dir(os.path.join(repo, "data", "learning", "patterns"))
|
|
177
186
|
|
|
178
187
|
# 10. 成员目录 (团队规模)
|
|
179
188
|
data["members"] = _list_dir(os.path.join(qd, "workspace", "members"))
|
|
@@ -10,7 +10,7 @@ for _ in range(10):
|
|
|
10
10
|
break
|
|
11
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
12
12
|
from bootstrap import setup; setup()
|
|
13
|
-
from foundation.core.paths import get_repo_root
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
16
|
archive_prd.py - PRD 按时间归档到个人工作区
|
|
@@ -45,44 +45,10 @@ except (AttributeError, TypeError, OSError, IOError):
|
|
|
45
45
|
except Exception:
|
|
46
46
|
pass
|
|
47
47
|
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
sys.path.insert(0, _COMMON)
|
|
53
|
-
|
|
54
|
-
try:
|
|
55
|
-
from paths import get_repo_root, get_developer, MEMBERS_DIR
|
|
56
|
-
except ImportError:
|
|
57
|
-
# 极端兜底:直接算路径
|
|
58
|
-
def get_repo_root():
|
|
59
|
-
current = Path(_THIS_DIR).resolve()
|
|
60
|
-
for _ in range(10):
|
|
61
|
-
if (current / ".qoder").is_dir():
|
|
62
|
-
return current
|
|
63
|
-
parent = current.parent
|
|
64
|
-
if parent == current:
|
|
65
|
-
break
|
|
66
|
-
current = parent
|
|
67
|
-
return Path(_THIS_DIR).parent.parent
|
|
68
|
-
|
|
69
|
-
def get_developer(repo_root=None):
|
|
70
|
-
dev = (repo_root or get_repo_root()) / ".qoder" / ".developer"
|
|
71
|
-
if not dev.is_file():
|
|
72
|
-
return None
|
|
73
|
-
for enc in ("utf-8", "gbk"):
|
|
74
|
-
try:
|
|
75
|
-
for line in dev.read_text(encoding=enc).splitlines():
|
|
76
|
-
line = line.strip()
|
|
77
|
-
if "=" in line and line.split("=")[0].strip() == "name":
|
|
78
|
-
return line.split("=", 1)[1].strip() or None
|
|
79
|
-
if ":" in line and line.split(":")[0].strip() == "name":
|
|
80
|
-
return line.split(":", 1)[1].strip() or None
|
|
81
|
-
except (OSError, IOError, UnicodeDecodeError):
|
|
82
|
-
continue
|
|
83
|
-
return None
|
|
84
|
-
|
|
85
|
-
MEMBERS_DIR = None # 下面用 repo_root 拼
|
|
48
|
+
# v3.x: 顶部 bootstrap 已 setup, 直接 import foundation.* (旧版重复尝试 from paths
|
|
49
|
+
# + 手写兜底, 兜底会与 foundation.core.paths 静默漂移, 这里统一走真源)。
|
|
50
|
+
from foundation.core.paths import get_repo_root as _grr, get_developer, MEMBERS_DIR
|
|
51
|
+
get_repo_root = _grr # 已在顶部 import, 这里显式重绑确保本模块可见
|
|
86
52
|
|
|
87
53
|
|
|
88
54
|
# ============================================================
|
|
@@ -60,15 +60,38 @@ class ZentaoClient:
|
|
|
60
60
|
|
|
61
61
|
@classmethod
|
|
62
62
|
def from_config(cls) -> Optional['ZentaoClient']:
|
|
63
|
-
"""从 .qoder/config.yaml 的 zentao 段构造(CLI 用)。凭据不全返回 None。
|
|
63
|
+
"""从 .qoder/config.yaml 的 zentao 段构造(CLI 用)。凭据不全返回 None。
|
|
64
|
+
|
|
65
|
+
v3.1.4 设计: url 团队共享(放 config.yaml), user/password 个人凭据(放
|
|
66
|
+
workspace/members/{dev}/.private/secrets/zentao.env, gitignored)。
|
|
67
|
+
所以这里 url 从 config 读, user/password 从 zentao.env 读 ——
|
|
68
|
+
与 mcp_launcher.launch_zentao() 完全对齐 (旧版从 config 读 user/password
|
|
69
|
+
→ 永远 None, 因为 config 故意不放个人凭据)。
|
|
70
|
+
"""
|
|
71
|
+
# ① url 从 config.yaml
|
|
72
|
+
url = ''
|
|
64
73
|
try:
|
|
65
74
|
from foundation.core.config import load_config_section, SECTIONS
|
|
66
75
|
cfg = load_config_section(SECTIONS.ZENTAO)
|
|
76
|
+
url = (cfg.get('url') or '').strip()
|
|
67
77
|
except Exception:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
user =
|
|
71
|
-
|
|
78
|
+
url = ''
|
|
79
|
+
# ② user/password 从当前开发者的 .private/secrets/zentao.env
|
|
80
|
+
user = pwd = ''
|
|
81
|
+
try:
|
|
82
|
+
from foundation.core.paths import get_secrets_dir, get_developer
|
|
83
|
+
dev = get_developer()
|
|
84
|
+
if dev:
|
|
85
|
+
env_file = os.path.join(get_secrets_dir(dev), 'zentao.env')
|
|
86
|
+
if os.path.isfile(env_file):
|
|
87
|
+
for line in open(env_file, encoding='utf-8'):
|
|
88
|
+
line = line.strip()
|
|
89
|
+
if line.startswith('ZENTAO_USER='):
|
|
90
|
+
user = line.split('=', 1)[1].strip().strip('"').strip("'")
|
|
91
|
+
elif line.startswith('ZENTAO_PASSWORD='):
|
|
92
|
+
pwd = line.split('=', 1)[1].strip().strip('"').strip("'")
|
|
93
|
+
except Exception:
|
|
94
|
+
pass
|
|
72
95
|
if not url or not user or not pwd:
|
|
73
96
|
return None
|
|
74
97
|
return cls(url, user, pwd)
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
# Figma 协作指南(设计师专用)
|
|
2
|
-
|
|
3
|
-
> 工作流出的 HTML 原型 → Figma 精修 → 录回 spec.json 闭环
|
|
4
|
-
|
|
5
|
-
## 为什么这条路可行
|
|
6
|
-
|
|
7
|
-
工作流用 `fill_prototype.py` 出的 HTML 原型有以下特征,**非常适合 html.to.design 插件转换**:
|
|
8
|
-
|
|
9
|
-
- CSS 用标准 CSS 变量(`:root { --primary: ... }`),插件能正确解析成 Figma Variables
|
|
10
|
-
- 布局用 Flexbox/Grid,转换后图层结构清晰
|
|
11
|
-
- 颜色是 Vben 真实 HSL token(不是 #1890ff),导入后直接是正确配色
|
|
12
|
-
- 图标是内联 SVG(Ant Design),导入后是可编辑矢量
|
|
13
|
-
|
|
14
|
-
## 完整流程(4 步)
|
|
15
|
-
|
|
16
|
-
### Step 1: PM 出原型(工作流侧)
|
|
17
|
-
|
|
18
|
-
PM 在 QoderWork 说"出个 XX 的原型",工作流输出:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
workspace/members/{pm}/drafts/prototype-{需求名}-web.html
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
设计师从 PM 那拿到这个 HTML 文件。
|
|
25
|
-
|
|
26
|
-
### Step 2: 导入 Figma(设计师侧)
|
|
27
|
-
|
|
28
|
-
1. 打开 Figma,新建一个 Frame
|
|
29
|
-
2. 菜单:**Plugins → html.to.design**(by ‹div›RIOTS)
|
|
30
|
-
- 没装的话:Figma Community 搜 "html.to.design" 安装(免费)
|
|
31
|
-
3. 插件面板里选 **File** 标签(不是 URL 标签)
|
|
32
|
-
4. 把 HTML 文件**拖进拖放区**(或点选文件)
|
|
33
|
-
5. 点 **Import**,等几秒
|
|
34
|
-
|
|
35
|
-
**结果**:HTML 变成完全可编辑的 Figma 图层——每个元素是独立的 Frame/Text/Rectangle,颜色是正确的 Vben 配色。
|
|
36
|
-
|
|
37
|
-
### Step 3: 设计师精修(Figma 侧)
|
|
38
|
-
|
|
39
|
-
设计师在 Figma 里做只有人能做的精修:
|
|
40
|
-
|
|
41
|
-
- 调间距/对齐(AI 的间距可能不精确)
|
|
42
|
-
- 优化交互细节(hover 态、动画、过渡)
|
|
43
|
-
- 换更合适的图标/插图
|
|
44
|
-
- 调整信息层级和视觉重点
|
|
45
|
-
- 加设计师特有的"手感"
|
|
46
|
-
|
|
47
|
-
**注意**:颜色 token(`--primary` 等)尽量别改——它们是系统统一的,改了前端实现时会对不上。
|
|
48
|
-
|
|
49
|
-
### Step 4: 录回工作流(闭环)
|
|
50
|
-
|
|
51
|
-
设计师精修完,在 QoderWork 里说:
|
|
52
|
-
|
|
53
|
-
> "录入设计稿"
|
|
54
|
-
|
|
55
|
-
工作流把 Figma 最终稿的关键决策(布局/配色/组件)录成 `data/style/{需求名}-design-spec.json`。
|
|
56
|
-
|
|
57
|
-
从此:
|
|
58
|
-
- 下次同需求出原型,工作流**优先用这份 spec**
|
|
59
|
-
- 前端拿到的 HTML 原型**匹配设计师的 Figma 终稿**
|
|
60
|
-
- 设计师的劳动成果**沉淀进知识图谱**,不浪费
|
|
61
|
-
|
|
62
|
-
## 常见问题
|
|
63
|
-
|
|
64
|
-
**Q: 导入后图层太碎怎么办?**
|
|
65
|
-
A: html.to.design 会按 HTML DOM 结构生成图层。fill_prototype 出的 HTML 结构已经很干净(侧边栏/搜索栏/表格各自独立),不会太碎。如果某个区域图层太多,选中后用 Figma 的 "Flatten" 合并。
|
|
66
|
-
|
|
67
|
-
**Q: 表格数据是假的怎么办?**
|
|
68
|
-
A: 对的,原型里的表格行是示例数据("XX示例1")。这是故意的——原型验证的是布局和交互,不是数据。真实数据前端会从 API 取。
|
|
69
|
-
|
|
70
|
-
**Q: 图标导入后变位图了?**
|
|
71
|
-
A: 不会。工作流用的图标是内联 SVG(不是图片标签),html.to.design 会保留为矢量。如果个别图标显示异常,从 `data/index/icon
|
|
72
|
-
|
|
73
|
-
**Q: APP 端原型也能导入吗?**
|
|
74
|
-
A: 能。`prototype-{需求名}-app.html` 同样是标准 HTML,导入方式一样。APP 原型用的是 Vant 风格(移动端组件库)。
|
|
75
|
-
|
|
76
|
-
## html.to.design 插件安装
|
|
77
|
-
|
|
78
|
-
- Figma Community 搜索:`html.to.design`
|
|
79
|
-
- 或直接访问:https://www.figma.com/community/plugin/1159123024924461424
|
|
80
|
-
- 免费版每次导入有限制,团队版无限
|
|
81
|
-
- 也有 Chrome 扩展版(适合截取在线页面)
|
|
1
|
+
# Figma 协作指南(设计师专用)
|
|
2
|
+
|
|
3
|
+
> 工作流出的 HTML 原型 → Figma 精修 → 录回 spec.json 闭环
|
|
4
|
+
|
|
5
|
+
## 为什么这条路可行
|
|
6
|
+
|
|
7
|
+
工作流用 `fill_prototype.py` 出的 HTML 原型有以下特征,**非常适合 html.to.design 插件转换**:
|
|
8
|
+
|
|
9
|
+
- CSS 用标准 CSS 变量(`:root { --primary: ... }`),插件能正确解析成 Figma Variables
|
|
10
|
+
- 布局用 Flexbox/Grid,转换后图层结构清晰
|
|
11
|
+
- 颜色是 Vben 真实 HSL token(不是 #1890ff),导入后直接是正确配色
|
|
12
|
+
- 图标是内联 SVG(Ant Design),导入后是可编辑矢量
|
|
13
|
+
|
|
14
|
+
## 完整流程(4 步)
|
|
15
|
+
|
|
16
|
+
### Step 1: PM 出原型(工作流侧)
|
|
17
|
+
|
|
18
|
+
PM 在 QoderWork 说"出个 XX 的原型",工作流输出:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
workspace/members/{pm}/drafts/prototype-{需求名}-web.html
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
设计师从 PM 那拿到这个 HTML 文件。
|
|
25
|
+
|
|
26
|
+
### Step 2: 导入 Figma(设计师侧)
|
|
27
|
+
|
|
28
|
+
1. 打开 Figma,新建一个 Frame
|
|
29
|
+
2. 菜单:**Plugins → html.to.design**(by ‹div›RIOTS)
|
|
30
|
+
- 没装的话:Figma Community 搜 "html.to.design" 安装(免费)
|
|
31
|
+
3. 插件面板里选 **File** 标签(不是 URL 标签)
|
|
32
|
+
4. 把 HTML 文件**拖进拖放区**(或点选文件)
|
|
33
|
+
5. 点 **Import**,等几秒
|
|
34
|
+
|
|
35
|
+
**结果**:HTML 变成完全可编辑的 Figma 图层——每个元素是独立的 Frame/Text/Rectangle,颜色是正确的 Vben 配色。
|
|
36
|
+
|
|
37
|
+
### Step 3: 设计师精修(Figma 侧)
|
|
38
|
+
|
|
39
|
+
设计师在 Figma 里做只有人能做的精修:
|
|
40
|
+
|
|
41
|
+
- 调间距/对齐(AI 的间距可能不精确)
|
|
42
|
+
- 优化交互细节(hover 态、动画、过渡)
|
|
43
|
+
- 换更合适的图标/插图
|
|
44
|
+
- 调整信息层级和视觉重点
|
|
45
|
+
- 加设计师特有的"手感"
|
|
46
|
+
|
|
47
|
+
**注意**:颜色 token(`--primary` 等)尽量别改——它们是系统统一的,改了前端实现时会对不上。
|
|
48
|
+
|
|
49
|
+
### Step 4: 录回工作流(闭环)
|
|
50
|
+
|
|
51
|
+
设计师精修完,在 QoderWork 里说:
|
|
52
|
+
|
|
53
|
+
> "录入设计稿"
|
|
54
|
+
|
|
55
|
+
工作流把 Figma 最终稿的关键决策(布局/配色/组件)录成 `data/style/{需求名}-design-spec.json`。
|
|
56
|
+
|
|
57
|
+
从此:
|
|
58
|
+
- 下次同需求出原型,工作流**优先用这份 spec**
|
|
59
|
+
- 前端拿到的 HTML 原型**匹配设计师的 Figma 终稿**
|
|
60
|
+
- 设计师的劳动成果**沉淀进知识图谱**,不浪费
|
|
61
|
+
|
|
62
|
+
## 常见问题
|
|
63
|
+
|
|
64
|
+
**Q: 导入后图层太碎怎么办?**
|
|
65
|
+
A: html.to.design 会按 HTML DOM 结构生成图层。fill_prototype 出的 HTML 结构已经很干净(侧边栏/搜索栏/表格各自独立),不会太碎。如果某个区域图层太多,选中后用 Figma 的 "Flatten" 合并。
|
|
66
|
+
|
|
67
|
+
**Q: 表格数据是假的怎么办?**
|
|
68
|
+
A: 对的,原型里的表格行是示例数据("XX示例1")。这是故意的——原型验证的是布局和交互,不是数据。真实数据前端会从 API 取。
|
|
69
|
+
|
|
70
|
+
**Q: 图标导入后变位图了?**
|
|
71
|
+
A: 不会。工作流用的图标是内联 SVG(不是图片标签),html.to.design 会保留为矢量。如果个别图标显示异常,从 `data/index/ref-icon.json` 找原始 SVG 手动替换。
|
|
72
|
+
|
|
73
|
+
**Q: APP 端原型也能导入吗?**
|
|
74
|
+
A: 能。`prototype-{需求名}-app.html` 同样是标准 HTML,导入方式一样。APP 原型用的是 Vant 风格(移动端组件库)。
|
|
75
|
+
|
|
76
|
+
## html.to.design 插件安装
|
|
77
|
+
|
|
78
|
+
- Figma Community 搜索:`html.to.design`
|
|
79
|
+
- 或直接访问:https://www.figma.com/community/plugin/1159123024924461424
|
|
80
|
+
- 免费版每次导入有限制,团队版无限
|
|
81
|
+
- 也有 Chrome 扩展版(适合截取在线页面)
|
|
@@ -32,21 +32,21 @@ Generate production-ready HTML prototypes that match the project's actual UI sty
|
|
|
32
32
|
- 若 `.qoder/.current-task` 存在,原型命名带上任务关键词
|
|
33
33
|
- 平台(Web/APP/Both)必须明确;如未指定,先问用户(见 prd-generator Step 0)
|
|
34
34
|
|
|
35
|
-
## ⚠️ 前置门: 用户是否选了"画原型"?(v3.1 新增)
|
|
36
|
-
|
|
37
|
-
本 skill **只在用户明确选择"画原型"后才进入**。
|
|
38
|
-
|
|
39
|
-
- 如果上游 `/wl-prd-full` 或 `/wl-prd` 在「批量确认」环节已决定**不画**(PRD 第 1 行
|
|
40
|
-
`@contract` 头标记 `prototype: none`),**立即退出本 skill**,不生成任何 HTML。
|
|
41
|
-
- 如果上游没有 contract 头(独立调用本 skill),**先问用户**:
|
|
42
|
-
`这个需求要画原型吗?(画 / 不画)`
|
|
43
|
-
用户答"不画"→ 退出;用户答"画"→ 继续。
|
|
44
|
-
- **绝不擅自决定画/不画**。决策权在用户,本 skill 只执行。
|
|
45
|
-
|
|
46
|
-
> 这条门治"AI 默默画了个塑料骨架"的反模式——比如"出交车点检固定为总部全局规则"
|
|
47
|
-
> 这种纯规则下发型需求,AI 不该自己往里塞一个配置页原型。
|
|
48
|
-
|
|
49
|
-
---
|
|
35
|
+
## ⚠️ 前置门: 用户是否选了"画原型"?(v3.1 新增)
|
|
36
|
+
|
|
37
|
+
本 skill **只在用户明确选择"画原型"后才进入**。
|
|
38
|
+
|
|
39
|
+
- 如果上游 `/wl-prd-full` 或 `/wl-prd` 在「批量确认」环节已决定**不画**(PRD 第 1 行
|
|
40
|
+
`@contract` 头标记 `prototype: none`),**立即退出本 skill**,不生成任何 HTML。
|
|
41
|
+
- 如果上游没有 contract 头(独立调用本 skill),**先问用户**:
|
|
42
|
+
`这个需求要画原型吗?(画 / 不画)`
|
|
43
|
+
用户答"不画"→ 退出;用户答"画"→ 继续。
|
|
44
|
+
- **绝不擅自决定画/不画**。决策权在用户,本 skill 只执行。
|
|
45
|
+
|
|
46
|
+
> 这条门治"AI 默默画了个塑料骨架"的反模式——比如"出交车点检固定为总部全局规则"
|
|
47
|
+
> 这种纯规则下发型需求,AI 不该自己往里塞一个配置页原型。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
50
|
## Step 0: Know the Platform
|
|
51
51
|
|
|
52
52
|
The platform MUST already be decided (asked by /wl-prd-full Step 0).
|
|
@@ -229,12 +229,12 @@ Key design tokens already in the templates (do not override):
|
|
|
229
229
|
|
|
230
230
|
## ⚠️ Icons: NEVER emoji, ALWAYS the project's real icon system
|
|
231
231
|
|
|
232
|
-
Source of truth: **data/index/icon
|
|
232
|
+
Source of truth: **data/index/ref-icon.json** (real usage counts +
|
|
233
233
|
ready-to-paste SVGs extracted from the actual projects).
|
|
234
234
|
|
|
235
|
-
- **Web (fywl-ui)**: Ant Design icons. Inline the SVG from icon
|
|
235
|
+
- **Web (fywl-ui)**: Ant Design icons. Inline the SVG from ref-icon.json:
|
|
236
236
|
```html
|
|
237
|
-
<span class="anticon">{svg from icon
|
|
237
|
+
<span class="anticon">{svg from ref-icon.json web.svg.outlined[...]}</span>
|
|
238
238
|
<style>.anticon svg{width:1em;height:1em;fill:currentColor}</style>
|
|
239
239
|
```
|
|
240
240
|
Most-used in the real app: Download(303x), Plus(171x), Delete, Search, Edit...
|
|
@@ -260,31 +260,31 @@ ready-to-paste SVGs extracted from the actual projects).
|
|
|
260
260
|
4. ICS 的菜单来自后端接口(`access_mode: backend`),静态代码里抓不到完整菜单树,
|
|
261
261
|
所以菜单层级**必须由需求/PRD 提供**,不要去代码里找。
|
|
262
262
|
|
|
263
|
-
## 🔒 Step 3.5: 来源锚定 + UTF-8(硬门 #3,eval A2 检查)
|
|
264
|
-
|
|
265
|
-
### 来源锚定(必做)
|
|
266
|
-
|
|
267
|
-
生成的 HTML 必须在 `<head>` 里写一行注释,标注样式来源的真实文件:
|
|
268
|
-
|
|
269
|
-
```html
|
|
270
|
-
<!-- @prototype-source: fywl-ui/apps/ics/src/views/xxx/index.vue, fywl-ui/apps/ics/src/api/xxx.ts -->
|
|
271
|
-
<meta name="x-source-pages" content="fywl-ui/.../index.vue">
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
- 来源文件**必须来自 Step 2 读过的真实 Vue/TS 文件**(prefetch 返回的 page_examples)
|
|
275
|
-
- 写不出具体文件名 = 你没做 Step 2 = 违规
|
|
276
|
-
- eval A2 会检查:HTML 含 `@prototype-source:` 或 `x-source-pages` → 通过;否则 A2 扣 5 分
|
|
277
|
-
|
|
278
|
-
### UTF-8 强制(治编码乱码)
|
|
279
|
-
|
|
280
|
-
生成的 HTML **必须用 UTF-8 写入**,否则中文 `<title>`/注释会变成 `鍑轰氦杞?` 乱码。
|
|
281
|
-
|
|
282
|
-
- Write 工具调用时,内容里的中文必须是原始 UTF-8(不要从 GBK 源复制)
|
|
283
|
-
- 如果用 Python 写文件:`open(path, 'w', encoding='utf-8')`
|
|
284
|
-
- **绝不要从 bash 输出里复制中文再粘贴**(bash 在 Windows 上可能转 GBK)→ 优先让
|
|
285
|
-
`fill_prototype` 脚本直接出文件,AI 只 Edit 占位符
|
|
286
|
-
|
|
287
|
-
---
|
|
263
|
+
## 🔒 Step 3.5: 来源锚定 + UTF-8(硬门 #3,eval A2 检查)
|
|
264
|
+
|
|
265
|
+
### 来源锚定(必做)
|
|
266
|
+
|
|
267
|
+
生成的 HTML 必须在 `<head>` 里写一行注释,标注样式来源的真实文件:
|
|
268
|
+
|
|
269
|
+
```html
|
|
270
|
+
<!-- @prototype-source: fywl-ui/apps/ics/src/views/xxx/index.vue, fywl-ui/apps/ics/src/api/xxx.ts -->
|
|
271
|
+
<meta name="x-source-pages" content="fywl-ui/.../index.vue">
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
- 来源文件**必须来自 Step 2 读过的真实 Vue/TS 文件**(prefetch 返回的 page_examples)
|
|
275
|
+
- 写不出具体文件名 = 你没做 Step 2 = 违规
|
|
276
|
+
- eval A2 会检查:HTML 含 `@prototype-source:` 或 `x-source-pages` → 通过;否则 A2 扣 5 分
|
|
277
|
+
|
|
278
|
+
### UTF-8 强制(治编码乱码)
|
|
279
|
+
|
|
280
|
+
生成的 HTML **必须用 UTF-8 写入**,否则中文 `<title>`/注释会变成 `鍑轰氦杞?` 乱码。
|
|
281
|
+
|
|
282
|
+
- Write 工具调用时,内容里的中文必须是原始 UTF-8(不要从 GBK 源复制)
|
|
283
|
+
- 如果用 Python 写文件:`open(path, 'w', encoding='utf-8')`
|
|
284
|
+
- **绝不要从 bash 输出里复制中文再粘贴**(bash 在 Windows 上可能转 GBK)→ 优先让
|
|
285
|
+
`fill_prototype` 脚本直接出文件,AI 只 Edit 占位符
|
|
286
|
+
|
|
287
|
+
---
|
|
288
288
|
## Step 4: Highlight Changes + Interactivity
|
|
289
289
|
|
|
290
290
|
- Mark NEW/CHANGED elements with the template's `highlight-new` class
|
|
@@ -37,7 +37,19 @@ git status && git diff HEAD --stat
|
|
|
37
37
|
|
|
38
38
|
### Step 2: 质量门禁(提交前自检)
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
**2a. 程序级强制门禁(syncgate)—— 先 git add 再跑**
|
|
41
|
+
```bash
|
|
42
|
+
# 1. 精确 add (不用 git add .)
|
|
43
|
+
git add <相关文件>
|
|
44
|
+
# 2. 对暂存文件跑零信任门禁 (身份/作者/秘密扫描/REQ-ID)
|
|
45
|
+
python -c "import sys; sys.path.insert(0, r'$R/.qoder/scripts'); from domain.task.syncgate import run_gates; from foundation.core.paths import get_developer, get_repo_root; import subprocess; staged=subprocess.check_output(['git','diff','--cached','--name-only'],cwd=r'$R',text=True).split(); ok,reason=run_gates(staged, get_developer(), str(get_repo_root())); print('GATE_PASS' if ok else ('GATE_FAIL: '+reason)); sys.exit(0 if ok else 2)"
|
|
46
|
+
```
|
|
47
|
+
- `GATE_PASS` → 继续 2b
|
|
48
|
+
- `GATE_FAIL: <原因>` → 停下,把原因告诉用户(如"检出疑似密钥 .env"),问修复还是强制。默认修复。
|
|
49
|
+
(这与 team_sync.py push 走的是同一道 syncgate,源码提交也不绕过零信任门禁。)
|
|
50
|
+
|
|
51
|
+
**2b. 人工自检(grep 类)**
|
|
52
|
+
逐项检查:
|
|
41
53
|
- [ ] 无 TODO / FIXME 残留(grep 一下)
|
|
42
54
|
- [ ] 金额字段用了 BigDecimal(不出现 double/float 存钱)
|
|
43
55
|
- [ ] 命名/风格跟周围代码一致
|
|
@@ -60,8 +72,8 @@ type 选 feat / fix / refactor / docs / test / chore。
|
|
|
60
72
|
**用户没明确说"提交/确认"之前,不要真的 commit。**
|
|
61
73
|
|
|
62
74
|
### Step 5: 提交 + 推送
|
|
75
|
+
(文件已在 Step 2a git add 过,门禁已过)
|
|
63
76
|
```bash
|
|
64
|
-
git add <相关文件> # 精确 add,不用 git add .
|
|
65
77
|
git commit -m "<确认后的信息>"
|
|
66
78
|
git pull --rebase # 先拉远端
|
|
67
79
|
git push
|