TRAE_CODING_GUIDELINES.md 7.9 KB

书嗨后台管理系统 - Trae AI 代码编写规范与指南

本文档旨在为 Trae AI(及开发者)提供统一的代码编写规范和最佳实践指南,确保代码风格一致、维护性高且符合项目架构要求。

1. 技术栈与环境

  • 核心框架: Vue 3 (Composition API)
  • 构建工具: Vite
  • UI 组件库: Element Plus + Ele Admin Plus (项目封装库)
  • CSS 框架: Tailwind CSS (优先使用) + SCSS
  • 语言: JavaScript (部分 TypeScript 支持)

2. 目录结构规范

src/
├── api/                # API 接口定义,按模块分类
├── components/         # 通用组件
│   ├── CommonPage/     # 列表页核心组件 (CommonTable, ProSearch 等)
│   ├── ProForm/        # 高级表单组件
│   └── ...
├── utils/              # 工具函数
│   ├── request.js      # Axios 封装 (核心)
│   ├── use-dict-data.js # 字典 Hook
│   └── ...
├── views/              # 页面视图,按模块划分
│   ├── finance/        # 财务模块
│   │   ├── withdrawal/ # 提现管理
│   │   │   ├── index.vue           # 列表主页
│   │   │   ├── components/         # 页面独有组件
│   │   │   │   ├── page-search.vue # 搜索栏
│   │   │   │   ├── audit-dialog.vue# 审核弹窗
│   │   │   │   └── ...
│   └── ...

3. 页面开发模式 (Page Patterns)

3.1 列表管理页 (List Page)

所有“增删改查”类列表页面必须遵循以下结构:

  1. 根容器: 使用 <ele-page flex-table> 实现高度自适应。
  2. 搜索区: 引入独立的 page-search.vue 组件。
  3. 表格区: 使用 <common-table> 组件。

index.vue 模板:

<template>
    <ele-page flex-table>
        <!-- 搜索栏 -->
        <page-search @search="reload" />

        <!-- 通用表格 -->
        <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns">
            <!-- 顶部工具栏 -->
            <template #toolbar>
                <div class="flex items-center mb-4">
                    <el-button type="primary" @click="handleAdd" v-permission="'module:add'">新增</el-button>
                    <!-- 统计信息等 -->
                </div>
            </template>
            
            <!-- 自定义列渲染 -->
            <template #status="{ row }">
                 <el-tag>{{ getStatusLabel(row.status) }}</el-tag>
            </template>
            
            <!-- 操作列 -->
            <template #action="{ row }">
                <el-button link type="primary" @click="handleEdit(row)" v-permission="'module:edit'">编辑</el-button>
            </template>
        </common-table>

        <!-- 弹窗组件 -->
        <edit-dialog ref="editDialogRef" @success="reload" />
    </ele-page>
</template>

<script setup>
import { ref, reactive } from 'vue';
import CommonTable from '@/components/CommonPage/CommonTable.vue';
import PageSearch from './components/page-search.vue';
import EditDialog from './components/edit-dialog.vue';

// 页面配置
const pageConfig = reactive({
    pageUrl: '/sys/module/list', // 列表接口 URL
    fileName: '导出文件名',
    rowKey: 'id'
});

// 列定义
const columns = ref([
    { label: '名称', prop: 'name', align: 'center' },
    { label: '状态', prop: 'status', slot: 'status', align: 'center' },
    { columnKey: 'action', label: '操作', slot: 'action', fixed: 'right', width: 140 }
]);

const pageRef = ref(null);
const editDialogRef = ref(null);

const reload = (where) => pageRef.value?.reload(where);
const handleAdd = () => editDialogRef.value?.handleOpen();
const handleEdit = (row) => editDialogRef.value?.handleOpen(row);
</script>

3.2 搜索组件 (Search Component)

文件路径: ./components/page-search.vue

