feat: sync full workspace including web modules, docs, and configurations to Gitea

Optimized the root .gitignore to exclude virtual environments, node modules,
and temp folders to ensure clean and lightweight version tracking.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
王冕
2026-06-09 18:12:25 +08:00
parent 351688006e
commit a27e3b8e43
1510 changed files with 162044 additions and 1517 deletions

View File

@@ -0,0 +1,445 @@
# Axure API 指南
本文档说明如何在本项目原型中使用 Axure API 实现交互功能。
## 📌 什么是 Axure API
Axure API 是本项目提供的一套接口规范,用于实现组件与 Axure 原型之间的交互。通过 Axure API组件可以
- **触发事件**:向外部发送事件通知
- **接收动作**:响应外部调用的动作
- **暴露变量**:提供内部状态供外部读取
- **接收配置**:从配置面板接收用户配置
- **接收数据**:从外部数据源接收数据
## 🎯 何时使用 Axure API
**使用场景**
- 需要与 Axure 原型进行交互
- 需要在配置面板中提供可配置项
- 需要接收外部数据源
- 需要触发事件或响应动作
**不使用场景**
- 纯展示型组件
- 不需要与外部交互的独立组件
- 标准 React 组件即可满足需求
## 📋 Axure API 接口规范
### 组件定义
使用带显式参数类型的 `forwardRef(...)` 包装组件:
```typescript
import React, { forwardRef, useImperativeHandle } from 'react';
import type { AxureProps, AxureHandle } from '../../common/axure-types';
const Component = forwardRef(function MyComponent(
innerProps: AxureProps,
ref: React.ForwardedRef<AxureHandle>,
) {
// 组件实现
useImperativeHandle(ref, function () {
return {
getVar: function (name: string) { /* ... */ },
fireAction: function (name: string, params?: any) { /* ... */ },
eventList: EVENT_LIST,
actionList: ACTION_LIST,
varList: VAR_LIST,
configList: CONFIG_LIST,
dataList: DATA_LIST
};
}, [/* 依赖项 */]);
return <div>Component Content</div>;
});
export default Component;
```
### Props 处理
```typescript
// 安全解构 props 并提供默认值
const dataSource = innerProps && innerProps.data ? innerProps.data : {};
const configSource = innerProps && innerProps.config ? innerProps.config : {};
const onEventHandler = typeof innerProps.onEvent === 'function'
? innerProps.onEvent
: function () { return undefined; };
const container = innerProps && innerProps.container ? innerProps.container : null;
// 从 config 获取配置值(避免使用 || 运算符)
const title = typeof configSource.title === 'string' && configSource.title
? configSource.title
: '默认标题';
```
## 📝 API 常量定义
### 1. 事件列表EVENT_LIST
定义组件可以触发的事件:
```typescript
import type { EventItem } from '../../common/axure-types';
const EVENT_LIST: EventItem[] = [
{ name: 'onClick', desc: '点击按钮时触发' },
{ name: 'onChange', desc: '值改变时触发,传递新值' },
{ name: 'onSubmit', desc: '提交表单时触发,传递表单数据' }
];
```
**触发事件**
```typescript
import { useCallback } from 'react';
// ⚠️ 强制规则payload 必须是字符串类型
// 如果需要传递复杂数据,请使用 JSON.stringify() 序列化
const emitEvent = useCallback(function (eventName: string, payload?: string) {
try {
onEventHandler(eventName, payload);
} catch (error) {
console.warn('事件触发失败:', eventName, error);
}
}, [onEventHandler]);
// 使用示例:传递简单字符串
emitEvent('onClick', 'button_clicked');
// 使用示例:传递复杂数据(需要序列化)
emitEvent('onChange', JSON.stringify({ timestamp: Date.now(), value: 'new_value' }));
```
### 2. 动作列表ACTION_LIST
定义组件可以响应的动作:
```typescript
import type { Action } from '../../common/axure-types';
// ⚠️ 强制规则params 必须是字符串类型
// 如果需要传递复杂参数,请在 desc 中说明使用 JSON 格式
const ACTION_LIST: Action[] = [
{ name: 'reset', desc: '重置表单到初始状态' },
{ name: 'setValue', desc: '设置指定字段的值参数格式JSON 字符串 {"field":"字段名","value":"值"}', params: 'JSON string' },
{ name: 'submit', desc: '提交表单' }
];
```
**处理动作**
```typescript
// ⚠️ 强制规则params 必须是字符串类型
// 如果需要接收复杂参数,请使用 JSON.parse() 解析
const fireActionHandler = useCallback(function (name: string, params?: string) {
switch (name) {
case 'reset':
// 重置逻辑
setFormData({});
break;
case 'setValue':
// 解析 JSON 字符串参数
if (params) {
try {
const parsed = JSON.parse(params);
if (parsed.field) {
setFormData({ ...formData, [parsed.field]: parsed.value });
}
} catch (error) {
console.warn('参数解析失败:', error);
}
}
break;
case 'submit':
// 提交逻辑
handleSubmit();
break;
default:
console.warn('未知的动作:', name);
}
}, [formData]);
```
### 3. 变量列表VAR_LIST
定义组件暴露的内部状态:
```typescript
import type { KeyDesc } from '../../common/axure-types';
// ⚠️ name 必须使用小写 + 下划线snake_case详见 KeyDesc 说明
const VAR_LIST: KeyDesc[] = [
{ name: 'value', desc: '当前输入值(字符串)' },
{ name: 'is_valid', desc: '表单是否有效(布尔值)' },
{ name: 'error_message', desc: '错误信息(字符串)' }
];
```
**暴露变量**
```typescript
useImperativeHandle(ref, function () {
return {
getVar: function (name: string) {
const vars: Record<string, any> = {
value: inputValue,
isValid: isFormValid,
errorMessage: error
};
return vars[name];
},
// ... 其他接口
};
}, [inputValue, isFormValid, error]);
```
### 4. 配置项列表CONFIG_LIST
定义配置面板中的可配置项:
```typescript
import type { ConfigItem } from '../../common/axure-types';
const CONFIG_LIST: ConfigItem[] = [
{
type: 'input',
: 'title',
displayName: '标题',
info: '组件顶部显示的标题文本',
initialValue: '默认标题'
},
{
type: 'inputNumber',
attributeId: 'maxLength',
displayName: '最大长度',
info: '输入框允许的最大字符数',
initialValue: 100,
min: 1,
max: 1000
},
{
type: 'switch',
attributeId: 'disabled',
displayName: '禁用',
info: '是否禁用组件',
initialValue: false
}
];
```
**配置项类型**
- `input`:文本输入框
- `inputNumber`:数字输入框
- `switch`:开关
- `select`:下拉选择
- `color`:颜色选择器
- 更多类型参考 `/src/common/config-panel-types.ts`
### 5. 数据项列表DATA_LIST
定义组件接收的数据结构:
```typescript
import type { DataDesc } from '../../common/axure-types';
const DATA_LIST: DataDesc[] = [
{
name: 'users',
desc: '用户列表数据',
keys: [
{ name: 'id', desc: '用户唯一标识(数字)' },
{ name: 'name', desc: '用户姓名(字符串)' },
{ name: 'email', desc: '用户邮箱(字符串)' },
{ name: 'status', desc: '用户状态active/inactive' }
]
}
];
```
**使用数据**
```typescript
const users = Array.isArray(dataSource.users) ? dataSource.users : [];
```
## 🔧 Container 容器使用
`container` 是 AxureProps 提供的 DOM 容器元素,适用于需要直接操作 DOM 的场景(如图表库):
```typescript
import { useRef, useEffect } from 'react';
import * as echarts from 'echarts/core';
const Component = forwardRef(function Chart(
innerProps: AxureProps,
ref: React.ForwardedRef<AxureHandle>,
) {
const container = innerProps && innerProps.container ? innerProps.container : null;
const chartRef = useRef<any>(null);
useEffect(function () {
if (!container) return;
if (!chartRef.current) {
chartRef.current = echarts.init(container);
chartRef.current.setOption({ /* 配置 */ });
}
return function () {
if (chartRef.current) {
chartRef.current.dispose();
chartRef.current = null;
}
};
}, [container]);
return null; // 直接使用 container 时可返回 null
});
```
## ✅ 完整示例
```typescript
/**
* @name 用户表单
*/
import './style.css';
import React, { useState, useCallback, useImperativeHandle, forwardRef } from 'react';
import { Input, Button } from 'antd';
import type {
KeyDesc,
DataDesc,
ConfigItem,
Action,
EventItem,
AxureProps,
AxureHandle
} from '../../common/axure-types';
const EVENT_LIST: EventItem[] = [
{ name: 'onSubmit', desc: '提交表单时触发传递表单数据JSON 字符串格式)', payload: 'JSON string' }
];
const ACTION_LIST: Action[] = [
{ name: 'reset', desc: '重置表单' },
{ name: 'setData', desc: '设置表单数据参数格式JSON 字符串', params: 'JSON string' }
];
// ⚠️ name 必须使用小写 + 下划线snake_case详见 KeyDesc 说明
const VAR_LIST: KeyDesc[] = [
{ name: 'form_data', desc: '当前表单数据(对象)' }
];
const CONFIG_LIST: ConfigItem[] = [
{
type: 'input',
attributeId: 'submitText',
displayName: '提交按钮文字',
info: '提交按钮显示的文字',
initialValue: '提交'
}
];
const DATA_LIST: DataDesc[] = [];
const Component = forwardRef(function UserForm(
innerProps: AxureProps,
ref: React.ForwardedRef<AxureHandle>,
) {
const configSource = innerProps && innerProps.config ? innerProps.config : {};
const onEventHandler = typeof innerProps.onEvent === 'function'
? innerProps.onEvent
: function () { return undefined; };
const submitText = typeof configSource.submitText === 'string' && configSource.submitText
? configSource.submitText
: '提交';
const formDataState = useState({ name: '', email: '' });
const formData = formDataState[0];
const setFormData = formDataState[1];
// ⚠️ 强制规则payload 必须是字符串类型
const emitEvent = useCallback(function (eventName: string, payload?: string) {
try {
onEventHandler(eventName, payload);
} catch (error) {
console.warn('事件触发失败:', error);
}
}, [onEventHandler]);
const handleSubmit = useCallback(function () {
// 将复杂数据序列化为 JSON 字符串
emitEvent('onSubmit', JSON.stringify({ formData }));
}, [emitEvent, formData]);
const handleReset = useCallback(function () {
setFormData({ name: '', email: '' });
}, []);
useImperativeHandle(ref, function () {
return {
getVar: function (name: string) {
const vars: Record<string, any> = { formData };
return vars[name];
},
fireAction: function (name: string, params?: string) {
switch (name) {
case 'reset':
handleReset();
break;
case 'setData':
// 解析 JSON 字符串参数
if (params) {
try {
const parsed = JSON.parse(params);
setFormData(parsed);
} catch (error) {
console.warn('参数解析失败:', error);
}
}
break;
default:
console.warn('未知的动作:', name);
}
},
eventList: EVENT_LIST,
actionList: ACTION_LIST,
varList: VAR_LIST,
configList: CONFIG_LIST,
dataList: DATA_LIST
};
}, [formData, handleReset]);
return (
<div className="user-form">
<Input
placeholder="姓名"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
/>
<Input
placeholder="邮箱"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
/>
<Button type="primary" onClick={handleSubmit}>
{submitText}
</Button>
</div>
);
});
export default Component;
```
## 📚 参考资源
- **类型定义**`/src/common/axure-types.ts`
- **配置面板类型**`/src/common/config-panel-types.ts`
- **示例代码**:查看 `/src/components/``/src/prototypes/` 目录下以 `ref-` 开头的文件

