新增:管理后台前端页面,以及openspec内容。

This commit is contained in:
2025-12-24 20:15:28 +08:00
parent 6d7ed38105
commit 845f1c6618
64 changed files with 9017 additions and 6 deletions

View File

@@ -0,0 +1,382 @@
# 会话管理和用户管理页面优化 - 技术实现
## 1. 工具函数实现
### 1.1 创建工具函数文件
创建了 `src/utils/formatters.js` 文件,用于存放通用的格式化工具函数:
```javascript
// 手机号脱敏处理
export const formatPhoneNumber = (phoneNumber, showFull = false) => {
if (!phoneNumber) return ''
const phone = phoneNumber.toString()
if (phone.length !== 11) return phone
if (showFull) {
return phone
} else {
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
}
// 时间格式转换将T替换为空格
export const formatDateTime = (dateTime) => {
if (!dateTime) return ''
return dateTime.toString().replace('T', ' ')
}
// 时间戳转换为格式化日期
export const formatTimestamp = (timestamp) => {
if (!timestamp) return ''
const date = new Date(timestamp)
return date.toISOString().replace('T', ' ').slice(0, 19)
}
```
### 1.2 工具函数设计思路
- **手机号脱敏**使用正则表达式将中间4位替换为"****",支持参数控制是否显示完整号码
- **时间格式转换**:简单高效地将"T"替换为空格,保持原有时间格式不变
- **时间戳转换**:将时间戳转换为标准的"YYYY-MM-DD HH:mm:ss"格式
## 2. 会话管理页面优化
### 2.1 发送方式Tag标签实现
```vue
<el-descriptions-item label="发送方式">
<el-tag :type="item.sendMethod === '文字' ? 'success' : ''">
{{ item.sendMethod === '文字' ? 'text' : 'voice' }}
</el-tag>
</el-descriptions-item>
```
### 2.2 手机号脱敏与点击交互
```vue
<el-descriptions-item label="手机号">
<span
class="phone-number"
@click="item.showFullPhone = !item.showFullPhone"
:title="'点击' + (item.showFullPhone ? '隐藏' : '显示') + '完整号码'"
>
{{ formatPhoneNumber(item.phoneNumber, item.showFullPhone) }}
</span>
</el-descriptions-item>
```
### 2.3 时间格式转换
```vue
<el-descriptions-item label="记录时间">
{{ formatDateTime(item.recordTime) }}
</el-descriptions-item>
```
### 2.4 Descriptions描述列表实现
#### 2.4.1 模板修改
```vue
<!-- 会话记录列表 -->
<el-card class="table-card">
<el-scrollbar height="500px" @scroll="handleScroll">
<div v-loading="loading" class="descriptions-container">
<div v-for="(item, index) in conversationList" :key="index" class="descriptions-item">
<!-- 主要信息3列显示 -->
<el-descriptions :column="3" border>
<el-descriptions-item label="记录时间">{{ formatDateTime(item.recordTime) }}</el-descriptions-item>
<el-descriptions-item label="用户名">{{ item.userName }}</el-descriptions-item>
<el-descriptions-item label="微信名">{{ item.weChatName }}</el-descriptions-item>
<el-descriptions-item label="手机号">
<span
class="phone-number"
@click="item.showFullPhone = !item.showFullPhone"
:title="'点击' + (item.showFullPhone ? '隐藏' : '显示') + '完整号码'"
>
{{ formatPhoneNumber(item.phoneNumber, item.showFullPhone) }}
</span>
</el-descriptions-item>
<el-descriptions-item label="部门">{{ item.department }}</el-descriptions-item>
<el-descriptions-item label="消息类型">
<el-tag :type="item.messageType === 1 ? 'success' : ''">
{{ item.messageType === 1 ? '公有' : '私有' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="发送方式">
<el-tag :type="item.sendMethod === '文字' ? 'success' : ''">
{{ item.sendMethod === '文字' ? 'text' : 'voice' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="语音时长">{{ item.speakingTime ? item.speakingTime + '秒' : '-' }}</el-descriptions-item>
<el-descriptions-item label="位置">{{ item.userLocation }}</el-descriptions-item>
</el-descriptions>
<!-- 会话内容单独一行显示在最下方 -->
<el-descriptions :column="1" border class="conversation-content">
<el-descriptions-item label="会话内容">
{{ item.conversationContent }}
</el-descriptions-item>
</el-descriptions>
</div>
<!-- 加载更多提示 -->
<div v-if="loadingMore" class="loading-more">
<el-icon class="is-loading"><Loading /></el-icon>
<span>正在加载中...</span>
</div>
<div v-else-if="!hasMoreData" class="no-more-data">
<span>已加载全部数据</span>
</div>
</div>
</el-scrollbar>
</el-card>
```
#### 2.4.2 滚动处理逻辑
```javascript
// 滚动处理
const handleScroll = (event) => {
const { scrollTop, scrollHeight, clientHeight } = event.target
// 当滚动到底部100px以内时加载下一页
if (scrollHeight - scrollTop - clientHeight < 100 && !loadingMore.value && hasMoreData.value) {
loadNextPage()
}
}
// 加载下一页数据
const loadNextPage = () => {
if (loadingMore.value || !hasMoreData.value) return
loadingMore.value = true
currentPage.value++
fetchConversations(true) // 传入true表示加载更多
}
```
#### 2.4.3 分页请求逻辑
```javascript
// 获取会话记录
const fetchConversations = async (isLoadMore = false) => {
if (isLoadMore) {
loadingMore.value = true
} else {
loading.value = true
conversationList.value = [] // 非加载更多时清空列表
hasMoreData.value = true // 重置加载状态
currentPage.value = 1 // 重置当前页
}
try {
// 构建请求参数,包含分页信息
const params = {
// 其他参数
page: currentPage.value,
pageSize: pageSize.value // 固定为20条/页
}
// 调用API获取会话记录
const data = await request.post('/Admin/QueryConversations', JSON.stringify(params))
// 处理返回数据
const rawData = Array.isArray(data) ? data : data.data || []
const sortedData = rawData.sort((a, b) => {
return b.recordTimeUTCStamp - a.recordTimeUTCStamp
})
// 如果是加载更多,则追加数据,否则替换数据
if (isLoadMore) {
conversationList.value = [...conversationList.value, ...sortedData]
} else {
conversationList.value = sortedData
}
// 判断是否已加载全部数据
if (sortedData.length < pageSize.value) {
hasMoreData.value = false
}
} catch (error) {
ElMessage.error('获取会话记录失败:' + error.message)
if (!isLoadMore) {
conversationList.value = []
}
} finally {
loading.value = false
loadingMore.value = false
}
}
```
### 2.5 样式优化
```scss
/* Descriptions容器样式 */
.descriptions-container {
width: 100%;
}
/* 每个Descriptions项的样式 */
.descriptions-item {
margin-bottom: 20px;
border-radius: 4px;
overflow: hidden;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
/* 会话内容样式 */
.conversation-content {
margin-top: 10px;
}
/* 响应式调整Descriptions列数 */
@media (max-width: 767px) {
.el-descriptions {
:deep(.el-descriptions__table) {
width: 100%;
}
:deep(.el-descriptions__cell) {
width: 50%;
}
}
}
```
## 3. 用户管理页面优化
### 3.1 移除分页控件
移除了以下内容:
- el-pagination组件
- 分页数据变量currentPage, pageSize, total
- 分页变化处理函数handlePageChange
### 3.2 应用时间格式转换和手机号脱敏
与会话管理页面类似,为时间列和手机号列应用了相同的格式化处理。
## 4. 样式优化
### 4.1 手机号样式
```scss
/* 手机号样式 */
.phone-number {
cursor: pointer;
color: #409eff;
text-decoration: underline;
}
.phone-number:hover {
color: #66b1ff;
}
```
### 4.2 加载更多样式
```scss
/* 加载更多样式 */
.loading-more,
.no-more-data {
display: flex;
justify-content: center;
align-items: center;
padding: 16px;
color: #909399;
font-size: 14px;
}
.loading-more .el-icon {
margin-right: 8px;
}
```
## 5. 最佳实践
### 5.1 代码组织
- 将通用工具函数抽离到单独的文件中,提高复用性和可维护性
- 使用Composition API和script setup语法简化组件代码
- 遵循单一职责原则,每个组件只负责一个功能模块
### 5.2 性能优化
- 无限滚动加载减少了初始加载时间,提高了用户体验
- 固定分页大小为20条/页,平衡了加载性能和用户体验
- 添加了加载状态提示和重复请求防止机制
### 5.3 用户体验
- 手机号脱敏保护了用户隐私
- 点击交互支持查看完整手机号,方便用户操作
- 时间格式优化提高了可读性
- 无限滚动减少了用户的操作步骤
- Descriptions描述列表提供了更清晰的数据展示方式
### 5.4 代码可读性
- 使用清晰的变量和函数命名
- 添加了必要的注释
- 遵循Vue 3的最佳实践
## 6. 技术选型理由
1. **Element Plus组件库**提供了丰富的UI组件包括tag标签、descriptions描述列表、scrollbar滚动条等简化了开发工作
2. **Descriptions描述列表**:相比表格,描述列表更适合展示一行数据的详细信息,提供了更好的视觉层次
3. **无限滚动分页**:相比传统分页,无限滚动提供了更流畅的用户体验,减少了用户的操作步骤
4. **工具函数设计**:将通用功能抽离为工具函数,提高了代码的复用性和可维护性
5. **手机号脱敏**:保护用户隐私,符合数据安全规范
6. **时间格式优化**:提高了数据的可读性,符合用户的阅读习惯
## 7. 影响范围
1. **会话管理页面**
- 模板结构变化表格替换为Descriptions描述列表
- 数据处理逻辑变化
- 交互方式变化
- 样式变化
2. **用户管理页面**
- 模板结构变化:移除了分页控件
- 数据处理逻辑变化
- 交互方式变化
3. **API调用**
- 会话记录API添加了分页参数
4. **新增文件**
- `src/utils/formatters.js`:工具函数文件
5. **文档**
- 更新了详细的修改记录文档
## 8. 后续优化建议
1. **添加搜索功能**:为会话记录和用户管理页面添加更强大的搜索功能
2. **支持导出功能**支持将数据导出为Excel或CSV格式
3. **添加筛选条件记忆功能**:记住用户的筛选条件,提高用户体验
4. **优化移动端体验**:进一步优化移动端的显示效果和交互方式
5. **添加数据统计功能**:在页面顶部添加数据统计卡片,展示关键指标
6. **支持自定义列**:允许用户自定义显示哪些列,提高灵活性
7. **添加批量操作功能**:支持批量删除或修改数据,提高操作效率
## 9. 总结
本次优化实现了会话管理和用户管理页面的多项改进包括发送方式tag标签显示、手机号脱敏、时间格式优化、表格替换为Descriptions描述列表、无限滚动分页等。这些改进提高了系统的用户体验、数据安全性和性能表现。
所有修改都遵循了openspec开发规范并更新了详细的修改记录文档便于后续维护和参考。

