# Nuxt4 + Pinia 前端规范化框架设计规范（终极完整版）

# 一、文档概述

## 1.1 文档基本信息

|项目|说明|
|---|---|
|文档版本|V1.0|
|适用场景|企业级Web应用、IM即时通讯系统、模块化前端项目、需自定义工具库及API服务的项目|
|核心技术栈|Nuxt4、Vue3、TypeScript、Pinia|
|设计原则|规范化、模块化、高可维护、单向数据流、工具与API统一管控、可扩展|
|文档用途|作为项目开发规范基准，统一团队开发标准，指导架构落地、后期迭代与扩展|
## 1.2 设计目标

- 实现前端全局状态中心化、规范化管理，杜绝零散状态污染，确保状态变更可追溯、可管控，对齐后端分层架构思维。

- 自定义工具库统一命名、集中归集，支持全局自动挂载，无需手动导入，提升开发效率，降低代码冗余。

- 工具层支持静态方法调用、new实例化调用两种形态，适配不同业务场景（无状态工具/有状态工具）。

- API服务统一封装、集中管理，支持全局自动导入，可直接实例化调用，简化接口请求流程，统一请求/响应处理逻辑。

- 保障全局长连接（如IM）、登录态稳定，适配后期插件化扩展（多插件商城、用户体系等），确保架构可扩展、不崩解。

- 实现前后端开发规范对齐，降低跨端协作成本，前期立死规矩，后期开发更快、更不乱。

# 二、整体架构设计

## 2.1 架构核心理念

采用「分层治理 + 模块化拆分」架构，严格遵循单向数据流原则，实现视图、业务逻辑、状态、工具层、API服务层完全解耦；全局状态由Pinia统一管控，自定义工具与API服务统一规约归集，所有公共模块（Stores、Composables、EXTEND工具、API服务）自动注入，简化开发流程，强化团队开发规范一致性，避免代码冗余与混乱，确保项目可维护、可扩展。

## 2.2 架构分层拓扑

```plain text
浏览器客户端
    ↓
视图渲染层（Layout布局 + Page页面 + 公共组件）
    ↓
业务逻辑层（Composables组合式函数）
    ↓
全局工具层（EXTEND结尾自定义工具库）
    ↓
API服务层（SERVICE结尾接口服务库）
    ↓
状态管理层（Pinia模块化仓库）
    ↓
数据请求层（API接口、长连接服务）
    ↓
后端服务 + 本地持久化缓存（兜底）
```

## 2.3 工程目录规范（src源码模式）

遵循Nuxt4官方推荐的src目录结构，结合项目需求定制，新增API服务专属目录，确保目录清晰、职责明确，所有核心模块集中归集，便于维护与扩展：

