2991692032 2 weeks ago
parent 7170c136a8
commit 63ffb1bb2a

@ -1,50 +1,102 @@
# UniLife —— 有你生活,优你生活
## 项目简介
UniLife 是一款面向学生的在线论坛,致力于提升校园生活体验。其口号为 “有你生活优你生活”核心功能包括论坛交流、学习资源共享、课程管理、AI 学习辅助等。项目初期以网站形式开发,后续可能扩展为移动端应用。
# UniLife - 大学生活综合平台
## 最新更新 🎉
### v1.4.0 - AI助手重构 (2025-05-30)
- ✅ **流式AI对话**: 实现真正的实时流式响应,告别等待时间
- ✅ **优化用户体验**: 文字逐字显示,就像真实对话一样自然
- ✅ **技术优化**: 使用Spring AI + WebFlux + 原生fetch API确保稳定性
- ✅ **美观界面**: 保持现代化设计支持Markdown渲染和代码高亮
## 功能特性
### 1.用户系统 ✅
+ 账号注册/登录(支持邮箱验证码登录)
+ 个人资料管理
+ JWT认证机制
### 2.论坛功能 ✅
+ 主题发布/评论/点赞
+ 话题分类(学习、校园生活、兴趣交流等)
+ 嵌套评论系统
### 3.学习资源共享 ✅
+ 资源上传/下载
+ 资源分类管理
+ 文件存储支持阿里云OSS
### 4.课程表 & 个人行程安排 ✅
+ 课程信息管理
+ 个人日程管理
+ 课程冲突检测
+ 日程提醒功能
### 5.搜索功能 ✅
+ 综合搜索(帖子/资源/用户)
+ 分类搜索和过滤
+ 搜索建议
+ 热门搜索词
### 6.AI 辅助学习 🚧
+ 学习计划制定(开发中)
+ 智能任务提醒(开发中)
+ AI问答助手开发中
### 7.积分系统 🚧
+ 贡献积分系统(规划中)
+ 成就系统(规划中)
+ 积分排行榜(规划中)
### 8.实时通知 🚧
+ WebSocket实时推送规划中
+ 消息中心(规划中)
+ 私信功能(规划中)
## 小组成员:
王雨菲 蔡子钦 钟宏烨 贾瀚翔 胡天琦 刘宇航
### 🤖 AI智能助手
- **实时流式对话**: 支持连续对话AI回复实时显示
- **多会话管理**: 创建多个独立的对话会话
- **学习辅导**: 专业的学习计划制定和学习方法指导
- **智能问答**: 快速获得各类学习问题的解答
### 📚 学习资源共享
- 课件、笔记、考试资料上传下载
- 资源分类管理和搜索
- 用户评分和推荐系统
### 💬 学术论坛
- 学习交流和问题讨论
- 帖子发布、评论、点赞
- 热门话题和精华内容推荐
### 📅 课程表与日程管理
- 个人课程表管理
- 学习任务和截止时间提醒
- 日程安排和时间规划
## 技术架构
### 后端技术栈
- **Spring Boot 3.x**: 主应用框架
- **Spring AI**: AI集成框架支持多种AI提供商
- **WebFlux**: 响应式Web框架支持流式响应
- **MySQL**: 主数据库
- **JWT**: 身份认证
- **OSS**: 文件存储
### 前端技术栈
- **Vue 3**: 前端框架
- **TypeScript**: 类型安全
- **Element Plus**: UI组件库
- **Pinia**: 状态管理
- **md-editor-v3**: Markdown编辑器
- **Native Fetch API**: 流式响应处理
## 快速开始
### 1. 克隆项目
```bash
git clone https://github.com/your-repo/unilife.git
cd unilife
```
### 2. 启动后端
```bash
cd unilife-server
mvn spring-boot:run -Dmaven.test.skip=true
```
### 3. 启动前端
```bash
cd unilife-frontend
npm install
npm run dev
```
### 4. 访问应用
- 前端地址: http://localhost:5175
- 后端地址: http://localhost:8087
## AI助手使用指南
### 基本使用
1. 登录系统后,点击导航栏的"AI助手"
2. 在输入框中输入你的问题或需求
3. 按Enter发送AI会实时回复
### 功能示例
- **学习计划**: "帮我制定一个学期的学习计划"
- **课程推荐**: "推荐一些适合我专业的课程"
- **学习方法**: "分享一些高效的学习方法"
- **答疑解惑**: "如何学好Python编程"
### 技术特点
- **实时响应**: 无需等待AI回复逐字显示
- **上下文理解**: 支持连续对话,记住前面的对话内容
- **多会话管理**: 可以创建多个不同主题的对话
- **Markdown支持**: AI回复支持代码高亮、表格等格式
## 贡献指南
欢迎提交Issue和Pull Request来帮助改进项目
## 许可证
本项目基于MIT许可证开源。

