Files
Road_roller/.claude/skills/project-structure/SKILL.md
2026-09-17 08:52:53 +08:00

11 KiB
Raw Blame History

Project Structure Skill

本 skill 定义项目的分层架构和文件组织规范,用于指导 Agent 在创建新页面、组件时遵循统一的目录结构。

核心原则

  1. 页面放在 pages/ - 每个页面一个目录,包含 index.vue
  2. 组件放在 components/ - 公共组件直接放目录下,页面专属组件按页面名分子目录
  3. 页面专属组件与页面同名 - 如 home 页面的组件放在 components/home/
  4. 使用 easycom 自动加载 - 无需手动 import,组件通过文件路径自动生成标签名

组件放置规则(重要)

公共组件(跨页面复用)

当用户要求创建公共组件时,直接放在 components/ 根目录下:

components/
├── backNav.vue      # 通用返回导航栏
├── tabBar.vue       # 通用底部栏
├── modal.vue        # 通用弹窗
└── ...

标签名:<back-nav />、<tab-bar />、<modal />

页面专属组件(仅特定页面使用)

当组件只在某个页面内使用时,放在 components/{pageName}/ 子目录下:

components/
├── home/            # 首页专属组件
│   ├── status.vue
│   └── overview.vue
├── message/         # 消息页专属组件
│   └── list.vue
└── bluetooth/       # 蓝牙页专属组件
    └── device.vue

标签名:<home-status />、<message-list />、<bluetooth-device />

判断依据

需求描述 放置位置 示例
"做一个通用的返回导航" components/backNav.vue <back-nav />
"做一个通用的弹窗组件" components/modal.vue <modal />
"首页的项目列表组件" components/home/projectList.vue <home-projectList />
"消息页的消息列表" components/message/list.vue <message-list />
"蓝牙页的设备卡片" components/bluetooth/device.vue <bluetooth-device />

目录结构

src/
├── pages/                    # 页面目录
│   ├── home/                 # 首页
│   │   └── index.vue
│   ├── report/               # 报告页
│   │   └── index.vue
│   ├── message/              # 消息页
│   │   └── index.vue
│   ├── bluetooth/            # 蓝牙页
│   │   └── index.vue
│   └── work/                 # 工作页
│       └── index.vue
│
├── components/               # 组件目录
│   ├── backNav.vue           # 公共组件:通用返回导航栏
│   │
│   ├── home/                 # 首页专属组件
│   │   ├── homeNav.vue       # 首页导航栏
│   │   ├── overview.vue      # 今日作业概览
│   │   ├── status.vue        # 实时作业状态
│   │   ├── projectList.vue   # 项目列表容器
│   │   ├── list.vue          # 项目列表项
│   │   ├── progress.vue      # 项目作业进度
│   │   ├── construction.vue  # 当前施工段
│   │   ├── warning.vue       # 异常警告容器
│   │   └── warning_list.vue  # 异常警告项
│   │
│   ├── message/              # 消息页专属组件
│   │   └── list.vue          # 消息列表项
│   │
│   └── bluetooth/            # 蓝牙页专属组件
│       └── device.vue        # 蓝牙设备卡片
│
├── composables/              # 组合式函数
├── store/                    # Pinia 状态管理
├── api/                      # 接口请求
├── utils/                    # 工具函数
├── static/                   # 静态资源
└── layouts/                  # 布局组件

命名规范

文件命名

  • 页面: index.vue(固定)
  • 组件: camelCase.vue(如 projectList.vue)
  • 组合式函数: useXxx.ts(如 useCount.ts)

组件标签名(easycom 规则)

  • 公共组件: backNav.vue → <back-nav />
  • 页面专属组件: home/status.vue → <home-status />
  • 嵌套组件: home/list.vue → <home-list />

easycom 自动扫描规则

{
  "easycom": {
    "autoscan": true,
    "custom": {
      "^wd-(.*)": "@wot-ui/ui/components/wd-$1/wd-$1.vue",
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
    }
  }
}

easycom 自动生成标签名规则

文件路径 自动生成标签名
components/backNav.vue <back-nav />
components/modal.vue <modal />
components/home/status.vue <home-status />
components/message/list.vue <message-list />
components/bluetooth/device.vue <bluetooth-device />

组件拆分原则

何时拆分组件

  1. 模板超过 100 行 - 拆分为子组件
  2. 重复使用的 UI 块 - 提取为独立组件
  3. 逻辑独立的功能块 - 拆分便于维护

拆分模式

页面容器组件(如 projectList.vue)
  └── 列表项组件(如 projectList_list.vue)

页面容器组件(如 warning.vue)
  └── 列表项组件(如 warning_list.vue)

示例:项目列表

components/home/
├── projectList.vue    # 容器:卡片标题 + card-body
└── projectList_list.vue      # 内容:项目信息 + 参数 + 操作按钮

使用方式:

<home-projectList>
  <home-projectList_list />
</home-projectList>

创建新页面步骤

  1. 创建页面目录

    src/pages/{pageName}/index.vue
    
  2. 创建页面专属组件目录(如需要)

    src/components/{pageName}/
    
  3. 配置路由(如需要)

    // src/pages.json
    {
      "path": "pages/{pageName}/index",
      "type": "page",
      "style": {
        "navigationBarTitleText": "页面标题"
      }
    }
    
  4. 使用组件