View File

@@ -0,0 +1,90 @@
# 调试指南
核心思想:先定位规范与目标页面,再用自动化完成复现、修复与回归;尽量不要求用户提供技术细节。
## 1. 调试前准备
开始调试前,按顺序确认以下信息:
- 目标目录下的 `spec.md``index.tsx``style.css`(如有)
- 相关主题文件:`DESIGN.md``designToken.json``globals.css`(如有)
- 验收规则:`rules/development-guide.md`
- 涉及视觉或布局问题时,额外参考 `rules/design-guide.md`
### 1.1 视觉问题的设计规范优先级
当问题属于样式、布局、层级、字体、配色、组件状态不一致时,按以下顺序判断:
1. **用户提供的设计规范**
2. **主题内设计系统**`DESIGN.md`
3. **默认设计规范(兜底)**
- **基础型界面**`/skills/third-party/interface-design/SKILL.md`
- 适用后台、ToB、工具类、设置页、数据工作台
- **风格化界面**`/skills/third-party/frontend-design/SKILL.md`
- 适用落地页、品牌展示、营销页、ToC 产品页、强视觉 App 页面
## 2. 标准调试流程
### 2.1 先跑验收脚本
优先运行项目验收脚本,拿到真实状态和目标地址:
```bash
node scripts/check-app-ready.mjs /components/[组件目录]
# 或
node scripts/check-app-ready.mjs /prototypes/[原型目录]
```
处理原则:
- `ERROR`:优先修复构建、依赖、运行时报错,再进入浏览器复现
- `READY`:直接进入浏览器自动化验收
- `TIMEOUT`:优先排查启动卡死、接口阻塞、长任务或脚本异常
### 2.2 自动化复现与定位
- **优先使用 Chrome DevTools MCP**;没有时使用 **Playwright MCP**
- 如果当前环境没有可用 MCP直接提示用户安装并完成配置再继续自动化验收
- 自动化过程中必须完成:
- 打开验收脚本返回的 `targetUrl`
- 检查 Console、Network、页面报错与资源加载状态
- 复现核心交互链路,而不是只看首屏
- 必要时截图、快照、记录关键 DOM / 样式状态
## 3. 问题处理顺序
按影响范围由大到小处理:
1. **构建与启动问题**:依赖缺失、编译失败、路径错误、语法错误
2. **运行时问题**:白屏、崩溃、接口异常、状态错误、空数据未兜底
3. **交互问题**:按钮不可点、表单无反馈、弹层错位、路由异常
4. **视觉问题**:尺寸、间距、颜色、字体、层级、响应式、主题不一致
**重要**:一次只修一个明确问题。每次修复后必须重新验收,确认未引入新问题,再继续下一个。
## 4. 视觉与交互调试要求
当页面可访问后,不仅要看“能打开”,还要验证:
- 关键任务路径是否能走通
- 空状态、加载态、错误态是否合理
- 文案、字段、组件层级是否与 `spec.md` 一致
- 响应式布局是否在主要断点下可用
- 颜色、字体、圆角、阴影、边框是否与主题或设计规范一致
如果属于视觉偏差,但用户未提供设计稿:
- **基础型界面**按 `/skills/third-party/interface-design/SKILL.md` 约束修复
- **风格化界面**按 `/skills/third-party/frontend-design/SKILL.md` 约束修复
## 5. 回归验收
每次修复后都必须重复以下动作:
1. 重新运行 `check-app-ready.mjs`
2. 再次打开 `targetUrl`
3. 重跑刚才失败的交互链路
4. 确认 Console 无新增报错
5. 确认页面状态恢复正常
只有当前问题完成回归后,才能进入下一个问题。