@ -153,32 +153,86 @@ public class Result<T> {
### 🤖 AI辅助学习模块
#### 技术选型建议
- **AI服务**:百度文心一言、阿里通义千问
- **集成方式**HTTP API调用
- **功能设计**
- 学习计划生成
- 智能问答
- 学习进度分析
- **AI服务**Spring AI + ChatClient支持多种AI提供商
- **流式响应**WebFlux Flux<String>
- **集成方式**Spring Boot ReactiveWeb
#### 流式响应核心技术
```java
// 后端实现要点
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> sendMessage(@RequestParam("prompt") String prompt) {
return chatClient.prompt(prompt)
.stream()
.content();
}
```
```javascript
// 前端实现要点
const sendMessage = async (prompt) => {
const params = new URLSearchParams()
params.append('prompt', prompt)
const response = await fetch('/ai/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params
})
const reader = response.body.getReader()
const decoder = new TextDecoder('utf-8')
let accumulatedContent = ''
while (true) {
const { value, done } = await reader.read()
if (done) break
accumulatedContent += decoder.decode(value)
// 实时更新UI
updateMessage(accumulatedContent)
}
}
```
#### 关键技术要点
1. **使用原生fetch而不是axios**: axios对流式响应支持有限
2. **URLSearchParams参数传递**: 比JSON格式更稳定
3. **UTF-8编码处理**: 确保中文字符正确显示
4. **累积内容渲染**: 避免字符被截断
5. **错误处理机制**: 流式传输中的异常捕获
#### 功能设计
- 实时流式AI对话
- 多会话管理
- 学习计划生成
- 智能问答
- 学习进度分析
#### 数据库设计
```sql
-- 学习计划表
CREATE TABLE study_plans (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
title VARCHAR(100) NOT NULL,
content TEXT,
ai_generated TINYINT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
-- AI聊天会话表
CREATE TABLE ai_chat_sessions (
id VARCHAR(64) PRIMARY KEY COMMENT '会话ID前端生成',
user_id BIGINT NOT NULL COMMENT '用户ID',
title VARCHAR(100) NOT NULL DEFAULT '新对话' COMMENT '会话标题',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_user_id (user_id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- AI对话记录
CREATE TABLE ai_conversations (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
question TEXT NOT NULL,
answer TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
-- AI聊天消息表
CREATE TABLE ai_chat_messages (
id VARCHAR(64) PRIMARY KEY COMMENT '消息ID前端生成',
session_id VARCHAR(64) NOT NULL COMMENT '会话ID',
role ENUM('user', 'assistant', 'system') NOT NULL COMMENT '角色',
content TEXT NOT NULL COMMENT '消息内容',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX idx_session_id (session_id),
FOREIGN KEY (session_id) REFERENCES ai_chat_sessions (id) ON DELETE CASCADE
);
```

@ -2,6 +2,14 @@
## 更新日志
### v1.4.0 (2025-05-30)
- **重构AI助手流式响应**: 完全重构AI聊天功能实现真正的流式显示
- **优化接口参数格式**: AI聊天接口改用`application/x-www-form-urlencoded`格式,简化参数传递
- **改进前端实现**: 使用原生fetch API替代axios确保流式响应的稳定性
- **参考成功案例**: 基于已验证的流式响应实现模式进行重构
- **UI体验提升**: 保持美观界面的同时,实现真正的实时流式文字显示
- **响应格式优化**: 从Server-Sent Events改为直接文本流提高兼容性
### v1.3.0 (2025-01-27)
- **新增AI辅助学习模块**: 实现了完整的AI聊天助手功能
- **AI会话管理**: 支持创建、查询、更新、删除聊天会话
@ -1666,62 +1674,26 @@ CREATE TABLE `schedules` (
- **方法**: POST
- **描述**: 向AI发送消息并获取流式回复
- **认证**: 需要JWT Token
- **响应类型**: `text/event-stream`Server-Sent Events
- **Content-Type**: `application/x-www-form-urlencoded`
- **响应类型**: `text/html;charset=UTF-8`(流式文本响应)
请求参数:
```json
{
"message": "如何学好Python编程",
"sessionId": "session_1234567890",
"conversationHistory": [
{
"id": "msg_001",
"role": "user",
"content": "你好",
"timestamp": "2025-01-27T10:00:00"
}
]
}
请求参数Form Data格式
```
prompt=如何学好Python编程
sessionId=session_1234567890
```
**参数说明**:
- `message`: 用户发送的消息内容
- `sessionId` (可选): 会话ID如果不提供则创建新会话
- `conversationHistory` (可选): 会话历史记录用于AI理解上下文
- `prompt`: 用户发送的消息内容(必填)
- `sessionId`: 会话ID如果不提供则由后端创建新会话可选
**流式响应**:
接口返回Server-Sent Events流每个事件包含AI回复的一部分内容
接口返回原始文本流AI的回复内容会逐字符或逐词流式返回
```
data: 学好Python编程需要
data: 循序渐进地学习
data: ,首先掌握基础语法
data: ,然后通过实际项目练习
data: [END]
学好Python编程需要循序渐进地学习首先掌握基础语法然后通过实际项目练习...
```
**前端处理示例**:
```javascript
const response = await fetch('/ai/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify(requestData)
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// 处理流式数据块
console.log(chunk);
}
```
#### 7.1.2 获取聊天会话列表
- **URL**: `/ai/sessions`
@ -1937,9 +1909,45 @@ await sendMessage({
**后端流式实现**:
```java
@PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> sendMessage(@RequestBody AiSendMessageDTO sendMessageDTO) {
return aiService.sendMessage(sendMessageDTO);
@RestController
@RequestMapping("/ai")
public class AiController {
private final AiService aiService;
@Operation(summary = "发送消息给AI")
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> sendMessage(
@RequestParam("prompt") String prompt,
@RequestParam(value = "sessionId", required = false) String sessionId) {
log.info("发送消息给AI: {}", prompt);
AiSendMessageDTO sendMessageDTO = new AiSendMessageDTO();
sendMessageDTO.setMessage(prompt);
sendMessageDTO.setSessionId(sessionId);
return aiService.sendMessage(sendMessageDTO);
}
}
```
**Service层实现**:
```java
@Service
public class AiServiceImpl implements AiService {
@Autowired
private ChatClient chatClient;
@Override
public Flux<String> sendMessage(AiSendMessageDTO sendMessageDTO) {
log.info("发送消息给AI: {}", sendMessageDTO.getMessage());
// 使用Spring AI ChatClient的流式响应
return chatClient.prompt(sendMessageDTO.getMessage())
.stream()
.content();
}
}
```

@ -37,17 +37,30 @@ export interface ChatMessagesResponse {
// 发送消息给AI流式响应
export const sendMessage = async (
data: SendMessageRequest
prompt: string,
sessionId?: string | null
): Promise<ReadableStreamDefaultReader<Uint8Array>> => {
const token = localStorage.getItem('token')
// 使用URLSearchParams构建请求参数
const params = new URLSearchParams()
params.append('prompt', prompt)
if (sessionId && sessionId.trim()) {
params.append('sessionId', sessionId.trim())
console.log('API请求包含sessionId:', sessionId.trim())
} else {
console.log('API请求不包含sessionId')
}
console.log('发送到后端的参数:', params.toString())
const response = await fetch(`${api.defaults.baseURL}/ai/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': token ? `Bearer ${token}` : ''
},
body: JSON.stringify(data)
body: params
})
if (!response.ok) {

File diff suppressed because it is too large Load Diff

@ -27,9 +27,16 @@ public class AiController {
private final AiService aiService;
@Operation(summary = "发送消息给AI")
@PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> sendMessage(@RequestBody AiSendMessageDTO sendMessageDTO) {
log.info("发送消息给AI: {}", sendMessageDTO.getMessage());
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> sendMessage(
@RequestParam("prompt") String prompt,
@RequestParam(value = "sessionId", required = false) String sessionId) {
log.info("发送消息给AI: {}", prompt);
AiSendMessageDTO sendMessageDTO = new AiSendMessageDTO();
sendMessageDTO.setMessage(prompt);
sendMessageDTO.setSessionId(sessionId);
return aiService.sendMessage(sendMessageDTO);
}

@ -1,182 +0,0 @@
# 问题修复和Stagewise集成说明
## 🔧 已修复的问题
### 1. Schedule实体类reminder字段类型错误
**问题描述**
```
Value '1440' is outside of valid range for type java.lang.Byte
```
**根本原因**
- 数据库中schedules表的reminder字段已修改为INT类型
- 但Java实体类中的reminder字段仍然是Byte类型范围-128到127
- 测试数据中有1440、720等超出Byte范围的值
**解决方案**
修改了以下文件中的reminder字段类型从Byte改为Integer
- `unilife-server/src/main/java/com/unilife/model/entity/Schedule.java`
- `unilife-server/src/main/java/com/unilife/model/vo/ScheduleVO.java`
- `unilife-server/src/main/java/com/unilife/model/dto/CreateScheduleDTO.java`
### 2. 评论显示问题分析
**问题描述**
前端显示评论数量9条但实际只显示2条评论
**初步分析**
- 数据库中确实存在评论数据
- 一级评论和回复查询逻辑正常
- 可能是前端渲染或API调用的问题
**需要进一步调试**
- 检查浏览器网络请求
- 查看前端控制台错误
- 验证API返回数据
### 3. 点赞按钮样式优化
**问题描述**
已点赞状态的蓝色背景过于突兀,与整体设计不协调
**解决方案**
- 替换突兀的蓝色为柔和的紫色主题
- 使用半透明背景代替实色背景
- 添加悬停动效和平滑过渡
- 保持状态清晰可辨的同时更加优雅
### 4. 发布帖子功能优化
**问题描述**
原发布帖子界面简陋,仅支持纯文本,用户体验不佳
**优化内容**
- ✅ **集成Markdown编辑器**:使用`md-editor-v3`支持富文本编辑
- ✅ **改进界面设计**:现代化的对话框布局和样式
- ✅ **增强表单验证**:完整的客户端验证和错误提示
- ✅ **优化用户体验**:字数限制、清空功能、响应式设计
- ✅ **Markdown语法提示**:帮助用户了解支持的语法
**技术实现**
```bash
npm install md-editor-v3 --save
```
**新增功能**
- 实时预览Markdown内容
- 工具栏支持各种格式化操作
- 支持代码高亮、表格、链接等
- 字数统计和限制标题最多100字符
- 表单验证和错误处理
- 响应式设计适配移动端
### 5. 帖子详情页面优化
**问题描述**
帖子详情页面UI不够美观且不支持Markdown内容渲染
**优化内容**
- ✅ **支持Markdown渲染**:使用`MdPreview`组件渲染Markdown内容
- ✅ **改善UI设计**:优化内容展示区域的样式和布局
- ✅ **增强可读性**:改进字体、间距、颜色等视觉元素
- ✅ **代码高亮**:支持代码块的语法高亮
- ✅ **表格样式**:美化表格显示效果
- ✅ **图片展示**:优化图片显示和圆角效果
**技术实现**
- 复用已安装的`md-editor-v3`库的预览组件
- 自定义CSS样式覆盖默认主题
- 使用紫色主题保持设计一致性
- 优化各种Markdown元素的显示效果
**视觉改进**
- 独立的白色背景内容区域
- 更好的标题层次和分割线
- 紫色主题的引用块和链接
- 优雅的代码块样式
- 现代化的表格设计
## 🚀 Stagewise开发工具集成
### 安装的包
```bash
npm install @stagewise/toolbar-vue --save-dev
```
### 集成位置
修改了 `unilife-frontend/src/App.vue` 文件:
```vue
<template>
<div id="app">
<router-view />
<!-- Stagewise工具栏 - 仅在开发模式下显示 -->
<component :is="stagewiseComponent" v-if="isDevelopment && stagewiseComponent" :config="stagewiseConfig" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, type Component } from 'vue'
// 检查是否为开发环境
const isDevelopment = import.meta.env.DEV
// Stagewise组件引用
const stagewiseComponent = ref<Component | null>(null)
// Stagewise配置
const stagewiseConfig = {
plugins: []
}
// 仅在开发模式下动态加载stagewise组件
if (isDevelopment) {
onMounted(async () => {
try {
const { StagewiseToolbar } = await import('@stagewise/toolbar-vue')
stagewiseComponent.value = StagewiseToolbar as Component
} catch (error) {
console.warn('Stagewise toolbar not available:', error)
}
})
}
</script>
```
### 特性
1. ✅ **仅在开发模式运行**:使用 `import.meta.env.DEV` 检查
2. ✅ **动态导入**避免在生产环境中包含stagewise代码
3. ✅ **错误处理**:如果包未安装或导入失败,会优雅降级
4. ✅ **TypeScript支持**:正确的类型定义避免编译错误
5. ✅ **Vue 3兼容**使用组合式API和动态组件
### 使用方法
1. 启动开发服务器:`npm run dev`
2. 打开浏览器访问应用
3. stagewise工具栏将在开发模式下自动显示
4. 可以选择页面元素并添加AI编辑注释
## 📝 后续步骤
### 立即处理
1. **重启后端服务**以应用Schedule实体类修改
2. **测试日程功能**确保reminder字段正常工作
3. **调试评论显示问题**
### 评论问题调试步骤
1. 在浏览器中访问帖子详情页
2. 打开开发者工具检查网络请求
3. 查看 `/comments/post/{postId}` API的返回数据
4. 检查前端控制台是否有JavaScript错误
5. 验证CommentVO的数据映射是否正确
### Stagewise工具测试
1. 确认工具栏在开发模式下可见
2. 测试选择页面元素功能
3. 验证不会在生产构建中包含
## 🎯 预期结果
1. **Schedule功能**日程提醒时间可以正常设置为大于127分钟的值
2. **评论功能**:所有评论应该正确显示,包括回复
3. **Stagewise工具**在开发模式下提供AI驱动的页面编辑能力
---
*最后更新2025年5月29日*
Loading…
Cancel
Save