初始化项目版本
This commit is contained in:
29
.cursor/hooks.json
Normal file
29
.cursor/hooks.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"version": 1,
|
||||
"hooks": {
|
||||
"sessionStart": [
|
||||
{
|
||||
"command": "python3 .cursor/hooks/token_budget_session.py",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
"beforeSubmitPrompt": [
|
||||
{
|
||||
"command": "python3 .cursor/hooks/token_budget_prompt.py",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
"afterAgentResponse": [
|
||||
{
|
||||
"command": "python3 .cursor/hooks/token_budget_turn.py",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
"subagentStart": [
|
||||
{
|
||||
"command": "python3 .cursor/hooks/token_budget_subagent.py",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
116
.cursor/hooks/token_budget_prompt.py
Executable file
116
.cursor/hooks/token_budget_prompt.py
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""beforeSubmitPrompt: soft-block once for expensive/long-session patterns."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
STATE_DIR = Path(__file__).resolve().parent / "state"
|
||||
LONG_TURN_THRESHOLD = 15
|
||||
|
||||
EXPENSIVE_RE = re.compile(
|
||||
r"(全仓|全部文件|先全局|扫一遍仓库|多开几个\s*agent|并行探索|best[-\s]?of[-\s]?n|同时开\d+个)",
|
||||
re.I,
|
||||
)
|
||||
ALLOW_LONG_RE = re.compile(r"继续本会话")
|
||||
ALLOW_EXPENSIVE_RE = re.compile(r"确认高耗")
|
||||
|
||||
|
||||
def load_state(session_id: str) -> tuple[Path, dict]:
|
||||
STATE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
path = STATE_DIR / f"session-{session_id}.json"
|
||||
state = {
|
||||
"session_id": session_id,
|
||||
"turns": 0,
|
||||
"warned_long": False,
|
||||
"warned_expensive": False,
|
||||
}
|
||||
if path.exists():
|
||||
try:
|
||||
state.update(json.loads(path.read_text(encoding="utf-8")))
|
||||
except Exception:
|
||||
pass
|
||||
return path, state
|
||||
|
||||
|
||||
def save_state(path: Path, state: dict) -> None:
|
||||
path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
raw = sys.stdin.read().strip()
|
||||
payload = json.loads(raw) if raw else {}
|
||||
prompt = str(payload.get("prompt") or "")
|
||||
session_id = (
|
||||
os.environ.get("ONEOS_TOKEN_BUDGET_SESSION")
|
||||
or payload.get("conversation_id")
|
||||
or payload.get("session_id")
|
||||
)
|
||||
if not session_id:
|
||||
latest = STATE_DIR / "latest-session.json"
|
||||
if latest.exists():
|
||||
try:
|
||||
session_id = json.loads(latest.read_text(encoding="utf-8")).get("session_id")
|
||||
except Exception:
|
||||
session_id = None
|
||||
session_id = session_id or "unknown"
|
||||
path, state = load_state(str(session_id))
|
||||
turns = int(state.get("turns") or 0)
|
||||
|
||||
# Long session soft gate (once unless user confirms)
|
||||
if (
|
||||
turns >= LONG_TURN_THRESHOLD
|
||||
and not state.get("warned_long")
|
||||
and not ALLOW_LONG_RE.search(prompt)
|
||||
):
|
||||
state["warned_long"] = True
|
||||
save_state(path, state)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"continue": False,
|
||||
"user_message": (
|
||||
f"省用量提醒:本会话已约 {turns} 轮,继续长聊会明显烧 token。\n"
|
||||
"建议:复制当前进度摘要 → 新开聊天继续。\n"
|
||||
"若必须继续本会话,请在消息里加上「继续本会话」后再发送。"
|
||||
),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
# Expensive intent soft gate (once unless user confirms)
|
||||
if (
|
||||
EXPENSIVE_RE.search(prompt)
|
||||
and not state.get("warned_expensive")
|
||||
and not ALLOW_EXPENSIVE_RE.search(prompt)
|
||||
):
|
||||
state["warned_expensive"] = True
|
||||
save_state(path, state)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"continue": False,
|
||||
"user_message": (
|
||||
"省用量提醒:这句话容易触发全仓扫描 / 并行多 Agent,费用很高。\n"
|
||||
"更省的写法:点名文件/目录,或拆成短会话。\n"
|
||||
"若确认就要高耗执行,请在消息里加上「确认高耗」后再发送。"
|
||||
),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
print(json.dumps({"continue": True}))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception:
|
||||
print(json.dumps({"continue": True}))
|
||||
54
.cursor/hooks/token_budget_session.py
Executable file
54
.cursor/hooks/token_budget_session.py
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""sessionStart: inject token-budget context and init turn counter."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
STATE_DIR = Path(__file__).resolve().parent / "state"
|
||||
CONTEXT = """[Token Budget · auto]
|
||||
省用量模式已开启:
|
||||
1) 默认短会话、窄检索,禁止无必要全仓扫描
|
||||
2) 日常任务用 Auto/Composer;不要主动升到 High/Grok High
|
||||
3) 禁止默认并行多 Agent / Best-of-N
|
||||
4) 长会话收口后建议用户新开聊天,先给摘要
|
||||
用户说「确认高耗」或「继续本会话」时可放宽。"""
|
||||
|
||||
|
||||
def main() -> None:
|
||||
raw = sys.stdin.read().strip()
|
||||
payload = json.loads(raw) if raw else {}
|
||||
session_id = payload.get("session_id") or payload.get("conversation_id") or "unknown"
|
||||
STATE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
state = {
|
||||
"session_id": session_id,
|
||||
"turns": 0,
|
||||
"warned_long": False,
|
||||
"warned_expensive": False,
|
||||
}
|
||||
state_path = STATE_DIR / f"session-{session_id}.json"
|
||||
state_path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
(STATE_DIR / "latest-session.json").write_text(
|
||||
json.dumps({"session_id": session_id}, ensure_ascii=False),
|
||||
encoding="utf-8",
|
||||
)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"env": {
|
||||
"ONEOS_TOKEN_BUDGET": "1",
|
||||
"ONEOS_TOKEN_BUDGET_SESSION": str(session_id),
|
||||
},
|
||||
"additional_context": CONTEXT,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception:
|
||||
print("{}")
|
||||
39
.cursor/hooks/token_budget_subagent.py
Executable file
39
.cursor/hooks/token_budget_subagent.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
"""subagentStart: block default parallel / best-of-n workers to save tokens."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def main() -> None:
|
||||
raw = sys.stdin.read().strip()
|
||||
payload = json.loads(raw) if raw else {}
|
||||
subagent_type = str(payload.get("subagent_type") or "")
|
||||
is_parallel = bool(payload.get("is_parallel_worker"))
|
||||
task = str(payload.get("task") or "")
|
||||
allow_high = "确认高耗" in task
|
||||
|
||||
if (subagent_type == "best-of-n-runner" or is_parallel) and not allow_high:
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"permission": "deny",
|
||||
"user_message": (
|
||||
"已自动拦截并行/Best-of-N 子代理(省用量)。"
|
||||
"如确需并行,请在需求里写明「确认高耗」。"
|
||||
),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
print(json.dumps({"permission": "allow"}))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception:
|
||||
print(json.dumps({"permission": "allow"}))
|
||||
42
.cursor/hooks/token_budget_turn.py
Executable file
42
.cursor/hooks/token_budget_turn.py
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
"""afterAgentResponse: count turns for long-session guard."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
STATE_DIR = Path(__file__).resolve().parent / "state"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
# Drain stdin even if unused
|
||||
sys.stdin.read()
|
||||
session_id = os.environ.get("ONEOS_TOKEN_BUDGET_SESSION")
|
||||
if not session_id:
|
||||
latest = STATE_DIR / "latest-session.json"
|
||||
if latest.exists():
|
||||
try:
|
||||
session_id = json.loads(latest.read_text(encoding="utf-8")).get("session_id")
|
||||
except Exception:
|
||||
session_id = None
|
||||
session_id = session_id or "unknown"
|
||||
STATE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
path = STATE_DIR / f"session-{session_id}.json"
|
||||
state = {"session_id": session_id, "turns": 0, "warned_long": False, "warned_expensive": False}
|
||||
if path.exists():
|
||||
try:
|
||||
state.update(json.loads(path.read_text(encoding="utf-8")))
|
||||
except Exception:
|
||||
pass
|
||||
state["turns"] = int(state.get("turns") or 0) + 1
|
||||
path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
print("{}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception:
|
||||
print("{}")
|
||||
28
.cursor/rules/one-prototype-one-sidebar.mdc
Normal file
28
.cursor/rules/one-prototype-one-sidebar.mdc
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
description: 一个原型只对应侧栏一项;默认单页内切换,禁止默认拆列表/详情下级页
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# 原型侧栏:一原型一项(强制偏好)
|
||||
|
||||
产品偏好:**一个原型目录 = Make 侧栏一个入口**,不在侧栏下再挂「列表 / 详情 / 新建」等下级页。
|
||||
|
||||
## 默认做法
|
||||
|
||||
- 列表、看板、主从、详情、弹窗、抽屉等,一律在**同一页内用状态切换**模拟(参考 `lease-contract-management`、已收拢的 `vehicle-management`)。
|
||||
- **不要**默认使用 `defineHashPageRoute` / `useHashPage` 拆出多个 `#page=`,以免侧栏出现套娃文件夹。
|
||||
- `annotation-source.json` 的 `directory` **不要**为同一原型挂多个 `type: "route"` 的 list/detail 下级项;说明文档用 markdown 节点即可。
|
||||
|
||||
## 何时才允许多页面 hash
|
||||
|
||||
仅当用户**明确要求**以下任一情形时再拆 `#page=`:
|
||||
|
||||
- 需要侧栏直达某一独立流程页(如独立「新建合同」且用户要单独入口)
|
||||
- 需要可分享的固定 URL(`#page=xxx`)做验收/外发
|
||||
- 用户书面指定「要下级页面」
|
||||
|
||||
## 新建 / 改造检查
|
||||
|
||||
- [ ] 侧栏预览为单项,无「××列表 / ××详情」子树
|
||||
- [ ] 详情/编辑通过页内面板、主从或同页替换打开,返回不离开本原型
|
||||
- [ ] 未新增无必要的 `defineHashPageRoute([...多个 page])`
|
||||
95
.cursor/rules/oneos-v2-design-system.mdc
Normal file
95
.cursor/rules/oneos-v2-design-system.mdc
Normal file
@@ -0,0 +1,95 @@
|
||||
---
|
||||
description: OneOS V2 全局定版设计规范(Stripe Violet 紫光高规 + 3视角架构 + PC/H5 移动端 100% 响应式 + 全量 UI 控件库 + 若依动态主题色 + 车牌号无点标准)
|
||||
globs: src/prototypes/oneos-v2/**/*, src/prototypes/lease-contract-management/**/*, src/resources/design-system/**/*, src/prototypes/**/*
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# OneOS V2 全局定版设计规范(Cursor Agent 强制执行规则)
|
||||
|
||||
> **【硬性准则】**:在 `OneOS V2` 目录下**生成新页面、修改或迁移任何原型页面**时,AI Agent **必须首先 Read** 并严格遵守 `src/resources/design-system/DESIGN.md` 或 `src/prototypes/oneos-v2/DESIGN.md`!
|
||||
|
||||
---
|
||||
|
||||
## 0. 新页面生成与修改工作流 (Mandatory Workflow)
|
||||
|
||||
1. **强前置步骤**:在创建或修改 `OneOS V2` 下的任何页面前,必须读取 `src/resources/design-system/DESIGN.md`,确认最新的 Token、UI 控件用法、3 视图模板和响应式规范。
|
||||
2. **禁止使用原生 HTML 控件**:严禁直接使用原生 `<select>`、`<input type="date">` 或未经过 V2 封装的第三方组件。必须统一导入并使用 `UIComponents.tsx` 导出的封装控件:
|
||||
- `V2Button`(主/次/描边/幽灵/危险/返回;详见 `DESIGN.md` §3.0)
|
||||
- `V2Select`
|
||||
- `V2DatePicker`
|
||||
- `V2DateRangePicker`
|
||||
- `V2SingleInputDateRangePicker`(单输入框双日历,默认推荐)
|
||||
- `V2TimePicker`
|
||||
- `V2SingleInputTimeRangePicker`(单输入框双时间)
|
||||
- `V2RadioGroup`
|
||||
- `V2CheckboxGroup`
|
||||
- `V2Switch`
|
||||
- `V2Steps`
|
||||
- `V2Timeline`
|
||||
- `V2ApprovalProgress`(默认 `direction="vertical"` 垂直贯穿时间轴)
|
||||
- `V2Pagination`(统一分页控制器)
|
||||
- `V2Empty`(空状态与异常页组件)
|
||||
- `V2SegmentedControl`(顶栏视图/模式分段切换控件)
|
||||
- `V2StatusTabs`(分类/状态过滤页签条)
|
||||
- `V2ImageUpload`(图片拖拽/新增上传 · Web Dropzone + H5 拍照/相册;详见 `DESIGN.md` §3.17)
|
||||
- `V2MobileHeader`
|
||||
- `V2MobileBottomNav`
|
||||
- `V2MobileActionBar`
|
||||
|
||||
2b. **按钮硬门禁(吸底栏 / 页头 / 弹窗脚)**:
|
||||
- **禁止**页面内自写 `ActionButton`、`className="…-btn-*"`、或手写 `border/background` 的 `<button>` 冒充主次按钮。
|
||||
- 详情吸底、表单页头、弹窗 footer **必须**用 `V2Button`;变体只从 `primary | secondary | outline | ghost | danger | back | link` 中选。
|
||||
- **现网/Ant 映射**:`primary`→`primary`;默认描边次按钮→`secondary`;主色描边→`outline`;幽灵/取消→`ghost`;危险实心→`danger`;危险描边(如现网 `ghost + danger` 终止)→`secondary` + `style={{ color/borderColor: var(--ln-error) }}`,**禁止**再造一套 CSS 变体。
|
||||
- 交付前自检:操作区源码能否 `grep` 到 `V2Button`;若出现自制 `*-action-btn*` 样式类,视为未达标。
|
||||
3. **母版参考**:
|
||||
- **台账三视角**:`src/prototypes/lease-contract-management/LeaseContractHub.tsx`(13 项高阶筛选、3 视图、嵌套车辆子表)。
|
||||
- **表单页二选一(强制声明 `layout: sidebar | fullBleed`)**:
|
||||
- **A · 侧栏工作台**:`src/prototypes/lease-contract-redesign/FaultDispositionForm.tsx`(左主表单三段卡 + 右 340px 指派/SLA;`DESIGN.md` §4.8)。
|
||||
- **B · 横向整屏(B1)**:无右栏 340;主区 `width: 100%` + PC 水平边距 20–24px(非贴边);`DESIGN.md` §4.9。有右栏业务用 A,无右栏需横向空间用 B;同一页禁止混用。
|
||||
4. **筛选查询收起(强制)**:台账筛选栏 /「更多筛选」展开后,点击 **查询** 必须应用条件并**自动收起**筛选栏(H5 为关闭 Bottom Sheet);**重置**清空后同样收起。详见 `DESIGN.md` §2.4.3。
|
||||
5. **列表操作列(强制)**:常用「编辑 / 处理(处置)」**外侧**展示(最多 2 个);低频「查看记录 / 操作记录 / 历史」及危险操作收入 **⋮ 更多**。统一使用 `OperationActions`(`DESIGN.md` §3.16 / `vm-shared/DESIGN.md`)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 核心视觉与配色规范 (Stripe Fintech UI)
|
||||
|
||||
- **主色 (Primary Accent)**:Stripe Violet `#533AFD`(悬停 `#6346FF`,Focus 环 `#4226E8`,浅亮底 `#E0E7FF`,暗亮底 `rgba(83, 58, 253, 0.18)`)
|
||||
- **画布背景**:浅色 `#F6F9FC` / 深色 `#0A0B0D`
|
||||
- **卡片容器**:浅色 `#FFFFFF` / 深色 `#121418`
|
||||
- **边框线**:浅色 `#E3E8EE` / 深色 `#23272F`
|
||||
- **主正文**:浅色 `#0A2540` / 深色 `#F7FAFC`
|
||||
- **次要正文**:浅色 `#425466` / 深色 `#A0AEC0`
|
||||
- **语义色**:成功 `#10B981` · 预警 `#D97706` · 危险/错误 `#EF4444` · 提示 `#3B82F6`
|
||||
- **若依 (RuoYi) 框架动态主题色**:所有组件背景、边框、选中态必须消费 CSS 变量 `var(--oneos-primary, var(--ln-primary, #533AFD))`,兼容若依的主题色动态切换。
|
||||
- **双色模式**:通过 `[data-ds-mode="dark"]` 或 `[data-oneos-theme="dark"]` 响应,严禁出现外壳深内容浅的失配情况。
|
||||
- **车牌号规范**:车牌号严禁出现间隔点 `·`(必须形如 `浙A88888F`、`京A66666`)。
|
||||
|
||||
---
|
||||
|
||||
## 2. PC / H5 移动端 App 嵌入 100% 响应式 (Mobile H5 Standard)
|
||||
|
||||
- **双形态适配**:所有 V2 原型必须支持 PC 屏宽 (≥1024px) 与 H5 移动端 (≤767px) 形态。
|
||||
- **触控规格**:移动端 (≤767px) 场景下,所有可点击元素与输入框触控高度必须 **`≥ 44px`**(`min-height: 44px`),正文字号 **`≥ 14px`**。
|
||||
- **Mobile Bottom Sheet**:移动端下 `V2Select`、`V2DatePicker` 等弹窗自动转为固定吸底 **Bottom Sheet 面板**,配有顶部抓手条与 44px 确定按钮。
|
||||
- **移动端底部操作条**:提交与主操作按钮在移动端自动固定吸底(`V2MobileActionBar`)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 统一的三视角页面架构 (Three Core Views)
|
||||
|
||||
任何台账、列表、审批与履约管理页面必须提供或集成 3 视角模板(`V2SegmentedControl`):
|
||||
1. **列表模式 (List View)**:Bento KPI + Pill Tabs(带 count)+ 高阶筛选(查询/重置后自动收起)+ **可含主表+嵌套子表**(合同/项目主行 + 车辆期账单等子行;见 `DESIGN.md` §5.0 / §5.1)。**禁止**把嵌套子表叫成「主从工作台」。
|
||||
2. **看板模式 (Kanban View)**:通常 4 列 Pipeline(列名按业务域定制,如账单:待收款/部分/逾期/已结清)。
|
||||
3. **主从工作台 (Split)**:左侧 320–340px 搜索单据列表 + 右侧深度工作台。
|
||||
|
||||
单单据填报页(非台账三视角)须按 `DESIGN.md` §4.9 二选一:**A 侧栏** 或 **B 横向整屏 B1**,生成前声明 `layout`。
|
||||
|
||||
---
|
||||
|
||||
## 4. 规范参考文件路径
|
||||
|
||||
- 全局主规范文档:`src/resources/design-system/DESIGN.md`
|
||||
- 规范展示页:`src/prototypes/oneos-v2/DesignSystemShowcase.tsx`
|
||||
- 组件库文件:`src/resources/design-system/components/UIComponents.tsx`
|
||||
- 全局 Token CSS:`src/resources/design-system/oneos-ds-tokens.css`
|
||||
- 若依预设导出:`src/resources/design-system/ruoyi-theme-preset.json` & `ruoyi-oneos-v2-theme.css`
|
||||
46
.cursor/rules/oneos-v2-detail-form-header.mdc
Normal file
46
.cursor/rules/oneos-v2-detail-form-header.mdc
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
description: OneOS V2 详情/表单页头强制对齐(禁止自建白卡片顶栏)
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# OneOS V2 · 详情 / 表单页头(强制)
|
||||
|
||||
凡**离开台账进入全页**(查看详情、处置/填报、档案工作台等),页头必须对齐已定版母版,**禁止**再发明「白底描边整条卡片顶栏」。
|
||||
|
||||
## 必须对齐的母版
|
||||
|
||||
| 场景 | 对照 |
|
||||
|------|------|
|
||||
| 结构化工单 / 处置填报 | `DESIGN.md` **§4.8** + `lease-contract-redesign/FaultDispositionForm.tsx` |
|
||||
| 档案 / 只读详情全页 | `vehicle-management` 的 `va-form-header`(`DetailView.tsx`) |
|
||||
| 合同详情 | `LeaseContractView` 顶栏至少含「返回列表」 |
|
||||
|
||||
## 页头强制结构(PC)
|
||||
|
||||
```text
|
||||
[← 返回…] | 页面标题(20px / font-weight 800) · 单号紫色胶囊(若有) [次操作] [主 CTA]
|
||||
```
|
||||
|
||||
硬性要求:
|
||||
|
||||
1. **扁平页头行**:返回 + 竖分割线 + 文案区 + 右侧操作;**不要**再包一层 `border + border-radius + 白底卡片` 当顶栏容器。
|
||||
2. **返回**:描边/次按钮,文案如「返回列表 / 返回台账」。
|
||||
3. **不展示面包屑**:页头**不要**再挂「条线 / 模块」路径文案(外壳顶栏标签页已承担切换/定位,再挂易重复)。
|
||||
4. **单号**:有单据号时用主色浅底**紫色胶囊**(等宽/monospace),放在标题旁;不要把单号当普通灰字塞进标题。
|
||||
5. **标题**:业务页名(如「新增工单」「故障处置详情」),**不要**把车牌/主键顶成唯一大标题替代页名(主键可放在下方上下文卡)。
|
||||
6. **状态标签**:任务态 / 解决情况 / 临期逾期等放在**上下文卡**,不要和页头标题挤成一行装饰条。
|
||||
7. **表单页右侧**:至少「暂存/保存」描边 +「提交/归档」主色 CTA(§4.8)。
|
||||
|
||||
## 明确禁止
|
||||
|
||||
- 自绘「返回 + 车牌大字 + 副文案 + 状态 Tag」白卡片顶栏(故障页曾出现的错误形态)
|
||||
- 用台账三视角 `V2SegmentedControl` 顶栏冒充详情/表单页头
|
||||
- 详情/表单全页默认改回抽屉(用户明确要求抽屉除外)
|
||||
- 页头重复展示与外壳标签页同义的面包屑路径
|
||||
|
||||
## 新建 / 改造检查
|
||||
|
||||
- [ ] 已对照 §4.8 或 `va-form-header`,而非临摹错误旧页
|
||||
- [ ] 页头无整条白卡片外壳
|
||||
- [ ] 有返回、20px 标题;有单号则紫胶囊;**无**条线/模块面包屑
|
||||
- [ ] 状态 Tag 在内容卡,不在页头主标题行
|
||||
55
.cursor/rules/oneos-v2-prototype-visual-align.mdc
Normal file
55
.cursor/rules/oneos-v2-prototype-visual-align.mdc
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
description: 新建/迁移/改版 OneOS V2 原型时,必须对照设计规范与标杆页做视觉审计并对齐,禁止自创顶栏/筛选/表格样式
|
||||
globs: src/prototypes/**/*
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# OneOS V2 原型视觉对齐(强制)
|
||||
|
||||
凡 **新建、迁移、改版** `src/prototypes/**` 台账/工作台类页面,在交付前必须完成「规范比对 → 不一致则改」循环,**不要等用户复述**。
|
||||
|
||||
## 0. 必读标杆(按优先级)
|
||||
|
||||
1. `src/resources/design-system/DESIGN.md`(Token、三视角、筛选网格、控件)
|
||||
2. **台账交互母版**:`src/prototypes/vehicle-management/`(Pill Tabs + 搜索 + 更多筛选 + 表格连体)
|
||||
3. **三视角母版**:`src/prototypes/lease-contract-management/LeaseContractHub.tsx`
|
||||
4. 控件:`src/resources/design-system/components/UIComponents.tsx`(`V2Select` / 日期 / `V2Empty` / `V2Pagination` / Badge·Tag)
|
||||
|
||||
独立 H5:对齐 `oneos-v2-h5-vehicle-assets` / `oneos-v2-h5-lease-contract`(手机壳 + 底栏 + Bottom Sheet),**不要**把 PC 标题卡片硬塞进 H5。
|
||||
|
||||
## 1. 交付前视觉审计清单(逐项打勾)
|
||||
|
||||
对照标杆截图或代码,检查本页是否一致:
|
||||
|
||||
| # | 检查项 | 合格标准 | 常见错误(必须改掉) |
|
||||
|---|---|---|---|
|
||||
| 1 | 台账顶栏 | 仅「三视角切换 + 主操作」,无大标题说明卡片 | 自创 icon+标题+副标题卡片条 |
|
||||
| 1b | 详情/表单页头 | §4.8 / `va-form-header`:扁平返回+20px 标题+单号紫胶囊(若有);**无**条线/模块面包屑 | 白底描边整条卡片顶栏;车牌当唯一大标题;状态 Tag 挤页头;页头再挂面包屑 |
|
||||
| 2 | KPI | 4 列 Bento,`18px 20px`,数字 24/800 tabular | 过重阴影、夸张 hover 抬升 |
|
||||
| 3 | 筛选工具条 | Pill Tabs(带 count)+ 搜索框 +「更多筛选」+ 查询/重置同排;PC 工具链 `nowrap`,搜索可缩(§2.4.3.1);更多筛选与 Tabs **去重** | 首屏永远露出整排 Filter Grid;「重置」掉到搜索框下一行;Tabs 状态再塞进更多筛选 |
|
||||
| 4 | 更多筛选 | 展开后 `auto-fill minmax(200px,1fr)`,gap `16px 12px`,`align-items: end`;用 `V2Select`/V2 日期 | 原生 select/date;标签不对齐 |
|
||||
| 5 | 台账连体 | 筛选面板与表格默认无缝拼接;展开筛选后表格下移并恢复圆角 | 两块独立卡片、双边框夹缝 |
|
||||
| 6 | 表格密度 | thead 12/600 pearl;td padding≈14–16;首列主标题 14/700 + mono 单号 | 列过多堆 Tag、行高混乱、操作链过密无层级 |
|
||||
| 7 | 状态表达 | `V2Badge` 用 `status`+`label`;`V2Tag` 用 `type`;SLA 用统一 pill | 错用 `variant="error"` 等旧 API |
|
||||
| 7b | **按钮 / 吸底栏** | 页头、吸底、弹窗脚一律 `V2Button`;次按钮可见描边(`secondary`/`ghost`/`outline`);危险次操作用 secondary + 红描边或弹窗内 `danger` | 自写 `ActionButton` / `*-action-btn*`;透明底导致无边框;手写紫/红 HEX |
|
||||
| 8 | Token | 主色 `var(--oneos-primary, var(--ln-primary, #533AFD))`;深浅双色 | 硬编码紫/灰导致若依主题失效 |
|
||||
| 9 | 车牌 | `浙A88888F`,禁止中间 `·` | 带点车牌 |
|
||||
| 10 | 空态/分页 | `V2Empty` + `V2Pagination` | 灰字空行、自制分页 |
|
||||
|
||||
## 2. 强制工作流
|
||||
|
||||
```text
|
||||
改/新建原型 → Read DESIGN.md → 打开车辆资产或租赁合同对照
|
||||
→ 按上表审计 → 不一致则改到一致 → 再预览 PC(及独立 H5)
|
||||
```
|
||||
|
||||
- **纯样式对齐**:可小步改 CSS/结构,不必扩写业务。
|
||||
- **涉及流程/文案/判定**:同期按 AutoPRD 规则更新 `.spec/requirements-prd.md` 与 annotation。
|
||||
- 侧栏仍遵守「一原型一项」,列表/详情同页切换。
|
||||
|
||||
## 3. 禁止
|
||||
|
||||
- 以「本页特殊」为由偏离台账连体与三视角骨架(除非用户书面指定)
|
||||
- 同时维护两套互相矛盾的筛选 UI(始终展开 + 更多筛选重复)
|
||||
- 在 PC 台账页塞 H5 专用顶栏/底栏(H5 用独立 `oneos-v2-h5-*` 原型)
|
||||
- **为「对齐现网文案」而自造按钮皮肤**:现网 Ant/若依按钮文案可对齐,视觉必须落在 `V2Button` 变体上;禁止复制现网 CSS 类名或手写一套 action-btn
|
||||
31
.cursor/rules/token-budget.mdc
Normal file
31
.cursor/rules/token-budget.mdc
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
description: OneOS 会话用量预算:短会话、窄检索、少并行、默认便宜模型
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Token 预算(强制偏好)
|
||||
|
||||
本仓库近期用量偏高。默认按「省用量」执行,除非用户明确要求高耗模式(如「确认高耗」「继续本会话」)。
|
||||
|
||||
## 会话
|
||||
|
||||
- 优先短会话、单任务;跨主题先总结再建议用户新开聊天。
|
||||
- 同一会话已多轮(约 ≥15 次有效往返)且任务可收口时:先给可复制摘要,再明确建议新开会话,不要无必要继续长聊。
|
||||
- 不要为了「顺便」扩大范围。
|
||||
|
||||
## 检索与阅读
|
||||
|
||||
- 禁止默认全仓扫描。先用路径/文件名定位,再读必要文件。
|
||||
- 已有 `.cursorignore`:勿主动翻二进制、截图包、`node_modules`、`.axhub/make`。
|
||||
- 需要图片/zip/pptx 时,等用户 `@` 精确路径再读。
|
||||
|
||||
## 模型与子代理
|
||||
|
||||
- 日常改原型/文案/样式:默认 Auto/Composer 即可,不要主动升级到 High/Grok High。
|
||||
- 禁止默认开启并行多 Agent / Best-of-N;仅当用户明确要求时再开。
|
||||
- 能单 Agent 完成的,不要拆多个 explore/generalPurpose。
|
||||
|
||||
## 回复
|
||||
|
||||
- 先做后说;少复述大段上下文。
|
||||
- 工具调用失败时先读错误再重试,避免盲目循环。
|
||||
Reference in New Issue
Block a user