# 情绪博物馆Web端技术方案
## 技术选型说明
### WebSocket通信方案选择
本方案选择 **STOMP + 原生WebSocket** 而非 Socket.io 的原因:
1. **后端集成优势**: 项目后端使用Spring Boot,STOMP是Spring WebSocket的原生支持协议
2. **标准化协议**: STOMP是标准的消息传递协议,不依赖特定实现
3. **消息队列支持**: 天然支持点对点和发布订阅模式,适合聊天和通知场景
4. **轻量级**: 相比Socket.io更轻量,减少前端包体积
5. **Token认证支持**: 原生WebSocket支持在握手时传递自定义请求头进行Token认证
### 技术栈版本策略
- **稳定性优先**: 选择经过验证的稳定版本
- **生态兼容**: 确保各组件间良好兼容
- **长期支持**: 优先选择有LTS支持的版本
- **性能考虑**: 新版本的性能优化和bug修复
## 1. 核心技术栈(推荐版本)
### 1.1 前端框架
- **Vue.js**: `3.4.21` (最新稳定版)
- **TypeScript**: `5.4.2` (最新稳定版)
- **Vite**: `5.1.6` (最新稳定版,更好的构建性能)
### 1.2 UI框架与样式
- **Element Plus**: `2.6.1` (最新稳定版,更好的Vue3支持)
- **Tailwind CSS**: `3.4.1` (最新稳定版)
- **@tailwindcss/forms**: `0.5.7` (表单样式增强)
- **@tailwindcss/typography**: `0.5.10` (文本排版增强)
### 1.3 状态管理与路由
- **Pinia**: `2.1.7` (保持现有版本,稳定可靠)
- **Vue Router**: `4.3.0` (最新稳定版)
- **@pinia/nuxt**: `0.5.1` (如果需要SSR支持)
### 1.4 HTTP客户端与实时通信
- **Axios**: `1.6.8` (最新稳定版)
- **@stomp/stompjs**: `7.1.1` (WebSocket通信,与Spring Boot后端集成,支持Token认证)
### 1.5 数据可视化
- **ECharts**: `5.5.0` (最新稳定版)
- **vue-echarts**: `6.7.3` (Vue3专用ECharts组件)
- **@antv/g2**: `5.1.15` (备选图表库,更现代化)
### 1.6 工具库
- **Day.js**: `1.11.10` (最新稳定版)
- **Lodash-es**: `4.17.21` (ES模块版本)
- **Zod**: `3.22.4` (数据验证)
- **VueUse**: `10.9.0` (Vue组合式API工具集)
### 1.7 开发工具
- **@vitejs/plugin-vue**: `5.0.4`
- **@vue/tsconfig**: `0.5.1`
- **vue-tsc**: `2.0.6`
- **unplugin-auto-import**: `0.17.5` (自动导入)
- **unplugin-vue-components**: `0.26.0` (组件自动导入)
## 2. 新增推荐技术栈
### 2.1 表单处理
- **@vuelidate/core**: `2.0.3` (表单验证)
- **@vuelidate/validators**: `2.0.4`
- **vue-hooks-form**: `0.8.6` (表单状态管理)
### 2.2 动画与交互
- **@vueuse/motion**: `2.0.0` (动画库)
- **vue-toastification**: `2.0.0-rc.5` (通知组件)
- **nprogress**: `0.2.0` (页面加载进度条)
### 2.3 文件处理
- **vue-upload-component**: `3.1.4` (文件上传)
- **cropperjs**: `1.6.1` (图片裁剪)
- **file-saver**: `2.0.5` (文件下载)
### 2.4 富文本编辑
- **@tiptap/vue-3**: `2.2.4` (现代富文本编辑器)
- **@tiptap/starter-kit**: `2.2.4`
- **@tiptap/extension-image**: `2.2.4`
### 2.5 PWA支持
- **vite-plugin-pwa**: `0.19.2` (PWA支持)
- **workbox-window**: `7.0.0` (Service Worker管理)
## 3. 开发工具与代码质量
### 3.1 代码规范
- **ESLint**: `8.57.0`
- **@vue/eslint-config-typescript**: `12.0.0`
- **@vue/eslint-config-prettier**: `9.0.0`
- **Prettier**: `3.2.5`
- **lint-staged**: `15.2.2`
- **husky**: `9.0.11`
### 3.2 测试框架
- **Vitest**: `1.4.0` (单元测试)
- **@vue/test-utils**: `2.4.5` (Vue组件测试)
- **jsdom**: `24.0.0` (DOM环境模拟)
- **Cypress**: `13.7.1` (E2E测试)
### 3.3 构建优化
- **rollup-plugin-visualizer**: `5.12.0` (构建分析)
- **vite-plugin-compression**: `0.5.1` (Gzip压缩)
- **vite-plugin-mock**: `3.0.1` (Mock数据)
## 4. 项目结构设计
```
src/
├── api/ # API接口定义
│ ├── auth.ts # 认证相关接口
│ ├── chat.ts # 聊天相关接口
│ ├── diary.ts # 日记相关接口
│ └── user.ts # 用户相关接口
├── assets/ # 静态资源
│ ├── images/ # 图片资源
│ ├── icons/ # 图标资源
│ └── styles/ # 全局样式
├── components/ # 公共组件
│ ├── common/ # 通用组件
│ ├── forms/ # 表单组件
│ ├── charts/ # 图表组件
│ └── layout/ # 布局组件
├── composables/ # 组合式API
│ ├── useAuth.ts # 认证逻辑
│ ├── useChat.ts # 聊天逻辑
│ ├── useWebSocket.ts # WebSocket逻辑
│ └── useApi.ts # API调用逻辑
├── config/ # 配置文件
│ ├── env.ts # 环境配置
│ ├── constants.ts # 常量定义
│ └── routes.ts # 路由配置
├── layouts/ # 页面布局
│ ├── DefaultLayout.vue # 默认布局
│ ├── AuthLayout.vue # 认证布局
│ └── ChatLayout.vue # 聊天布局
├── pages/ # 页面组件
│ ├── auth/ # 认证页面
│ ├── chat/ # 聊天页面
│ ├── diary/ # 日记页面
│ └── dashboard/ # 仪表盘页面
├── stores/ # 状态管理
│ ├── auth.ts # 认证状态
│ ├── chat.ts # 聊天状态
│ ├── user.ts # 用户状态
│ └── app.ts # 应用状态
├── types/ # 类型定义
│ ├── api.ts # API类型
│ ├── user.ts # 用户类型
│ ├── chat.ts # 聊天类型
│ └── global.d.ts # 全局类型
├── utils/ # 工具函数
│ ├── request.ts # HTTP请求工具
│ ├── websocket.ts # WebSocket工具
│ ├── storage.ts # 存储工具
│ ├── validation.ts # 验证工具
│ └── format.ts # 格式化工具
└── views/ # 页面视图
├── Home.vue # 首页
├── Login.vue # 登录页
├── Chat.vue # 聊天页
└── Dashboard.vue # 仪表盘
```
## 5. 核心功能实现方案
### 5.1 认证系统
- **JWT Token管理**: 使用Pinia存储,自动刷新机制
- **路由守卫**: 基于Vue Router的权限控制
- **第三方登录**: 支持微信、QQ、GitHub等
- **验证码**: 图形验证码 + 短信验证码
### 5.2 实时通信
- **STOMP协议**: 基于@stomp/stompjs,与Spring Boot WebSocket集成
- **原生WebSocket**: 支持Token认证,无需降级方案
- **连接管理**: 自动重连、心跳检测、连接状态监控
- **消息队列**: 支持点对点和发布订阅模式
- **Token认证**: 在WebSocket握手时传递Authorization头部
- **消息类型**: 文本、图片、表情、文件、系统通知
- **离线处理**: 离线消息缓存和同步机制
### 5.3 数据可视化
- **情绪趋势图**: 基于ECharts的时间序列图
- **情绪雷达图**: 多维度情绪分析
- **成长轨迹**: 交互式时间轴
- **数据导出**: 支持PDF、Excel导出
### 5.4 响应式设计
- **移动端适配**: 基于Tailwind CSS的响应式布局
- **触摸手势**: 支持滑动、缩放等手势操作
- **PWA支持**: 离线缓存、桌面安装
- **性能优化**: 虚拟滚动、懒加载
## 6. 环境配置优化
### 6.1 多环境配置
```typescript
// config/env.ts
export const envConfigs = {
local: {
name: '本地环境',
apiBaseUrl: 'http://localhost:19089/api',
wsBaseUrl: 'ws://localhost:19089',
uploadUrl: 'http://localhost:19089/api/upload',
debug: true,
mock: false
},
dev: {
name: '开发环境',
apiBaseUrl: 'https://dev-api.emotion-museum.com/api',
wsBaseUrl: 'wss://dev-api.emotion-museum.com',
uploadUrl: 'https://dev-api.emotion-museum.com/api/upload',
debug: true,
mock: false
},
test: {
name: '测试环境',
apiBaseUrl: 'https://test-api.emotion-museum.com/api',
wsBaseUrl: 'wss://test-api.emotion-museum.com',
uploadUrl: 'https://test-api.emotion-museum.com/api/upload',
debug: false,
mock: false
},
prod: {
name: '生产环境',
apiBaseUrl: 'https://api.emotion-museum.com/api',
wsBaseUrl: 'wss://api.emotion-museum.com',
uploadUrl: 'https://api.emotion-museum.com/api/upload',
debug: false,
mock: false
}
}
```
### 6.2 构建优化配置
```typescript
// vite.config.ts
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
dts: true
}),
Components({
resolvers: [ElementPlusResolver()],
dts: true
}),
VitePWA({
registerType: 'autoUpdate',
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg}']
}
})
],
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
elementPlus: ['element-plus'],
echarts: ['echarts'],
utils: ['axios', 'dayjs', 'lodash-es']
}
}
}
}
})
```
## 7. 部署方案
### 7.1 Docker部署
```dockerfile
# Dockerfile
FROM node:18-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```
### 7.2 CI/CD配置
```yaml
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm ci
- run: npm run build
- run: npm run test
- name: Deploy to server
run: |
# 部署脚本
```
### 7.3 Nginx配置
```nginx
# nginx.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# 处理Vue Router的history模式
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API代理
location /api/ {
proxy_pass http://backend:19089/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# WebSocket代理
location /ws/ {
proxy_pass http://backend:19089/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
## 8. 性能优化策略
### 8.1 代码分割
- **路由级别懒加载**: 使用动态import()
- **组件级别动态导入**: 按需加载大型组件
- **第三方库按需加载**: Tree-shaking优化
- **图片懒加载**: Intersection Observer API
### 8.2 缓存策略
- **HTTP缓存配置**: 静态资源长期缓存
- **Service Worker缓存**: 离线访问支持
- **本地存储优化**: IndexedDB存储大量数据
- **CDN加速**: 静态资源CDN分发
### 8.3 监控与分析
- **Sentry**: `7.108.0` (错误监控)
- **Google Analytics**: `gtag` (用户行为分析)
- **Web Vitals**: `3.5.2` (性能指标监控)
- **Bundle Analyzer**: 构建分析工具
### 8.4 性能指标
- **首屏加载时间**: < 2秒
- **交互响应时间**: < 100ms
- **代码分割**: 单个chunk < 250KB
- **图片优化**: WebP格式,响应式图片
## 9. 安全考虑
### 9.1 前端安全
- **XSS防护**: 内容安全策略(CSP)
- **CSRF防护**: Token验证
- **敏感信息加密**: 本地存储加密
- **依赖安全**: 定期更新依赖包
### 9.2 API安全
- **Token自动刷新**: JWT令牌管理
- **请求签名验证**: HMAC签名
- **接口限流**: 防止恶意请求
- **数据加密传输**: HTTPS强制
### 9.3 内容安全策略
```html
```
## 10. 开发规范
### 10.1 代码规范
- **命名规范**:
- 组件: PascalCase (UserProfile.vue)
- 文件: kebab-case (user-profile.ts)
- 变量: camelCase (userName)
- 常量: UPPER_SNAKE_CASE (API_BASE_URL)
### 10.2 Git提交规范
```
feat: 新功能
fix: 修复bug
docs: 文档更新
style: 代码格式调整
refactor: 代码重构
test: 测试相关
chore: 构建工具或辅助工具的变动
```
### 10.3 组件开发规范
```vue
```
### 10.4 API接口规范
```typescript
// api/user.ts
import type { User, UserProfile, UpdateUserRequest } from '@/types/user'
import { request } from '@/utils/request'
export const userApi = {
// 获取用户信息
getProfile(): Promise {
return request.get('/user/profile')
},
// 更新用户信息
updateProfile(data: UpdateUserRequest): Promise {
return request.put('/user/profile', data)
},
// 上传头像
uploadAvatar(file: File): Promise<{ url: string }> {
const formData = new FormData()
formData.append('avatar', file)
return request.post('/user/avatar/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
}
```
### 10.5 WebSocket实现方案
#### 为什么选择STOMP而不是Socket.io?
1. **后端集成**: 项目后端使用Spring Boot,STOMP是Spring WebSocket的标准协议
2. **消息队列**: STOMP天然支持消息队列模式,适合聊天和通知场景
3. **标准化**: STOMP是标准协议,不依赖特定实现
4. **轻量级**: 相比Socket.io更轻量,减少包体积
#### WebSocket工具类实现
```typescript
// utils/websocket.ts
import { Client } from '@stomp/stompjs'
import { envConfig } from '@/config/env'
export class WebSocketService {
private client: Client
private connected = false
private reconnectAttempts = 0
private maxReconnectAttempts = 5
private currentToken = ''
constructor() {
this.client = new Client({
// 使用原生WebSocket,支持Token认证
brokerURL: `${envConfig.wsBaseUrl}/ws`,
// 心跳检测
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
// 重连配置
reconnectDelay: 5000,
// 调试模式
debug: envConfig.debug ? console.log : undefined,
onConnect: () => {
this.connected = true
this.reconnectAttempts = 0
console.log('WebSocket连接成功')
},
onDisconnect: () => {
this.connected = false
console.log('WebSocket连接断开')
},
onStompError: (frame) => {
console.error('STOMP错误:', frame)
this.handleReconnect()
},
// WebSocket连接前的配置
beforeConnect: () => {
// 在WebSocket握手时添加Token
if (this.currentToken) {
this.client.configure({
connectHeaders: {
Authorization: `Bearer ${this.currentToken}`,
'X-Requested-With': 'XMLHttpRequest'
}
})
}
}
})
}
// 连接WebSocket
connect(token: string) {
this.currentToken = token
this.client.configure({
connectHeaders: {
Authorization: `Bearer ${token}`,
'X-Requested-With': 'XMLHttpRequest'
}
})
this.client.activate()
}
// 更新Token(用于Token刷新场景)
updateToken(newToken: string) {
this.currentToken = newToken
if (this.connected) {
// 断开当前连接
this.disconnect()
// 使用新Token重新连接
setTimeout(() => {
this.connect(newToken)
}, 1000)
}
}
// 断开连接
disconnect() {
this.client.deactivate()
}
// 订阅消息
subscribe(destination: string, callback: (message: any) => void) {
if (!this.connected) {
console.warn('WebSocket未连接')
return
}
return this.client.subscribe(destination, (message) => {
try {
const data = JSON.parse(message.body)
callback(data)
} catch (error) {
console.error('消息解析失败:', error)
}
})
}
// 发送消息
send(destination: string, body: any) {
if (!this.connected) {
console.warn('WebSocket未连接,消息将被缓存')
// 这里可以实现消息缓存逻辑
return
}
this.client.publish({
destination,
body: JSON.stringify(body)
})
}
// 处理重连
private handleReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++
setTimeout(() => {
console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
this.client.activate()
}, 5000 * this.reconnectAttempts)
}
}
}
```
#### 聊天功能使用示例
```typescript
// composables/useChat.ts
import { ref, onMounted, onUnmounted } from 'vue'
import { WebSocketService } from '@/utils/websocket'
import { useAuthStore } from '@/stores/auth'
export function useChat() {
const authStore = useAuthStore()
const wsService = new WebSocketService()
const messages = ref([])
const isConnected = ref(false)
// 连接WebSocket
const connect = () => {
if (authStore.token) {
wsService.connect(authStore.token)
// 订阅个人消息
wsService.subscribe(`/user/${authStore.user.id}/queue/messages`, (message) => {
messages.value.push(message)
})
// 订阅聊天室消息
wsService.subscribe('/topic/chat', (message) => {
messages.value.push(message)
})
isConnected.value = true
}
}
// 发送消息
const sendMessage = (content: string, type: 'text' | 'image' = 'text') => {
const message = {
content,
type,
timestamp: Date.now(),
userId: authStore.user.id
}
wsService.send('/app/chat.send', message)
}
// 组件挂载时连接
onMounted(() => {
connect()
})
// 组件卸载时断开连接
onUnmounted(() => {
wsService.disconnect()
})
return {
messages,
isConnected,
sendMessage,
connect
}
}
```
### 10.6 WebSocket Token认证详解
#### Token传递方式
原生WebSocket + STOMP协议支持Token认证:
1. **WebSocket握手时传递** (推荐)
```typescript
// 在WebSocket连接建立时传递Token
brokerURL: `${envConfig.wsBaseUrl}/ws`,
connectHeaders: {
Authorization: `Bearer ${token}`,
'X-Requested-With': 'XMLHttpRequest'
}
```
2. **URL参数传递** (备选方案)
```typescript
// 如果后端不支持连接头部,可以通过URL传递
brokerURL: `${envConfig.wsBaseUrl}/ws?token=${token}`
```
**为什么移除SockJS?**
- ❌ SockJS不支持在WebSocket握手时传递自定义请求头
- ❌ 无法在连接建立时进行Token认证
- ❌ 只能通过URL参数传递Token,安全性较低
- ✅ 原生WebSocket完全支持Token认证
- ✅ 现代浏览器WebSocket支持度已经很好
#### WebSocket方案对比
| 特性 | 原生WebSocket + STOMP | SockJS + STOMP | Socket.io |
|------|---------------------|----------------|-----------|
| **Token认证** | ✅ 支持请求头传递 | ❌ 不支持请求头 | ✅ 支持 |
| **浏览器兼容** | ✅ 现代浏览器完全支持 | ✅ 兼容性最好 | ✅ 兼容性好 |
| **包体积** | ✅ 最小 | ⚠️ 中等 | ❌ 最大 |
| **Spring Boot集成** | ✅ 原生支持 | ✅ 原生支持 | ❌ 需要额外配置 |
| **标准化** | ✅ 标准协议 | ✅ 标准协议 | ❌ 私有协议 |
| **安全性** | ✅ 握手时认证 | ⚠️ URL参数认证 | ✅ 握手时认证 |
**最终选择:原生WebSocket + STOMP**
- 🎯 **安全性优先**: 支持在握手时进行Token认证
- 🎯 **性能最优**: 无额外协议层,直接使用WebSocket
- 🎯 **标准化**: 基于标准STOMP协议
- 🎯 **轻量级**: 最小的包体积
- 🎯 **兼容性**: 现代浏览器支持度已经足够
#### Token刷新处理
```typescript
// stores/auth.ts - 认证状态管理
import { defineStore } from 'pinia'
import { ref, watch } from 'vue'
import { WebSocketService } from '@/utils/websocket'
export const useAuthStore = defineStore('auth', () => {
const token = ref('')
const user = ref(null)
const wsService = ref(null)
// 监听Token变化,自动更新WebSocket连接
watch(token, (newToken, oldToken) => {
if (newToken && newToken !== oldToken && wsService.value) {
wsService.value.updateToken(newToken)
}
})
// 登录
const login = async (credentials: LoginRequest) => {
try {
const response = await authApi.login(credentials)
token.value = response.token
user.value = response.user
// 登录成功后建立WebSocket连接
if (!wsService.value) {
wsService.value = new WebSocketService()
}
wsService.value.connect(token.value)
return response
} catch (error) {
throw error
}
}
// 登出
const logout = () => {
// 断开WebSocket连接
if (wsService.value) {
wsService.value.disconnect()
wsService.value = null
}
token.value = ''
user.value = null
}
// Token刷新
const refreshToken = async () => {
try {
const response = await authApi.refreshToken()
token.value = response.token
// watch会自动处理WebSocket重连
return response
} catch (error) {
// Token刷新失败,执行登出
logout()
throw error
}
}
return {
token,
user,
wsService,
login,
logout,
refreshToken
}
})
```
#### 后端WebSocket安全配置
对应的Spring Boot后端配置示例:
```java
// WebSocketConfig.java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOriginPatterns("*");
// 移除.withSockJS(),使用原生WebSocket支持Token认证
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new AuthChannelInterceptor());
}
}
// AuthChannelInterceptor.java - Token验证拦截器
@Component
public class AuthChannelInterceptor implements ChannelInterceptor {
@Override
public Message> preSend(Message> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String token = accessor.getFirstNativeHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
String jwt = token.substring(7);
// 验证JWT Token
if (jwtTokenProvider.validateToken(jwt)) {
String userId = jwtTokenProvider.getUserIdFromToken(jwt);
accessor.setUser(new StompPrincipal(userId));
} else {
throw new IllegalArgumentException("Invalid token");
}
} else {
throw new IllegalArgumentException("Missing token");
}
}
return message;
}
}
```
#### 错误处理和重连机制
```typescript
// 增强的WebSocket错误处理
export class WebSocketService {
private tokenExpiredCallback?: () => void
constructor(onTokenExpired?: () => void) {
this.tokenExpiredCallback = onTokenExpired
// ... 其他初始化代码
}
private handleStompError(frame: any) {
console.error('STOMP错误:', frame)
// 检查是否是Token相关错误
if (frame.headers && frame.headers.message) {
const errorMessage = frame.headers.message.toLowerCase()
if (errorMessage.includes('unauthorized') ||
errorMessage.includes('invalid token') ||
errorMessage.includes('token expired')) {
console.warn('Token认证失败,触发重新登录')
this.tokenExpiredCallback?.()
return
}
}
// 其他错误进行重连
this.handleReconnect()
}
}
// 在应用中使用
const authStore = useAuthStore()
const wsService = new WebSocketService(() => {
// Token过期回调
authStore.logout()
router.push('/login')
})
```
#### 安全最佳实践
1. **Token验证**: 每次WebSocket连接都验证Token有效性
2. **权限控制**: 基于用户角色限制订阅和发送权限
3. **连接限制**: 限制单用户的并发连接数
4. **消息加密**: 敏感消息内容加密传输
5. **审计日志**: 记录WebSocket连接和消息日志
这个方案完全支持Token认证,并且提供了完整的Token生命周期管理,包括刷新、过期处理和安全重连机制。
## 11. 测试策略
### 11.1 单元测试
```typescript
// tests/components/UserProfile.test.ts
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import UserProfile from '@/components/UserProfile.vue'
describe('UserProfile', () => {
it('renders user information correctly', () => {
const user = {
id: '1',
username: 'testuser',
nickname: 'Test User',
avatar: 'https://example.com/avatar.jpg'
}
const wrapper = mount(UserProfile, {
props: { user }
})
expect(wrapper.text()).toContain('Test User')
expect(wrapper.find('img').attributes('src')).toBe(user.avatar)
})
})
```
### 11.2 E2E测试
```typescript
// cypress/e2e/auth.cy.ts
describe('Authentication', () => {
it('should login successfully', () => {
cy.visit('/login')
cy.get('[data-cy=username]').type('testuser')
cy.get('[data-cy=password]').type('password123')
cy.get('[data-cy=login-btn]').click()
cy.url().should('include', '/dashboard')
cy.get('[data-cy=user-menu]').should('be.visible')
})
})
```
### 11.3 测试配置
```typescript
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: ['./tests/setup.ts']
},
resolve: {
alias: {
'@': '/src'
}
}
})
```
## 12. 国际化支持
### 12.1 i18n配置
- **vue-i18n**: `9.10.2` (国际化支持)
- **@intlify/unplugin-vue-i18n**: `4.0.0` (构建时优化)
```typescript
// i18n/index.ts
import { createI18n } from 'vue-i18n'
import zh from './locales/zh.json'
import en from './locales/en.json'
export const i18n = createI18n({
legacy: false,
locale: 'zh',
fallbackLocale: 'en',
messages: {
zh,
en
}
})
```
### 12.2 语言文件结构
```json
// i18n/locales/zh.json
{
"common": {
"confirm": "确认",
"cancel": "取消",
"save": "保存",
"delete": "删除"
},
"auth": {
"login": "登录",
"register": "注册",
"logout": "退出登录"
},
"chat": {
"sendMessage": "发送消息",
"typing": "正在输入...",
"offline": "离线"
}
}
```
## 13. 移动端适配
### 13.1 响应式断点
```css
/* tailwind.config.js */
module.exports = {
theme: {
screens: {
'xs': '475px',
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
}
}
}
```
### 13.2 移动端优化
- **触摸优化**: 44px最小触摸目标
- **手势支持**: 滑动、缩放、长按
- **性能优化**: 虚拟滚动、图片懒加载
- **离线支持**: Service Worker缓存
### 13.3 PWA配置
```typescript
// vite.config.ts PWA配置
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
manifest: {
name: '情绪博物馆',
short_name: '情绪博物馆',
description: '记录情绪,分享心情的温暖空间',
theme_color: '#4A90E2',
background_color: '#ffffff',
display: 'standalone',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
}
})
```
## 14. 总结
本技术方案基于现代化的Vue3生态系统,采用TypeScript提供类型安全,使用Vite构建工具提升开发体验。方案涵盖了:
### 14.1 技术优势
- **现代化技术栈**: Vue3 + TypeScript + Vite
- **完整的工具链**: 从开发到部署的全流程支持
- **性能优化**: 代码分割、懒加载、缓存策略
- **开发体验**: 热更新、自动导入、类型检查
### 14.2 可扩展性
- **模块化设计**: 清晰的项目结构和职责分离
- **组件化开发**: 可复用的UI组件库
- **插件系统**: 支持功能扩展和第三方集成
- **国际化支持**: 多语言适配能力
### 14.3 维护性
- **代码规范**: ESLint + Prettier统一代码风格
- **测试覆盖**: 单元测试 + E2E测试
- **文档完善**: 组件文档和API文档
- **版本管理**: 语义化版本控制
### 14.4 部署方案
- **多环境支持**: local/dev/test/prod环境配置
- **容器化部署**: Docker + Nginx部署方案
- **CI/CD流程**: 自动化构建和部署
- **监控告警**: 错误监控和性能分析
这个技术方案能够很好地支持情绪博物馆Web端的所有功能需求,同时具备良好的可维护性和扩展性,为项目的长期发展奠定坚实基础。