# HasChatApp **Repository Path**: thc/has-chat-app ## Basic Information - **Project Name**: HasChatApp - **Description**: 一款极简聊天应用,比较完整,略好看 - **Primary Language**: JavaScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: https://howcode.online/haschatapp - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 90 - **Created**: 2025-07-22 - **Last Updated**: 2025-08-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README
![]() |
![]() |
👍👍👍👍👍👍 您的捐助和赞赏,将会是作者howcode更好的维护动力!
# 伊言一语
这是一个基于uni-app开发的智能咨询助手应用,支持与AI模型进行对话咨询。
## 功能特点
- 智能咨询:与AI模型进行对话咨询
- 历史记录:保存历史咨询记录,方便随时查看
- 多媒体支持:支持发送文字、图片、语音、视频等多种消息类型
## 页面结构
- 咨询页面:显示历史咨询记录,支持新建咨询
- 聊天页面:与AI模型进行对话交流
- 我的页面:用户个人信息和设置
## 使用方法
1. 打开应用,进入咨询页面
2. 点击"新建咨询"按钮,开始新的咨询会话
3. 在聊天界面输入问题,与AI模型进行对话
4. 返回咨询页面可以查看历史咨询记录
## AI模型信息
默认使用default模型,作为Cursor IDE的核心功能之一,可协助完成各类开发任务。
## 后端API接口文档
应用支持与后端API交互,实现数据持久化存储。以下是主要API接口:
### 1. 获取咨询列表
```
GET /api/consultation/list
```
**响应示例:**
```json
{
"code": 200,
"message": "success",
"data": [
{
"id": "1234567890",
"title": "咨询标题",
"lastMessage": "最后一条消息",
"lastTime": "2023-07-01T12:00:00.000Z",
"unreadCount": 0,
"avatar": "../../static/img/ai_avatar.png"
}
]
}
```
### 2. 获取咨询消息
```
GET /api/consultation/messages?id={consultationId}
```
**响应示例:**
```json
{
"code": 200,
"message": "success",
"data": [
{
"id": "msg123456",
"SendId": "ai",
"ReciverId": "user123",
"Content": "您好,我是由default模型提供支持...
", "Type": 0, "State": 1, "NoCode": "1234567890", "CreateDateUtc": "2023-07-01T12:00:00.000Z", "Avatar": "../../static/img/ai_avatar.png", "ReadFlag": true, "SoundStatus": 0 } ] } ``` ### 3. 创建咨询 ``` POST /api/consultation/create ``` **请求参数:** ```json { "title": "新咨询", "avatar": "../../static/img/ai_avatar.png" } ``` **响应示例:** ```json { "code": 200, "message": "success", "data": { "id": "1234567890", "title": "新咨询", "lastMessage": "开始您的智能咨询吧", "lastTime": "2023-07-01T12:00:00.000Z", "unreadCount": 0, "avatar": "../../static/img/ai_avatar.png" } } ``` ### 4. 发送咨询消息 ``` POST /api/consultation/message/send ``` **请求参数:** ```json { "consultationId": "1234567890", "message": { "SendId": "user123", "ReciverId": "ai", "Content": "您好,我有个问题
", "Type": 0, "Avatar": "../../static/img/user_avatar.png" } } ``` **响应示例:** ```json { "code": 200, "message": "success", "data": { "id": "msg123456", "SendId": "user123", "ReciverId": "ai", "Content": "您好,我有个问题
", "Type": 0, "State": 1, "NoCode": "1234567890", "CreateDateUtc": "2023-07-01T12:00:00.000Z", "Avatar": "../../static/img/user_avatar.png", "ReadFlag": false, "SoundStatus": 0 } } ``` ### 5. 删除咨询 ``` POST /api/consultation/delete ``` **请求参数:** ```json { "id": "1234567890" } ``` **响应示例:** ```json { "code": 200, "message": "success", "data": true } ``` ## 开发注意事项 1. 应用优先使用后端API存储数据,当API不可用时会回退到本地存储模式 2. 本地存储仅作为临时方案,不保证长期数据持久性 3. 要实现完整功能,需要按照API文档实现相应的后端服务 # 伊言一语后端API文档 ## Socket.io 事件列表 ### 客户端发送事件 1. **joinChat** - 客户端连接时发送 ```javascript { SendId: "用户ID", SendName: "用户名称", ReviceId: -1, ReviceName: "", NoCode: "唯一码" } ``` 2. **sendMsg** - 发送消息 ```javascript { Conversition: { id: "消息ID", SendId: "发送者ID", ReciverId: "接收者ID", // 0 表示发给AI Content: "消息内容
", Type: 0, // 0: 文本, 1: 图片, 2: 视频, 3: 语音 State: 0, // 0: 发送中, 1: 已发送 NoCode: "唯一码", CreateDateUtc: "2023-07-01T12:00:00.000Z", Avatar: "头像URL", ReadFlag: false, SoundStatus: 0, consultationId: "咨询ID" // 新增字段,标识所属咨询 }, ReciverId: 0, // 接收者ID,0 表示发给AI Sender: { /* 发送者信息 */ }, consultationId: "咨询ID", // 咨询ID isConsultation: true // 标记这是一个咨询消息 } ``` 3. **getConsultationList** - 获取咨询列表 ```javascript { userId: "用户ID" } ``` 4. **getConsultationMessages** - 获取咨询消息 ```javascript { consultationId: "咨询ID", userId: "用户ID" } ``` 5. **createConsultation** - 创建咨询 ```javascript { id: "咨询ID", title: "咨询标题", lastMessage: "最后一条消息", lastTime: "2023-07-01T12:00:00.000Z", unreadCount: 0, avatar: "头像URL", userId: "用户ID" } ``` 6. **deleteConsultation** - 删除咨询 ```javascript { consultationId: "咨询ID", userId: "用户ID" } ``` ### 服务端发送事件 1. **reviceMsg** - 接收消息 ```javascript { // 消息对象,与sendMsg中的Conversition结构相同 ReciverId: "接收者ID", SendId: "发送者ID", Content: "消息内容
", // ...其他字段 isConsultation: true // 标记这是一个咨询消息 } ``` 2. **aiResponse** - AI回复 ```javascript { Content: "AI回复内容
", consultationId: "咨询ID" } ``` 3. **consultationList** - 咨询列表响应 ```javascript [ { id: "咨询ID", title: "咨询标题", lastMessage: "最后一条消息", lastTime: "2023-07-01T12:00:00.000Z", unreadCount: 0, avatar: "头像URL" }, // ...更多咨询 ] ``` 4. **consultationMessages** - 咨询消息响应 ```javascript [ { id: "消息ID", SendId: "发送者ID", // 0 表示AI发送 ReciverId: "接收者ID", Content: "消息内容
", Type: 0, State: 1, NoCode: "唯一码", CreateDateUtc: "2023-07-01T12:00:00.000Z", Avatar: "头像URL", ReadFlag: false, SoundStatus: 0, consultationId: "咨询ID" }, // ...更多消息 ] ``` 5. **consultationCreated** - 咨询创建响应 ```javascript { id: "咨询ID", title: "咨询标题", lastMessage: "最后一条消息", lastTime: "2023-07-01T12:00:00.000Z", unreadCount: 0, avatar: "头像URL" } ``` 6. **consultationDeleted** - 咨询删除响应 ```javascript { success: true, consultationId: "咨询ID" } ``` ## 后端实现指南 ### 1. 数据库表结构 #### 咨询表 (consultations) ```sql CREATE TABLE consultations ( id VARCHAR(50) PRIMARY KEY, title VARCHAR(100) NOT NULL, lastMessage TEXT, lastTime DATETIME, unreadCount INT DEFAULT 0, avatar VARCHAR(255), userId VARCHAR(50) NOT NULL, createTime DATETIME DEFAULT CURRENT_TIMESTAMP, updateTime DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); ``` #### 咨询消息表 (consultation_messages) ```sql CREATE TABLE consultation_messages ( id VARCHAR(50) PRIMARY KEY, consultationId VARCHAR(50) NOT NULL, SendId VARCHAR(50) NOT NULL, ReciverId VARCHAR(50) NOT NULL, Content TEXT, Type INT DEFAULT 0, State INT DEFAULT 0, NoCode VARCHAR(50), CreateDateUtc DATETIME, Avatar VARCHAR(255), ReadFlag BOOLEAN DEFAULT FALSE, SoundStatus INT DEFAULT 0, createTime DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (consultationId) REFERENCES consultations(id) ON DELETE CASCADE ); ``` ### 2. Socket.io 事件处理 #### 连接处理 ```javascript io.on('connection', (socket) => { console.log('用户连接: ' + socket.id); // 加入聊天 socket.on('joinChat', (data) => { // 存储用户信息 socket.userId = data.SendId; socket.userName = data.SendName; // 加入用户房间 socket.join(data.SendId); console.log(`用户 ${data.SendName}(${data.SendId}) 加入聊天`); }); // 断开连接 socket.on('disconnect', () => { console.log('用户断开连接: ' + socket.id); }); // 其他事件处理... }); ``` #### 发送消息处理 ```javascript socket.on('sendMsg', async (data) => { try { // 检查是否是咨询消息 if (data.isConsultation) { // 保存咨询消息到数据库 const message = data.Conversition; await db.query( 'INSERT INTO consultation_messages (id, consultationId, SendId, ReciverId, Content, Type, State, NoCode, CreateDateUtc, Avatar, ReadFlag, SoundStatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [message.id, data.consultationId, message.SendId, message.ReciverId, message.Content, message.Type, message.State, message.NoCode, message.CreateDateUtc, message.Avatar, message.ReadFlag, message.SoundStatus] ); // 更新咨询的最后消息和时间 await db.query( 'UPDATE consultations SET lastMessage = ?, lastTime = ? WHERE id = ?', [message.Content.replace(/<[^>]*>/g, ''), new Date().toISOString(), data.consultationId] ); // 如果是发送给AI的消息,生成AI回复 if (message.ReciverId === 0) { // 模拟AI处理延迟 setTimeout(() => { const aiResponse = { Content: '您好,我是由default模型提供支持,作为Cursor IDE的核心功能之一,可协助完成各类开发任务,只要是编程相关的问题,都可以问我!您现在有什么想做的吗?
', consultationId: data.consultationId }; // 发送AI回复给客户端 io.to(message.SendId).emit('aiResponse', aiResponse); // 创建AI回复消息 const aiMessage = { id: Date.now().toString(), consultationId: data.consultationId, SendId: 0, ReciverId: message.SendId, Content: aiResponse.Content, Type: 0, State: 1, NoCode: Date.now() + 1 + "", CreateDateUtc: new Date().toISOString(), Avatar: '../../static/img/ai_avatar.png', ReadFlag: false, SoundStatus: 0 }; // 保存AI回复消息到数据库 db.query( 'INSERT INTO consultation_messages (id, consultationId, SendId, ReciverId, Content, Type, State, NoCode, CreateDateUtc, Avatar, ReadFlag, SoundStatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [aiMessage.id, aiMessage.consultationId, aiMessage.SendId, aiMessage.ReciverId, aiMessage.Content, aiMessage.Type, aiMessage.State, aiMessage.NoCode, aiMessage.CreateDateUtc, aiMessage.Avatar, aiMessage.ReadFlag, aiMessage.SoundStatus] ); // 更新咨询的最后消息和时间 db.query( 'UPDATE consultations SET lastMessage = ?, lastTime = ? WHERE id = ?', [aiResponse.Content.replace(/<[^>]*>/g, ''), new Date().toISOString(), data.consultationId] ); // 发送消息给接收者 io.to(aiMessage.ReciverId).emit('reviceMsg', { ...aiMessage, isConsultation: true }); }, 1000); } // 发送消息给接收者 if (message.ReciverId !== 0) { io.to(message.ReciverId).emit('reviceMsg', { ...message, isConsultation: true }); } } else { // 处理普通聊天消息(原有逻辑) // ... } } catch (error) { console.error('发送消息错误:', error); } }); ``` #### 获取咨询列表 ```javascript socket.on('getConsultationList', async (data) => { try { // 从数据库获取咨询列表 const [consultations] = await db.query( 'SELECT * FROM consultations WHERE userId = ? ORDER BY lastTime DESC', [data.userId] ); // 发送咨询列表给客户端 socket.emit('consultationList', consultations); } catch (error) { console.error('获取咨询列表错误:', error); socket.emit('consultationList', []); } }); ``` #### 获取咨询消息 ```javascript socket.on('getConsultationMessages', async (data) => { try { // 从数据库获取咨询消息 const [messages] = await db.query( 'SELECT * FROM consultation_messages WHERE consultationId = ? ORDER BY CreateDateUtc ASC', [data.consultationId] ); // 发送咨询消息给客户端 socket.emit('consultationMessages', messages); } catch (error) { console.error('获取咨询消息错误:', error); socket.emit('consultationMessages', []); } }); ``` #### 创建咨询 ```javascript socket.on('createConsultation', async (data) => { try { // 保存咨询到数据库 await db.query( 'INSERT INTO consultations (id, title, lastMessage, lastTime, unreadCount, avatar, userId) VALUES (?, ?, ?, ?, ?, ?, ?)', [data.id, data.title, data.lastMessage, data.lastTime, data.unreadCount, data.avatar, data.userId] ); // 发送创建成功响应给客户端 socket.emit('consultationCreated', data); } catch (error) { console.error('创建咨询错误:', error); socket.emit('consultationCreated', null); } }); ``` #### 删除咨询 ```javascript socket.on('deleteConsultation', async (data) => { try { // 从数据库删除咨询 await db.query( 'DELETE FROM consultations WHERE id = ? AND userId = ?', [data.consultationId, data.userId] ); // 从数据库删除咨询消息 await db.query( 'DELETE FROM consultation_messages WHERE consultationId = ?', [data.consultationId] ); // 发送删除成功响应给客户端 socket.emit('consultationDeleted', { success: true, consultationId: data.consultationId }); } catch (error) { console.error('删除咨询错误:', error); socket.emit('consultationDeleted', { success: false, consultationId: data.consultationId }); } }); ``` ## 注意事项 1. 确保数据库连接稳定,建议使用连接池 2. 添加适当的错误处理和日志记录 3. 考虑添加消息队列,处理高并发场景 4. 实现用户认证和授权,确保安全性 5. 对敏感数据进行加密处理 6. 定期备份数据库 7. 考虑添加消息读取状态更新功能 8. 实现消息分页加载,提高性能