<template>
    <ele-card :body-style="{ paddingBottom: '8px' }">
        <ProSearch :items="formItems" @search="search" />
    </ele-card>
</template>

<script setup>
import { reactive } from 'vue';
import ProSearch from '@/components/CommonPage/ProSearch2.vue';

const emit = defineEmits(['search']);

const formItems = reactive([
    { type: 'input', label: '关键词', prop: 'keywords' },
    { 
        type: 'dictSelect', 
        label: '状态', 
        prop: 'status', 
        props: { code: 'sys_status' } // 对应字典编码
    }
]);

const search = (data) => emit('search', data);
</script>

3.3 弹窗组件 (Dialog Component)

文件路径: ./components/*-dialog.vue

<template>
    <ele-modal v-model="visible" :title="title" width="600px">
        <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
            <el-form-item label="名称" prop="name">
                <el-input v-model="form.name" />
            </el-form-item>
        </el-form>
        <template #footer>
            <el-button @click="visible = false">取消</el-button>
            <el-button type="primary" @click="handleSubmit">确定</el-button>
        </template>
    </ele-modal>
</template>

<script setup>
import { ref, reactive } from 'vue';
import request from '@/utils/request';
import { ElMessage } from 'element-plus';

const emit = defineEmits(['success']);
const visible = ref(false);
const title = ref('新增');
const formRef = ref();
const form = reactive({ id: null, name: '' });
const rules = { name: [{ required: true, message: '请输入名称' }] };

const handleOpen = (row) => {
    if (row) {
        title.value = '编辑';
        Object.assign(form, row);
    } else {
        title.value = '新增';
        // 重置表单逻辑
        form.id = null;
        form.name = '';
    }
    visible.value = true;
};

const handleSubmit = async () => {
    await formRef.value.validate();
    const url = form.id ? '/sys/module/update' : '/sys/module/add';
    const res = await request.post(url, form);
    if (res.data.code === 200) {
        ElMessage.success(res.data.msg);
        visible.value = false;
        emit('success');
    }
};

defineExpose({ handleOpen });
</script>

4. 编码规范

4.1 样式 (CSS/SCSS)

  • Tailwind CSS: 优先使用 Tailwind 类名处理布局和间距。
    • flex, items-center, justify-between
    • m-4 (margin), p-4 (padding)
    • w-full, h-full
  • Element Plus 样式覆盖: 尽量通过 props 控制,必要时在 <style scoped> 中使用 :deep()

4.2 脚本 (Script)

  • 使用 <script setup> 语法。
  • 导入顺序: Vue 核心 -> 第三方库 -> 项目组件 -> 工具函数/API。
  • 字典数据: 必须使用 useDictData Hook 获取字典数据。

    import { useDictData } from '@/utils/use-dict-data';
    const [statusOptions] = useDictData(['sys_status']);
    

4.3 网络请求

  • 使用 @/utils/request 实例。
  • 必须处理 res.data.code === 200 的业务成功逻辑。
  • 错误处理通常由拦截器统一处理,但在特定业务场景下可单独 catch

5. Trae AI 执行清单

当用户请求创建新页面或功能时,请按以下步骤执行:

  1. 需求分析: 确认页面功能(列表/表单)、字段定义、API 接口。
  2. 文件创建:
    • src/api/module/index.js (如需)
    • src/views/module/page/index.vue
    • src/views/module/page/components/page-search.vue
    • src/views/module/page/components/*-dialog.vue
  3. 代码实现:
    • 套用上述“页面开发模式”模板。
    • 确保所有文本标签、字典编码与业务匹配。
    • 添加必要的权限指令 (v-permission)。
  4. 路由配置: 检查并提示用户更新路由(如果是动态路由通常由后端控制,如果是静态路由需修改 router/routes.js)。
  5. 预览验证: 使用 open_preview 工具检查 UI 布局。

注意: 在修改现有代码时,请先读取原文件理解上下文,避免破坏现有逻辑。