```plain text
src/
├── app.vue                    # 项目根入口文件，全局样式、全局挂载入口
├── layouts/                   # 全局布局模板，路由切换不销毁（核心常驻组件载体）
│   ├── default.vue            # 默认主布局（承载导航栏、页脚、IM常驻悬浮组件）
│   └── empty.vue              # 空白布局（登录页、弹窗、独立页面专用）
├── pages/                     # 约定式路由页面，按路由路径组织
│   ├── index.vue              # 首页
│   ├── login.vue              # 登录页
│   └── im/                    # IM模块页面
│       ├── chat.vue           # 聊天页面
│       └── contact.vue        # 联系人页面
├── components/                # 全局公共组件，自动导入，按功能分类
│   ├── ui/                    # 基础UI组件（Button、Card、Input等）
│   └── business/              # 业务组件（IM消息气泡、用户卡片等）
├── stores/                    # Pinia状态仓库，模块化拆分，自动导入
│   ├── user.ts                # 用户登录状态仓库（登录信息、Token等）
│   ├── im.ts                  # IM聊天状态仓库（未读总数、会话列表等）
│   └── app.ts                 # 全局应用状态仓库（主题、加载态等）
├── composables/               # 业务组合式函数，自动导入，封装复用逻辑
│   ├── useAuth.ts             # 权限校验逻辑
│   └── useImSocket.ts         # IM长连接逻辑（SignalR/WebSocket封装）
├── extends/                   # 【核心】自定义工具库专属目录，统一归集
│   ├── dateEXTEND.ts          # 日期处理工具（格式化、日期差等）
│   ├── cryptoEXTEND.ts        # 加密解密工具（对称加密、Base64等）
│   ├── requestEXTEND.ts       # 网络请求工具（Axios/ofetch封装、拦截器等）
│   └── imHelperEXTEND.ts      # IM业务辅助工具（消息格式化、会话处理等）
├── services/                  # 【新增核心】API服务专属目录，统一归集，自动导入
│   ├── userSERVICE.ts         # 用户相关API服务（登录、获取用户信息等）
│   ├── imSERVICE.ts           # IM相关API服务（获取会话、发送消息等）
│   └── commonSERVICE.ts       # 通用API服务（字典查询、文件上传等）
├── types/                     # 全局TypeScript类型定义，统一收口
│   ├── user.ts                # 用户相关类型（IUserInfo等）
│   ├── im.ts                  # IM相关类型（IMessage、ISession等）
│   ├── api.ts                 # API服务相关类型（请求参数、响应体等）
│   └── common.ts              # 通用类型（分页、响应体等）
└── server/                    # Nuxt服务端逻辑（SSR接口、中间件等）
    ├── api/                   # 服务端接口
    └── middleware/            # 服务端中间件（权限校验等）
```

# 三、命名规范（强制遵守）

## 3.1 文件命名规范

- 页面/组件文件：采用大驼峰（PascalCase），语义化清晰，如`UserLogin.vue`、`ImChat.vue`；组件按功能分类存放（ui/业务），避免杂乱。

- Pinia状态仓库文件：采用小驼峰（camelCase），以业务域命名，如`user.ts`、`im.ts`，禁止以业务无关名称命名。

- 自定义工具库文件：**固定格式「功能名+EXTEND.ts」，必须以EXTEND结尾，无多余符号**，如`dateEXTEND.ts`、`validateEXTEND.ts`、`imHelperEXTEND.ts`，统一放在`src/extends/`目录下。

- API服务文件：**固定格式「功能名+SERVICE.ts」，必须以SERVICE结尾，无多余符号**，如`userSERVICE.ts`、`imSERVICE.ts`，统一放在`src/services/`目录下。

- 类型文件：采用小驼峰（camelCase），按业务分类，如`user.ts`、`common.ts`、`api.ts`，类型定义统一收口，避免重复定义。

- Composables函数文件：采用小驼峰（camelCase），前缀统一加`use`，如`useAuth.ts`、`useImSocket.ts`，符合Nuxt自动导入约定。

## 3.2 变量/函数/类命名规范

- 变量/函数：采用小驼峰（camelCase），语义化清晰，禁止使用拼音、简写（通用简写除外，如`uid`），如`loginUser`、`formatTime`。

- 类/接口：采用大驼峰（PascalCase），接口前缀加`I`，如`IUserInfo`、`IMessage`；工具类名称与文件名一致，以EXTEND结尾，如`DateEXTEND`、`CryptoEXTEND`；API服务类名称与文件名一致，以SERVICE结尾，如`UserSERVICE`、`ImSERVICE`。

- 常量：采用全大写（UPPER_CASE），下划线分隔，如`MAX_PAGE_SIZE`、`TOKEN_KEY`，统一放在对应工具、API服务或类型文件中。

# 四、Pinia状态管理规范（核心规范）

## 4.1 核心设计原则

- 单一职责原则：一个仓库只管理一个业务域的状态，禁止跨业务域冗余数据（如用户状态与IM状态分开管理），确保模块解耦。

