酒店新媒体智能体 - 前端工程化开发标准
概述
本文档定义了 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: 修复 bugdocs: 文档更新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
}常见问题排查
样式不生效
- 检查 SCSS 文件路径是否正确
- 确认 CSS 变量是否已定义
- 检查
scoped是否影响样式作用域
组件不更新
- 检查响应式数据是否正确使用
.value - 确认计算属性依赖是否正确
- 检查 props 是否变化
性能问题
- 使用 Vue DevTools 检查组件渲染
- 确认是否有不必要的响应式数据
- 检查是否有内存泄漏
参考资源
最后更新: 2024-03-17 维护者: 开发团队