chore(addon/aikefu): update html
This commit is contained in:
@@ -1,98 +1,104 @@
|
|||||||
<!DOCTYPE html>
|
<style>
|
||||||
<html lang="zh-CN">
|
.word-aux {
|
||||||
<head>
|
margin-left: 110px;
|
||||||
<meta charset="UTF-8">
|
color: #999;
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
font-size: 12px;
|
||||||
<title>智能客服配置</title>
|
margin-top: 5px;
|
||||||
<link rel="stylesheet" href="/__STATIC__/admin/css/global.css">
|
}
|
||||||
<link rel="stylesheet" href="/__STATIC__/admin/css/form.css">
|
.required {
|
||||||
</head>
|
color: red;
|
||||||
<body>
|
}
|
||||||
<div class="main">
|
</style>
|
||||||
<div class="container">
|
|
||||||
<div class="page-title">
|
<div class="layui-form form-wrap">
|
||||||
<h2>智能客服配置</h2>
|
<div class="layui-form-item">
|
||||||
</div>
|
<label class="layui-form-label"><span class="required">*</span>Dify API密钥:</label>
|
||||||
<div class="card">
|
<div class="layui-input-block">
|
||||||
<form id="kefuConfigForm">
|
<input type="text" name="api_key" placeholder="请输入Dify API密钥" value="{$config_info.data.value.api_key ?? ''}" class="layui-input">
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="api_key">Dify API密钥</label>
|
<div class="word-aux">
|
||||||
<input type="text" name="api_key" id="api_key" value="{$config_info.api_key ?? ''}" placeholder="请输入Dify API密钥">
|
从Dify平台获取的API密钥,用于调用Dify聊天机器人API。
|
||||||
<div class="form-tips">
|
<a href="https://dify.ai/" target="_blank">前往Dify平台</a>
|
||||||
从Dify平台获取的API密钥,用于调用Dify聊天机器人API。
|
|
||||||
<a href="https://dify.ai/" target="_blank">前往Dify平台</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="base_url">API基础地址</label>
|
|
||||||
<input type="text" name="base_url" id="base_url" value="{$config_info.base_url ?? 'https://api.dify.ai/v1'}" placeholder="请输入Dify API基础地址">
|
|
||||||
<div class="form-tips">
|
|
||||||
Dify API的基础地址,默认为https://api.dify.ai/v1
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="chat_endpoint">聊天接口端点</label>
|
|
||||||
<input type="text" name="chat_endpoint" id="chat_endpoint" value="{$config_info.chat_endpoint ?? '/chat-messages'}" placeholder="请输入聊天接口端点">
|
|
||||||
<div class="form-tips">
|
|
||||||
聊天接口的端点,默认为/chat-messages
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="status">状态</label>
|
|
||||||
<div class="radio-group">
|
|
||||||
<label class="radio-item">
|
|
||||||
<input type="radio" name="status" value="1" {if isset($config_info.status) && $config_info.status == 1}checked{/if}>
|
|
||||||
<span>启用</span>
|
|
||||||
</label>
|
|
||||||
<label class="radio-item">
|
|
||||||
<input type="radio" name="status" value="0" {if !isset($config_info.status) || $config_info.status == 0}checked{/if}>
|
|
||||||
<span>禁用</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-tips">
|
|
||||||
启用或禁用智能客服功能
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-actions">
|
|
||||||
<button type="submit" class="btn btn-primary">保存配置</button>
|
|
||||||
<button type="reset" class="btn btn-default">重置</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/__STATIC__/admin/js/jquery.min.js"></script>
|
<div class="layui-form-item">
|
||||||
<script src="/__STATIC__/admin/js/layer/layer.js"></script>
|
<label class="layui-form-label">API基础地址:</label>
|
||||||
<script>
|
<div class="layui-input-block">
|
||||||
$(function() {
|
<input type="text" name="base_url" placeholder="请输入Dify API基础地址" value="{$config_info.data.value.base_url ?? 'https://api.dify.ai/v1'}" class="layui-input">
|
||||||
$('#kefuConfigForm').on('submit', function(e) {
|
</div>
|
||||||
e.preventDefault();
|
<div class="word-aux">Dify API的基础地址,默认为https://api.dify.ai/v1</div>
|
||||||
|
</div>
|
||||||
var formData = $(this).serialize();
|
|
||||||
|
<div class="layui-form-item">
|
||||||
$.ajax({
|
<label class="layui-form-label">聊天接口端点:</label>
|
||||||
url: '/shop/aikefu/kefu/saveConfig',
|
<div class="layui-input-block">
|
||||||
type: 'POST',
|
<input type="text" name="chat_endpoint" placeholder="请输入聊天接口端点" value="{$config_info.data.value.chat_endpoint ?? '/chat-messages'}" class="layui-input">
|
||||||
data: formData,
|
</div>
|
||||||
dataType: 'json',
|
<div class="word-aux">聊天接口的端点,默认为/chat-messages</div>
|
||||||
success: function(res) {
|
</div>
|
||||||
if (res.code === 0) {
|
|
||||||
layer.msg('保存成功', {icon: 1});
|
<div class="layui-form-item">
|
||||||
} else {
|
<label class="layui-form-label"><span class="required">*</span>状态:</label>
|
||||||
layer.msg(res.message, {icon: 2});
|
<div class="layui-input-block">
|
||||||
}
|
<input type="checkbox" name="status" value="1" lay-skin="switch" {if condition="isset($config_info.data.value.status) && $config_info.data.value.status == 1"} checked {/if}>
|
||||||
},
|
</div>
|
||||||
error: function() {
|
<div class="word-aux">启用或禁用智能客服功能</div>
|
||||||
layer.msg('请求失败,请稍后重试', {icon: 2});
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
|
||||||
|
<button class="layui-btn layui-btn-primary" onclick="back()">返回</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
layui.use('form', function() {
|
||||||
|
var form = layui.form;
|
||||||
|
var repeat_flag = false; //防重复标识
|
||||||
|
form.render();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听提交
|
||||||
|
*/
|
||||||
|
form.on('submit(save)', function(data) {
|
||||||
|
if (repeat_flag) return false;
|
||||||
|
repeat_flag = true;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: ns.url("aikefu://shop/kefu/saveConfig"),
|
||||||
|
type: 'POST',
|
||||||
|
data: data.field,
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(res) {
|
||||||
|
repeat_flag = false;
|
||||||
|
if (res.code === 0) {
|
||||||
|
layer.confirm('保存成功', {
|
||||||
|
title: '操作提示',
|
||||||
|
btn: ['返回列表', '继续编辑'],
|
||||||
|
yes: function(index, layero) {
|
||||||
|
location.reload();
|
||||||
|
layer.close(index);
|
||||||
|
},
|
||||||
|
btn2: function(index, layero) {
|
||||||
|
layer.close(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
layer.msg(res.message, {icon: 2});
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
error: function() {
|
||||||
|
repeat_flag = false;
|
||||||
|
layer.msg('请求失败,请稍后重试', {icon: 2});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
</script>
|
});
|
||||||
</body>
|
|
||||||
</html>
|
function back() {
|
||||||
|
window.history.back();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -1,192 +1,180 @@
|
|||||||
<!DOCTYPE html>
|
<style>
|
||||||
<html lang="zh-CN">
|
.search-box {
|
||||||
<head>
|
padding: 10px 0;
|
||||||
<meta charset="UTF-8">
|
border-bottom: 1px solid #eee;
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
margin-bottom: 15px;
|
||||||
<title>会话管理</title>
|
}
|
||||||
<link rel="stylesheet" href="/__STATIC__/admin/css/global.css">
|
.search-item {
|
||||||
<link rel="stylesheet" href="/__STATIC__/admin/css/table.css">
|
display: inline-block;
|
||||||
</head>
|
margin-right: 15px;
|
||||||
<body>
|
vertical-align: middle;
|
||||||
<div class="main">
|
}
|
||||||
<div class="container">
|
.search-item label {
|
||||||
<div class="page-title">
|
display: inline-block;
|
||||||
<h2>会话管理</h2>
|
width: 80px;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.search-item input,
|
||||||
|
.search-item select {
|
||||||
|
width: 150px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.layui-btn-container {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.layui-btn-sm {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
.status-active {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
.status-inactive {
|
||||||
|
color: #faad14;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<!-- 搜索区域 -->
|
||||||
|
<div class="search-box">
|
||||||
|
<form class="layui-form" id="searchForm">
|
||||||
|
<div class="search-item">
|
||||||
|
<label for="user_id">用户ID</label>
|
||||||
|
<input type="text" name="user_id" id="user_id" placeholder="请输入用户ID" class="layui-input">
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="search-item">
|
||||||
<div class="search-box">
|
<label for="status">状态</label>
|
||||||
<div class="search-item">
|
<select name="status" id="status" class="layui-select">
|
||||||
<label for="user_id">用户ID</label>
|
<option value="">全部</option>
|
||||||
<input type="text" name="user_id" id="user_id" placeholder="请输入用户ID">
|
<option value="1">活跃</option>
|
||||||
</div>
|
<option value="0">已结束</option>
|
||||||
<div class="search-item">
|
</select>
|
||||||
<label for="status">状态</label>
|
|
||||||
<select name="status" id="status">
|
|
||||||
<option value="">全部</option>
|
|
||||||
<option value="1">活跃</option>
|
|
||||||
<option value="0">已结束</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="search-item">
|
|
||||||
<button type="button" class="btn btn-primary" id="searchBtn">搜索</button>
|
|
||||||
<button type="button" class="btn btn-default" id="resetBtn">重置</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-container">
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>会话ID</th>
|
|
||||||
<th>用户ID</th>
|
|
||||||
<th>会话名称</th>
|
|
||||||
<th>状态</th>
|
|
||||||
<th>创建时间</th>
|
|
||||||
<th>更新时间</th>
|
|
||||||
<th>操作</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="conversationList">
|
|
||||||
<!-- 会话列表将通过JavaScript动态加载 -->
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="pagination" id="pagination">
|
|
||||||
<!-- 分页将通过JavaScript动态加载 -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="search-item">
|
||||||
|
<button type="button" class="layui-btn layui-btn-primary" id="searchBtn">搜索</button>
|
||||||
|
<button type="button" class="layui-btn layui-btn-primary" id="resetBtn">重置</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/__STATIC__/admin/js/jquery.min.js"></script>
|
<!-- 表格区域 -->
|
||||||
<script src="/__STATIC__/admin/js/layer/layer.js"></script>
|
<table class="layui-table" id="conversationTable" lay-filter="conversationTable"></table>
|
||||||
<script>
|
</div>
|
||||||
$(function() {
|
|
||||||
// 分页参数
|
<script type="text/html" id="toolbarDemo">
|
||||||
var page = 1;
|
<div class="layui-btn-container">
|
||||||
var limit = 10;
|
<!-- 可以在这里添加按钮 -->
|
||||||
var total = 0;
|
</div>
|
||||||
|
</script>
|
||||||
// 加载会话列表
|
|
||||||
function loadConversationList() {
|
<script type="text/html" id="statusTpl">
|
||||||
var user_id = $('#user_id').val();
|
{{# if(d.status === 1) {
|
||||||
var status = $('#status').val();
|
return '<span class="status-active">活跃</span>';
|
||||||
|
} else {
|
||||||
$.ajax({
|
return '<span class="status-inactive">已结束</span>';
|
||||||
url: '/shop/aikefu/kefu/getConversationList',
|
}}}
|
||||||
type: 'POST',
|
</script>
|
||||||
data: {
|
|
||||||
page: page,
|
<script type="text/html" id="barDemo">
|
||||||
limit: limit,
|
<a class="layui-btn layui-btn-xs" lay-event="view">查看消息</a>
|
||||||
user_id: user_id,
|
<a class="layui-btn layui-btn-xs layui-btn-warning" lay-event="end">结束会话</a>
|
||||||
status: status
|
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="delete">删除</a>
|
||||||
},
|
</script>
|
||||||
dataType: 'json',
|
|
||||||
success: function(res) {
|
<script>
|
||||||
if (res.code === 0) {
|
layui.use(['table', 'form', 'layer'], function() {
|
||||||
var list = res.data.list;
|
var table = layui.table;
|
||||||
total = res.data.total;
|
var form = layui.form;
|
||||||
|
var layer = layui.layer;
|
||||||
var html = '';
|
|
||||||
if (list.length > 0) {
|
// 渲染表格
|
||||||
list.forEach(function(item) {
|
var tableIns = table.render({
|
||||||
html += '<tr>';
|
elem: '#conversationTable',
|
||||||
html += '<td>' + item.id + '</td>';
|
url: ns.url("aikefu://shop/kefu/getConversationList"),
|
||||||
html += '<td>' + item.conversation_id + '</td>';
|
method: 'POST',
|
||||||
html += '<td>' + item.user_id + '</td>';
|
toolbar: '#toolbarDemo',
|
||||||
html += '<td>' + item.name + '</td>';
|
defaultToolbar: ['filter', 'exports', 'print'],
|
||||||
html += '<td>' + (item.status === 1 ? '<span class="status-active">活跃</span>' : '<span class="status-inactive">已结束</span>') + '</td>';
|
title: '会话管理',
|
||||||
html += '<td>' + item.create_time + '</td>';
|
cols: [[
|
||||||
html += '<td>' + item.update_time + '</td>';
|
{field: 'id', title: 'ID', width: 80, align: 'center', fixed: 'left'},
|
||||||
html += '<td>';
|
{field: 'conversation_id', title: '会话ID', width: 200, align: 'center'},
|
||||||
html += '<a href="javascript:;" class="btn btn-small btn-primary" onclick="viewMessages(' + item.id + ', \'' + item.conversation_id + '\')">查看消息</a>';
|
{field: 'user_id', title: '用户ID', width: 150, align: 'center'},
|
||||||
html += '<a href="javascript:;" class="btn btn-small btn-warning" onclick="endConversation(' + item.id + ')">结束会话</a>';
|
{field: 'name', title: '会话名称', width: 180, align: 'center'},
|
||||||
html += '<a href="javascript:;" class="btn btn-small btn-danger" onclick="deleteConversation(' + item.id + ')">删除</a>';
|
{field: 'status', title: '状态', width: 100, align: 'center', templet: '#statusTpl'},
|
||||||
html += '</td>';
|
{field: 'create_time', title: '创建时间', width: 180, align: 'center'},
|
||||||
html += '</tr>';
|
{field: 'update_time', title: '更新时间', width: 180, align: 'center'},
|
||||||
});
|
{fixed: 'right', title: '操作', width: 200, align: 'center', toolbar: '#barDemo'}
|
||||||
} else {
|
]],
|
||||||
html += '<tr><td colspan="8" class="text-center">暂无会话数据</td></tr>';
|
page: true,
|
||||||
}
|
limit: 10,
|
||||||
|
limits: [10, 20, 30, 50, 100],
|
||||||
$('#conversationList').html(html);
|
height: 'full-200',
|
||||||
// 渲染分页
|
text: {
|
||||||
renderPagination();
|
none: '暂无会话数据'
|
||||||
} else {
|
|
||||||
layer.msg('加载失败:' + res.message, {icon: 2});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
layer.msg('请求失败,请稍后重试', {icon: 2});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// 渲染分页
|
|
||||||
function renderPagination() {
|
// 搜索按钮点击事件
|
||||||
var pages = Math.ceil(total / limit);
|
$('#searchBtn').click(function() {
|
||||||
var html = '';
|
// 执行搜索
|
||||||
|
tableIns.reload({
|
||||||
if (pages > 1) {
|
page: {
|
||||||
html += '<ul class="pagination-list">';
|
curr: 1
|
||||||
|
},
|
||||||
// 上一页
|
where: {
|
||||||
if (page > 1) {
|
user_id: $('#user_id').val(),
|
||||||
html += '<li><a href="javascript:;" onclick="changePage(' + (page - 1) + ')">上一页</a></li>';
|
status: $('#status').val()
|
||||||
} else {
|
|
||||||
html += '<li class="disabled"><a href="javascript:;">上一页</a></li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 页码
|
|
||||||
for (var i = 1; i <= pages; i++) {
|
|
||||||
if (i === page) {
|
|
||||||
html += '<li class="active"><a href="javascript:;">' + i + '</a></li>';
|
|
||||||
} else {
|
|
||||||
html += '<li><a href="javascript:;" onclick="changePage(' + i + ')">' + i + '</a></li>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下一页
|
|
||||||
if (page < pages) {
|
|
||||||
html += '<li><a href="javascript:;" onclick="changePage(' + (page + 1) + ')">下一页</a></li>';
|
|
||||||
} else {
|
|
||||||
html += '<li class="disabled"><a href="javascript:;">下一页</a></li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</ul>';
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
$('#pagination').html(html);
|
});
|
||||||
}
|
|
||||||
|
// 重置按钮点击事件
|
||||||
|
$('#resetBtn').click(function() {
|
||||||
|
$('#user_id').val('');
|
||||||
|
$('#status').val('');
|
||||||
|
form.render('select');
|
||||||
|
|
||||||
// 切换页码
|
// 执行重置后的搜索
|
||||||
window.changePage = function(p) {
|
tableIns.reload({
|
||||||
page = p;
|
page: {
|
||||||
loadConversationList();
|
curr: 1
|
||||||
}
|
},
|
||||||
|
where: {
|
||||||
|
user_id: '',
|
||||||
|
status: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听行工具事件
|
||||||
|
table.on('tool(conversationTable)', function(obj) {
|
||||||
|
var data = obj.data;
|
||||||
|
var layEvent = obj.event;
|
||||||
|
|
||||||
// 查看消息
|
if (layEvent === 'view') {
|
||||||
window.viewMessages = function(id, conversation_id) {
|
// 查看消息
|
||||||
layer.open({
|
layer.open({
|
||||||
type: 2,
|
type: 2,
|
||||||
title: '消息记录',
|
title: '消息记录',
|
||||||
content: '/shop/aikefu/kefu/message?conversation_id=' + conversation_id,
|
content: ns.url("aikefu://shop/kefu/message", {conversation_id: data.conversation_id}),
|
||||||
area: ['90%', '90%']
|
area: ['90%', '90%']
|
||||||
});
|
});
|
||||||
}
|
} else if (layEvent === 'end') {
|
||||||
|
// 结束会话
|
||||||
// 结束会话
|
|
||||||
window.endConversation = function(id) {
|
|
||||||
layer.confirm('确定要结束该会话吗?', function(index) {
|
layer.confirm('确定要结束该会话吗?', function(index) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/shop/aikefu/kefu/endConversation',
|
url: ns.url("aikefu://shop/kefu/endConversation"),
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: {id: id},
|
data: {id: data.id},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('会话已结束', {icon: 1});
|
layer.msg('会话已结束', {icon: 1});
|
||||||
loadConversationList();
|
// 重新加载表格数据
|
||||||
|
tableIns.reload();
|
||||||
} else {
|
} else {
|
||||||
layer.msg('操作失败:' + res.message, {icon: 2});
|
layer.msg('操作失败:' + res.message, {icon: 2});
|
||||||
}
|
}
|
||||||
@@ -197,20 +185,19 @@
|
|||||||
});
|
});
|
||||||
layer.close(index);
|
layer.close(index);
|
||||||
});
|
});
|
||||||
}
|
} else if (layEvent === 'delete') {
|
||||||
|
// 删除会话
|
||||||
// 删除会话
|
|
||||||
window.deleteConversation = function(id) {
|
|
||||||
layer.confirm('确定要删除该会话吗?删除后将无法恢复', function(index) {
|
layer.confirm('确定要删除该会话吗?删除后将无法恢复', function(index) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/shop/aikefu/kefu/deleteConversation',
|
url: ns.url("aikefu://shop/kefu/deleteConversation"),
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: {id: id},
|
data: {id: data.id},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('会话已删除', {icon: 1});
|
layer.msg('会话已删除', {icon: 1});
|
||||||
loadConversationList();
|
// 重新加载表格数据
|
||||||
|
tableIns.reload();
|
||||||
} else {
|
} else {
|
||||||
layer.msg('操作失败:' + res.message, {icon: 2});
|
layer.msg('操作失败:' + res.message, {icon: 2});
|
||||||
}
|
}
|
||||||
@@ -222,24 +209,6 @@
|
|||||||
layer.close(index);
|
layer.close(index);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索
|
|
||||||
$('#searchBtn').click(function() {
|
|
||||||
page = 1;
|
|
||||||
loadConversationList();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重置
|
|
||||||
$('#resetBtn').click(function() {
|
|
||||||
$('#user_id').val('');
|
|
||||||
$('#status').val('');
|
|
||||||
page = 1;
|
|
||||||
loadConversationList();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 初始化加载
|
|
||||||
loadConversationList();
|
|
||||||
});
|
});
|
||||||
</script>
|
});
|
||||||
</body>
|
</script>
|
||||||
</html>
|
|
||||||
@@ -1,276 +1,274 @@
|
|||||||
<!DOCTYPE html>
|
<style>
|
||||||
<html lang="zh-CN">
|
.message-list {
|
||||||
<head>
|
max-height: 600px;
|
||||||
<meta charset="UTF-8">
|
overflow-y: auto;
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
padding: 20px;
|
||||||
<title>消息管理</title>
|
background-color: #f5f7fa;
|
||||||
<link rel="stylesheet" href="/__STATIC__/admin/css/global.css">
|
border-radius: 8px;
|
||||||
<link rel="stylesheet" href="/__STATIC__/admin/css/table.css">
|
margin-bottom: 20px;
|
||||||
<style>
|
border: 1px solid #e6e6e6;
|
||||||
.message-list {
|
}
|
||||||
max-height: 600px;
|
.message-item {
|
||||||
overflow-y: auto;
|
margin-bottom: 20px;
|
||||||
padding: 20px;
|
display: flex;
|
||||||
background-color: #f5f7fa;
|
align-items: flex-start;
|
||||||
border-radius: 8px;
|
}
|
||||||
margin-bottom: 20px;
|
.message-item.user {
|
||||||
}
|
justify-content: flex-end;
|
||||||
.message-item {
|
}
|
||||||
margin-bottom: 20px;
|
.message-item.assistant {
|
||||||
display: flex;
|
justify-content: flex-start;
|
||||||
align-items: flex-start;
|
}
|
||||||
}
|
.message-avatar {
|
||||||
.message-item.user {
|
width: 40px;
|
||||||
justify-content: flex-end;
|
height: 40px;
|
||||||
}
|
border-radius: 50%;
|
||||||
.message-item.assistant {
|
margin: 0 10px;
|
||||||
justify-content: flex-start;
|
}
|
||||||
}
|
.message-content {
|
||||||
.message-avatar {
|
max-width: 70%;
|
||||||
width: 40px;
|
padding: 12px 16px;
|
||||||
height: 40px;
|
border-radius: 18px;
|
||||||
border-radius: 50%;
|
word-wrap: break-word;
|
||||||
margin: 0 10px;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.message-content {
|
.message-item.user .message-content {
|
||||||
max-width: 70%;
|
background-color: #1E9FFF;
|
||||||
padding: 12px 16px;
|
color: white;
|
||||||
border-radius: 18px;
|
border-bottom-right-radius: 4px;
|
||||||
word-wrap: break-word;
|
}
|
||||||
}
|
.message-item.assistant .message-content {
|
||||||
.message-item.user .message-content {
|
background-color: white;
|
||||||
background-color: #409eff;
|
color: #333;
|
||||||
color: white;
|
border-bottom-left-radius: 4px;
|
||||||
border-bottom-right-radius: 4px;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
.message-item.assistant .message-content {
|
.message-time {
|
||||||
background-color: white;
|
font-size: 12px;
|
||||||
color: #333;
|
color: #909399;
|
||||||
border-bottom-left-radius: 4px;
|
margin-top: 5px;
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
text-align: center;
|
||||||
}
|
}
|
||||||
.message-time {
|
.message-role {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
margin-top: 5px;
|
margin-bottom: 5px;
|
||||||
text-align: center;
|
}
|
||||||
}
|
.conversation-info {
|
||||||
.message-role {
|
margin-bottom: 20px;
|
||||||
font-size: 12px;
|
padding: 15px;
|
||||||
color: #909399;
|
background-color: white;
|
||||||
margin-bottom: 5px;
|
border-radius: 8px;
|
||||||
}
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
.conversation-info {
|
border: 1px solid #e6e6e6;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
padding: 15px;
|
.conversation-info h3 {
|
||||||
background-color: white;
|
margin: 0 0 10px 0;
|
||||||
border-radius: 8px;
|
font-size: 16px;
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
color: #333;
|
||||||
}
|
font-weight: bold;
|
||||||
.conversation-info h3 {
|
}
|
||||||
margin: 0 0 10px 0;
|
.conversation-info p {
|
||||||
font-size: 16px;
|
margin: 5px 0;
|
||||||
color: #333;
|
font-size: 14px;
|
||||||
}
|
color: #606266;
|
||||||
.conversation-info p {
|
}
|
||||||
margin: 5px 0;
|
.status-active {
|
||||||
font-size: 14px;
|
color: #52c41a;
|
||||||
color: #606266;
|
}
|
||||||
}
|
.status-inactive {
|
||||||
</style>
|
color: #faad14;
|
||||||
</head>
|
}
|
||||||
<body>
|
.search-box {
|
||||||
<div class="main">
|
margin-bottom: 20px;
|
||||||
<div class="container">
|
padding: 15px;
|
||||||
<div class="page-title">
|
background-color: white;
|
||||||
<h2>消息管理</h2>
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
}
|
||||||
|
.search-item {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
.search-item label {
|
||||||
|
display: inline-block;
|
||||||
|
width: 80px;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.layui-btn-sm {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<!-- 搜索区域 -->
|
||||||
|
<div class="search-box">
|
||||||
|
<form class="layui-form" id="searchForm">
|
||||||
|
<div class="search-item">
|
||||||
|
<label for="conversation_id">会话ID</label>
|
||||||
|
<input type="text" name="conversation_id" id="conversation_id" placeholder="请输入会话ID" value="{$conversation_id ?? ''}" class="layui-input" style="width: 200px; display: inline-block;">
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="search-item">
|
||||||
<div id="conversationInfo" class="conversation-info">
|
<button type="button" class="layui-btn layui-btn-primary" id="searchBtn">搜索</button>
|
||||||
<!-- 会话信息将通过JavaScript动态加载 -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="search-box">
|
|
||||||
<div class="search-item">
|
|
||||||
<label for="conversation_id">会话ID</label>
|
|
||||||
<input type="text" name="conversation_id" id="conversation_id" placeholder="请输入会话ID" value="{$conversation_id ?? ''}">
|
|
||||||
</div>
|
|
||||||
<div class="search-item">
|
|
||||||
<button type="button" class="btn btn-primary" id="searchBtn">搜索</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="message-list" id="messageList">
|
|
||||||
<!-- 消息列表将通过JavaScript动态加载 -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pagination" id="pagination">
|
|
||||||
<!-- 分页将通过JavaScript动态加载 -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/__STATIC__/admin/js/jquery.min.js"></script>
|
<!-- 会话信息 -->
|
||||||
<script src="/__STATIC__/admin/js/layer/layer.js"></script>
|
<div id="conversationInfo" class="conversation-info">
|
||||||
<script>
|
<!-- 会话信息将通过JavaScript动态加载 -->
|
||||||
$(function() {
|
</div>
|
||||||
// 分页参数
|
|
||||||
var page = 1;
|
<!-- 消息列表 -->
|
||||||
var limit = 50;
|
<div class="message-list" id="messageList">
|
||||||
var total = 0;
|
<!-- 消息列表将通过JavaScript动态加载 -->
|
||||||
var conversation_id = $('#conversation_id').val();
|
</div>
|
||||||
|
|
||||||
// 加载会话信息
|
<!-- 分页 -->
|
||||||
function loadConversationInfo() {
|
<div class="layui-fixbar" id="pagination"></div>
|
||||||
if (!conversation_id) return;
|
</div>
|
||||||
|
|
||||||
$.ajax({
|
<script>
|
||||||
url: '/shop/aikefu/kefu/getConversationInfo',
|
layui.use(['laypage', 'layer'], function() {
|
||||||
type: 'POST',
|
var laypage = layui.laypage;
|
||||||
data: {
|
var layer = layui.layer;
|
||||||
conversation_id: conversation_id
|
|
||||||
},
|
// 分页参数
|
||||||
dataType: 'json',
|
var page = 1;
|
||||||
success: function(res) {
|
var limit = 50;
|
||||||
if (res.code === 0) {
|
var total = 0;
|
||||||
var info = res.data;
|
var conversation_id = $('#conversation_id').val();
|
||||||
var html = '<h3>会话详情</h3>';
|
|
||||||
html += '<p><strong>会话ID:</strong>' + info.conversation_id + '</p>';
|
// 加载会话信息
|
||||||
html += '<p><strong>用户ID:</strong>' + info.user_id + '</p>';
|
function loadConversationInfo() {
|
||||||
html += '<p><strong>会话名称:</strong>' + info.name + '</p>';
|
if (!conversation_id) {
|
||||||
html += '<p><strong>状态:</strong>' + (info.status === 1 ? '<span class="status-active">活跃</span>' : '<span class="status-inactive">已结束</span>') + '</p>';
|
$('#conversationInfo').html('<h3>会话详情</h3><p>请输入会话ID进行搜索</p>');
|
||||||
html += '<p><strong>创建时间:</strong>' + info.create_time + '</p>';
|
return;
|
||||||
html += '<p><strong>更新时间:</strong>' + info.update_time + '</p>';
|
|
||||||
$('#conversationInfo').html(html);
|
|
||||||
} else {
|
|
||||||
$('#conversationInfo').html('<h3>会话详情</h3><p>未找到会话信息</p>');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
$('#conversationInfo').html('<h3>会话详情</h3><p>加载会话信息失败</p>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载消息列表
|
$.ajax({
|
||||||
function loadMessageList() {
|
url: ns.url("aikefu://shop/kefu/getConversationInfo"),
|
||||||
if (!conversation_id) {
|
type: 'POST',
|
||||||
$('#messageList').html('<div style="text-align: center; padding: 50px;">请输入会话ID进行搜索</div>');
|
data: {
|
||||||
return;
|
conversation_id: conversation_id
|
||||||
}
|
},
|
||||||
|
dataType: 'json',
|
||||||
$.ajax({
|
success: function(res) {
|
||||||
url: '/shop/aikefu/kefu/getMessageList',
|
if (res.code === 0) {
|
||||||
type: 'POST',
|
var info = res.data;
|
||||||
data: {
|
var html = '<h3>会话详情</h3>';
|
||||||
page: page,
|
html += '<p><strong>会话ID:</strong>' + info.conversation_id + '</p>';
|
||||||
limit: limit,
|
html += '<p><strong>用户ID:</strong>' + info.user_id + '</p>';
|
||||||
conversation_id: conversation_id
|
html += '<p><strong>会话名称:</strong>' + info.name + '</p>';
|
||||||
},
|
html += '<p><strong>状态:</strong>' + (info.status === 1 ? '<span class="status-active">活跃</span>' : '<span class="status-inactive">已结束</span>') + '</p>';
|
||||||
dataType: 'json',
|
html += '<p><strong>创建时间:</strong>' + info.create_time + '</p>';
|
||||||
success: function(res) {
|
html += '<p><strong>更新时间:</strong>' + info.update_time + '</p>';
|
||||||
if (res.code === 0) {
|
$('#conversationInfo').html(html);
|
||||||
var list = res.data.list;
|
|
||||||
total = res.data.total;
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
if (list.length > 0) {
|
|
||||||
list.forEach(function(item) {
|
|
||||||
var role = item.role === 'user' ? '用户' : '机器人';
|
|
||||||
var roleClass = item.role === 'user' ? 'user' : 'assistant';
|
|
||||||
var avatar = item.role === 'user' ? '/__STATIC__/admin/img/user.png' : '/__STATIC__/admin/img/robot.png';
|
|
||||||
|
|
||||||
html += '<div class="message-item ' + roleClass + '">';
|
|
||||||
if (item.role === 'assistant') {
|
|
||||||
html += '<img src="' + avatar + '" class="message-avatar">';
|
|
||||||
}
|
|
||||||
html += '<div>';
|
|
||||||
html += '<div class="message-role">' + role + '</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>';
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
html += '<div style="text-align: center; padding: 50px;">暂无消息记录</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#messageList').html(html);
|
|
||||||
// 滚动到底部
|
|
||||||
$('#messageList').scrollTop($('#messageList')[0].scrollHeight);
|
|
||||||
// 渲染分页
|
|
||||||
renderPagination();
|
|
||||||
} else {
|
|
||||||
layer.msg('加载失败:' + res.message, {icon: 2});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
layer.msg('请求失败,请稍后重试', {icon: 2});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渲染分页
|
|
||||||
function renderPagination() {
|
|
||||||
var pages = Math.ceil(total / limit);
|
|
||||||
var html = '';
|
|
||||||
|
|
||||||
if (pages > 1) {
|
|
||||||
html += '<ul class="pagination-list">';
|
|
||||||
|
|
||||||
// 上一页
|
|
||||||
if (page > 1) {
|
|
||||||
html += '<li><a href="javascript:;" onclick="changePage(' + (page - 1) + ')">上一页</a></li>';
|
|
||||||
} else {
|
} else {
|
||||||
html += '<li class="disabled"><a href="javascript:;">上一页</a></li>';
|
$('#conversationInfo').html('<h3>会话详情</h3><p>未找到会话信息</p>');
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// 页码
|
error: function() {
|
||||||
for (var i = 1; i <= pages; i++) {
|
$('#conversationInfo').html('<h3>会话详情</h3><p>加载会话信息失败</p>');
|
||||||
if (i === page) {
|
|
||||||
html += '<li class="active"><a href="javascript:;">' + i + '</a></li>';
|
|
||||||
} else {
|
|
||||||
html += '<li><a href="javascript:;" onclick="changePage(' + i + ')">' + i + '</a></li>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下一页
|
|
||||||
if (page < pages) {
|
|
||||||
html += '<li><a href="javascript:;" onclick="changePage(' + (page + 1) + ')">下一页</a></li>';
|
|
||||||
} else {
|
|
||||||
html += '<li class="disabled"><a href="javascript:;">下一页</a></li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</ul>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#pagination').html(html);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换页码
|
|
||||||
window.changePage = function(p) {
|
|
||||||
page = p;
|
|
||||||
loadMessageList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索
|
|
||||||
$('#searchBtn').click(function() {
|
|
||||||
conversation_id = $('#conversation_id').val();
|
|
||||||
page = 1;
|
|
||||||
loadConversationInfo();
|
|
||||||
loadMessageList();
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
// 初始化加载
|
|
||||||
if (conversation_id) {
|
// 加载消息列表
|
||||||
loadConversationInfo();
|
function loadMessageList() {
|
||||||
loadMessageList();
|
if (!conversation_id) {
|
||||||
|
$('#messageList').html('<div style="text-align: center; padding: 50px; color: #999;">请输入会话ID进行搜索</div>');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: ns.url("aikefu://shop/kefu/getMessageList"),
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
page: page,
|
||||||
|
limit: limit,
|
||||||
|
conversation_id: conversation_id
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(res) {
|
||||||
|
if (res.code === 0) {
|
||||||
|
var list = res.data.list;
|
||||||
|
total = res.data.total;
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
if (list.length > 0) {
|
||||||
|
list.forEach(function(item) {
|
||||||
|
var role = item.role === 'user' ? '用户' : '机器人';
|
||||||
|
var roleClass = item.role === 'user' ? 'user' : 'assistant';
|
||||||
|
var avatar = item.role === 'user' ? '/__STATIC__/admin/img/user.png' : '/__STATIC__/admin/img/robot.png';
|
||||||
|
|
||||||
|
html += '<div class="message-item ' + roleClass + '">';
|
||||||
|
if (item.role === 'assistant') {
|
||||||
|
html += '<img src="' + avatar + '" class="message-avatar">';
|
||||||
|
}
|
||||||
|
html += '<div>';
|
||||||
|
html += '<div class="message-role">' + role + '</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>';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
html += '<div style="text-align: center; padding: 50px; color: #999;">暂无消息记录</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#messageList').html(html);
|
||||||
|
// 滚动到底部
|
||||||
|
$('#messageList').scrollTop($('#messageList')[0].scrollHeight);
|
||||||
|
// 渲染分页
|
||||||
|
renderPagination();
|
||||||
|
} else {
|
||||||
|
layer.msg('加载失败:' + res.message, {icon: 2});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
layer.msg('请求失败,请稍后重试', {icon: 2});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染分页
|
||||||
|
function renderPagination() {
|
||||||
|
if (total <= limit) {
|
||||||
|
$('#pagination').html('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
laypage.render({
|
||||||
|
elem: 'pagination',
|
||||||
|
count: total,
|
||||||
|
limit: limit,
|
||||||
|
curr: page,
|
||||||
|
layout: ['prev', 'page', 'next', 'count', 'skip'],
|
||||||
|
jump: function(obj, first) {
|
||||||
|
if (!first) {
|
||||||
|
page = obj.curr;
|
||||||
|
loadMessageList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮点击事件
|
||||||
|
$('#searchBtn').click(function() {
|
||||||
|
conversation_id = $('#conversation_id').val();
|
||||||
|
page = 1;
|
||||||
|
loadConversationInfo();
|
||||||
|
loadMessageList();
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
</body>
|
// 初始化加载
|
||||||
</html>
|
if (conversation_id) {
|
||||||
|
loadConversationInfo();
|
||||||
|
loadMessageList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user