- 禁止直接修改原则：state为私有状态，**严禁外部直接修改state值**，所有状态变更必须通过actions方法，确保状态变更可追溯、可管控，避免脏数据。

- 计算派生原则：getters作为只读计算属性，封装状态判断、数据格式化、派生逻辑，禁止在组件中重复编写计算逻辑，提升代码复用性。

- 持久化管控原则：仅核心状态（登录Token、用户基础信息）开启持久化，禁止大量数据（如会话列表、消息记录）存入本地，避免占用本地存储、影响性能。

- 自动导入原则：stores目录下所有仓库自动全局导入，无需手动编写import语句，直接调用即可，简化开发流程。

- 类型安全原则：所有状态、方法均需指定TypeScript类型，避免any类型，确保代码健壮性，降低后期维护成本。

## 4.2 依赖安装与配置

安装Pinia及持久化插件，确保状态持久化功能正常，适配Nuxt4自动导入（同步新增services目录自动导入配置）：

```bash
# 安装Pinia及Nuxt适配模块
npm install pinia @pinia/nuxt pinia-plugin-persistedstate
```

在`nuxt.config.ts`中配置，启用Pinia、自动导入Stores、Composables、EXTEND工具、API服务：

```typescript
export default defineNuxtConfig({
  srcDir: 'src/', // 指定源码目录
  modules: [
    '@pinia/nuxt', // Pinia Nuxt适配模块
    'pinia-plugin-persistedstate/nuxt' // 持久化插件
  ],
  imports: {
    dirs: [
      'stores', // 自动扫描Pinia仓库，全局自动导入
      'composables', // 自动扫描组合式函数
      'extends', // 自动扫描EXTEND工具库，全局自动导入
      'services' // 【新增】自动扫描SERVICE API服务，全局自动导入
    ]
  }
})
```

## 4.3 标准仓库编写格式（可直接复制使用）

```typescript
// src/stores/user.ts（用户状态仓库示例）
import { defineStore } from 'pinia'
import type { IUserInfo } from '~/types/user'

// 仓库命名规范：use+业务域+Store（小驼峰），与文件名对应
export const useUserStore = defineStore('user', {
  // 1. 原始状态：仅存基础数据，不做任何计算、判断，类型明确
  state: () => ({
    userInfo: null as IUserInfo | null, // 用户基础信息
    token: '' as string,                // 登录Token
    isLoading: false as boolean         // 登录加载态
  }),

  // 2. 只读计算属性：封装派生逻辑，全局只读，自动缓存，避免重复计算
  getters: {
    // 判断是否登录（核心派生逻辑，统一封装）
    isLogin: (state) => !!state.token,
    // 获取用户ID（默认值兜底，避免报错）
    userId: (state) => state.userInfo?.id ?? 0,
    // 格式化用户昵称（派生逻辑，组件直接使用）
    userNickname: (state) => state.userInfo?.nickname || '未知用户'
  },

  // 3. 唯一状态修改入口：所有状态变更必须走actions，可添加日志、校验、拦截
  actions: {
    // 登录成功：设置用户信息与Token
    setUserInfo(data: IUserInfo, token: string) {
      this.userInfo = data
      this.token = token
      this.isLoading = false
    },
    // 退出登录：清空用户状态
    clearUserInfo() {
      this.userInfo = null
      this.token = ''
      this.isLoading = false
    },
    // 设置登录加载态
    setLoginLoading(loading: boolean) {
      this.isLoading = loading
    }
  },

  // 4. 本地持久化配置：使用 pinia-plugin-persistedstate 插件
  // 仅缓存核心状态，刷新页面不丢失，避免大量数据存储
  persist: {
    storage: piniaPluginPersistedstate.localStorage(),
    pick: ['token', 'userInfo'] // 仅持久化指定字段，减少存储开销
  }
})
```

## 4.4 状态使用规范

- 获取状态：优先使用getters获取派生数据，禁止直接读取state（如优先用`userStore.isLogin`，而非`userStore.state.token`），确保逻辑统一。