View File

@@ -0,0 +1,66 @@
# 会话管理和用户管理页面优化
## 1. 问题描述
当前系统的会话管理和用户管理页面存在以下问题:
1. **会话记录页面**
- 发送方式以纯文本形式显示,不够直观
- 手机号直接显示完整号码,存在隐私泄露风险
- 时间格式包含"T"字符,不符合用户阅读习惯
- 使用传统分页方式,用户体验不佳
2. **用户管理页面**
- 存在不必要的分页控件,增加用户操作复杂度
- 时间格式包含"T"字符,不符合用户阅读习惯
- 手机号直接显示完整号码,存在隐私泄露风险
## 2. 解决方案
1. **优化发送方式显示**将发送方式重构为tag标签形式文字类型显示success样式语音类型显示默认样式
2. **实现手机号脱敏功能**
- 默认隐藏中间4-8位数字为"*"符号
- 支持点击交互,点击显示完整号码,再次点击恢复脱敏状态
3. **优化时间格式**:将所有时间数据中的"T"字符替换为空格,提高可读性
4. **重构表格组件为Descriptions描述列表**
- 将表格替换为Descriptions描述列表一行表格数据放入一个Descriptions描述列表
- 实现"无限滚动"分页加载机制每次加载20条滚动到最底时加载下20条
- 会话内容单独一行显示在最下方
- 其他内容排成3列显示
- 当查询结果不足20条时判断为已加载全部数据
5. **优化用户管理页面**
- 移除分页控件及相关分页逻辑
- 不分页加载所有用户数据
- 应用时间格式转换,将时间数据中的"T"字符替换为空格
## 3. 预期效果
- 会话记录页面:
- 发送方式以tag标签形式显示
- 手机号自动脱敏,支持点击显示/隐藏完整号码
- 时间格式统一为"YYYY-MM-DD HH:mm:ss"
- 表格替换为Descriptions描述列表一行数据一个描述列表
- 会话内容单独一行显示在最下方其他内容排成3列
- 实现无限滚动加载每次加载20条提升用户体验
- 用户管理页面:
- 移除分页控件,不分页加载所有用户数据
- 时间格式统一为"YYYY-MM-DD HH:mm:ss"
- 手机号自动脱敏,支持点击显示/隐藏完整号码
- 整体效果:
- 提高系统的用户体验和视觉效果
- 增强数据安全性,保护用户隐私
- 优化页面性能,提高数据加载效率
- 简化用户操作,减少不必要的交互步骤
## 4. 影响范围
- 会话管理页面ConversationList.vue
- 用户管理页面UserList.vue
- 新增工具函数文件formatters.js
- 相关API调用AdminController的QueryConversations方法

