chore(addon/aikefu): 增加可以选择消息排序
This commit is contained in:
@@ -271,6 +271,8 @@ class Kefu extends BaseShop
|
|||||||
$limit = input("limit/d", 50);
|
$limit = input("limit/d", 50);
|
||||||
$conversation_id = input("conversation_id/s", "");
|
$conversation_id = input("conversation_id/s", "");
|
||||||
$user_id = input("user_id/s", "");
|
$user_id = input("user_id/s", "");
|
||||||
|
$sort_field = input("sort_field/s", "create_time"); // 排序字段
|
||||||
|
$sort_order = input("sort_order/s", "desc"); // 排序方式:asc或desc
|
||||||
|
|
||||||
$kefu_message_model = new KefuMessageModel();
|
$kefu_message_model = new KefuMessageModel();
|
||||||
$condition = [
|
$condition = [
|
||||||
@@ -287,7 +289,9 @@ class Kefu extends BaseShop
|
|||||||
$condition[] = ['user_id', '=', $user_id];
|
$condition[] = ['user_id', '=', $user_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
$message_list = $kefu_message_model->getMessageList($condition, '*', 'create_time asc', $page, $limit);
|
// 构建排序字符串
|
||||||
|
$order = $sort_field . ' ' . $sort_order;
|
||||||
|
$message_list = $kefu_message_model->getMessageList($condition, '*', $order, $page, $limit);
|
||||||
// 适配layui table的返回格式,同时保持与Dify API风格一致
|
// 适配layui table的返回格式,同时保持与Dify API风格一致
|
||||||
$result = [
|
$result = [
|
||||||
'code' => 0, // layui table要求成功状态码为0
|
'code' => 0, // layui table要求成功状态码为0
|
||||||
|
|||||||
@@ -20,48 +20,110 @@
|
|||||||
color: #faad14;
|
color: #faad14;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 简单消息列表样式 */
|
/* 消息列表样式优化 - 从message.html复制 */
|
||||||
.simple-message-list {
|
.message-list {
|
||||||
max-height: 500px;
|
max-height: 650px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 15px;
|
padding: 25px;
|
||||||
|
background-color: #fafbfc;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 消息项样式 */
|
||||||
.message-item {
|
.message-item {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 25px;
|
||||||
padding: 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.message-item.user {
|
|
||||||
background-color: #e6f7ff;
|
|
||||||
border-left: 3px solid #1890ff;
|
|
||||||
}
|
|
||||||
.message-item.assistant {
|
|
||||||
background-color: #f6ffed;
|
|
||||||
border-left: 3px solid #52c41a;
|
|
||||||
}
|
|
||||||
.message-header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
align-items: flex-start;
|
||||||
margin-bottom: 5px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
}
|
||||||
.message-role {
|
|
||||||
font-weight: bold;
|
.message-item.user {
|
||||||
color: #333;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
.message-time {
|
|
||||||
color: #999;
|
.message-item.assistant {
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 头像样式 */
|
||||||
|
.message-avatar {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0 12px;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 消息内容样式 */
|
||||||
.message-content {
|
.message-content {
|
||||||
font-size: 14px;
|
max-width: 70%;
|
||||||
line-height: 1.4;
|
padding: 16px 20px;
|
||||||
color: #666;
|
border-radius: 18px;
|
||||||
word-break: break-word;
|
word-wrap: break-word;
|
||||||
|
line-height: 1.6;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.empty-message {
|
|
||||||
text-align: center;
|
.message-item.user .message-content {
|
||||||
|
background-color: #1E9FFF;
|
||||||
|
color: white;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(30, 159, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item.assistant .message-content {
|
||||||
|
background-color: white;
|
||||||
|
color: #333;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 消息时间样式 */
|
||||||
|
.message-time {
|
||||||
|
font-size: 12px;
|
||||||
color: #999;
|
color: #999;
|
||||||
padding: 30px;
|
margin-top: 8px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 消息角色样式 */
|
||||||
|
.message-role {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item.user .message-role {
|
||||||
|
color: rgba(106, 38, 38, 0.9);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item.assistant .message-role {
|
||||||
|
color: #666;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态样式 */
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 60px 20px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state i {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.message-content {
|
||||||
|
max-width: 85%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -118,25 +180,35 @@
|
|||||||
}}}
|
}}}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- 简单消息列表模板 -->
|
<!-- 消息列表模板 - 与message.html一致 -->
|
||||||
<script type="text/html" id="messageListTpl">
|
<script type="text/html" id="messageListTpl">
|
||||||
<div class="simple-message-list">
|
<div class="message-list">
|
||||||
{{# if(d.length > 0) {
|
{{# if(d.length > 0) {
|
||||||
d.forEach(function(item) {
|
d.forEach(function(item) {
|
||||||
|
var role = item.role === 'user' ? (item.user_id ? '用户-' + item.user_id : '用户') : '机器人';
|
||||||
var roleClass = item.role === 'user' ? 'user' : 'assistant';
|
var roleClass = item.role === 'user' ? 'user' : 'assistant';
|
||||||
var roleText = item.role === 'user' ? '用户' : '机器人';
|
var avatar = item.role === 'user' ? '/addon/aikefu/static/images/user.svg' : '/addon/aikefu/static/images/robot.svg';
|
||||||
}}}
|
}}}
|
||||||
<div class="message-item {{roleClass}}">
|
<div class="message-item {{roleClass}}">
|
||||||
<div class="message-header">
|
{{# if(item.role === 'assistant') {
|
||||||
<span class="message-role">{{roleText}}</span>
|
<img src="{{avatar}}" class="message-avatar">
|
||||||
<span class="message-time">{{item.create_time}}</span>
|
}}}
|
||||||
|
<div>
|
||||||
|
<div class="message-role">{{role}}</div>
|
||||||
|
<div class="message-content">{{item.content}}</div>
|
||||||
|
<div class="message-time">{{item.create_time}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">{{item.content}}</div>
|
{{# if(item.role === 'user') {
|
||||||
|
<img src="{{avatar}}" class="message-avatar">
|
||||||
|
}}}
|
||||||
</div>
|
</div>
|
||||||
{{# });
|
{{# });
|
||||||
} else {
|
} else {
|
||||||
}}}
|
}}}
|
||||||
<div class="empty-message">暂无消息记录</div>
|
<div class="empty-state">
|
||||||
|
<i class="layui-icon layui-icon-message"></i>
|
||||||
|
<p>暂无消息记录</p>
|
||||||
|
</div>
|
||||||
{{# }
|
{{# }
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
@@ -243,7 +315,7 @@
|
|||||||
layer.open({
|
layer.open({
|
||||||
type: 1,
|
type: 1,
|
||||||
title: '消息记录',
|
title: '消息记录',
|
||||||
content: '<div class="simple-message-list" style="padding: 15px; max-height: 500px; overflow-y: auto;">加载中...</div>',
|
content: '<div class="message-list" style="padding: 25px; max-height: 650px; overflow-y: auto;">加载中...</div>',
|
||||||
area: ['80%', '70%'],
|
area: ['80%', '70%'],
|
||||||
success: function(layero, index) {
|
success: function(layero, index) {
|
||||||
// 获取消息列表
|
// 获取消息列表
|
||||||
@@ -253,34 +325,48 @@
|
|||||||
data: {
|
data: {
|
||||||
conversation_id: data.conversation_id,
|
conversation_id: data.conversation_id,
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: 100 // 加载最多100条消息
|
limit: 100, // 加载最多100条消息
|
||||||
|
sort_field: 'create_time',
|
||||||
|
sort_order: 'desc' // 默认最新消息在前面
|
||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
var messageList = res.data.messages || [];
|
var messageList = res.data?.messages || [];
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
if (messageList.length > 0) {
|
if (messageList.length > 0) {
|
||||||
messageList.forEach(function(item) {
|
messageList.forEach(function(item) {
|
||||||
|
var role = item.role === 'user' ? (item.user_id ? '用户-' + item.user_id : '用户') : '机器人';
|
||||||
var roleClass = item.role === 'user' ? 'user' : 'assistant';
|
var roleClass = item.role === 'user' ? 'user' : 'assistant';
|
||||||
var roleText = item.role === 'user' ? '用户' : '机器人';
|
var avatar = item.role === 'user' ? '/addon/aikefu/static/images/user.svg' : '/addon/aikefu/static/images/robot.svg';
|
||||||
|
|
||||||
html += '<div class="message-item ' + roleClass + '">';
|
html += '<div class="message-item ' + roleClass + '">';
|
||||||
html += '<div class="message-header">';
|
if (item.role === 'assistant') {
|
||||||
html += '<span class="message-role">' + roleText + '</span>';
|
html += '<img src="' + avatar + '" class="message-avatar">';
|
||||||
html += '<span class="message-time">' + item.create_time + '</span>';
|
}
|
||||||
html += '</div>';
|
html += '<div>';
|
||||||
|
html += '<div class="message-role">' + role + '</div>';
|
||||||
html += '<div class="message-content">' + item.content + '</div>';
|
html += '<div class="message-content">' + item.content + '</div>';
|
||||||
|
html += '<div class="message-time">' + item.create_time + '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
if (item.role === 'user') {
|
||||||
|
html += '<img src="' + avatar + '" class="message-avatar">';
|
||||||
|
}
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
html += '<div class="empty-message">暂无消息记录</div>';
|
html += '<div class="empty-state">';
|
||||||
|
html += '<i class="layui-icon layui-icon-message"></i>';
|
||||||
|
html += '<p>暂无消息记录</p>';
|
||||||
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
layero.find('.simple-message-list').html(html);
|
layero.find('.message-list').html(html);
|
||||||
|
// 默认滚动到底部(最新消息)
|
||||||
|
layero.find('.message-list').scrollTop(layero.find('.message-list')[0].scrollHeight);
|
||||||
},
|
},
|
||||||
error: function() {
|
error: function() {
|
||||||
layero.find('.simple-message-list').html('<div class="empty-message">加载消息失败</div>');
|
layero.find('.message-list').html('<div class="empty-state">加载消息失败</div>');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,6 +220,13 @@
|
|||||||
<label for="user_id">用户ID</label>
|
<label for="user_id">用户ID</label>
|
||||||
<input type="text" name="user_id" id="msg_user_id" placeholder="请输入用户ID进行过滤" value="{$user_id ?? ''}" class="layui-input" style="width: 200px; display: inline-block;">
|
<input type="text" name="user_id" id="msg_user_id" placeholder="请输入用户ID进行过滤" value="{$user_id ?? ''}" class="layui-input" style="width: 200px; display: inline-block;">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search-item">
|
||||||
|
<label for="sort_order">排序方式</label>
|
||||||
|
<select name="sort_order" id="msg_sortOrder" class="layui-select" style="width: 200px; display: inline-block;">
|
||||||
|
<option value="desc">最新消息在前面</option>
|
||||||
|
<option value="asc">最新消息在后面</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="search-item">
|
<div class="search-item">
|
||||||
<button type="button" class="layui-btn layui-btn-primary" id="msg_searchBtn">搜索</button>
|
<button type="button" class="layui-btn layui-btn-primary" id="msg_searchBtn">搜索</button>
|
||||||
<button type="button" class="layui-btn" id="msg_resetBtn">重置</button>
|
<button type="button" class="layui-btn" id="msg_resetBtn">重置</button>
|
||||||
@@ -247,12 +254,14 @@
|
|||||||
var laypage = layui.laypage;
|
var laypage = layui.laypage;
|
||||||
var layer = layui.layer;
|
var layer = layui.layer;
|
||||||
|
|
||||||
// 分页参数
|
// 分页和排序参数
|
||||||
var page = 1;
|
var page = 1;
|
||||||
var limit = 50;
|
var limit = 50;
|
||||||
var total = 0;
|
var total = 0;
|
||||||
var conversation_id = $('#msg_conversation_id').val();
|
var conversation_id = $('#msg_conversation_id').val();
|
||||||
var user_id = $('#msg_user_id').val();
|
var user_id = $('#msg_user_id').val();
|
||||||
|
var sortField = 'create_time'; // 排序字段:创建时间
|
||||||
|
var sortOrder = 'desc'; // 默认倒序(最新消息在前面)
|
||||||
|
|
||||||
// 加载会话信息(当指定会话ID时显示)
|
// 加载会话信息(当指定会话ID时显示)
|
||||||
function loadConversationInfo() {
|
function loadConversationInfo() {
|
||||||
@@ -294,7 +303,9 @@
|
|||||||
// 构建请求数据
|
// 构建请求数据
|
||||||
var requestData = {
|
var requestData = {
|
||||||
page: page,
|
page: page,
|
||||||
limit: limit
|
limit: limit,
|
||||||
|
sort_field: sortField, // 排序字段:创建时间
|
||||||
|
sort_order: sortOrder // 排序方式:倒序/正序
|
||||||
};
|
};
|
||||||
|
|
||||||
// 如果有会话ID,则添加到请求数据中
|
// 如果有会话ID,则添加到请求数据中
|
||||||
@@ -376,8 +387,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('#msg_messageList').html(html);
|
$('#msg_messageList').html(html);
|
||||||
// 滚动到底部
|
// 根据排序方式调整滚动位置
|
||||||
$('#msg_messageList').scrollTop($('#msg_messageList')[0].scrollHeight);
|
if (sortOrder === 'asc') {
|
||||||
|
// 正序时滚动到顶部
|
||||||
|
$('#msg_messageList').scrollTop(0);
|
||||||
|
} else {
|
||||||
|
// 倒序时滚动到底部
|
||||||
|
$('#msg_messageList').scrollTop($('#msg_messageList')[0].scrollHeight);
|
||||||
|
}
|
||||||
// 渲染分页
|
// 渲染分页
|
||||||
renderPagination();
|
renderPagination();
|
||||||
} else {
|
} else {
|
||||||
@@ -434,6 +451,7 @@
|
|||||||
$('#msg_searchBtn').click(function() {
|
$('#msg_searchBtn').click(function() {
|
||||||
conversation_id = $('#msg_conversation_id').val().trim();
|
conversation_id = $('#msg_conversation_id').val().trim();
|
||||||
user_id = $('#msg_user_id').val().trim();
|
user_id = $('#msg_user_id').val().trim();
|
||||||
|
sortOrder = $('#msg_sortOrder').val(); // 获取当前选择的排序方式
|
||||||
page = 1;
|
page = 1;
|
||||||
loadConversationInfo();
|
loadConversationInfo();
|
||||||
loadMessageList();
|
loadMessageList();
|
||||||
@@ -443,13 +461,22 @@
|
|||||||
$('#msg_resetBtn').click(function() {
|
$('#msg_resetBtn').click(function() {
|
||||||
$('#msg_conversation_id').val('');
|
$('#msg_conversation_id').val('');
|
||||||
$('#msg_user_id').val('');
|
$('#msg_user_id').val('');
|
||||||
|
$('#msg_sortOrder').val('desc'); // 重置为默认排序
|
||||||
conversation_id = '';
|
conversation_id = '';
|
||||||
user_id = '';
|
user_id = '';
|
||||||
|
sortOrder = 'desc'; // 重置为默认排序
|
||||||
page = 1;
|
page = 1;
|
||||||
loadConversationInfo();
|
loadConversationInfo();
|
||||||
loadMessageList();
|
loadMessageList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 排序方式变更事件
|
||||||
|
$('#msg_sortOrder').change(function() {
|
||||||
|
sortOrder = $(this).val();
|
||||||
|
page = 1; // 切换排序时重置到第一页
|
||||||
|
loadMessageList();
|
||||||
|
});
|
||||||
|
|
||||||
// 初始化加载(默认显示所有消息)
|
// 初始化加载(默认显示所有消息)
|
||||||
loadConversationInfo();
|
loadConversationInfo();
|
||||||
loadMessageList();
|
loadMessageList();
|
||||||
|
|||||||
Reference in New Issue
Block a user