- 修改状态：必须调用actions方法，禁止直接赋值修改（如`userStore.setUserInfo(data, token)`，禁止`userStore.userInfo = data`），确保状态变更可追溯。

- 跨模块通信：不同仓库之间通过引入对应仓库、调用其actions方法实现通信，禁止直接操作其他仓库的state，避免模块耦合。

- 生命周期：Pinia状态常驻浏览器内存，路由切换、组件销毁时不丢失；刷新页面时，通过persist配置恢复核心状态（如登录态），非核心状态重新初始化。

- 性能优化：Pinia的getters自带缓存特性，重复调用不重复计算；对于复杂状态，可使用shallowRef处理，降低响应式开销。

# 五、EXTEND自定义工具库规范（核心定制规范）

## 5.1 核心规约（强制遵守）

- 目录归集：所有自定义工具库必须放在`src/extends/`目录下，禁止散落至其他目录（如utils、composables），确保工具层统一管控，便于查找与维护。

- 命名规范：工具文件名固定为「功能名+EXTEND.ts」，必须以EXTEND结尾，工具类名称与文件名一致（如文件`dateEXTEND.ts`，类名`DateEXTEND`），禁止随意命名。

- 自动挂载：通过Nuxt配置实现extends目录全局自动扫描、自动导入，页面/组件/仓库/API服务中无需手动import，直接使用，提升开发效率。

- 职责边界：工具层仅封装纯逻辑、通用方法，不涉及业务状态修改，不直接操作Pinia仓库；业务相关逻辑下沉至composables，确保工具层复用性。

- 调用形态：支持两种编写与调用形态，可根据业务场景自由选择（无状态工具用静态类，有状态工具用实例化类），兼顾灵活性与规范性。

- 类型安全：工具方法、参数、返回值均需指定TypeScript类型，禁止any类型，确保代码健壮性，便于团队协作。

## 5.2 工具编写与调用形态（可直接复制使用）

### 形态一：静态类工具（无需new，直接调用）

适合无实例属性、纯工具方法场景（如日期格式化、加密解密、正则校验），无需创建实例，直接通过类名调用方法，简洁高效，全局统一调用入口。

```typescript
// src/extends/dateEXTEND.ts（日期工具示例，静态类）
export class DateEXTEND {
  /**
   * 格式化时间戳为本地时间字符串
   * @param timestamp 时间戳（毫秒）
   * @returns 格式化后的时间字符串（如：2026-04-09 23:59:59）
   */
  static format(timestamp: number): string {
    if (!timestamp) return ''
    const date = new Date(timestamp)
    const year = date.getFullYear()
    const month = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    const hour = String(date.getHours()).padStart(2, '0')
    const minute = String(date.getMinutes()).padStart(2, '0')
    const second = String(date.getSeconds()).padStart(2, '0')
    return `${year}-${month}-${day} ${hour}:${minute}:${second}`
  }

  /**
   * 计算两个时间戳的天数差
   * @param start 开始时间戳
   * @param end 结束时间戳
   * @returns 天数差（正数：end在start之后；负数：end在start之前）
   */
  static diffDay(start: number, end: number): number {
    const oneDay = 1000 * 60 * 60 * 24
    return Math.floor((end - start) / oneDay)
  }

  /**
   * 判断是否为今天
   * @param timestamp 时间戳（毫秒）
   * @returns boolean 是今天返回true，否则返回false
   */
  static isToday(timestamp: number): boolean {
    const today = new Date()
    const target = new Date(timestamp)
    return (
      today.getFullYear() === target.getFullYear() &&
      today.getMonth() === target.getMonth() &&
      today.getDate() === target.getDate()
    )
  }
}

// 调用方式（无需import，全局直接使用）
// const time = DateEXTEND.format(Date.now())
// const dayDiff = DateEXTEND.diffDay(startTime, endTime)
// const isToday = DateEXTEND.isToday(timestamp)
```