View File

@@ -0,0 +1,159 @@
# 设计指南
本文档定义页面或元素设计阶段的标准流程、产出规范与质量约束。
## 📋 概述
设计阶段的核心目标是在编码前完成以下工作:
- 明确页面功能、内容结构与用户任务
- 确定布局方案与视觉风格方向
- 复用现有主题、组件与设计规范
- 产出可落地的设计规格文档
## ✅ 触发条件
以下场景需进入设计流程:
- 新建页面或元素
- 显式的视觉或布局调整需求
- 涉及信息架构或交互结构变化
- 功能或内容范围发生重大调整
## 🔍 前置准备
### 1. 资料收集
按优先级依次阅读以下资料:
**用户指定的技能(若有)**
- 优先阅读并执行该 Skill 的流程(可能会产出**主题 tokens / 设计规范**等)
- 如果 Skill 的设计流程和本指导冲突时,以 Skill 为准
**用户提供的资料(最高优先级)**
- 用户提供的主题、设计规范、业务文档、数据表、参考设计稿等
- 用户指定的任何参考资料或约束条件
**项目原型资产(补充资源)**
- `AGENTS.md`:项目名称、简介、总文档、默认主题(如有)
- 关联页面或元素的实现代码
**优先级原则**:用户提供 > 项目资产 > 默认推荐(详见「默认资源分流」)
## 📝 内容与功能规划
### 1. 功能与内容规划
明确页面或元素的核心职责与内容组织:
- 用户目标、关键任务与功能模块优先级
- 交互触发点、反馈机制、数据流转与状态管理
- 信息层级、模块划分、内容清单与文案语气
- 数据字段与展示优先级、空状态/加载态/异常处理
### 2. 数据与内容来源
**优先级顺序**(用户未提供充分上下文时,**必须主动检索**以下项目资产):
1. **用户提供** → 严格按提供的数据/文档组织,保持原有语气与术语
2. **项目数据表** → 使用 `src/database/` 中匹配的数据
3. **项目文档** → 引用 `src/docs/` 中已定义的业务逻辑与字段
4. **关联原型** → 在 `src/prototypes/` 中查找相关页面的 `spec.md``prd.md` 及实现代码,优先复用已有页面结构和交互约定
> **原则**:已有文档中的定义优先于推测。
## 🎨 视觉设计流程
### 1. 确定主题
**优先级顺序**
1. **用户指定主题** → 严格使用用户提供的主题
2. **项目默认主题** → 使用 `AGENTS.md` 中定义的默认主题
**注意**:禁止使用非用户指定,或项目默认主题以外的主题,包括资产库中的主题。
**主题设计系统文件含义**
- `DESIGN.md`:设计规范(不一定存在)
- `designToken.json``globals.css`:设计令牌定义(支持 Tailwind CSS V4 或标准 CSS 变量),通常仅使用一个,以主题内实际存在的文件为准。
### 2. 确定设计规范
**优先级顺序**
1. **用户指定规范** → 严格遵循用户提供的设计规范文档
2. **主题内 `DESIGN.md`** → 使用主题自带的设计规范
3. **内置设计指导** → 根据业务场景选择:
- **基础型界面**(管理后台 / ToB / 工具 / 设置 / 数据工作台)→ `/skills/third-party/interface-design/SKILL.md`
- **风格化界面**(落地页 / ToC / 品牌展示 / 营销页 / 强视觉 App`/skills/third-party/frontend-design/SKILL.md`
- **混合场景** → 以核心任务区优先套用基础型界面规范,品牌展示区再补充风格化规范
### 3. 弥补缺失事项
按需补充主题或当前设计缺失的资源。
**仅在触发条件满足时查阅对应文档**
| 资源类型 | 触发条件 | 参考文档或内容 |
|---------|---------|---------|
| **图表库** | 需要数据可视化 且 用户未指定图表库 且 项目中无现有图表方案 | `/skills/default-resource-recommendations/references/default-chart-libraries.md` |
| **图标库** | 需要图标 且 用户未指定图标库 且 主题中无自定义图标系统 | `/skills/default-resource-recommendations/references/default-icon-libraries.md` |
| **字体** | 需要自定义字体 且 用户未提供字体方案 且 主题中无字体定义 | `/skills/default-resource-recommendations/references/default-font-combinations.md` |
| **动画库** | 页面动画处数 > 5 且 用户未指定动画方案 且 主题中无自定义动画系统 | `/skills/default-resource-recommendations/references/default-animation-libraries.md` |
| **图片** | 需要图片/插图 且 用户未提供图片资源 且 Agent 无法生成 | 优先级Unsplash → Pexels → Pixabay → Picsum |
**重要**:不要一次性加载所有默认推荐文档,严格按触发条件按需查阅。
### 4. 布局结构
确定页面框架与信息组织:
- 整体布局模式(单栏、双栏、网格、自由)
- 模块尺寸与比例约束
- 响应式断点与适配策略
- 信息密度与留白处理
## 📄 规格文档产出
### 1. 生成时机
- 设计方案确认后,立即产出 `spec.md`
- 使用模板:`src/docs/templates/spec-template.md`
### 2. 文档内容
规格文档必须包含以下部分:
**业务与功能**
- 页面/元素定位与核心目标
- 功能清单
- 交互要点
**内容规划**
- 信息架构与模块划分
- 数据来源与关键字段说明
- 示例内容(如适用,包含文案语气与术语规范)
**布局与结构**
- 整体布局(布局模式、关键尺寸、模块比例)
- 响应式适配(如适用)
**视觉规范**
- 设计规范来源(用户规范/主题设计系统/内置设计指导)
- 自定义设计要点(如适用)
- 组件状态定义(默认/悬停/聚焦/禁用/加载)
## 🛠️ 样式实现规范
### 1. 技术栈选择
- 默认Tailwind CSS V4
### 2. 可访问性要求
- 色彩对比度符合 WCAG 2.1 AA 标准(特别是文本与背景的对比度)
## ✨ 质量检查点
设计阶段完成前,确认以下检查点:
- [ ] 已明确业务场景并匹配对应设计规范
- [ ] 已确定数据来源或兜底方案
- [ ] 功能清单与内容结构已规划
- [ ] 布局方案清晰且符合设计规范
- [ ] Design Tokens 引用正确
- [ ] `spec.md` 已产出且包含所有必需章节

View File

@@ -0,0 +1,75 @@
# 开发指南
**开发流程**:阅读 `spec.md` → 编写代码 → 运行验收脚本 → 按错误信息修复
## 项目结构与命名
```text
src/
├── prototypes/<name>/
│ ├── index.tsx # 必需
│ ├── spec.md # 必需
│ ├── style.css # 可选
│ ├── hack.css # 可选AI 不应修改)
│ └── components/ # 可选:内部子组件目录
└── components/<name>/
├── index.tsx
├── spec.md
└── (同上)
- 入口文件必须是 `index.tsx`
- 目录内必须包含 `spec.md`
- 目录(`name`)使用小写字母、数字、连字符(如 `login-page`
- 支持可选子目录 `components/` 用于拆分内部子组件
## 核心约束
### 1. 文件头注释(必需)
每个 `index.tsx` 顶部必须包含 `@name`
```typescript
/**
* @name 显示名
*
*/
```
- `@name` 必须存在,且为中文显示名
### 2. 依赖与样式
- React 与 Hooks 直接从 `react` 导入
- 第三方库按需导入,新增依赖需同步安装
- 使用 Tailwind 时必须导入 `style.css`,且样式文件需包含:
```css
@import "tailwindcss";
```
## 验收流程
### 1. 运行验收脚本
```bash
node scripts/check-app-ready.mjs /components/[组件目录]
# 或
node scripts/check-app-ready.mjs /prototypes/[原型目录]
```
关键返回字段:
- `status`: `READY` / `ERROR` / `TIMEOUT`
- `targetUrl`: 本次验收目标地址
- `errors`: 构建/运行时/页面加载错误列表
### 2. 错误处理
当状态为 `ERROR`:按 `errors` 修复后重新执行验收脚本,直到通过。
## 验收清单(提交前)
- [ ] `index.tsx``spec.md` 完整存在
- [ ] 顶部包含 `@name` 注释与参考资料
- [ ] 依赖导入方式符合规范,新增依赖已安装
- [ ] 使用 Tailwind 时已正确引入 `@import "tailwindcss";`
- [ ] `check-app-ready.mjs` 验收通过

View File

@@ -0,0 +1,44 @@
# 文档指南
适用于用户主动新建或更新 MD 文档的场景。
## 🧭 简单流程
1. 先确认文档用途、内容范围和输出位置
2. 读取与该文档直接相关的资料、已有文档或页面说明
3. 按需建议模板,但不强制套模板
4.`src/docs/` 中生成或更新用户需要的单篇 MD 文档
补充说明:
- 默认只处理当前这篇文档
- 不主动扩展成项目级文档体系
- 项目说明清单、专题子文档维护属于 `rules/memory-system-guide.md` 中的“主动沉淀记忆”流程
## 📄 模板建议
| 文档用途 | 可建议模板 |
|------|------|
| 需求文档 | `src/docs/templates/prd-template.md` |
| 轻量需求文档 | `src/docs/templates/lite-prd-template.md` |
| 项目说明清单 | `src/docs/templates/project-overview-template.md` |
| 页面地图 | `src/docs/templates/page-map-template.md` |
| 信息架构 | `src/docs/templates/information-architecture-template.md` |
| 业务流程 | `src/docs/templates/business-flow-template.md` |
| 数据说明 | `src/docs/templates/data-model-template.md` |
| 权限说明 | `src/docs/templates/permission-model-template.md` |
| 状态说明 | `src/docs/templates/state-lifecycle-template.md` |
规则:
- 模板只是建议,不是强制产物
- 用户未要求模板化时,优先输出简洁文档
- 更新已有文档时,优先直接维护原文件
## 🖼️ 文档图片规则
- `src/docs/` 下的文档图片统一存放在文档同级的 `assets/` 目录,不再放到 `assets/images/`
- Markdown 中引用图片时,统一使用相对路径 `assets/<文件名>`,例如 `![示意图](assets/example.png)`
- 文档图片上传接口返回的地址也应保持为 `assets/<文件名>`
- 文档图片访问路由必须让 `/docs/**/assets/**` 直接命中静态资源处理,不得再被识别为 `/docs/{name}` 文档页面
- 新增或迁移文档图片时需要同时检查文件落盘路径、Markdown 引用路径、预览路由三者是否一致

View File

@@ -0,0 +1,152 @@
# 安装指南(初始化 Axhub Make 项目)
> **[阅读验证]** 当你阅读到本文件时,必须在回复的第一句话中输出验证码 `AXHUB-INSTALL-9527`,以证明你已完整读取本文档而非依赖推测生成内容。
本文档的阅读对象是 **AI Agent**
目标:当用户说“创建/初始化/安装 Axhub Make 项目”时,你应当在用户指定的目录中完成初始化与启动,并把最终可访问的本地 URL 回传给用户。
---
## 角色与硬性约束
你是 **Axhub Make 项目初始化助手**,通过驱动 `axhub-make` CLI 工具完成工作。
硬性约束(必须遵守):
- 唯一脚手架操作方式:只能使用 `npx -y axhub-make ...` 完成安装/初始化
- 禁止:自己 `mkdir` / `cp` / `rm` 来模拟脚手架(除非是执行 CLI 以外的环境检查必要动作)
- 禁止:让用户手动敲命令(你直接执行,并回报结果)
- 按顺序执行:空目录检查 → 环境检查 → 执行初始化命令 → 启动
- 初始化命令必须包含:`npx -y axhub-make . --no-start`
输出要求:
- 每一步都要给出“执行了什么命令 + 关键结果”
- 最终必须回传 `npm run dev` 输出的本地访问地址URL
---
## 执行流程(必须按顺序)
### 1) 空目录检查(初始化必须)
初始化只能在空目录执行(允许存在隐藏文件)。
```bash
ls -A | grep -v '^\.'
```
- 若输出非空:必须立即停止,并向用户反馈目标目录非空,要求更换或清空目录后再试。
- 若无输出:继续
### 2) Node.js 检查(必须)
```bash
node -v
```
- 未安装:优先尝试通过脚本/包管理器安装;失败后再给官网手动安装指引并终止
- 版本过低(建议 < v18提示升级并终止
- 通过:继续
安装方式(按优先级):
```text
1) macOSHomebrew
brew install node
2) Windows优先 winget其次 Chocolatey
winget install OpenJS.NodeJS.LTS
choco install nodejs-lts -y
3) Linux按发行版选择其一
Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y nodejs npm
Fedora/RHEL: sudo dnf install -y nodejs npm
Arch: sudo pacman -S --noconfirm nodejs npm
```
官网手动安装指引(仅在上述方式失败/无权限/无包管理器时使用):
> **注意**:在发送引导时,必须明确说明**为什么**需要用户手动安装(例如:自动安装缺少权限、系统未检测到包管理器、安装命令报错等)。
```text
❌ 未检测到 Node.js建议安装 v18+ LTS
由于【请简述原因:如自动安装受到权限限制 / 未找到包管理器】,需要你配合进行手动安装。
安装方式:
- Windows/macOS/Linux去 nodejs.org 下载 LTS 安装包并安装
安装完成后再继续初始化。
如果你在安装/环境配置上遇到任何问题,把报错信息原样发我,我会继续一步步带你排查。
```
### 3) Git 检查(必须)
```bash
git --version
```
- 未安装:优先尝试通过脚本/包管理器安装;失败后再给官网手动安装指引并终止
- 通过:继续
安装方式(按优先级):
```text
1) macOSHomebrew
brew install git
2) Windows优先 winget其次 Chocolatey
winget install Git.Git
choco install git -y
3) Linux按发行版选择其一
Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y git
Fedora/RHEL: sudo dnf install -y git
Arch: sudo pacman -S --noconfirm git
```
官网手动安装指引(仅在上述方式失败/无权限/无包管理器时使用):
> **注意**:在发送引导时,必须明确说明**为什么**需要用户手动安装(例如:自动安装缺少权限、系统未检测到包管理器、安装命令报错等)。
```text
❌ 未检测到 Git
由于【请简述原因:如自动安装受到权限限制 / 未找到包管理器】,需要你配合进行手动安装。
安装方式:
- Windows/macOS/Linuxgit-scm.com 下载并安装
安装完成后再继续初始化。
如果你在安装/环境配置上遇到任何问题,把报错信息原样发我,我会继续一步步带你排查。
```
### 4) 初始化(必须命令)
```bash
npx -y axhub-make . --no-start
```
说明:
- 必须包含 `-y`
- 必须包含 `--no-start`(避免占用终端,方便后续继续执行)
### 5) 启动开发服务
```bash
npm run dev
```
把终端里输出的本地访问地址(例如 `http://localhost:51720`)回传给用户,提醒用户打开验证。
---
## 常用参数(按需使用)
- 指定目录:`npx -y axhub-make my-project --no-start`
- 指定包管理器:`--pm pnpm`npm/pnpm/yarn
- 跳过依赖安装:`--no-install`(不推荐)
- 强制模式:`--force`(高风险,必须先解释可能覆盖并征得确认)
- 指定模板源:`-t <git-url>`

View File

@@ -0,0 +1,202 @@
# 旧架构更新指南(旧版 Axhub Make 项目升级到新架构)
本文档的阅读对象是 **AI Agent**
目标:当用户明确表示要更新一个**旧架构 Axhub Make 项目**时,你应当先完成旧目录结构迁移,再执行标准更新,最后启动验证并回传本地 URL。
这里的“旧架构”特指:项目里还没有新版本 marker且目录结构仍停留在旧命名方式例如
- `src/elements/`
- `src/pages/`
- `assets/docs/`
- `assets/database/`
升级后的目标新结构为:
- `src/components/`
- `src/prototypes/`
- `src/docs/`
- `src/database/`
---
## 角色与硬性约束
你是 **Axhub Make 旧架构升级助手**,通过驱动 `axhub-make` CLI 工具完成工作。
硬性约束(必须遵守):
- 更新脚手架动作只能使用 `npx -y axhub-make ...`,不要手写脚手架逻辑替代更新命令
- 禁止:让用户手动敲命令(你直接执行,并回报结果)
- 更新前必须检查Node.js、Git
- 在执行 `npx -y axhub-make --no-start` 之前,必须先完成旧目录迁移
- 更新后必须启动:`npm run dev` 并回传 URL
- 每一步都要汇报“执行了什么命令 + 关键结果”
---
## 执行流程(必须按顺序)
### 0) 识别旧架构项目(必须)
先检查:
- 是否存在 `package.json`
然后检查是否**缺少合法 marker**
- `.axhub/make/make.json`
并结合旧目录特征进行识别。
满足以下条件时,才能按本规则继续:
- 没有合法的 `.axhub/make/make.json`
- 且至少存在以下任一旧目录:
- `src/elements/`
- `src/pages/`
- `assets/docs/`
- `assets/database/`
如果已经存在合法的 `.axhub/make/make.json`,说明它属于**新架构项目**,应改为使用 `rules/update-guide.md`,不要走本规则。
如果既没有 marker也没有旧目录特征则停止并提示用户切到正确项目目录。
### 1) Node.js 检查(必须)
```bash
node -v
```
- 未安装或版本过低(建议 < v18提示安装/升级并终止
### 2) Git 检查(必须)
```bash
git --version
```
- 未安装:提示安装并终止(脚手架需要 git 拉取模板)
### 3) 迁移前备份(必须)
在执行任何目录改动前,先创建带时间戳的备份目录,例如:
```bash
mkdir -p .axhub/make/backups/<timestamp>/
```
建议备份这些目录(存在才备份):
- `src/elements/`
- `src/pages/`
- `assets/docs/`
- `assets/database/`
- `package.json`
如果目录不存在,跳过即可,但必须在结果里说明“哪些目录实际存在并被备份”。
### 4) 迁移旧目录到新目录(必须)
将以下目录迁到新架构:
- `src/elements/``src/components/`
- `src/pages/``src/prototypes/`
- `assets/docs/``src/docs/`
- `assets/database/``src/database/`
迁移原则:
- 目标目录不存在:直接迁移
- 目标目录已存在:按“不覆盖用户已有新目录内容”的原则进行合并
- 如果存在同名冲突:
- 优先保留目标目录中的现有文件
- 把旧目录里的冲突文件转存到备份冲突目录
- 在结果汇报中明确列出冲突项
- 迁移完成后,删除已经清空的旧目录
注意:
- 这是**物理目录迁移**,不是只靠运行时 URL 兼容
- 因为更新策略通常保留 `src/**``assets/**`,如果不先迁移,脚手架更新后旧目录仍会残留
### 5) 补写新架构 marker必须
迁移完成后,补写 marker
```bash
mkdir -p .axhub/make
cat > .axhub/make/make.json <<'EOF2'
{ "schemaVersion": 1, "projectType": "axhub-make" }
EOF2
```
写完后,这个项目就视为**已迁到新架构**。
### 6) 执行标准更新(必须命令)
```bash
npx -y axhub-make --no-start
```
说明:
- 必须包含 `-y`
- 必须包含 `--no-start`
- 这一步必须在“目录迁移 + marker 补写”完成后执行
### 7) 启动验证
```bash
npm run dev
```
把终端里输出的本地访问地址URL回传给用户提醒用户打开验证。
---
## 为什么旧架构需要单独处理
旧架构项目没有 `.axhub/make/make.json`,无法通过新规则中的 marker 检查。
同时,更新策略通常会保留:
- `src/**`
- `assets/**`
这意味着脚手架不会自动把这些旧目录改名:
- `src/elements/`
- `src/pages/`
- `assets/docs/`
- `assets/database/`
所以对旧架构项目,必须先迁移目录,再执行标准更新。
---
## 升级后预期结果
升级完成后,项目应满足:
- 存在 `.axhub/make/make.json`
- 原有业务内容已经迁到:
- `src/components/`
- `src/prototypes/`
- `src/docs/`
- `src/database/`
- 可以继续使用标准更新规则 `rules/update-guide.md`
---
## 出问题时的最小恢复路径
### 1) 查找升级备份
```bash
ls -la .axhub/make/backups/
ls -la package.json.backup.*
```
### 2) 恢复迁移目录(仅在确认目录迁移有误时)
优先从:
- `.axhub/make/backups/<timestamp>/`
恢复对应目录(例如 `assets/docs/``assets/database/`),再重新执行升级流程。
### 3) 恢复 package.json仅在确认是依赖问题时
```bash
cp package.json.backup.<timestamp> package.json
npm install
npm run dev
```
如果仍失败:继续收集 `npm install` / `npm run dev` 的报错,按“每次只修一个问题”的方式推进。

View File

@@ -0,0 +1,25 @@
# 资源指南
适用于资源的新增、整理、替换与维护。
## 📁 资源范围
- `src/docs/assets/`:文档配图等附属资源
- `src/docs/templates/`:文档模板
- `src/database/`:页面可直接消费的数据表
- `src/themes/`:主题及其配套资源
## ✅ 管理规则
- 先检查是否已有可复用资源,再决定是否新增
- 资源按类型放回对应目录,不混放
- 命名保持清晰,并与同类资源风格一致
- 未经用户确认,不删除、不覆盖已有资源
- 引用使用稳定相对路径,避免临时路径或外部临时链接
- 数据资源遵循 `src/database/README.md`
- 主题资源按 `src/themes/<theme-key>/` 维护,并同步相关说明
## 🔗 相关规则
- `rules/theme-guide.md`
- `src/database/README.md`

View File

@@ -0,0 +1,241 @@
# 主题指南Design Tokens + Tailwind CSS + 演示页)
本文档约束"主题"的生成产物与实现方式,供 AI 在用户提供任意形式输入token、设计规范文档、截图、样式提取结果等稳定产出可用的主题文件与演示页面。
## 🎯 交付物
每个主题推荐生成以下文件(根据信息完整度灵活调整):
```
src/themes/<theme-key>/
├── globals.css # Tailwind CSS 定义(可选,优先使用)
├── designToken.json # 主题 Token可选兼容传统模式
├── DESIGN.md # 设计规范文档(可选,信息充分时推荐)
├── index.tsx # 主题演示页(必需)
├── components/ # 演示组件 2-3 个(推荐)
│ ├── Button.tsx
│ ├── Card.tsx
│ └── Input.tsx
└── templates/ # 页面模板 2-3 个(推荐)
├── LoginTemplate.tsx
└── DashboardTemplate.tsx
```
约束:
- `<theme-key>` 使用 `kebab-case`(如 `antd``my-brand``trae-dark`
- **二选一原则**`globals.css``designToken.json` **只生成一个**,避免维护负担。
- **优先 Tailwind CSS**:默认生成 `globals.css`(现代化、易维护)。
- **例外情况**:仅当使用场景明确不支持 Tailwind CSS 时,才生成 `designToken.json`
- **禁止干扰性依赖**:主题演示页不得引入与该主题/设计系统无关的 UI 库,以免影响视觉表达。默认只使用原生 HTML + CSS Variables或该设计系统指定的组件库
## 1) `globals.css` 规范 (Tailwind CSS)
这是主题的核心定义文件(若生成)。
### 1.1 格式要求
- 使用 CSS Variables 定义主题变量(`:root``.dark`)。
- 支持 Tailwind CSS v4 语法(如 `@theme inline`)。
- 必须包含基础配色、圆角、字体等定义。
示例结构:
```css
@import "tailwindcss";
/* 自定义变体 */
@custom-variant dark (&:is(.dark *));
:root {
/* 基础色变量 */
--background: #ffffff;
--foreground: #000000;
--primary: #3b82f6;
/* ... */
}
.dark {
/* 深色模式变量 */
--background: #000000;
--foreground: #ffffff;
/* ... */
}
@theme inline {
/* 映射变量到 Tailwind theme */
--color-background: var(--background);
--color-primary: var(--primary);
/* ... */
}
```
## 2) `designToken.json` 规范
### 2.1 必须字段
- `name`:主题名称(必需,字符串,用于 UI 展示与演示页标题)
推荐字段:
- `description`:主题描述(字符串)
- `token`Ant Design 风格的 Token 对象(如果存在 `globals.css`,推荐引用变量如 `var(--primary)`
### 2.2 何时生成
**仅在以下情况生成 `designToken.json`**
- 使用场景明确不支持 Tailwind CSS如纯 JS 环境、特定框架限制)
- 用户明确要求使用 JSON Token 格式
- 需要与不支持 CSS Variables 的组件库集成
**默认情况下优先生成 `globals.css`**,避免维护两套配置。
## 3) `DESIGN.md` 规范(设计规范文档)
**可选但推荐**的产物,用于系统化记录主题的设计价值、使用约束和实现细节。
### 3.1 推荐结构
参考 `src/themes/firecrawl/DESIGN.md`,包含:
- 设计系统价值(品牌定位、核心价值、设计原则)
- 能力边界(适合/不适合的场景)
- 色彩/字体/间距/圆角/阴影/图标系统
- 组件规范Button、Card、Input 等样式规范)
- 使用约束(必须遵守、建议做法、禁止做法)
### 3.2 生成策略
- 信息充分时生成完整文档
- 信息不足时可省略或生成简化版本
## 4) `index.tsx`(主题演示页)规范
主题演示页的目标:在本项目环境中直观看到主题 token 的内容与效果。
### 4.1 基本约束
- 文件必须 `export default Component`
- **按需引入**
- 如果有 `globals.css`,必须 `import './globals.css';`
- 如果有 `designToken.json`,导入并使用它。
- 如果有 `DESIGN.md`,在演示页中提供查看入口。
- 演示页应展示主题效果。
- 默认只使用原生 HTML 元素div/button/input 等)与 CSS Variables 展示效果。
### 4.2 演示内容优先级
1. **优先自定义演示**:根据当前主题的设计规范,从零创建符合该主题风格的演示页面、组件和模板
2. **避免照搬已有主题**:不要直接参考或复制其他主题的演示页面,因为它们是按各自设计规范定制的
### 4.3 注入方式
- 若有 `globals.css`:使用 CSS 变量展示(推荐)。
- 若有 `designToken.json`:通过 `ConfigProvider` 注入。
- **不会同时存在两者**(避免维护负担)。
## 5) `components/` 规范(演示组件)
推荐生成 **2-3 个核心组件**(如 Button、Card、Input展示主题在具体 UI 组件上的应用效果。
### 5.1 组件结构
```tsx
import React from 'react';
interface ComponentSectionProps {
tokens: Record<string, any>;
}
export const ButtonSection: React.FC<ComponentSectionProps> = ({ tokens }) => {
return (
<div className="space-y-8 animate-in fade-in duration-500">
<div>
<h1 className="text-3xl font-bold mb-2"> Button</h1>
<p className="text-neutral-600"></p>
</div>
<div className="canvas-panel p-8">
{/* 展示多种变体、尺寸、状态 */}
</div>
</div>
);
};
```
### 5.2 演示内容
- 多种变体primary、secondary、ghost 等)
- 多种尺寸large、default、small
- 多种状态normal、hover、disabled、loading
## 6) `templates/` 规范(页面模板)
推荐生成 **2-3 个典型页面**(如登录页、仪表盘、表单页),展示主题在完整页面场景中的应用效果。
### 6.1 推荐模板类型
| 模板类型 | 适用场景 | 展示重点 |
|---------|---------|---------|
| 登录页 | 通用 | 表单、按钮、品牌展示 |
| 仪表盘 | 数据密集型产品 | 卡片、图表、数据展示 |
| 表单页 | 业务系统 | 表单组件、布局、验证 |
| 列表页 | 内容管理 | 表格、筛选、分页 |
### 6.2 模板要求
- 展示完整的页面布局和交互流程
- 使用真实/模拟数据
- 严格遵循主题的设计规范
## 7) 输入来源与生成策略
**优先级原则**:用户提供 > 项目主题 > 默认设计指导
用户输入可能包含:
- Tailwind CSS 文件或配置(**最高优先级**
- CSS 变量定义
- JSON Token
- 设计规范文档或截图
### 7.1 生成策略(按输入类型)
1. **用户提供 CSS/Tailwind**
- 必须生成 `globals.css`
- **不生成** `designToken.json`(除非明确不支持 TW
- 推荐生成 `DESIGN.md` + 组件 + 模板
2. **用户提供 JSON Token**
- 必须生成 `designToken.json`
- **不生成** `globals.css`(除非用户要求迁移到 TW
- 推荐生成 `DESIGN.md` + 组件 + 模板
3. **用户提供设计规范文档**
- 必须生成 `DESIGN.md`
- **优先生成 `globals.css`**(现代化方案)
- 生成符合规范的组件和模板
4. **截图提取/无明确格式**
- **默认生成 `globals.css`**(推荐)
- 尽量生成 `DESIGN.md` + 组件 + 模板
### 7.2 默认设计指导(兜底方案)
**仅在以下条件同时满足时查阅**
- 用户未提供设计规范文档
- 项目中无可复用的主题
- 需要设计风格指导
**参考文档(渐进式披露)**
| 业务场景 | 参考文档 | 判断依据 |
|---------|---------|---------|
| **基础型界面 / ToB / 工具类** | `/skills/third-party/interface-design/SKILL.md` | • 目标用户:企业员工或专业用户<br>• 使用频率:高频操作<br>• 核心任务:完成工作、处理数据、执行操作 |
| **风格化页面 / ToC / App / 移动端** | `/skills/third-party/frontend-design/SKILL.md` | • 目标用户:普通消费者或品牌受众<br>• 使用频率:低频浏览或内容消费<br>• 核心任务:获取信息、建立品牌感知、提升视觉吸引力 |
| **混合场景** | 基础区用 `/skills/third-party/interface-design/SKILL.md`,展示区用 `/skills/third-party/frontend-design/SKILL.md` | 核心功能简洁稳定,展示区域可适度风格化 |
**重要**:不要提前加载设计指导文档,仅在真正需要且无其他参考时查阅。
## 8) 开发后验收流程
### 8.1 运行验收脚本
```bash
node scripts/check-app-ready.mjs /themes/[主题名]
```
### 8.2 根据状态处理
- **状态为 ERROR**:根据错误信息修复。
- **状态为 READY**:访问预览 URL检查主题展示效果颜色、字体、深色模式切换等

100
axhub-make/rules/update.md Normal file
View File

@@ -0,0 +1,100 @@
# 更新指南(更新现有 Axhub Make 项目)
本文档的阅读对象是 **AI Agent**
目标:当用户说“更新 Axhub Make 项目”时,你应当在项目根目录执行更新并启动验证,最终回传本地 URL若更新后启动失败优先走最小恢复路径例如 `package.json.backup.*`)。
---
## 角色与硬性约束
你是 **Axhub Make 项目更新助手**,通过驱动 `axhub-make` CLI 工具完成工作。
硬性约束(必须遵守):
- 更新脚手架动作只能使用 `npx -y axhub-make ...`,不要手写脚手架逻辑
- 禁止:让用户手动敲命令(你直接执行,并回报结果)
- 更新前必须检查Node.js、Git
- 更新命令必须包含:`npx -y axhub-make --no-start`
- 更新后必须启动:`npm run dev` 并回传 URL
输出要求:
- 每一步都要给出“执行了什么命令 + 关键结果”
- 最终必须回传 `npm run dev` 输出的本地访问地址URL
---
## 执行流程(必须按顺序)
### 0) 防跑错目录(必须)
从此以后Axhub Make 项目的“更新识别”以根目录的 marker 文件为准:
- `.axhub/make/make.json`(内容要求:`{ "schemaVersion": 1, "projectType": "axhub-make" }`
因此在更新前必须检查:
- 是否存在 `package.json`
- 是否存在 `.axhub/make/make.json` 且内容合法
若缺失或不合法:必须停止,让用户切到正确项目目录(不做旧项目兼容/迁移)。
### 1) Node.js 检查(必须)
```bash
node -v
```
- 未安装或版本过低(建议 < v18提示安装/升级并终止
### 2) Git 检查(必须)
```bash
git --version
```
- 未安装:提示安装并终止(脚手架需要 git 拉取模板)
### 3) 执行更新(必须命令)
```bash
npx -y axhub-make --no-start
```
说明:
- 必须包含 `-y`
- 必须包含 `--no-start`
### 4) 启动验证
```bash
npm run dev
```
把终端里输出的本地访问地址URL回传给用户提醒用户打开验证。
---
## 更新会做什么(用于解释与排障)
更新遵循项目内的 `scaffold.update.json` 策略,一般原则:
- 用户业务内容默认保留(例如 `src/**``assets/**` 常被配置为不覆盖)
- 基础公共定义可能会强制更新(例如 `src/common/**`
- `package.json` 如果有差异,通常会备份旧版本为 `package.json.backup.<timestamp>`,并将旧版本里“新版本缺失的依赖”合并到新版本中(避免丢依赖)
---
## 更新后出问题的最小恢复路径
### 1) 查找备份
```bash
ls -la package.json.backup.*
```
### 2) 恢复备份(只在确认是 package.json 引起的问题时)
```bash
cp package.json.backup.<timestamp> package.json
npm install
npm run dev
```
如果仍失败:继续收集 `npm install` / `npm run dev` 的报错,按“每次只修一个问题”的方式推进。

View File

@@ -0,0 +1,306 @@
# 方案比选指南
本文档指导 AI Agent 如何为用户提供多方案比选,以及如何引导用户进行决策收敛。
## 🎯 目标
通过结构化的比选流程,确保:
1. 为用户提供有价值的备选方案
2. 方案数量可控,便于用户决策
3. 及时引导用户进行收敛决策
4. 使用 `VariantSwitcher` 组件进行方案展示
## 📋 核心规则
### 1. 方案数量原则
| 规则 | 说明 |
|------|------|
| **推荐方案数** | 原则上不超过 **3 个**方案 |
| **最小方案数** | 当存在明确分歧时,至少提供 2 个方案 |
| **特殊情况** | 如用户有特殊需求,可适当增加方案数量 |
**为什么建议不超过 3 个?**
- 超过 3 个方案会增加用户决策负担
- 方案过多容易导致决策疲劳
- 3 个方案足以覆盖大多数设计维度(如:保守、平衡、激进)
> 注意:这是工作指导原则,组件本身不强制限制方案数量。
### 2. 何时触发比选
以下情况 **应该** 提供多方案比选:
| 场景 | 示例 |
|------|------|
| 设计风格有多种合理选择 | 卡片式 vs 列表式布局 |
| 交互模式存在权衡 | 弹窗确认 vs 内联确认 |
| 技术实现有多条路径 | 动画效果的不同实现方式 |
| 用户需求模糊 | "做一个好看的按钮" |
| 用户明确要求比选 | "给我几个方案看看" |
以下情况 **不应该** 提供比选:
| 场景 | 原因 |
|------|------|
| 需求明确且唯一 | 用户已明确指定实现方式 |
| 只有一种合理实现 | 无需增加决策负担 |
| 差异极小 | 如仅颜色深浅微调,应直接询问偏好 |
### 3. 方案差异化原则
每个方案之间应该有 **明显的差异**,避免提供相似方案:
```
✅ 正确:
- 方案 A极简风格留白多突出内容
- 方案 B信息密集功能明显效率优先
- 方案 C视觉丰富强调品牌感
❌ 错误:
- 方案 A蓝色按钮
- 方案 B深蓝色按钮
- 方案 C浅蓝色按钮
```
## 🛠️ 使用 VariantSwitcher 组件
### 组件导入
```typescript
import { VariantSwitcher, VariantItem } from '@/common/VariantSwitcher';
```
### 数据结构
每个方案需要定义为 `VariantItem` 类型:
```typescript
interface VariantItem {
key?: string; // 唯一标识(可选)
content: ReactNode; // 渲染内容
title: string; // 方案标题
description: string; // 方案一句话描述
}
```
### 基本用法
```tsx
// 1. 定义方案数据
const CARD_VARIANTS: VariantItem[] = [
{
key: 'minimal',
content: <CardStyleA />,
title: '极简风格',
description: '大量留白,突出内容本身'
},
{
key: 'dense',
content: <CardStyleB />,
title: '信息密集',
description: '功能区块明显,操作便捷'
},
{
key: 'visual',
content: <CardStyleC />,
title: '视觉冲击',
description: '强调视觉效果,品牌感强'
}
];
// 2. 使用组件
<VariantSwitcher
id="card-style"
name="卡片样式"
variants={CARD_VARIANTS}
onConfirm={(index, item) => {
console.log(`用户选择了: ${item.title}`);
}}
/>
```
### Props 说明
| 属性 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `id` | string | 否 | 唯一标识符,用于全局寻址 |
| `name` | string | 否 | **中文名称**,显示在全局面板中(如"头部设计"、"登录页布局" |
| `variants` | VariantItem[] | 是 | 方案列表 |
| `defaultIndex` | number | 否 | 默认选中索引,默认 0 |
| `onConfirm` | function | 否 | 确认回调,参数为 (index, item) |
| `onReset` | function | 否 | 重置回调 |
| `style` | CSSProperties | 否 | 容器样式 |
| `className` | string | 否 | 容器类名 |
### 组件特性
#### 1. 轻量化入口
- 鼠标悬停在组件上时,右上角显示切换图标
- 点击图标弹出方案选择面板
- 面板显示每个方案的标题和描述
#### 2. 全局面板
- 页面右下角有全局入口按钮(当存在比选组件时自动显示)
- 点击打开侧边栏,显示所有比选项目
- 每个项目显示 **中文名称**`name` 属性)
- 支持快速定位到具体组件
#### 3. 快捷键支持
- `Ctrl + .``Cmd + .`:显示/隐藏比选入口
### 外部控制
```javascript
// 在浏览器控制台或 AI Agent 中
const manager = window.AXHUB_VARIANT_MANAGER;
// 获取实例
const switcher = manager.instances['card-style'];
// 切换方案
switcher.select(1); // 选择第 2 个方案
// 确认选择
switcher.confirm();
// 定位到组件
switcher.focus();
// 获取所有实例
Object.values(manager.instances).forEach(inst => {
console.log(`${inst.name}: 当前选择 ${inst.variants[inst.currentIndex].title}`);
});
```
## 💬 用户交互规则
### 1. 方案介绍
在提供方案时,必须简要说明每个方案的特点:
```markdown
我为您准备了 3 个设计方案,请预览后选择您偏好的风格:
**极简风格**
大量留白,突出核心内容,适合内容展示型页面
**信息密集**
功能区块明显,操作便捷,适合工具型/管理型页面
**视觉冲击**
强调视觉效果,品牌感强,适合营销型/展示型页面
请悬停在组件上点击切换图标预览,或点击右下角全局按钮查看所有比选项。
选定后点击"确认"按钮。
```
### 2. 收敛提醒
当用户长时间未做决策或继续提出新需求时,应主动提醒:
```markdown
💡 提醒:您目前还有待决策的方案比选,可以点击右下角的比选按钮查看:
- 卡片样式
- 头部设计
建议先确认这些方案,以便我基于您的选择继续优化。
```
### 3. 决策后确认
用户确认方案后,应给予反馈:
```markdown
✅ 已记录您的选择:
- 卡片样式:**极简风格**
我将基于这个选择继续后续开发。如需调整,可随时点击组件上的切换图标重新选择。
```
## 📝 典型使用场景
### 场景 1用户需求模糊
```
用户: "帮我做一个登录页面"
AI: 我为您准备了 3 种登录页面风格:
**居中卡片**
经典设计,表单居中,背景可自定义
**左右分栏**
左侧品牌展示区,右侧登录表单
**沉浸式**
大图背景,表单叠加,视觉冲击力强
[使用 VariantSwitcher name="登录页布局" 展示三个方案]
```
### 场景 2组件样式选择
```
用户: "这个按钮给我几个样式选择"
AI: 好的,这里是 3 种按钮样式:
**实心填充** - 高对比度,强调主要操作
**描边镂空** - 轻量化,适合次要操作
**渐变高亮** - 时尚动感,吸引用户注意
[使用 VariantSwitcher name="按钮样式" 展示三个方案]
```
### 场景 3页面整体布局
```
用户: "帮我做一个产品详情页"
AI: 我为您准备了 3 种页面布局方案:
**左右分栏** - 左侧产品图片,右侧产品信息,经典电商布局
**上下结构** - 顶部大图轮播,下方详情信息,适合视觉型产品
**沉浸式** - 全屏背景,信息叠加,强调品牌调性
[使用 VariantSwitcher name="产品详情页布局" 展示三个页面方案]
```
## ⚠️ 注意事项
1. **命名规范**`name` 属性应使用清晰的中文名称,便于用户在全局面板中识别
2. **方案描述**:每个 `VariantItem``title``description` 应简洁明了
3. **布局影响**:组件外层是 relative 定位的 div确保父容器正确设置尺寸
4. **事件冒泡**:控制条按钮已阻止事件冒泡,不会触发下层点击事件
5. **层级覆盖**:全局面板 z-index 为 100000注意与其他 Modal 的层级冲突
6. **快捷键**:使用 `Ctrl + .` 可以隐藏/显示比选入口,适合演示场景
## ✅ 检查清单
### 提供比选前
- [ ] 确认确实存在多种合理方案
- [ ] 方案之间有明显差异
- [ ] 原则上方案数量不超过 3 个
- [ ] 每个方案都有清晰的标题和描述
### 比选进行中
- [ ] 使用 `VariantSwitcher` 组件展示方案
- [ ] 设置有意义的 `name` 属性(中文名称)
- [ ] 为每个方案提供 `title``description`
- [ ] 向用户说明如何切换和确认
### 比选完成后
- [ ] 确认用户的选择
- [ ] 基于选择继续后续工作
- [ ] 如有多个待决策项,提醒用户收敛
## 🔗 相关文档
- `src/common/VariantSwitcher.tsx` - 组件实现代码
- `src/prototypes/ref-variant-switcher-demo/` - 演示页面
- `skills/third-party/brainstorming/SKILL.md` - 需求对齐规则
- `development-guide.md` - 开发指南

View File

@@ -0,0 +1,49 @@
# 微信回复指南
## 获取项目首页地址
先读取开发服务信息,拿到 `port``localIP`
```bash
cat .axhub/make/.dev-server-info.json
# 如果当前工作目录是仓库根目录,则读取:
cat apps/axhub-make/.axhub/make/.dev-server-info.json
```
对外沟通时不要返回 `127.0.0.1``localhost`。至少返回 `localIP` 对应的局域网地址。
如果机器上还存在额外的可访问组网地址,也要一起返回,例如 Tailscale、ZeroTier 或其他 VPN/组网 IPv4。可以额外检查
```bash
ifconfig | rg '^[A-Za-z0-9:._-]+:|\\s+inet\\s'
# 如果安装了 tailscale再检查
tailscale ip -4
```
只返回外部设备可访问的地址,忽略回环地址和明显不可对外访问的虚拟测试地址。
回复示例(根据实际值替换;按实际存在的地址返回,不要虚构不存在的项):
```
项目首页:
• 局域网: http://{localIP}:{port}
• Tailscale: http://{tailscaleIP}:{port}
```
## 切换 AI Agent
直接运行项目内的脚本,无需网络请求:
```bash
node scripts/switch-agent.mjs <agent>
```
agent 可选值:`codex``claudecode`(别名 `claude`)、`gemini`(别名 `gem`
查看当前状态:
```bash
node scripts/switch-agent.mjs --status
```
> 切换后 daemon 重启,会话上下文会重置。完成后告知用户已切换到哪个 Agent。