```

页面专属组件 vs 公共组件

类型 位置 标签名 示例
公共组件 components/ 根目录 {name} <back-nav />
页面专属组件 components/{pageName}/ {pageName}-{name} <home-status />

页面样式规范

内容区域样式

所有使用自定义导航栏(<back-nav />)的页面,.content 容器必须使用以下样式:

.content {
  padding: 16px;
  padding-top: 72px;
}
  • padding-top: 72px 为导航栏预留空间,避免内容被遮挡
  • padding: 16px 保持左右边距一致

卡片样式规范(重要)

每个组件自身就是一个卡片,页面不要用额外的 .card 容器包裹组件,否则多个组件会合并成一个卡片。

卡片间距规则:

  • 卡片之间间距统一为 12px
  • 页面通过 gap: 12px 设置间距,组件内部不要添加 margin
  • 组件只负责自身样式(背景、圆角、内边距),不负责与其他组件的间距

正确做法 - 页面用 gap 设置间距:

<!-- 页面 -->
<template>
  <view class="page">
    <back-nav title="页面标题" />
    <view class="content">
      <component-a />
      <component-b />
    </view>
  </view>
</template>

<template>
  <view class="card">
    <!-- 内容 -->
  </view>
</template>

<!-- 组件 a.vue -->
<style scoped>
.content {
  display: flex;
  flex-direction: column;
  gap: 12px;  /* 卡片间距 */
}
</style>

<style scoped>
.card {
  background: #fff;
  border-radius: 12px;
  padding: 16px;
  /* 不要添加 margin */
}
</style>

错误做法 - 组件添加 margin 影响间距:

/* 错误:组件添加 margin */
.card {
  margin-bottom: 16px;  /* 不要用 margin */
}

组件卡片统一样式:

.card {
  background: #fff;
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
}

例外情况 - 多个子组件需要合并展示时: 当明确要求将多个组件放在同一个卡片内时,由最外层容器组件统一设置卡片样式,子组件背景透明:

/* 容器组件 */
.container {
  background: #fff;
  border-radius: 12px;
  padding: 16px;
}

/* 子组件 */
.child {
  background: transparent;
  padding: 0;
}

页面模板示例

<template>
  <view class="page">
    <back-nav title="页面标题" />

    <view class="content">
      <view class="card">
        <!-- 卡片内容 -->
      </view>
    </view>
  </view>
</template>

<style scoped>
.page {
  min-height: 100vh;
  background-color: #EAEFF9;
}

.content {
  padding: 16px;
  padding-top: 72px;
}

.card {
  background: #fff;
  border-radius: 12px;
  padding: 16px;
}
</style>

字体规范

项目使用三级字体体系:

级别 字号 用途 示例
一级 22px 最大标题 页面标题、卡片大标题
二级 18px 次级正常字体 正文、列表项、表单标签
三级 14px 最小描述字体 辅助说明、placeholder、元信息

CSS 变量:

/* 一级标题 */
--font-size-title: 22px;

/* 二级正文 */
--font-size-body: 18px;

/* 三级描述 */
--font-size-caption: 14px;

使用示例:

<template>
  <view class="card">
    <text class="title">
      项目名称
    </text>
    <text class="body">
      项目描述内容
    </text>
    <text class="caption">
      辅助说明文字
    </text>
  </view>
</template>

<style scoped>
.title {
  font-size: 22px;
  font-weight: bold;
  color: #333;
}

.body {
  font-size: 18px;
  color: #333;
}

.caption {
  font-size: 14px;
  color: #999;
}
</style>

注意事项

  1. 不要在页面中直接写大段模板 - 超过 100 行考虑拆分
  2. 组件样式使用 scoped - 避免样式污染
  3. 组件 props 要有默认值 - 提高组件易用性
  4. 事件命名使用 kebab-case - 如 @handle-click
  5. 插槽优先于 props 传内容 - 灵活性更高
  6. 禁止使用 git 提交 - 代码的改动必须经过手动提交

UI 组件库使用规范(重要)

项目使用两套 UI 组件库,按场景分工:

uni-ui(表单/表格场景)

仅用于表单、表格相关的组件:

  • 下拉选择:<uni-data-select>
  • 单选框:<uni-radio> / <uni-radio-group>
  • 多选框:<uni-checkbox> / <uni-checkbox-group>
  • 日期选择:<uni-datetime-picker>
  • 输入框:<uni-easyinput>
  • 数据选择器:<uni-data-picker>
  • 图标:<uni-icons>

官网:https://uniapp.dcloud.net.cn/component/uniui/uni-data-select.html

wot-ui(其他所有场景)

除表单表格外,其他所有 UI 组件统一使用 wot-ui:

  • 按钮:<wd-button>
  • 图标:<wd-icon>
  • 弹窗:<wd-dialog>
  • 导航栏:<wd-nav-bar>
  • 标签:<wd-tag>
  • 步骤条:<wd-steps>
  • 加载:<wd-loading>
  • 等等

快速判断

场景 使用库 组件示例
输入框 uni-ui <uni-easyinput>
下拉选择 uni-ui <uni-data-select>
单选/多选 uni-ui <uni-radio> / <uni-checkbox>
日期时间选择 uni-ui <uni-datetime-picker>
按钮 wot-ui <wd-button>
图标 wot-ui <wd-icon>
弹窗/通知 wot-ui <wd-dialog> / <wd-toast>
导航栏 wot-ui <wd-nav-bar>
标签/徽标 wot-ui <wd-tag> / <wd-badge>
表格展示 uni-ui <uni-table>