### 形态二：实例化类工具（支持new创建实例）

适合需要独立实例、携带私有属性场景（如加密解密、请求拦截、多实例独立上下文），通过new创建实例，每个实例拥有独立的私有属性，避免全局污染。

```typescript
// src/extends/cryptoEXTEND.ts（加密工具示例，可实例化）
export class CryptoEXTEND {
  // 私有属性：加密密钥，每个实例独立拥有
  private key: string

  /**
   * 构造函数：初始化加密密钥
   * @param key 加密密钥（不同实例可传入不同密钥）
   */
  constructor(key: string) {
    this.key = key
  }

  /**
   * 加密字符串（Base64 + 密钥拼接）
   * @param data 需要加密的字符串
   * @returns 加密后的字符串
   */
  encrypt(data: string): string {
    // 加密逻辑：拼接密钥后进行Base64编码
    const encryptStr = data + this.key
    return btoa(encodeURIComponent(encryptStr))
  }

  /**
   * 解密字符串
   * @param data 需要解密的字符串
   * @returns 解密后的原始字符串
   */
  decrypt(data: string): string {
    // 解密逻辑：Base64解码后移除密钥
    const decryptStr = decodeURIComponent(atob(data))
    return decryptStr.replace(this.key, '')
  }

  /**
   * 验证加密字符串是否有效（匹配当前密钥）
   * @param data 加密后的字符串
   * @returns boolean 有效返回true，否则返回false
   */
  validate(data: string): boolean {
    try {
      const decryptStr = this.decrypt(data)
      return decryptStr !== data // 解密后与原始加密串不一致，说明有效
    } catch (error) {
      return false
    }
  }
}

// 调用方式（无需import，全局直接new实例使用）
// const crypto1 = new CryptoEXTEND('custom-key-1')
// const encryptData1 = crypto1.encrypt('test-data-1')
// const decryptData1 = crypto1.decrypt(encryptData1)

// const crypto2 = new CryptoEXTEND('custom-key-2') // 不同密钥的实例
// const encryptData2 = crypto2.encrypt('test-data-2')
```

## 5.3 工具库使用注意事项

- 工具方法需保证纯函数特性（无副作用），输入相同参数，输出结果一致，便于复用与测试。

- 避免工具库之间相互依赖，若需依赖，需明确依赖关系，避免循环依赖。

- 工具库中禁止直接操作DOM、Pinia状态，所有业务相关操作需通过composables中转。

- 常用工具（如日期、加密）优先使用EXTEND工具库，禁止在组件中重复编写相同逻辑，提升代码复用性。

- API服务中可直接调用EXTEND工具（如请求拦截中使用加密工具），实现逻辑复用。

# 六、SERVICE API服务规范（新增核心规范）

## 6.1 核心规约（强制遵守）

- 目录归集：所有API服务必须放在`src/services/`目录下，禁止散落至其他目录（如pages、composables），确保API服务统一管控，便于维护、调试与迭代。

- 命名规范：API服务文件名固定为「功能名+SERVICE.ts」，必须以SERVICE结尾，服务类名称与文件名一致（如文件`userSERVICE.ts`，类名`UserSERVICE`），禁止随意命名。

- 自动挂载：通过Nuxt配置实现services目录全局自动扫描、自动导入，页面/组件/仓库中无需手动import，直接实例化调用，简化接口请求流程。

- 职责边界：API服务仅封装接口请求逻辑（请求参数处理、接口调用、响应数据格式化），不涉及业务逻辑、状态修改；业务逻辑下沉至composables，状态修改通过Pinia actions实现。

- 调用形态：统一采用「实例化调用」，通过new创建服务实例，每个实例可独立配置请求参数、拦截逻辑，适配多场景接口调用（如不同模块的请求头差异）。

- 类型安全：所有API请求参数、响应数据均需指定TypeScript类型（统一在`types/api.ts`中定义），禁止any类型，确保接口调用的健壮性，减少类型错误。

