Skip to content

酒店新媒体智能体 - 前端工程化开发标准

概述

本文档定义了 hotel-web 项目的前端工程化开发标准,基于 Vue 3 + Vite + Element Plus + SCSS 技术栈,确保代码质量、可维护性和一致性。

目录结构规范

项目目录结构

hotel-web/
├── src/
│   ├── assets/              # 静态资源
│   │   ├── images/
│   │   ├── fonts/
│   │   └── icons/
│   ├── components/          # 通用组件
│   │   ├── SmartCreatorInput.vue
│   │   ├── EmptyState.vue
│   │   ├── LoadingState.vue
│   │   └── ...
│   ├── layouts/            # 布局组件
│   │   └── SidebarLayout.vue
│   ├── views/              # 页面视图
│   │   ├── dashboard/
│   │   │   └── Index.vue
│   │   ├── copy-generator/
│   │   │   └── Index.vue
│   │   ├── poster-generator/
│   │   │   └── Index.vue
│   │   ├── video-generator/
│   │   │   └── Index.vue
│   │   ├── template-market/
│   │   │   └── Index.vue
│   │   ├── my-works/
│   │   │   └── Index.vue
│   │   └── design-system/
│   │       └── Index.vue
│   ├── router/             # 路由配置
│   │   └── index.js
│   ├── stores/             # Pinia 状态管理
│   │   └── theme.js
│   ├── styles/             # 样式文件
│   │   ├── layouts/        # 布局样式
│   │   │   └── SidebarLayout.scss
│   │   ├── views/          # 页面样式
│   │   │   ├── dashboard/
│   │   │   │   └── Index.scss
│   │   │   ├── copy-generator/
│   │   │   │   └── Index.scss
│   │   │   ├── poster-generator/
│   │   │   │   └── Index.scss
│   │   │   ├── video-generator/
│   │   │   │   └── Index.scss
│   │   │   ├── design-system/
│   │   │   │   └── Index.scss
│   │   │   └── ...
│   │   ├── variables.scss       # 全局变量
│   │   ├── element-plus-variables.scss  # Element Plus 变量
│   │   └── index.scss         # 全局样式入口
│   ├── utils/              # 工具函数
│   │   └── theme.js
│   ├── services/           # API 服务
│   │   └── api/
│   │       └── copy-api.js
│   ├── App.vue
│   └── main.js
├── public/
├── index.html
├── package.json
├── vite.config.js
└── ...

Vue 3 组件开发规范

单文件组件 (SFC) 结构

vue
<template>
  <div class="component-name">
    <!-- 模板内容 -->
  </div>
</template>

<script setup>
// 1. 导入
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { IconName } from '@element-plus/icons-vue'

// 2. 外部依赖
const router = useRouter()

// 3. 响应式数据
const count = ref(0)
const form = reactive({
  name: '',
  email: ''
})

// 4. 计算属性
const doubledCount = computed(() => count.value * 2)

// 5. 方法
const handleClick = () => {
  count.value++
}

// 6. 生命周期
onMounted(() => {
  console.log('Component mounted')
})
</script>

<style lang="scss" scoped>
// 只保留导入语句,样式放在独立文件中
@import '@/styles/path/to/component.scss';
</style>

组件命名规范

  • 文件命名:PascalCase,如 SmartCreatorInput.vue
  • 组件注册:PascalCase,如 <SmartCreatorInput />
  • CSS 类名:kebab-case,如 .smart-creator-input

Props 定义

javascript
const props = defineProps({
  title: {
    type: String,
    required: true,
    default: ''
  },
  count: {
    type: Number,
    default: 0
  },
  items: {
    type: Array,
    default: () => []
  }
})

Emits 定义

javascript
const emit = defineEmits(['update:modelValue', 'submit', 'cancel'])

const handleSubmit = () => {
  emit('submit', { data: 'value' })
}

样式工程化规范

样式分离原则

所有样式必须放在独立的 SCSS 文件中,Vue 组件只保留 @import 语句。

样式文件命名与目录

  • 布局样式src/styles/layouts/ComponentName.scss
  • 页面样式src/styles/views/page-name/Index.scss
  • 通用组件样式src/styles/components/ComponentName.scss

SCSS 导入规范

vue
<!-- Vue 组件中的样式块 -->
<style lang="scss" scoped>
@import '@/styles/views/dashboard/Index.scss';
</style>

SCSS 编写规范

1. BEM 命名规范

scss
.block {
  // 块样式
  
  &__element {
    // 元素样式
  }
  
  &--modifier {
    // 修饰符样式
  }
}

