初始化项目
This commit is contained in:
@@ -0,0 +1,869 @@
|
||||
# Vue3 后台管理项目开发规范
|
||||
|
||||
## 项目概述
|
||||
|
||||
本项目是一个基于 Vue3 的后台管理系统,采用现代化技术栈构建,提供高效、美观的管理界面。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **Vue 3**: 渐进式 JavaScript 框架
|
||||
- **Vite**: 下一代前端构建工具
|
||||
- **Ant Design Vue**: 基于 Vue 3 的 UI 组件库
|
||||
- **Vue Router**: Vue.js 官方路由管理器
|
||||
- **Pinia**: Vue 3 官方状态管理库
|
||||
- **Axios**: HTTP 客户端
|
||||
- **JavaScript**: 主要开发语言(非 TypeScript)
|
||||
- **Composition API**: 组合式 API 开发模式
|
||||
|
||||
## 图标系统
|
||||
|
||||
项目采用 Ant Design Vue 图标库,已全局引入:
|
||||
|
||||
- **Ant Design Vue Icons**: Ant Design Vue 官方图标库
|
||||
|
||||
**重要提示**: 图标已全局默认引入,开发时请勿重复引入或按需引入,直接使用即可。
|
||||
|
||||
## 开发规范
|
||||
|
||||
### 1. 项目结构
|
||||
|
||||
```
|
||||
resources/admin/
|
||||
├── src/
|
||||
│ ├── api/ # API 接口层
|
||||
│ │ ├── auth.js # 认证相关接口
|
||||
│ │ ├── menu.js # 菜单接口
|
||||
│ │ └── system.js # 系统相关接口
|
||||
│ ├── assets/ # 静态资源
|
||||
│ │ ├── images/ # 图片资源
|
||||
│ │ └── style/ # 全局样式
|
||||
│ ├── components/ # 公共组件
|
||||
│ │ ├── scEditor/ # 富文本编辑器
|
||||
│ │ ├── scForm/ # 表单组件
|
||||
│ │ ├── scIconPicker/ # 图标选择器
|
||||
│ │ ├── scTable/ # 表格组件
|
||||
│ │ └── scUpload/ # 上传组件
|
||||
│ ├── config/ # 配置文件
|
||||
│ │ ├── index.js # 主配置
|
||||
│ │ ├── routes.js # 路由配置
|
||||
│ │ └── upload.js # 上传配置
|
||||
│ ├── hooks/ # 组合式 API Hooks
|
||||
│ │ ├── useI18n.js # 国际化 Hook
|
||||
│ │ └── useTable.js # 表格 Hook
|
||||
│ ├── i18n/ # 国际化配置
|
||||
│ │ ├── index.js # i18n 配置
|
||||
│ │ └── locales/ # 语言包
|
||||
│ ├── layouts/ # 布局组件
|
||||
│ │ ├── components/ # 布局子组件
|
||||
│ │ ├── other/ # 其他布局
|
||||
│ │ └── index.vue # 主布局
|
||||
│ ├── pages/ # 页面组件
|
||||
│ │ ├── auth/ # 认证页面
|
||||
│ │ ├── home/ # 首页
|
||||
│ │ ├── login/ # 登录页
|
||||
│ │ ├── system/ # 系统管理
|
||||
│ │ └── ucenter/ # 个人中心
|
||||
│ ├── router/ # 路由配置
|
||||
│ │ ├── index.js # 主路由
|
||||
│ │ └── systemRoutes.js # 系统路由
|
||||
│ ├── stores/ # 状态管理
|
||||
│ │ ├── index.js # Store 入口
|
||||
│ │ ├── persist.js # 持久化配置
|
||||
│ │ └── modules/ # Store 模块
|
||||
│ ├── utils/ # 工具函数
|
||||
│ │ ├── request.js # Axios 封装
|
||||
│ │ └── tool.js # 工具函数
|
||||
│ ├── App.vue # 根组件
|
||||
│ ├── boot.js # 引导文件
|
||||
│ ├── main.js # 入口文件
|
||||
│ └── style.css # 全局样式
|
||||
├── public/ # 公共资源
|
||||
├── index.html # HTML 模板
|
||||
├── package.json # 依赖配置
|
||||
├── vite.config.js # Vite 配置
|
||||
└── README.md # 项目说明
|
||||
```
|
||||
|
||||
### 2. 组件开发规范
|
||||
|
||||
#### 组件命名
|
||||
|
||||
- **单文件组件**: 使用 PascalCase 命名,如 `UserList.vue`
|
||||
- **公共组件**: 以 `sc` 开头,如 `scTable.vue`
|
||||
- **页面组件**: 使用语义化命名,如 `UserManagement.vue`
|
||||
|
||||
#### 组件结构
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<!-- 模板内容 -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 导入
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
|
||||
// 响应式数据
|
||||
const state = ref({})
|
||||
|
||||
// 计算属性
|
||||
const computedValue = computed(() => {})
|
||||
|
||||
// 方法
|
||||
const handleAction = () => {}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 样式 */
|
||||
</style>
|
||||
```
|
||||
|
||||
### 3. API 接口开发规范
|
||||
|
||||
#### API 文件组织
|
||||
|
||||
每个业务模块对应一个 API 文件,统一放在 `src/api/` 目录下。
|
||||
|
||||
```javascript
|
||||
// src/api/auth.js
|
||||
import request from '@/utils/request'
|
||||
|
||||
export default {
|
||||
// 认证相关
|
||||
login: {
|
||||
post: async function (params) {
|
||||
return await request.post('auth/login', params)
|
||||
},
|
||||
},
|
||||
logout: {
|
||||
post: async function () {
|
||||
return await request.post('auth/logout')
|
||||
},
|
||||
},
|
||||
me: {
|
||||
get: async function () {
|
||||
return await request.get('auth/me')
|
||||
},
|
||||
},
|
||||
|
||||
// 权限和菜单
|
||||
permissions: {
|
||||
menu: {
|
||||
get: async function () {
|
||||
return await request.get('permissions/menu')
|
||||
},
|
||||
},
|
||||
tree: {
|
||||
get: async function () {
|
||||
return await request.get('permissions/tree')
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```javascript
|
||||
import authApi from '@/api/auth'
|
||||
|
||||
const login = async () => {
|
||||
try {
|
||||
const res = await authApi.login.post({
|
||||
username: 'admin',
|
||||
password: '123456'
|
||||
})
|
||||
// 处理响应
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户菜单
|
||||
const getMenu = async () => {
|
||||
const res = await authApi.permissions.menu.get()
|
||||
return res.data
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 路由开发规范
|
||||
|
||||
#### 路由类型
|
||||
|
||||
项目包含两类路由:
|
||||
|
||||
1. **静态路由**: 定义在 `src/router/systemRoutes.js` 中的基础路由,如登录页、404 页面等
|
||||
2. **动态路由**: 用户登录后,通过 API 获取菜单数据,动态添加到路由中
|
||||
|
||||
#### 静态路由定义
|
||||
|
||||
```javascript
|
||||
// src/router/systemRoutes.js
|
||||
export default [
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import('@/pages/login/index.vue'),
|
||||
meta: {
|
||||
title: '登录',
|
||||
hidden: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
name: 'Layout',
|
||||
component: () => import('@/layouts/index.vue'),
|
||||
redirect: '/dashboard',
|
||||
children: [
|
||||
// 动态路由将被添加到这里
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### 动态路由加载
|
||||
|
||||
用户登录后,系统会自动执行以下流程:
|
||||
|
||||
1. 调用后端 API 获取用户菜单和权限信息
|
||||
2. 将菜单数据转换为路由格式
|
||||
3. 将动态路由添加到路由器中
|
||||
4. 生成菜单树用于侧边栏展示
|
||||
|
||||
**路由元信息 (meta)**:
|
||||
- `title`: 页面标题
|
||||
- `icon`: 菜单图标(使用 Ant Design Vue 图标名称)
|
||||
- `hidden`: 是否隐藏菜单
|
||||
- `noAuth`: 是否不需要认证
|
||||
- `keepAlive`: 是否缓存页面
|
||||
- `affix`: 是否固定标签页
|
||||
|
||||
**后端菜单数据格式**:
|
||||
|
||||
```javascript
|
||||
{
|
||||
path: '/system',
|
||||
name: 'System',
|
||||
title: '系统管理',
|
||||
icon: 'Setting',
|
||||
component: 'views/system', // 组件路径,相对于 pages 目录
|
||||
redirect: '/system/user',
|
||||
children: [
|
||||
{
|
||||
path: 'user',
|
||||
name: 'SystemUser',
|
||||
title: '用户管理',
|
||||
icon: 'User',
|
||||
component: 'views/system/user'
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**路由转换逻辑**:
|
||||
|
||||
```javascript
|
||||
// 将后端菜单转换为路由格式
|
||||
function transformMenusToRoutes(menus) {
|
||||
return menus.map(menu => {
|
||||
const route = {
|
||||
path: menu.path,
|
||||
name: menu.name,
|
||||
meta: {
|
||||
title: menu.title,
|
||||
icon: menu.icon,
|
||||
hidden: menu.hidden,
|
||||
keepAlive: menu.keepAlive || false
|
||||
}
|
||||
}
|
||||
|
||||
if (menu.component) {
|
||||
route.component = loadComponent(menu.component)
|
||||
}
|
||||
|
||||
if (menu.children) {
|
||||
route.children = transformMenusToRoutes(menu.children)
|
||||
}
|
||||
|
||||
return route
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
#### 路由守卫
|
||||
|
||||
系统通过路由守卫实现权限控制和动态路由加载:
|
||||
|
||||
```javascript
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const userStore = useUserStore()
|
||||
const isLoggedIn = userStore.isLoggedIn()
|
||||
|
||||
// 白名单直接放行
|
||||
if (whiteList.includes(to.path)) {
|
||||
return next()
|
||||
}
|
||||
|
||||
// 未登录跳转登录页
|
||||
if (!isLoggedIn) {
|
||||
return next({ path: '/login', query: { redirect: to.fullPath } })
|
||||
}
|
||||
|
||||
// 动态路由加载
|
||||
if (!isDynamicRouteLoaded) {
|
||||
const menus = userStore.getMenu()
|
||||
const dynamicRoutes = transformMenusToRoutes(menus)
|
||||
|
||||
// 添加动态路由
|
||||
dynamicRoutes.forEach(route => {
|
||||
router.addRoute('Layout', route)
|
||||
})
|
||||
|
||||
isDynamicRouteLoaded = true
|
||||
next({ ...to, replace: true })
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 5. 状态管理规范
|
||||
|
||||
#### Pinia Store 定义
|
||||
|
||||
使用组合式 API 定义 Store。
|
||||
|
||||
#### User Store(用户认证与权限)
|
||||
|
||||
`src/stores/modules/user.js` 负责管理用户认证信息和权限数据:
|
||||
|
||||
```javascript
|
||||
// src/stores/modules/user.js
|
||||
import { ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { resetRouter } from '../../router'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
// State
|
||||
const token = ref('') // 访问令牌
|
||||
const refreshToken = ref('') // 刷新令牌
|
||||
const userInfo = ref(null) // 用户信息
|
||||
const menu = ref([]) // 用户菜单
|
||||
const permissions = ref([]) // 用户权限节点
|
||||
|
||||
// Getters
|
||||
const isLoggedIn = () => !!token.value
|
||||
|
||||
// Actions
|
||||
function setToken(newToken) {
|
||||
token.value = newToken
|
||||
}
|
||||
|
||||
function setUserInfo(info) {
|
||||
userInfo.value = info
|
||||
}
|
||||
|
||||
// 设置菜单(合并静态菜单和后端菜单)
|
||||
function setMenu(newMenu) {
|
||||
const staticMenus = userRoutes || []
|
||||
let mergedMenus = [...staticMenus]
|
||||
|
||||
if (newMenu && newMenu.length > 0) {
|
||||
const menuMap = new Map()
|
||||
|
||||
// 添加静态菜单
|
||||
staticMenus.forEach(m => {
|
||||
if (m.path) menuMap.set(m.path, m)
|
||||
})
|
||||
|
||||
// 添加后端菜单(覆盖重复路径)
|
||||
newMenu.forEach(m => {
|
||||
if (m.path) menuMap.set(m.path, m)
|
||||
})
|
||||
|
||||
mergedMenus = Array.from(menuMap.values())
|
||||
}
|
||||
menu.value = mergedMenus
|
||||
}
|
||||
|
||||
function getMenu() {
|
||||
return menu.value
|
||||
}
|
||||
|
||||
function setPermissions(data) {
|
||||
permissions.value = data
|
||||
}
|
||||
|
||||
function hasPermission(permission) {
|
||||
if (!permissions.value || permissions.value.length === 0) {
|
||||
return false
|
||||
}
|
||||
return permissions.value.includes(permission)
|
||||
}
|
||||
|
||||
function logout() {
|
||||
token.value = ''
|
||||
refreshToken.value = ''
|
||||
userInfo.value = null
|
||||
menu.value = []
|
||||
resetRouter()
|
||||
}
|
||||
|
||||
return {
|
||||
token,
|
||||
refreshToken,
|
||||
userInfo,
|
||||
menu,
|
||||
permissions,
|
||||
setToken,
|
||||
setUserInfo,
|
||||
setMenu,
|
||||
getMenu,
|
||||
setPermissions,
|
||||
hasPermission,
|
||||
logout,
|
||||
isLoggedIn
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Store 使用
|
||||
|
||||
```javascript
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 使用 state
|
||||
console.log(userStore.token)
|
||||
console.log(userStore.menu)
|
||||
console.log(userStore.permissions)
|
||||
|
||||
// 调用 action
|
||||
userStore.setToken('xxx')
|
||||
userStore.setMenu(menus)
|
||||
userStore.setPermissions(permissions)
|
||||
|
||||
// 检查权限
|
||||
if (userStore.hasPermission('user.create')) {
|
||||
// 有权限,执行操作
|
||||
}
|
||||
|
||||
// 登出
|
||||
userStore.logout()
|
||||
```
|
||||
|
||||
#### Store 持久化
|
||||
|
||||
使用 `pinia-plugin-persistedstate` 实现数据持久化:
|
||||
|
||||
```javascript
|
||||
{
|
||||
persist: {
|
||||
key: 'user-store',
|
||||
storage: customStorage,
|
||||
pick: ['token', 'refreshToken', 'userInfo', 'menu']
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 权限指令
|
||||
|
||||
项目提供权限指令,用于在模板中控制元素显示:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<!-- 只有拥有 user.create 权限时显示 -->
|
||||
<a-button v-permission="'user.create'">新增</a-button>
|
||||
|
||||
<!-- 拥有多个权限之一时显示 -->
|
||||
<a-button v-permission="['user.create', 'user.update']">编辑</a-button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
</script>
|
||||
```
|
||||
|
||||
### 6. 表格开发规范
|
||||
|
||||
#### 使用 useTable Hook
|
||||
|
||||
项目提供了 `useTable` Hook 简化表格开发:
|
||||
|
||||
```javascript
|
||||
import { useTable } from '@/hooks/useTable'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const {
|
||||
loading,
|
||||
dataSource,
|
||||
pagination,
|
||||
handleSearch,
|
||||
handleReset,
|
||||
handlePageChange
|
||||
} = useTable({
|
||||
api: userApi.getList, // API 方法
|
||||
immediate: true // 是否立即加载
|
||||
})
|
||||
|
||||
// 搜索参数
|
||||
const searchParams = ref({
|
||||
keyword: '',
|
||||
status: ''
|
||||
})
|
||||
```
|
||||
|
||||
#### scTable 组件使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<sc-table
|
||||
:columns="columns"
|
||||
:data-source="dataSource"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
>
|
||||
<template #action="{ record }">
|
||||
<a-button @click="handleEdit(record)">编辑</a-button>
|
||||
</template>
|
||||
</sc-table>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 7. 表单开发规范
|
||||
|
||||
#### scForm 组件使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<sc-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
:items="formItems"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const formRef = ref(null)
|
||||
const formData = ref({
|
||||
username: '',
|
||||
email: ''
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: '请输入邮箱', trigger: 'blur' },
|
||||
{ type: 'email', message: '请输入正确的邮箱', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
const formItems = [
|
||||
{
|
||||
type: 'input',
|
||||
prop: 'username',
|
||||
label: '用户名',
|
||||
placeholder: '请输入用户名'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
prop: 'email',
|
||||
label: '邮箱',
|
||||
placeholder: '请输入邮箱'
|
||||
}
|
||||
]
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await formRef.value.validate()
|
||||
// 提交逻辑
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 8. 图标使用规范
|
||||
|
||||
#### Ant Design Vue Icons
|
||||
|
||||
```vue
|
||||
<!-- 直接使用,无需导入 -->
|
||||
<template>
|
||||
<a-icon type="user" />
|
||||
<a-icon type="setting" />
|
||||
</template>
|
||||
```
|
||||
|
||||
#### 常用图标
|
||||
|
||||
- `user`: 用户
|
||||
- `setting`: 设置
|
||||
- `delete`: 删除
|
||||
- `edit`: 编辑
|
||||
- `plus`: 添加
|
||||
- `search`: 搜索
|
||||
- `reload`: 刷新
|
||||
- `download`: 下载
|
||||
- `upload`: 上传
|
||||
- `eye`: 查看
|
||||
- `eye-invisible`: 隐藏
|
||||
- `check-circle`: 成功
|
||||
- `close-circle`: 失败
|
||||
- `info-circle`: 信息
|
||||
- `warning`: 警告
|
||||
|
||||
### 9. 国际化 (i18n) 规范
|
||||
|
||||
#### 使用 i18n
|
||||
|
||||
```javascript
|
||||
import { useI18n } from '@/hooks/useI18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// 使用
|
||||
console.log(t('common.save'))
|
||||
console.log(t('user.deleteConfirm'))
|
||||
```
|
||||
|
||||
#### 语言文件组织
|
||||
|
||||
```javascript
|
||||
// src/i18n/locales/zh.js
|
||||
export default {
|
||||
common: {
|
||||
save: '保存',
|
||||
cancel: '取消',
|
||||
confirm: '确认',
|
||||
delete: '删除'
|
||||
},
|
||||
user: {
|
||||
deleteConfirm: '确定要删除该用户吗?'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10. 文件上传规范
|
||||
|
||||
#### scUpload 组件使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<sc-upload
|
||||
v-model="imageUrl"
|
||||
:limit="1"
|
||||
accept="image/*"
|
||||
list-type="picture-card"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const imageUrl = ref('')
|
||||
</script>
|
||||
```
|
||||
|
||||
### 11. 富文本编辑器规范
|
||||
|
||||
#### scEditor 组件使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<sc-editor
|
||||
v-model="content"
|
||||
:height="400"
|
||||
:toolbar="toolbarConfig"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const content = ref('')
|
||||
const toolbarConfig = [
|
||||
'bold', 'italic', 'underline', 'strike',
|
||||
'list', 'orderedList', 'quote', 'codeBlock',
|
||||
'image', 'link'
|
||||
]
|
||||
</script>
|
||||
```
|
||||
|
||||
### 12. 样式规范
|
||||
|
||||
#### 全局样式
|
||||
|
||||
在 `src/style.css` 中定义全局样式。
|
||||
|
||||
#### 组件样式
|
||||
|
||||
使用 `scoped` 避免样式污染:
|
||||
|
||||
```vue
|
||||
<style scoped>
|
||||
.user-list {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.user-list .table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
#### 命名规范
|
||||
|
||||
- 使用 BEM 命名法
|
||||
- 类名使用 kebab-case
|
||||
|
||||
### 13. 工具函数使用
|
||||
|
||||
#### request.js (HTTP 请求)
|
||||
|
||||
```javascript
|
||||
import request from '@/utils/request'
|
||||
|
||||
// GET 请求
|
||||
request.get('/api/users', { params: { page: 1 } })
|
||||
|
||||
// POST 请求
|
||||
request.post('/api/users', { name: 'test' })
|
||||
|
||||
// PUT 请求
|
||||
request.put('/api/users/1', { name: 'updated' })
|
||||
|
||||
// DELETE 请求
|
||||
request.delete('/api/users/1')
|
||||
```
|
||||
|
||||
#### tool.js (工具函数)
|
||||
|
||||
```javascript
|
||||
import { formatDate, deepClone } from '@/utils/tool'
|
||||
|
||||
// 格式化日期
|
||||
formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss')
|
||||
|
||||
// 深拷贝
|
||||
deepClone(originalObject)
|
||||
```
|
||||
|
||||
### 14. 开发流程
|
||||
|
||||
#### 登录流程
|
||||
|
||||
1. 用户输入用户名和密码
|
||||
2. 调用 `authApi.login.post()` 发送登录请求
|
||||
3. 后端返回 `token`、`refreshToken`、`userInfo`、`menu`、`permissions`
|
||||
4. 前端保存数据到 Store(持久化)
|
||||
5. 路由守卫检测到登录状态,加载动态路由
|
||||
6. 跳转到首页或重定向页
|
||||
|
||||
```javascript
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
import authApi from '@/api/auth'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
const res = await authApi.login.post({
|
||||
username: 'admin',
|
||||
password: '123456'
|
||||
})
|
||||
|
||||
// 保存 token
|
||||
userStore.setToken(res.data.token)
|
||||
userStore.setRefreshToken(res.data.refreshToken)
|
||||
|
||||
// 保存用户信息
|
||||
userStore.setUserInfo(res.data.user)
|
||||
|
||||
// 保存菜单(合并静态菜单)
|
||||
userStore.setMenu(res.data.menu)
|
||||
|
||||
// 保存权限节点
|
||||
userStore.setPermissions(res.data.permissions)
|
||||
|
||||
// 跳转首页
|
||||
router.push('/dashboard')
|
||||
} catch (error) {
|
||||
message.error('登录失败')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 添加新页面
|
||||
|
||||
1. 在 `src/pages/` 对应模块下创建页面组件
|
||||
2. 在 `src/api/` 中创建对应的 API 文件
|
||||
3. 在后端添加对应的菜单和权限配置
|
||||
4. 前端会自动加载动态路由(无需手动配置路由)
|
||||
|
||||
#### 添加新组件
|
||||
|
||||
1. 在 `src/components/` 或对应子目录下创建组件
|
||||
2. 遵循组件结构规范
|
||||
3. 添加必要的 Props 和 Emits
|
||||
4. 编写组件文档
|
||||
|
||||
### 15. 常用命令
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 开发环境启动
|
||||
npm run dev
|
||||
|
||||
# 生产环境构建
|
||||
npm run build
|
||||
|
||||
# 预览生产构建
|
||||
npm run preview
|
||||
|
||||
# 代码格式化
|
||||
npm run format
|
||||
|
||||
# 代码检查
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### 16. 注意事项
|
||||
|
||||
1. **禁止重复引入图标**: Ant Design Vue 图标已全局引入,直接使用即可
|
||||
2. **使用组合式 API**: 新代码统一使用 `<script setup>` 语法
|
||||
3. **组件复用**: 优先使用项目提供的公共组件(scTable、scForm 等)
|
||||
4. **API 统一管理**: 所有接口统一在 `src/api/` 目录下管理
|
||||
5. **路由懒加载**: 路由组件必须使用动态导入
|
||||
6. **环境变量**: 通过 `import.meta.env` 访问环境变量
|
||||
7. **不要编写 demo**: 开发过程中不编写示例代码
|
||||
8. **测试提示**: 如需测试,提示用户是否运行测试,不主动运行
|
||||
|
||||
### 17. 代码质量
|
||||
|
||||
- 遵循 Vue 3 官方风格指南
|
||||
- 保持代码简洁、可读
|
||||
- 适当添加注释说明复杂逻辑
|
||||
- 使用语义化的变量和函数命名
|
||||
- 避免过多的嵌套层级
|
||||
|
||||
### 18. 性能优化
|
||||
|
||||
- 合理使用 `v-if` 和 `v-show`
|
||||
- 列表渲染必须设置 `key`
|
||||
- 大列表使用虚拟滚动
|
||||
- 图片懒加载
|
||||
- 路由懒加载
|
||||
- 组件按需引入(除图标外)
|
||||
@@ -0,0 +1,996 @@
|
||||
# Laravel + Laravel-S 后端 API 项目开发规范
|
||||
|
||||
## 项目概述
|
||||
|
||||
本项目是一个基于 Laravel 框架开发的纯后端 API 系统,使用 `hhxsv5/laravel-s` 作为粘合剂,将 Swoole 与 Laravel 框架完美结合,提供高性能的异步服务能力。项目采用模块化开发架构,使用 `nwidart/laravel-modules` 扩展实现业务模块化管理。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **PHP**: 主要开发语言
|
||||
- **Laravel**: Web 应用框架
|
||||
- **Laravel-S (hhxsv5/laravel-s)**: Swoole 集成扩展
|
||||
- **Swoole**: 高性能 PHP 协程框架
|
||||
- **JWT (tymon/jwt-auth)**: 用户认证
|
||||
- **nwidart/laravel-modules**: 模块化开发扩展
|
||||
- **MySQL**: 关系型数据库
|
||||
|
||||
## 模块化架构
|
||||
|
||||
### 模块分类
|
||||
|
||||
项目分为两类模块:
|
||||
|
||||
1. **基础模块 (Base Modules)**
|
||||
- **Auth**: 认证授权模块(用户、角色、权限)
|
||||
- **System**: 系统配置模块(配置、日志、字典)
|
||||
- 特点:不使用 `nwidart/laravel-modules` 扩展,直接在 Laravel 应用结构中开发
|
||||
- 位置:`app/` 目录下
|
||||
|
||||
2. **业务模块 (Business Modules)**
|
||||
- 使用 `nwidart/laravel-modules` 扩展创建
|
||||
- 位置:`Modules/` 目录下
|
||||
- 每个业务模块独立拥有完整的 MVC 结构
|
||||
|
||||
### 项目结构
|
||||
|
||||
```
|
||||
├── app/ # 基础模块目录
|
||||
│ ├── Http/
|
||||
│ │ ├── Controllers/ # 基础模块控制器
|
||||
│ │ │ ├── Auth/ # 认证相关控制器
|
||||
│ │ │ │ └── Admin
|
||||
│ │ │ │ │ ├── Auth.php
|
||||
│ │ │ │ │ ├── User.php
|
||||
│ │ │ │ │ ├── Role.php
|
||||
│ │ │ │ │ └── Permission.php
|
||||
│ │ │ └── System/ # 系统相关控制器
|
||||
│ │ │ └── Admin
|
||||
│ │ │ └── Api
|
||||
│ │ └── Middleware/ # 中间件
|
||||
│ ├── Models/ # 基础模块模型
|
||||
│ │ └── Auth/
|
||||
│ │ ├── User.php
|
||||
│ │ ├── Role.php
|
||||
│ │ └── Permission.php
|
||||
│ └── Services/ # 基础模块服务层
|
||||
│ └── Auth/
|
||||
│ ├── AuthService.php
|
||||
│ ├── UserService.php
|
||||
│ ├── RoleService.php
|
||||
│ └── PermissionService.php
|
||||
├── Modules/ # 业务模块目录
|
||||
│ ├── ModuleName/ # 业务模块示例
|
||||
│ │ ├── App/
|
||||
│ │ │ ├── Http/
|
||||
│ │ │ │ ├── Controllers/ # 模块控制器
|
||||
│ │ │ │ │ ├── Admin/ # 后台管理控制器
|
||||
│ │ │ │ │ └── Api/ # 用户端API控制器
|
||||
│ │ │ │ ├── Middleware/ # 模块中间件
|
||||
│ │ │ │ └── Requests/ # 表单验证
|
||||
│ │ │ ├── Models/ # 模块模型
|
||||
│ │ │ ├── Services/ # 模块服务层
|
||||
│ │ │ └── Providers/ # 模块服务提供者
|
||||
│ │ ├── Database/
|
||||
│ │ │ ├── migrations/ # 模块迁移文件
|
||||
│ │ │ └── seeders/ # 模块数据填充
|
||||
│ │ ├── Routes/
|
||||
│ │ │ ├── admin.php # 后台管理路由(/admin前缀)
|
||||
│ │ │ └── api.php # 用户端API路由(/api前缀)
|
||||
│ │ ├── Resources/ # API 资源
|
||||
│ │ ├── config/ # 模块配置文件
|
||||
│ │ ├── module.json # 模块配置
|
||||
│ │ └── README.md # 模块说明文档
|
||||
├── config/
|
||||
│ ├── modules.php # 模块配置
|
||||
│ └── laravels.php # Laravel-S 配置文件
|
||||
├── database/
|
||||
│ ├── migrations/ # 基础模块迁移文件
|
||||
│ └── seeders/ # 基础模块数据填充
|
||||
├── routes/
|
||||
│ ├── admin.php # 后台管理路由(基础模块)
|
||||
│ └── api.php # 公共 API 路由(基础模块)
|
||||
└── storage/
|
||||
├── laravels.conf # Laravel-S 运行时配置
|
||||
└── laravels.pid # Laravel-S 进程 ID
|
||||
```
|
||||
|
||||
## 开发规范
|
||||
|
||||
### 1. 控制器层 (Controllers)
|
||||
|
||||
#### 基础模块控制器
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `app/Http/Controllers/{Module}/{Name}.php`
|
||||
- 类名: `{Name}` (不加 Controller 后缀)
|
||||
- 命名空间: `App\Http\Controllers\{Module}`
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\Auth\UserService;
|
||||
|
||||
class User extends Controller
|
||||
{
|
||||
protected $userService;
|
||||
|
||||
public function __construct(UserService $userService)
|
||||
{
|
||||
$this->userService = $userService;
|
||||
}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$result = $this->userService->getList($request->all());
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务模块控制器
|
||||
|
||||
业务模块控制器分为两类:
|
||||
|
||||
**1. 后台管理控制器**
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `Modules/{ModuleName}/App/Http/Controllers/Admin/{Name}.php`
|
||||
- 类名: `{Name}` (不加 Controller 后缀)
|
||||
- 命名空间: `Modules\{ModuleName}\App\Http\Controllers\Admin`
|
||||
- 访问路径: `/admin/{module}/{resource}`
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Modules\Blog\App\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Blog\App\Services\PostService;
|
||||
|
||||
class Post extends Controller
|
||||
{
|
||||
protected $postService;
|
||||
|
||||
public function __construct(PostService $postService)
|
||||
{
|
||||
$this->postService = $postService;
|
||||
}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$result = $this->postService->getList($request->all());
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**2. 用户端 API 控制器**
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `Modules/{ModuleName}/App/Http/Controllers/Api/{Name}.php`
|
||||
- 类名: `{Name}` (不加 Controller 后缀)
|
||||
- 命名空间: `Modules\{ModuleName}\App\Http\Controllers\Api`
|
||||
- 访问路径: `/api/{module}/{resource}`
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Modules\Blog\App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Blog\App\Services\PostService;
|
||||
|
||||
class Post extends Controller
|
||||
{
|
||||
protected $postService;
|
||||
|
||||
public function __construct(PostService $postService)
|
||||
{
|
||||
$this->postService = $postService;
|
||||
}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$result = $this->postService->getList($request->all());
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 服务层 (Services)
|
||||
|
||||
#### 基础模块服务
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `app/Services/{Module}/{Name}Service.php`
|
||||
- 类名: `{Name}Service`
|
||||
- 命名空间: `App\Services\{Module}`
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Services\Auth;
|
||||
|
||||
use App\Models\Auth\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UserService
|
||||
{
|
||||
public function create(array $data): User
|
||||
{
|
||||
$data['password'] = Hash::make($data['password']);
|
||||
return User::create($data);
|
||||
}
|
||||
|
||||
public function getById(int $id): ?User
|
||||
{
|
||||
return User::find($id);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务模块服务
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `Modules/{ModuleName}/App/Services/{Name}Service.php`
|
||||
- 类名: `{Name}Service`
|
||||
- 命名空间: `Modules\{ModuleName}\App\Services`
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Modules\Blog\App\Services;
|
||||
|
||||
use Modules\Blog\App\Models\Post;
|
||||
|
||||
class PostService
|
||||
{
|
||||
public function create(array $data): Post
|
||||
{
|
||||
return Post::create($data);
|
||||
}
|
||||
|
||||
public function getById(int $id): ?Post
|
||||
{
|
||||
return Post::find($id);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 模型层 (Models)
|
||||
|
||||
#### 基础模块模型
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `app/Models/{Module}/{Name}.php`
|
||||
- 类名: `{Name}` (单数形式)
|
||||
- 命名空间: `App\Models\{Module}`
|
||||
- 数据表: `{module}_{names}` (复数形式,带模块前缀)
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Models\Auth;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Role extends Model
|
||||
{
|
||||
protected $table = 'auth_roles';
|
||||
|
||||
protected $fillable = ['name', 'description'];
|
||||
|
||||
public function permissions(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Permission::class, 'auth_role_permission');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务模块模型
|
||||
|
||||
**命名规范:**
|
||||
- 文件路径: `Modules/{ModuleName}/App/Models/{Name}.php`
|
||||
- 类名: `{Name}` (单数形式)
|
||||
- 命名空间: `Modules\{ModuleName}\App\Models`
|
||||
- 数据表: `{module}_{names}` (复数形式,带模块前缀)
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Modules\Blog\App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
protected $table = 'blog_posts';
|
||||
|
||||
protected $fillable = ['title', 'content', 'status'];
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 中间件 (Middleware)
|
||||
|
||||
**常用中间件:**
|
||||
- `AdminAuth`: 后台管理认证
|
||||
- `api.throttle`: API 请求频率限制
|
||||
|
||||
### 5. API 路由
|
||||
|
||||
#### 基础模块路由
|
||||
|
||||
基础模块路由定义在 `routes/` 目录下,通过 `bootstrap/app.php` 进行配置:
|
||||
|
||||
- `routes/admin.php`: 后台管理路由,自动添加 `/admin` 前缀和 `admin.` 路由名称前缀
|
||||
- `routes/api.php`: 公共 API 路由,自动添加 `/api` 前缀
|
||||
- `routes/web.php`: Web 路由
|
||||
- `routes/console.php`: 命令行路由
|
||||
|
||||
**路由配置 (bootstrap/app.php):**
|
||||
```php
|
||||
<?php
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
api: __DIR__.'/../routes/api.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
then: function() {
|
||||
Route::middleware(['api'])
|
||||
->prefix('admin')
|
||||
->name('admin.')
|
||||
->group(base_path('routes/admin.php'));
|
||||
},
|
||||
health: '/up',
|
||||
)
|
||||
->create();
|
||||
```
|
||||
|
||||
**中间件配置:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
$middleware->alias([
|
||||
'auth.check' => \App\Http\Middleware\AuthCheckMiddleware::class,
|
||||
]);
|
||||
})
|
||||
```
|
||||
|
||||
**异常处理配置:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
$exceptions->shouldRenderJsonWhen(function(Request $request, Throwable $e){
|
||||
return $request->expectsJson();
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
**事件监听器配置:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
->withEvents(discover: [
|
||||
__DIR__ . '/../app/Listeners'
|
||||
])
|
||||
```
|
||||
|
||||
**路由示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
// routes/admin.php - 后台管理路由
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\Auth\User;
|
||||
|
||||
Route::middleware(['admin.auth'])->group(function () {
|
||||
Route::apiResource('users', User::class);
|
||||
// 路由名称: admin.users.index, admin.users.store, etc.
|
||||
});
|
||||
|
||||
// routes/api.php - 公共 API 路由
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\Auth\User;
|
||||
|
||||
Route::middleware(['auth:api'])->group(function () {
|
||||
Route::apiResource('profile', User::class);
|
||||
});
|
||||
```
|
||||
|
||||
#### 业务模块路由
|
||||
|
||||
业务模块路由包含两个文件,分别定义后台管理和用户端 API 路由:
|
||||
|
||||
**1. 后台管理路由 (Routes/admin.php)**
|
||||
|
||||
文件路径:`Modules/{ModuleName}/Routes/admin.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Blog\App\Http\Controllers\Admin\Post;
|
||||
|
||||
Route::middleware(['admin.auth'])->group(function () {
|
||||
Route::apiResource('blog/posts', Post::class);
|
||||
});
|
||||
```
|
||||
|
||||
路由访问路径:`/admin/{module}/{resource}`
|
||||
|
||||
**2. 用户端 API 路由 (Routes/api.php)**
|
||||
|
||||
文件路径:`Modules/{ModuleName}/Routes/api.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Blog\App\Http\Controllers\Api\Post;
|
||||
|
||||
Route::middleware(['auth:api'])->group(function () {
|
||||
Route::apiResource('blog/posts', Post::class);
|
||||
});
|
||||
```
|
||||
|
||||
路由访问路径:`/api/{module}/{resource}`
|
||||
|
||||
### 6. 模块创建命令
|
||||
|
||||
使用 `nwidart/laravel-modules` 创建新业务模块:
|
||||
|
||||
```bash
|
||||
# 创建模块
|
||||
php artisan module:make ModuleName
|
||||
|
||||
# 创建带有资源的模块
|
||||
php artisan module:make ModuleName --resource
|
||||
|
||||
# 创建多个模块
|
||||
php artisan module:make Blog Shop Order
|
||||
```
|
||||
|
||||
### 7. 模块组件创建命令
|
||||
|
||||
```bash
|
||||
# 在指定模块中创建后台管理控制器
|
||||
php artisan module:make-controller Admin/Post Blog
|
||||
|
||||
# 在指定模块中创建用户端API控制器
|
||||
php artisan module:make-controller Api/Post Blog
|
||||
|
||||
# 在指定模块中创建模型
|
||||
php artisan module:make-model Post Blog
|
||||
|
||||
# 在指定模块中创建迁移
|
||||
php artisan module:make-migration create_posts_table Blog
|
||||
|
||||
# 在指定模块中创建服务类(需要自定义)
|
||||
# 手动在 Modules/Blog/App/Services/ 目录创建
|
||||
```
|
||||
|
||||
**注意:** 使用 `module:make-controller` 命令创建的控制器会自动添加 `Controller` 后缀,需要手动重命名文件和类名以移除后缀。
|
||||
|
||||
## API 响应规范
|
||||
|
||||
### 统一响应格式
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
**错误响应:**
|
||||
```json
|
||||
{
|
||||
"code": 400,
|
||||
"message": "错误信息",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
**分页响应:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"list": [],
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP 状态码规范
|
||||
|
||||
- `200 OK`: 请求成功
|
||||
- `201 Created`: 创建成功
|
||||
- `204 No Content`: 删除成功
|
||||
- `400 Bad Request`: 请求参数错误
|
||||
- `401 Unauthorized`: 未认证
|
||||
- `403 Forbidden`: 无权限
|
||||
- `404 Not Found`: 资源不存在
|
||||
- `422 Unprocessable Entity`: 表单验证失败
|
||||
- `500 Internal Server Error`: 服务器错误
|
||||
|
||||
## Laravel-S / Swoole 开发注意事项
|
||||
|
||||
### 1. 长生命周期注意事项
|
||||
|
||||
由于 Swoole 是长生命周期运行,需注意以下几点:
|
||||
|
||||
**避免使用静态变量:**
|
||||
```php
|
||||
// ❌ 错误
|
||||
public function handle()
|
||||
{
|
||||
static $counter = 0; // 会累积,不会重置
|
||||
}
|
||||
|
||||
// ✅ 正确
|
||||
public function handle()
|
||||
{
|
||||
$counter = 0; // 每次请求重新初始化
|
||||
}
|
||||
```
|
||||
|
||||
**避免使用全局变量:**
|
||||
- 不要依赖 `$_GET`, `$_POST` 等超全局变量
|
||||
- 使用 Laravel 的 `Request` 对象获取请求数据
|
||||
|
||||
### 2. 连接池管理
|
||||
|
||||
数据库、Redis 等连接需要正确管理,避免连接泄漏。
|
||||
|
||||
**配置连接池:** 在 `config/laravels.php` 中配置:
|
||||
```php
|
||||
'swoole' => [
|
||||
'enable_coroutine' => true,
|
||||
'worker_num' => 4,
|
||||
'max_request' => 5000,
|
||||
'max_request_grace' => 500,
|
||||
]
|
||||
```
|
||||
|
||||
### 3. 热重载机制
|
||||
|
||||
开发环境可以使用文件监控实现热重载:
|
||||
|
||||
```bash
|
||||
# 使用 bin/laravels reload
|
||||
php bin/laravels reload
|
||||
|
||||
# 或使用文件监控
|
||||
bin/fswatch # Linux/Mac
|
||||
bin/inotify # Linux
|
||||
```
|
||||
|
||||
### 4. 定时器
|
||||
|
||||
使用 Swoole 定时器时,要确保定时器在合适的时机清除:
|
||||
|
||||
```php
|
||||
\Swoole\Timer::after(5000, function() {
|
||||
// 5秒后执行
|
||||
});
|
||||
|
||||
$timerId = \Swoole\Timer::tick(1000, function() {
|
||||
// 每秒执行
|
||||
return false; // 返回 false 停止定时器
|
||||
});
|
||||
```
|
||||
|
||||
## 数据库规范
|
||||
|
||||
### 迁移文件
|
||||
|
||||
#### 基础模块迁移
|
||||
|
||||
- 文件路径: `database/migrations/`
|
||||
- 迁移文件命名: `{YYYY_MM_DD_HHMMSS}_{description}.php`
|
||||
- 表命名: `{module}_{table_names}` (模块名小写 + 下划线 + 表名复数,所有模块表都必须带模块名前缀)
|
||||
|
||||
**表命名示例:**
|
||||
- Auth 模块: `auth_users`, `auth_roles`, `auth_permissions`, `auth_role_permission`
|
||||
- System 模块: `system_configs`, `system_logs`, `system_dictionaries`
|
||||
|
||||
**迁移文件示例:**
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('auth_users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('email')->unique();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('auth_users');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 业务模块迁移
|
||||
|
||||
- 文件路径: `Modules/{ModuleName}/Database/migrations/`
|
||||
- 迁移文件命名: `{YYYY_MM_DD_HHMMSS}_{description}.php`
|
||||
- 表命名: `{module}_{table_names}` (模块名小写 + 下划线 + 表名复数,所有模块表都必须带模块名前缀)
|
||||
|
||||
**表命名示例:**
|
||||
- Blog 模块: `blog_posts`, `blog_categories`, `blog_tags`, `blog_post_tag`
|
||||
- Shop 模块: `shop_products`, `shop_orders`, `shop_order_items`
|
||||
- Order 模块: `order_payments`, `order_shippings`
|
||||
|
||||
### 字段命名规范
|
||||
|
||||
- 使用蛇形命名: `user_id`, `created_at`
|
||||
- 布尔类型使用 `is_` 前缀: `is_active`, `is_deleted`
|
||||
- 主键统一使用 `id`
|
||||
|
||||
### 数据填充
|
||||
|
||||
#### 基础模块数据填充
|
||||
|
||||
- 文件路径: `database/seeders/`
|
||||
|
||||
#### 业务模块数据填充
|
||||
|
||||
- 文件路径: `Modules/{ModuleName}/Database/seeders/`
|
||||
|
||||
## 认证与授权
|
||||
|
||||
### JWT 认证
|
||||
|
||||
使用 `tymon/jwt-auth` 实现 JWT 认证:
|
||||
|
||||
```php
|
||||
// 登录获取 token
|
||||
$token = auth('api')->attempt($credentials);
|
||||
|
||||
// 使用 token 认证
|
||||
$user = auth('api')->user();
|
||||
|
||||
// 刷新 token
|
||||
$newToken = auth('api')->refresh();
|
||||
|
||||
// 登出
|
||||
auth('api')->logout();
|
||||
```
|
||||
|
||||
### RBAC 权限控制
|
||||
|
||||
基于角色的访问控制 (Role-Based Access Control):
|
||||
|
||||
- User (用户) - Role (角色) - Permission (权限)
|
||||
- 多对多关系设计
|
||||
|
||||
## 常用命令
|
||||
|
||||
### Laravel 命令
|
||||
|
||||
```bash
|
||||
# 创建基础模块控制器
|
||||
php artisan make:controller Auth/UserController
|
||||
|
||||
# 创建基础模块模型
|
||||
php artisan make:model Auth/User
|
||||
|
||||
# 创建基础模块迁移
|
||||
php artisan make:migration create_auth_users_table
|
||||
|
||||
# 执行迁移(包括所有模块)
|
||||
php artisan migrate
|
||||
|
||||
# 回滚迁移
|
||||
php artisan migrate:rollback
|
||||
|
||||
# 清除缓存
|
||||
php artisan cache:clear
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
```
|
||||
|
||||
### Laravel-S 命令
|
||||
|
||||
```bash
|
||||
# 启动服务
|
||||
php bin/laravels start
|
||||
|
||||
# 停止服务
|
||||
php bin/laravels stop
|
||||
|
||||
# 重启服务
|
||||
php bin/laravels restart
|
||||
|
||||
# 重载服务(平滑重启)
|
||||
php bin/laravels reload
|
||||
|
||||
# 查看状态
|
||||
php bin/laravels status
|
||||
|
||||
# 查看帮助
|
||||
php bin/laravels help
|
||||
```
|
||||
|
||||
### Laravel Modules 命令
|
||||
|
||||
```bash
|
||||
# 创建模块
|
||||
php artisan module:make ModuleName
|
||||
|
||||
# 列出所有模块
|
||||
php artisan module:list
|
||||
|
||||
# 启用模块
|
||||
php artisan module:enable ModuleName
|
||||
|
||||
# 禁用模块
|
||||
php artisan module:disable ModuleName
|
||||
|
||||
# 删除模块
|
||||
php artisan module:delete ModuleName
|
||||
|
||||
# 模块迁移
|
||||
php artisan module:migrate ModuleName
|
||||
|
||||
# 回滚模块迁移
|
||||
php artisan module:migrate-rollback ModuleName
|
||||
|
||||
# 刷新模块迁移
|
||||
php artisan module:migrate-refresh ModuleName
|
||||
|
||||
# 模块数据填充
|
||||
php artisan module:seed ModuleName
|
||||
|
||||
# 重新发布模块配置
|
||||
php artisan vendor:publish --tag=modules-config
|
||||
```
|
||||
|
||||
## 代码质量
|
||||
|
||||
### PSR 规范
|
||||
|
||||
遵循 PSR-4 自动加载规范和 PSR-12 编码规范。
|
||||
|
||||
### 注释规范
|
||||
|
||||
- 类和方法添加 DocBlock 注释
|
||||
- 复杂逻辑添加行内注释
|
||||
|
||||
**示例:**
|
||||
```php
|
||||
/**
|
||||
* 用户服务类
|
||||
*
|
||||
* @package App\Services\Auth
|
||||
*/
|
||||
class UserService
|
||||
{
|
||||
/**
|
||||
* 创建用户
|
||||
*
|
||||
* @param array $data 用户数据
|
||||
* @return User
|
||||
*/
|
||||
public function create(array $data): User
|
||||
{
|
||||
// 业务逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 模块开发规范
|
||||
|
||||
### 1. 模块独立性
|
||||
|
||||
每个业务模块应保持独立,避免直接依赖其他业务模块:
|
||||
|
||||
- 模块间通信通过接口或事件实现
|
||||
- 避免跨模块直接调用服务类
|
||||
- 使用 Laravel 事件系统实现模块间解耦
|
||||
|
||||
### 2. 模块配置
|
||||
|
||||
每个业务模块应提供配置文件:
|
||||
|
||||
```php
|
||||
// Modules/Blog/config/blog.php
|
||||
return [
|
||||
'per_page' => 20,
|
||||
'status' => [
|
||||
'draft' => 0,
|
||||
'published' => 1,
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
### 3. 模块 README
|
||||
|
||||
每个业务模块应包含 README.md 文档,说明:
|
||||
|
||||
- 模块功能描述
|
||||
- API 接口列表
|
||||
- 数据库表结构
|
||||
- 依赖说明
|
||||
- 使用示例
|
||||
|
||||
### 4. 模块版本控制
|
||||
|
||||
使用 `module.json` 文件管理模块版本:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Blog",
|
||||
"alias": "blog",
|
||||
"description": "Blog module",
|
||||
"keywords": [],
|
||||
"priority": 0,
|
||||
"providers": [
|
||||
"Modules\\Blog\\App\\Providers\\BlogServiceProvider"
|
||||
],
|
||||
"files": []
|
||||
}
|
||||
```
|
||||
|
||||
## 异常处理
|
||||
|
||||
### 自定义异常
|
||||
|
||||
创建自定义异常类处理业务异常:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class BusinessException extends Exception
|
||||
{
|
||||
protected $code;
|
||||
|
||||
public function __construct(string $message, int $code = 400)
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return response()->json([
|
||||
'code' => $this->code,
|
||||
'message' => $this->message,
|
||||
'data' => null
|
||||
], $this->code);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 测试规范
|
||||
|
||||
### 单元测试
|
||||
|
||||
```bash
|
||||
# 创建测试
|
||||
php artisan make:test UserTest
|
||||
|
||||
# 运行测试
|
||||
php artisan test
|
||||
```
|
||||
|
||||
### 模块测试
|
||||
|
||||
```bash
|
||||
# 创建模块测试
|
||||
php artisan module:test PostTest Blog
|
||||
|
||||
# 运行所有测试
|
||||
php artisan test
|
||||
```
|
||||
|
||||
## 部署注意事项
|
||||
|
||||
1. 生产环境关闭调试模式: `APP_ENV=production`, `APP_DEBUG=false`
|
||||
2. 配置合适的 Worker 数量
|
||||
3. 设置 `max_request` 防止内存泄漏
|
||||
4. 配置日志轮转
|
||||
5. 设置适当的超时时间
|
||||
6. 确保所有模块的迁移都已执行
|
||||
|
||||
## 安全规范
|
||||
|
||||
1. 所有用户输入必须经过验证
|
||||
2. 敏感数据必须加密存储
|
||||
3. 使用 CSRF 防护(API 除外)
|
||||
4. 使用 HTTPS 传输
|
||||
5. 定期更新依赖包
|
||||
6. 不要在代码中硬编码密码或密钥
|
||||
7. 模块间通信需进行权限验证
|
||||
|
||||
## 性能优化
|
||||
|
||||
1. 使用 Redis 缓存热点数据
|
||||
2. 使用队列处理耗时任务
|
||||
3. 优化数据库查询,避免 N+1 问题
|
||||
4. 使用 Eager Loading
|
||||
5. 合理使用索引
|
||||
6. 使用 Swoole 协程提高并发性能
|
||||
7. 模块按需加载,禁用不使用的模块
|
||||
|
||||
## Git 规范
|
||||
|
||||
### 提交信息格式
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
**Type 类型:**
|
||||
- `feat`: 新功能
|
||||
- `fix`: 修复
|
||||
- `docs`: 文档
|
||||
- `style`: 格式
|
||||
- `refactor`: 重构
|
||||
- `test`: 测试
|
||||
- `chore`: 构建/工具
|
||||
|
||||
**Scope 示例:**
|
||||
- `auth`: 认证模块
|
||||
- `system`: 系统模块
|
||||
- `blog`: 博客业务模块
|
||||
- `shop`: 商城业务模块
|
||||
|
||||
**示例:**
|
||||
```
|
||||
feat(auth): 添加用户登录功能
|
||||
|
||||
- 实现 JWT 认证
|
||||
- 添加登录接口
|
||||
- 完善权限验证
|
||||
|
||||
Closes #123
|
||||
```
|
||||
|
||||
## 资源链接
|
||||
|
||||
- [Laravel 文档](https://laravel.com/docs)
|
||||
- [Laravel-S 文档](https://github.com/hhxsv5/laravel-s)
|
||||
- [Swoole 文档](https://www.swoole.com/)
|
||||
- [JWT-Auth 文档](https://github.com/tymondesigns/jwt-auth)
|
||||
- [Laravel Modules 文档](https://nwidart.com/laravel-modules/)
|
||||
Reference in New Issue
Block a user