- 请求统一：所有API请求必须通过`extends/requestEXTEND.ts`封装的请求工具，禁止直接使用ofetch/axios调用接口，确保请求拦截、响应拦截、异常处理统一。

## 6.2 API服务编写与调用形态（可直接复制使用）

统一采用实例化类编写，支持构造函数传入自定义配置（如请求头、超时时间），适配不同业务场景，调用时直接new实例，无需手动导入，符合你的预期调用方式（`const userSerive = new UserSerivce(); var userInfo = userSerive.getinfo();`）。

```typescript
// 第一步：先在types/api.ts中定义请求/响应类型
// src/types/api.ts
import type { IUserInfo } from './user'

// 用户登录请求参数
export interface ILoginParams {
  username: string
  password: string
}

// 用户登录响应体
export interface ILoginResponse {
  code: number
  message: string
  data: {
    token: string
    userInfo: IUserInfo
  }
}

// 获取用户信息响应体
export interface IGetUserInfoResponse {
  code: number
  message: string
  data: IUserInfo
}

// 第二步：编写API服务（src/services/userSERVICE.ts）
import type { ILoginParams, ILoginResponse, IGetUserInfoResponse } from '~/types/api'
import { RequestEXTEND } from '~/extends/requestEXTEND' // 引入统一请求工具

export class UserSERVICE {
  // 私有属性：请求工具实例（可自定义配置）
  private request: RequestEXTEND

  /**
   * 构造函数：初始化请求工具，可传入自定义配置
   * @param config 自定义请求配置（可选，如超时时间、请求头）
   */
  constructor(config?: { timeout?: number; headers?: Record<string, string> }) {
    // 初始化请求工具，传入自定义配置（默认使用全局配置）
    this.request = new RequestEXTEND(config)
  }

  /**
   * 用户登录接口
   * @param params 登录请求参数
   * @returns 登录响应数据（格式化后）
   */
  async login(params: ILoginParams): Promise<ILoginResponse['data']> {
    try {
      const response = await this.request.post<ILoginResponse>('/api/user/login', params)
      // 统一响应处理：判断状态码，抛出异常或返回数据
      if (response.code !== 200) {
        throw new Error(response.message || '登录失败')
      }
      return response.data // 直接返回核心数据，简化组件调用
    } catch (error) {
      // 统一异常处理：可结合全局提示工具抛出异常
      console.error('登录接口异常：', error)
      throw error // 抛出异常，由调用方处理业务逻辑
    }
  }

  /**
   * 获取用户信息接口（需携带Token）
   * @param userId 用户ID（可选，默认取当前登录用户ID）
   * @returns 用户信息
   */
  async getInfo(userId?: number): Promise<IUserInfo> {
    try {
      const response = await this.request.get<IGetUserInfoResponse>('/api/user/info', {
        params: { userId } // 拼接请求参数
      })
      if (response.code !== 200) {
        throw new Error(response.message || '获取用户信息失败')
      }
      return response.data
    } catch (error) {
      console.error('获取用户信息接口异常：', error)
      throw error
    }
  }

  /**
   * 退出登录接口
   * @returns 退出结果
   */
  async logout(): Promise<boolean> {
    try {
      const response = await this.request.post<{ code: number; message: string }>('/api/user/logout')
      return response.code === 200
    } catch (error) {
      console.error('退出登录接口异常：', error)
      return false
    }
  }
}

// 调用方式（无需import，全局直接new实例使用，完全匹配你的需求）
// 1. 基础调用（使用默认配置）
// const userService = new UserSERVICE();
// const userInfo = await userService.getInfo(); // 获取当前用户信息
// const loginData = await userService.login({ username: 'admin', password: '123456' }); // 登录

// 2. 自定义配置调用（如设置超时时间、额外请求头）
// const userService = new UserSERVICE({
//   timeout: 10000,
//   headers: { 'X-Custom-Header': 'custom-value' }
// });
// const userInfo = await userService.getInfo(1001); // 传入用户ID查询指定用户
```

