🎨 重构用户端前端为vue开发,完善基础类和角色相关接口

This commit is contained in:
2026-02-10 21:55:45 +08:00
parent db934ebed7
commit 56e821b222
92 changed files with 18377 additions and 21 deletions

648
docs/Vue重构方案.md Normal file
View File

@@ -0,0 +1,648 @@
# web-app Vue 3 重构方案
## 📋 方案概述
将 web-app 从传统的 jQuery 项目重构为 Vue 3 现代化单页应用SPA
## 🎯 重构目标
### 技术目标
- ✅ 使用 Vue 3 + Vite + TypeScript
- ✅ 组件化、模块化开发
- ✅ 统一前后端技术栈(与管理后台一致)
- ✅ 优化性能和用户体验
- ✅ 便于维护和扩展
### 业务目标
- ✅ 保留所有原有功能
- ✅ 改善 UI/UX 设计
- ✅ 适配移动端
- ✅ 支持主题切换
- ✅ 国际化支持
## 🏗️ 技术栈选择
### 核心技术
```json
{
"框架": "Vue 3 (Composition API)",
"构建工具": "Vite 5",
"语言": "TypeScript",
"状态管理": "Pinia",
"路由": "Vue Router 4",
"HTTP": "Axios",
"WebSocket": "原生 WebSocket / Socket.io-client"
}
```
### UI 框架选择
#### 方案一Element Plus推荐
```bash
# 优点
✅ 与管理后台统一web/ 使用的就是 Element Plus
✅ 组件丰富,开箱即用
✅ 中文文档完善
✅ 支持深色主题
✅ TypeScript 支持好
# 缺点
⚠️ 组件较重(如果只需要简单 UI可能过度设计
```
#### 方案二Naive UI
```bash
# 优点
✅ 轻量级,性能好
✅ TypeScript 原生支持
✅ 组件设计现代
✅ 支持深色主题
# 缺点
⚠️ 与管理后台不统一
```
#### 方案三:自定义 UI参考 auth.html
```bash
# 优点
✅ 完全自定义,独特设计
✅ 轻量级
✅ 可以复用已有的 auth.css 样式
# 缺点
⚠️ 需要自己实现所有组件
⚠️ 开发时间较长
```
**推荐Element Plus + 自定义样式**
- 使用 Element Plus 的基础组件(表单、按钮、对话框等)
- 自定义主题和关键页面样式
- 兼顾开发效率和设计独特性
## 📂 项目结构
### 新项目结构(推荐)
```
web-app-vue/ # 新建的 Vue 项目
├── public/
│ ├── favicon.ico
│ └── img/ # 静态图片资源
├── src/
│ ├── api/ # API 接口
│ │ ├── auth.ts # 认证接口
│ │ ├── character.ts # 角色接口
│ │ ├── chat.ts # 对话接口
│ │ └── index.ts # axios 配置
│ ├── assets/ # 资源文件
│ │ ├── styles/ # 全局样式
│ │ │ ├── index.scss
│ │ │ ├── variables.scss
│ │ │ └── dark-theme.scss
│ │ └── images/
│ ├── components/ # 通用组件
│ │ ├── common/ # 基础组件
│ │ │ ├── AppHeader.vue
│ │ │ ├── AppSidebar.vue
│ │ │ └── Loading.vue
│ │ ├── chat/ # 对话组件
│ │ │ ├── ChatMessage.vue
│ │ │ ├── ChatInput.vue
│ │ │ ├── MessageSwipe.vue
│ │ │ └── VoiceInput.vue
│ │ ├── character/ # 角色组件
│ │ │ ├── CharacterCard.vue
│ │ │ ├── CharacterList.vue
│ │ │ ├── CharacterEditor.vue
│ │ │ └── CharacterImport.vue
│ │ └── settings/ # 设置组件
│ │ ├── AIConfig.vue
│ │ ├── ThemeConfig.vue
│ │ └── UserProfile.vue
│ ├── composables/ # 组合式函数
│ │ ├── useAuth.ts # 认证相关
│ │ ├── useChat.ts # 对话相关
│ │ ├── useCharacter.ts # 角色相关
│ │ └── useWebSocket.ts # WebSocket
│ ├── layouts/ # 布局组件
│ │ ├── DefaultLayout.vue # 默认布局
│ │ ├── AuthLayout.vue # 认证页布局
│ │ └── ChatLayout.vue # 对话页布局
│ ├── router/ # 路由配置
│ │ ├── index.ts
│ │ └── guards.ts # 路由守卫
│ ├── stores/ # Pinia 状态管理
│ │ ├── auth.ts # 用户认证
│ │ ├── chat.ts # 对话状态
│ │ ├── character.ts # 角色管理
│ │ ├── settings.ts # 设置
│ │ └── index.ts
│ ├── types/ # TypeScript 类型
│ │ ├── api.d.ts
│ │ ├── character.d.ts
│ │ ├── chat.d.ts
│ │ └── user.d.ts
│ ├── utils/ # 工具函数
│ │ ├── request.ts # HTTP 请求封装
│ │ ├── storage.ts # 本地存储
│ │ ├── websocket.ts # WebSocket 封装
│ │ ├── format.ts # 格式化
│ │ └── validate.ts # 验证
│ ├── views/ # 页面视图
│ │ ├── auth/ # 认证页
│ │ │ ├── Login.vue
│ │ │ └── Register.vue
│ │ ├── home/ # 主页
│ │ │ └── Index.vue
│ │ ├── character/ # 角色页
│ │ │ ├── List.vue
│ │ │ ├── Detail.vue
│ │ │ └── Create.vue
│ │ ├── chat/ # 对话页
│ │ │ └── Index.vue
│ │ ├── settings/ # 设置页
│ │ │ └── Index.vue
│ │ └── user/ # 用户中心
│ │ └── Profile.vue
│ ├── App.vue # 根组件
│ └── main.ts # 入口文件
├── .env.development # 开发环境配置
├── .env.production # 生产环境配置
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.md
```
### 与现有项目的关系
```
st/
├── server/ # Go 后端(不变)
├── web/ # Vue 管理后台(不变)
├── web-app/ # 旧项目(保留备份)
└── web-app-vue/ # 新的 Vue 前台(新建)
└── ...
```
## 🚀 实施步骤
### 阶段一项目初始化1-2 天)
#### 1.1 创建 Vue 项目
```bash
# 使用 Vite 创建项目
npm create vite@latest web-app-vue -- --template vue-ts
cd web-app-vue
npm install
```
#### 1.2 安装依赖
```bash
# UI 框架
npm install element-plus
# 路由和状态管理
npm install vue-router@4 pinia
# HTTP 和工具
npm install axios
npm install @vueuse/core # Vue 常用组合式函数
# 开发依赖
npm install -D sass
npm install -D unplugin-vue-components unplugin-auto-import
```
#### 1.3 配置 Vite
```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
imports: ['vue', 'vue-router', 'pinia'],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server: {
port: 3000,
proxy: {
'/app': {
target: 'http://localhost:8888',
changeOrigin: true,
},
},
},
})
```
#### 1.4 基础配置
```typescript
// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import router from './router'
import App from './App.vue'
import './assets/styles/index.scss'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.use(ElementPlus)
app.mount('#app')
```
### 阶段二核心功能开发5-7 天)
#### 2.1 认证模块1 天)
- [x] 登录页面
- [x] 注册页面
- [x] Token 管理
- [x] 路由守卫
#### 2.2 角色管理2 天)
- [ ] 角色列表
- [ ] 角色详情
- [ ] 角色创建/编辑
- [ ] 角色导入/导出
- [ ] 收藏功能
#### 2.3 对话功能3 天)
- [ ] 对话界面
- [ ] 消息发送
- [ ] 消息渲染
- [ ] Swipe 功能
- [ ] WebSocket 实时通信
- [ ] 流式输出
#### 2.4 设置页面1 天)
- [ ] AI 配置
- [ ] 主题设置
- [ ] 用户偏好
### 阶段三高级功能3-5 天)
#### 3.1 AI 功能
- [ ] 多模型支持
- [ ] Prompt 管理
- [ ] World Info
- [ ] 向量记忆
#### 3.2 UI/UX 优化
- [ ] 响应式布局
- [ ] 移动端适配
- [ ] 主题切换
- [ ] 动画效果
#### 3.3 文件管理
- [ ] 头像上传
- [ ] 文件管理
- [ ] 图片预览
### 阶段四测试和优化2-3 天)
- [ ] 单元测试
- [ ] E2E 测试
- [ ] 性能优化
- [ ] 打包优化
- [ ] 部署配置
## 📦 关键组件示例
### 1. 认证 Store
```typescript
// src/stores/auth.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { login, register, getUserInfo } from '@/api/auth'
import type { LoginRequest, User } from '@/types/user'
export const useAuthStore = defineStore('auth', () => {
const token = ref<string>(localStorage.getItem('st_access_token') || '')
const user = ref<User | null>(null)
const isLoggedIn = computed(() => !!token.value)
async function handleLogin(data: LoginRequest) {
const res = await login(data)
token.value = res.data.token
user.value = res.data.user
localStorage.setItem('st_access_token', res.data.token)
localStorage.setItem('st_user_info', JSON.stringify(res.data.user))
}
async function handleLogout() {
token.value = ''
user.value = null
localStorage.removeItem('st_access_token')
localStorage.removeItem('st_user_info')
}
async function fetchUserInfo() {
const res = await getUserInfo()
user.value = res.data
}
return {
token,
user,
isLoggedIn,
handleLogin,
handleLogout,
fetchUserInfo,
}
})
```
### 2. HTTP 请求封装
```typescript
// src/utils/request.ts
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { useAuthStore } from '@/stores/auth'
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8888',
timeout: 10000,
})
// 请求拦截器
request.interceptors.request.use(
(config) => {
const authStore = useAuthStore()
if (authStore.token) {
config.headers['x-token'] = authStore.token
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
request.interceptors.response.use(
(response) => {
const res = response.data
if (res.code !== 0) {
ElMessage.error(res.msg || '请求失败')
return Promise.reject(new Error(res.msg || '请求失败'))
}
return res
},
(error) => {
ElMessage.error(error.message || '网络错误')
return Promise.reject(error)
}
)
export default request
```
### 3. 角色卡片组件
```vue
<!-- src/components/character/CharacterCard.vue -->
<template>
<div class="character-card" @click="handleClick">
<div class="card-header">
<img :src="character.avatar" :alt="character.name" class="avatar" />
<el-icon v-if="isFavorite" class="favorite-icon">
<Star />
</el-icon>
</div>
<div class="card-body">
<h3 class="character-name">{{ character.name }}</h3>
<p class="character-description">{{ character.description }}</p>
</div>
<div class="card-footer">
<el-tag v-for="tag in character.tags" :key="tag" size="small">
{{ tag }}
</el-tag>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { Character } from '@/types/character'
interface Props {
character: Character
}
const props = defineProps<Props>()
const emit = defineEmits<{
click: [character: Character]
}>()
const isFavorite = computed(() => props.character.isFavorite)
function handleClick() {
emit('click', props.character)
}
</script>
<style scoped lang="scss">
.character-card {
border-radius: 12px;
overflow: hidden;
cursor: pointer;
transition: all 0.3s;
background: var(--el-bg-color);
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
.card-header {
position: relative;
.avatar {
width: 100%;
height: 200px;
object-fit: cover;
}
.favorite-icon {
position: absolute;
top: 12px;
right: 12px;
color: #f59e0b;
font-size: 24px;
}
}
.card-body {
padding: 16px;
.character-name {
font-size: 18px;
font-weight: bold;
margin-bottom: 8px;
}
.character-description {
color: var(--el-text-color-secondary);
font-size: 14px;
line-height: 1.6;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
.card-footer {
padding: 0 16px 16px;
display: flex;
gap: 8px;
flex-wrap: wrap;
}
}
</style>
```
## 🔄 迁移策略
### 渐进式迁移(推荐)
1. **Phase 1: 新功能使用 Vue**
- 保留旧 web-app用于稳定运行
- 新功能在 web-app-vue 开发
- 通过路由切换新旧页面
2. **Phase 2: 逐步迁移**
- 按模块迁移(认证 → 角色 → 对话 → 设置)
- 每个模块迁移后充分测试
- 确保功能完整
3. **Phase 3: 完全替换**
- 所有功能迁移完成
- 彻底删除旧代码
- web-app-vue 改名为 web-app
### 一次性重写(不推荐,风险高)
除非你有充足的时间和人力,否则不建议一次性重写整个项目。
## 📊 与现有项目的集成
### Go 后端配置
```go
// server/initialize/router.go
// 前台 Vue 应用静态文件
webAppVuePath := "../web-app-vue/dist"
if _, err := os.Stat(webAppVuePath); err == nil {
Router.Static("/assets", webAppVuePath+"/assets")
Router.StaticFile("/", webAppVuePath+"/index.html")
global.GVA_LOG.Info("前台 Vue 应用已启动: " + webAppVuePath)
}
```
### 环境配置
```bash
# .env.development
VITE_API_BASE_URL=http://localhost:8888
VITE_WS_URL=ws://localhost:8888
# .env.production
VITE_API_BASE_URL=https://your-domain.com
VITE_WS_URL=wss://your-domain.com
```
## 🎯 开发优先级
### P0必须
1. ✅ 用户认证(登录/注册)
2. ✅ 角色列表和详情
3. ✅ 基本对话功能
4. ✅ AI 配置
### P1重要
5. ⚪ 角色编辑和创建
6. ⚪ 消息 Swipe
7. ⚪ 文件上传
8. ⚪ 设置页面
### P2可选
9. ⚪ World Info
10. ⚪ 向量记忆
11. ⚪ 高级 AI 功能
12. ⚪ 主题切换
## 📝 注意事项
### 1. 保持功能一致性
- 确保所有原有功能都能在 Vue 版本中实现
- 参考旧版的交互逻辑
- 不要遗漏边界情况
### 2. 性能优化
- 使用虚拟滚动(角色列表、消息列表)
- 图片懒加载
- 路由懒加载
- 打包分析和优化
### 3. 移动端适配
- 响应式设计
- 触摸手势支持
- 移动端专用布局
### 4. 国际化
- 使用 vue-i18n
- 支持多语言切换
- 本地化日期和数字
## 📚 学习资源
- Vue 3 官方文档: https://cn.vuejs.org/
- Vite 文档: https://cn.vitejs.dev/
- Element Plus: https://element-plus.org/zh-CN/
- Pinia 文档: https://pinia.vuejs.org/zh/
- TypeScript 文档: https://www.typescriptlang.org/zh/
## 🎉 总结
### 为什么要重构?
1.**代码质量**:从混乱的 jQuery 代码到清晰的组件化代码
2.**开发效率**热更新、TypeScript、自动导入
3.**性能提升**Vite 构建、按需加载、虚拟滚动
4.**易于维护**:模块化、类型安全、单一职责
5.**技术统一**:与管理后台使用相同技术栈
6.**未来发展**:易于扩展新功能
### 建议的时间线
- **快速原型**1 周):核心功能,可以开始使用
- **MVP 版本**2-3 周):主要功能完成
- **完整版本**4-6 周):所有功能迁移完成
- **优化打磨**持续性能优化、bug 修复
---
**更新日期**: 2026-02-10
**版本**: v1.0.0