2. 嵌套层级不超过 4 层

scss
// ✅ 推荐
.card {
  .card-header {
    .card-title {
      font-size: 16px;
    }
  }
}

// ❌ 避免
.card {
  .card-header {
    .card-title {
      .title-text {
        font-size: 16px; // 4层嵌套
      }
    }
  }
}

3. 使用 CSS 变量

scss
// 定义在 element-plus-variables.scss 中
:root {
  --hotel-color-primary: #4a90e2;
  --hotel-bg-page: #f5f7fa;
  --hotel-text-primary: #1a202c;
}

// 使用
.card {
  background: var(--hotel-bg-page);
  color: var(--hotel-text-primary);
  border-color: var(--hotel-color-primary);
}

4. 莫兰迪配色使用

scss
// 使用定义好的 CSS 变量
.background-mocha {
  background: var(--hotel-bg-mocha);
}

.accent-sage {
  color: var(--hotel-accent-sage);
}

路由规范

路由定义

javascript
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'Dashboard',
    component: () => import('@/views/dashboard/Index.vue'),
    meta: {
      title: '首页',
      requiresAuth: false
    }
  },
  {
    path: '/copy-generator',
    name: 'CopyGenerator',
    component: () => import('@/views/copy-generator/Index.vue'),
    meta: {
      title: '文案生成'
    }
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

路由导航

javascript
// 编程式导航
router.push('/copy-generator')
router.push({ name: 'CopyGenerator' })
router.push({ path: '/copy-generator', query: { id: 1 } })

状态管理规范 (Pinia)

Store 定义

javascript
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useThemeStore = defineStore('theme', () => {
  // 状态
  const currentTheme = ref('light')
  
  // 计算属性
  const isDark = computed(() => currentTheme.value === 'dark')
  
  // 方法
  const toggleTheme = () => {
    currentTheme.value = isDark.value ? 'light' : 'dark'
  }
  
  return {
    currentTheme,
    isDark,
    toggleTheme
  }
})

Store 使用

javascript
import { useThemeStore } from '@/stores/theme'

const themeStore = useThemeStore()
const isDark = computed(() => themeStore.isDark)

Git 提交规范

提交信息格式

<type>(<scope>): <subject>

<body>

<footer>

Type 类型

  • feat: 新功能
  • fix: 修复 bug
  • docs: 文档更新
  • style: 代码格式调整
  • refactor: 重构
  • test: 测试相关
  • chore: 构建/工具相关

示例

feat(dashboard): 添加智能创作输入框

- 实现 SmartCreatorInput 组件
- 添加模板快捷功能
- 添加灵感标签功能

Closes #123

性能优化规范

1. 路由懒加载

javascript
// ✅ 使用动态导入
const Dashboard = () => import('@/views/dashboard/Index.vue')

// ❌ 避免直接导入
import Dashboard from '@/views/dashboard/Index.vue'

2. 组件懒加载

vue
<script setup>
import { defineAsyncComponent } from 'vue'

const HeavyComponent = defineAsyncComponent(() => 
  import('@/components/HeavyComponent.vue')
)
</script>

<template>
  <HeavyComponent v-if="showHeavy" />
</template>

3. 使用 v-once

vue
<!-- 静态内容只渲染一次 -->
<div v-once>
  <h1>静态标题</h1>
  <p>静态描述</p>
</div>

4. 避免不必要的响应式

javascript
// ✅ 不需要响应式的数据
const staticData = { name: 'value' }

// ❌ 避免对静态数据使用 ref
const staticData = ref({ name: 'value' })

测试规范

单元测试

javascript
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import Component from './Component.vue'

describe('Component', () => {
  it('renders properly', () => {
    const wrapper = mount(Component, {
      props: { title: 'Test' }
    })
    expect(wrapper.text()).toContain('Test')
  })
})

开发工具配置

VS Code 推荐插件

  • Volar (Vue 3 官方语言服务)
  • ESLint
  • Prettier
  • SCSS Formatter
  • Git Graph

推荐设置

json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "volar.completion.autoImportComponent": true
}

常见问题排查

样式不生效

  1. 检查 SCSS 文件路径是否正确
  2. 确认 CSS 变量是否已定义
  3. 检查 scoped 是否影响样式作用域

组件不更新

  1. 检查响应式数据是否正确使用 .value
  2. 确认计算属性依赖是否正确
  3. 检查 props 是否变化

性能问题

  1. 使用 Vue DevTools 检查组件渲染
  2. 确认是否有不必要的响应式数据
  3. 检查是否有内存泄漏

参考资源


最后更新: 2024-03-17 维护者: 开发团队