## 6.3 API服务使用注意事项

- API服务方法统一使用async/await语法，返回Promise对象，便于组件中异步调用、处理加载态。

- 所有接口请求必须通过`RequestEXTEND`工具，统一处理请求拦截（如添加Token、请求头）、响应拦截（如统一错误提示、Token过期处理）。

- API服务中禁止直接操作Pinia状态，若需修改状态（如登录后设置Token），需在组件/composables中调用API服务后，通过Pinia actions修改。

- 相同业务域的API接口统一放在一个SERVICE文件中，如用户相关接口都放在`userSERVICE.ts`，避免分散。

- 接口参数、响应体类型必须在`types/api.ts`中统一定义，禁止在服务中重复定义类型，确保类型统一。

- 复杂接口（如分页查询）可封装通用方法，传入分页参数，返回格式化后的分页数据，简化组件调用。

# 七、存储分层与性能规范

## 7.1 存储层级划分

采用「内存为主、磁盘兜底」的存储分层策略，兼顾性能与稳定性，避免性能瓶颈：

- 「内存存储（Pinia State）」：全局状态运行时载体，纳秒级读写，性能最优，业务核心读写优先使用。生命周期为页面运行期间，路由切换、组件销毁不丢失，刷新页面后非持久化状态清空。

- 「本地持久化（LocalStorage）」：仅作为Pinia持久化备份，用于存储核心状态（如登录Token、用户基础信息），刷新/重开页面可恢复核心状态。禁止直接操作LocalStorage，统一由Pinia持久化插件托管。

- 「禁止项」：禁止业务代码直接读写LocalStorage；禁止大量列表、非核心数据（如会话列表、消息记录）持久化，避免占用本地存储、影响首屏加载速度与性能。

## 7.2 性能管控规范

- Pinia性能：getters具备缓存特性，重复调用不重复计算；避免在state中存储大量数据，拆分模块化仓库，降低单个仓库体积。

- 工具库性能：工具方法纯函数封装，避免冗余逻辑；对于计算密集型任务，可考虑使用Web Worker，避免阻塞主线程。

- API服务性能：统一使用请求拦截、响应拦截，添加防抖节流，避免重复请求、无效请求；大文件上传/下载可封装单独方法，支持断点续传。

- 组件性能：全局常驻组件（如IM悬浮窗）放在Layout布局中，避免路由切换时重复创建/销毁；组件懒加载（Lazy前缀），降低首屏加载压力。

- 请求性能：网络请求统一封装在EXTEND工具中，添加请求拦截、响应拦截、防抖节流，避免重复请求、无效请求。

# 八、全局数据流规范

## 8.1 单向数据流原则（强制遵守）

严格遵循「View → Action → API Service/EXTEND → State → View」的单向闭环数据流，确保数据流可追溯、可管控，避免数据混乱：

1. View（页面/组件）：触发用户交互（如登录、发送消息）。

2. Action（调用Store Actions / Composables函数）：处理业务逻辑，调用API服务/EXTEND工具请求数据。

3. API Service/EXTEND：API服务调用后端接口获取数据，EXTEND工具处理数据逻辑，返回处理后的数据。

4. State（Pinia仓库）：通过Actions更新内存状态，持久化状态自动同步至LocalStorage。

5. View（页面/组件）：通过Getters获取状态，自动响应式更新视图。

## 8.2 通信规范

- 父子组件通信：使用Props/Emits，禁止使用全局状态传递简单父子组件数据。

- 兄弟/跨级组件通信：统一使用Pinia Store，通过修改/读取状态实现通信，禁止使用EventBus、全局变量。

- 页面与布局通信：页面（Page）与布局（Layout）之间的通信，必须通过Pinia Store，确保通信规范、可追溯。