View File

@@ -0,0 +1,67 @@
# 会话管理和用户管理页面优化 - 任务清单
## 1. 工具函数开发
- [x] 创建工具函数文件 `src/utils/formatters.js`
- [x] 实现手机号脱敏函数 `formatPhoneNumber`
- [x] 实现时间格式转换函数 `formatDateTime`
- [x] 实现时间戳转换函数 `formatTimestamp`
## 2. 会话管理页面优化
- [x] 导入工具函数到 `ConversationList.vue`
- [x] 将发送方式列重构为tag标签形式
- [x] 文字类型显示success样式tag内容为"text"
- [x] 语音类型显示默认样式tag内容为"voice"
- [x] 应用手机号脱敏功能到手机号列
- [x] 默认显示脱敏手机号
- [x] 添加点击交互,支持显示/隐藏完整号码
- [x] 应用时间格式转换到时间列,将"T"替换为空格
- [x] 重构表格组件为Descriptions描述列表
- [x] 将表格替换为Descriptions描述列表一行数据一个描述列表
- [x] 设置描述列表列数为3列
- [x] 会话内容单独一行显示在最下方
- [x] 实现滚动到底部自动加载下一页数据
- [x] 修改fetchConversations方法添加分页参数
- [x] 设置固定分页大小为20条/页
- [x] 添加加载状态提示
- [x] 移除传统分页控件
## 3. 用户管理页面优化
- [x] 导入工具函数到 `UserList.vue`
- [x] 移除分页控件及相关分页逻辑
- [x] 移除el-pagination组件
- [x] 移除分页数据变量
- [x] 移除分页变化处理函数
- [x] 应用时间格式转换到时间列,将"T"替换为空格
- [x] 应用手机号脱敏功能到手机号列
- [x] 默认显示脱敏手机号
- [x] 添加点击交互,支持显示/隐藏完整号码
## 4. 样式优化
- [x] 为手机号添加悬停效果
- [x] 为加载更多状态添加样式
- [x] 确保响应式设计正常工作
## 5. 文档编写
- [x] 创建 `proposal.md`,描述问题和解决方案
- [x] 创建 `tasks.md`,列出具体实现任务
- [x] 创建 `implementation.md`,详细记录技术实现和最佳实践
## 6. 测试验证
- [x] 验证发送方式tag标签显示正确
- [x] 验证手机号脱敏功能正常工作
- [x] 验证时间格式转换正确
- [x] 验证无限滚动分页正常工作
- [x] 验证用户管理页面不分页加载正常
- [x] 验证所有交互功能正常
## 7. 性能优化
- [x] 确保滚动加载过程中无重复请求
- [x] 确保数据量大时页面性能良好
- [x] 优化API请求减少不必要的数据传输