- 长连接通信：IM长连接（SignalR/WebSocket）统一封装在Composables中，通过Pinia Store管理连接状态、消息数据，避免连接混乱。

- API服务与Pinia通信：API服务仅返回数据，不直接操作Pinia状态，由调用方（组件/composables）通过Pinia actions更新状态。

# 九、开发强制约束（必须遵守）

- 全局状态统一使用Pinia，禁止使用useState做全局状态共享，禁止使用全局变量、EventBus，避免状态污染。

- 自定义工具必须放在extends目录，文件名以EXTEND结尾，禁止散落其他目录，禁止重复编写相同工具方法。

- API服务必须放在services目录，文件名以SERVICE结尾，禁止散落其他目录，禁止在组件中直接调用接口，必须通过API服务。

- 严禁直接修改Pinia state，所有状态变更必须通过actions，可添加日志、校验、拦截，确保状态变更可追溯。

- 页面与布局分离，全局常驻组件（IM、导航）必须放在layouts/default.vue中，保证长连接不中断、组件不重复销毁/创建。

- 业务逻辑下沉至composables和EXTEND工具，页面组件只做视图渲染，禁止在页面中编写复杂业务逻辑、工具方法、接口调用。

- 所有接口请求统一封装在API服务中，API服务统一使用RequestEXTEND工具，禁止页面直接请求，便于统一拦截、异常处理、请求优化。

- 严格遵循命名规范、目录规范，禁止随意修改目录结构、文件名，确保团队开发一致性。

- 所有代码必须使用TypeScript，禁止any类型，确保类型安全，降低后期维护成本。

- API服务统一采用实例化调用，禁止静态调用，确保每个服务实例可独立配置，适配多场景需求。

# 十、架构优势总结

- 规范化统一：状态、工具、API服务、目录、命名全流程规范，团队开发无歧义，降低协作成本，前期立死规矩，后期开发更快、更不乱。

- 开发高效：公共模块（Stores、Composables、EXTEND工具、API服务）自动导入，无需重复编写import，降低冗余代码，API服务可直接实例化调用，大幅提升开发效率。

- 可维护性强：分层清晰，模块职责单一，状态变更可追溯，工具与API服务统一管控，后期迭代、修改只需动一处，降低维护成本。

- 稳定性高：状态变更有管控，工具层纯逻辑封装，API服务统一请求/响应处理，长连接常驻布局，登录态持久化兜底，避免全局污染、数据混乱，适配高并发场景。

- 可扩展性强：模块化拆分，插件化扩展友好，IM长连接、多插件商城、用户体系可随意扩展，API服务与工具库可独立新增，架构不崩解，一步到位终身舒服。

- 类型安全：全程TypeScript支持，类型定义统一收口，API请求/响应、工具方法、状态均有类型约束，避免类型错误，提升代码健壮性，降低线上bug率。

# 十一、附录：常用命令与依赖清单

## 11.1 常用命令

```bash
# 初始化Nuxt4项目（src目录模式）
npx nuxi init my-project --src-dir

# 进入项目目录
cd my-project

# 安装核心依赖
npm install pinia @pinia/nuxt @pinia-plugin-persistedstate/nuxt

# 安装其他常用依赖（根据需求）
npm install axios ofetch scss

# 启动开发服务器
npm run dev

# 构建生产包
npm run build

# 预览生产包
npm run preview
```

## 11.2 核心依赖清单

|依赖名称|用途|
|---|---|
|pinia|全局状态管理核心库|
|@pinia/nuxt|Pinia适配Nuxt4的模块，支持自动导入|
|pinia-plugin-persistedstate|Pinia持久化插件，支持Nuxt模块化集成，SSR友好|
|ofetch|网络请求工具，统一封装请求逻辑（RequestEXTEND基础）|
|axios|备选网络请求工具，可根据需求替换ofetch|
|scss|样式预处理器，支持模块化样式|
> （注：文档部分内容可能由 AI 生成）