378 lines
17 KiB
HTML
378 lines
17 KiB
HTML
|
||||
|
|
<title>反馈管理</title>
|
|||
|
|
|
|||
|
|
<div class="layui-card layadmin-header">
|
|||
|
|
<div class="layui-breadcrumb" lay-filter="breadcrumb">
|
|||
|
|
<a lay-href="">主页</a>
|
|||
|
|
<a><cite>系统</cite></a>
|
|||
|
|
<a><cite>反馈管理</cite></a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-fluid">
|
|||
|
|
<div class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="layadmin-feedback-formlist">
|
|||
|
|
<div class="layui-form-item">
|
|||
|
|
<div class="layui-inline">
|
|||
|
|
<label class="layui-form-label">用户编号</label>
|
|||
|
|
<div class="layui-input-inline">
|
|||
|
|
<input type="text" name="userNumber" placeholder="请输入" autocomplete="off" class="layui-input">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-inline">
|
|||
|
|
<label class="layui-form-label">用户昵称</label>
|
|||
|
|
<div class="layui-input-inline">
|
|||
|
|
<input type="text" name="userName" placeholder="请输入" autocomplete="off" class="layui-input">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-inline">
|
|||
|
|
<label class="layui-form-label">反馈类型</label>
|
|||
|
|
<div class="layui-input-inline">
|
|||
|
|
<select name="type">
|
|||
|
|
<option value="">全部</option>
|
|||
|
|
<option value="1">功能建议</option>
|
|||
|
|
<option value="2">bug反馈</option>
|
|||
|
|
<option value="3">其他问题</option>
|
|||
|
|
<option value="4">充值问题</option>
|
|||
|
|
<option value="5">游戏问题</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-inline">
|
|||
|
|
<label class="layui-form-label">处理状态</label>
|
|||
|
|
<div class="layui-input-inline">
|
|||
|
|
<select name="status">
|
|||
|
|
<option value="">全部</option>
|
|||
|
|
<option value="0">待处理</option>
|
|||
|
|
<option value="1">处理中</option>
|
|||
|
|
<option value="2">已回复</option>
|
|||
|
|
<option value="3">已解决</option>
|
|||
|
|
<option value="4">已关闭</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-inline">
|
|||
|
|
<label class="layui-form-label">时间范围</label>
|
|||
|
|
<div class="layui-input-inline">
|
|||
|
|
<input type="text" name="timeRange" id="timeRange" placeholder="选择时间范围" autocomplete="off" class="layui-input">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-inline">
|
|||
|
|
<button class="layui-btn layuiadmin-btn-list" lay-submit lay-filter="LAY-feedback-front-search">
|
|||
|
|
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i> 搜索
|
|||
|
|
</button>
|
|||
|
|
<button class="layui-btn layui-btn-primary" lay-filter="LAY-feedback-front-reset">
|
|||
|
|
<i class="layui-icon layui-icon-refresh layuiadmin-button-btn"></i> 重置
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="layui-card">
|
|||
|
|
<div class="layui-card-body">
|
|||
|
|
<table id="LAY-feedback-manage" lay-filter="LAY-feedback-manage"></table>
|
|||
|
|
|
|||
|
|
<script type="text/html" id="table-feedback-toolbar">
|
|||
|
|
<div class="layui-btn-container">
|
|||
|
|
<button class="layui-btn layui-btn-sm layui-btn-primary" lay-event="refresh">
|
|||
|
|
<i class="layui-icon layui-icon-refresh"></i> 刷新
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<script type="text/html" id="table-feedback-bar">
|
|||
|
|
<a class="layui-btn layui-btn-xs" lay-event="detail"><i class="layui-icon layui-icon-about"></i>详情</a>
|
|||
|
|
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="reply"><i class="layui-icon layui-icon-reply-fill"></i>回复</a>
|
|||
|
|
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<script type="text/html" id="typeTpl">
|
|||
|
|
{{#
|
|||
|
|
var typeNames = {1:'功能建议',2:'bug反馈',3:'其他问题',4:'充值问题',5:'游戏问题'};
|
|||
|
|
return typeNames[d.type] || '未知';
|
|||
|
|
}}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<script type="text/html" id="statusTpl">
|
|||
|
|
{{#
|
|||
|
|
var statusMap = {
|
|||
|
|
0:'<span class="layui-badge layui-bg-gray">待处理</span>',
|
|||
|
|
1:'<span class="layui-badge layui-bg-blue">处理中</span>',
|
|||
|
|
2:'<span class="layui-badge layui-bg-green">已回复</span>',
|
|||
|
|
3:'<span class="layui-badge layui-bg-cyan">已解决</span>',
|
|||
|
|
4:'<span class="layui-badge layui-bg-black">已关闭</span>'
|
|||
|
|
};
|
|||
|
|
return statusMap[d.status] || '未知';
|
|||
|
|
}}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<script type="text/html" id="hasReplyTpl">
|
|||
|
|
{{# if(d.reply && d.reply.length > 0){ }}
|
|||
|
|
<span class="layui-badge layui-bg-green">已回复</span>
|
|||
|
|
{{# } else { }}
|
|||
|
|
<span class="layui-badge layui-bg-gray">未回复</span>
|
|||
|
|
{{# } }}
|
|||
|
|
</script>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
layui.use(['admin', 'table', 'form', 'laydate'], function () {
|
|||
|
|
var $ = layui.$,
|
|||
|
|
admin = layui.admin,
|
|||
|
|
table = layui.table,
|
|||
|
|
form = layui.form,
|
|||
|
|
laydate = layui.laydate,
|
|||
|
|
setter = layui.setter;
|
|||
|
|
|
|||
|
|
// 时间范围选择器
|
|||
|
|
laydate.render({
|
|||
|
|
elem: '#timeRange',
|
|||
|
|
type: 'datetime',
|
|||
|
|
range: '~'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
form.render(null, 'layadmin-feedback-formlist');
|
|||
|
|
|
|||
|
|
// 监听搜索
|
|||
|
|
form.on('submit(LAY-feedback-front-search)', function (data) {
|
|||
|
|
var field = data.field;
|
|||
|
|
if (field.timeRange) {
|
|||
|
|
var times = field.timeRange.split('~');
|
|||
|
|
field.startTime = new Date(times[0].trim()).getTime();
|
|||
|
|
field.endTime = new Date(times[1].trim()).getTime();
|
|||
|
|
}
|
|||
|
|
delete field.timeRange;
|
|||
|
|
|
|||
|
|
// 转换类型
|
|||
|
|
if (field.type) field.type = parseInt(field.type);
|
|||
|
|
if (field.status) field.status = parseInt(field.status);
|
|||
|
|
|
|||
|
|
table.reload('LAY-feedback-manage', {
|
|||
|
|
where: field,
|
|||
|
|
page: { curr: 1 }
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 监听重置
|
|||
|
|
form.on('submit(LAY-feedback-front-reset)', function (data) {
|
|||
|
|
$('input[name="userNumber"]').val('');
|
|||
|
|
$('input[name="userName"]').val('');
|
|||
|
|
$('select[name="type"]').val('');
|
|||
|
|
$('select[name="status"]').val('');
|
|||
|
|
$('input[name="timeRange"]').val('');
|
|||
|
|
form.render('select');
|
|||
|
|
table.reload('LAY-feedback-manage', {
|
|||
|
|
where: {},
|
|||
|
|
page: { curr: 1 }
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 刷新按钮
|
|||
|
|
$('.layui-btn-container').on('click', '[lay-event="refresh"]', function () {
|
|||
|
|
table.reload('LAY-feedback-manage');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
table.render({
|
|||
|
|
elem: "#LAY-feedback-manage",
|
|||
|
|
url: setter.baseurl + "adminapi/FeedbackManage/List",
|
|||
|
|
method: "post",
|
|||
|
|
contentType: "application/json",
|
|||
|
|
headers: {
|
|||
|
|
'token': layui.data(setter.tableName)[setter.request.tokenName]
|
|||
|
|
},
|
|||
|
|
page: true,
|
|||
|
|
toolbar: '#table-feedback-toolbar',
|
|||
|
|
defaultToolbar: ['filter', 'exports', 'print'],
|
|||
|
|
where: {},
|
|||
|
|
request: {
|
|||
|
|
pageName: 'pageIndex',
|
|||
|
|
limitName: 'pageSize'
|
|||
|
|
},
|
|||
|
|
limit: 10,
|
|||
|
|
cols: [[
|
|||
|
|
{ type: 'checkbox', fixed: 'left' },
|
|||
|
|
{ type: 'numbers', title: '序号', width: 60 },
|
|||
|
|
{ field: "userNumber", title: "用户编号", width: 100 },
|
|||
|
|
{ field: "userName", title: "用户昵称", width: 120 },
|
|||
|
|
{ field: "type", title: "类型", width: 100, templet: '#typeTpl' },
|
|||
|
|
{ field: "title", title: "标题", minWidth: 150 },
|
|||
|
|
{ field: "status", title: "状态", width: 100, templet: '#statusTpl' },
|
|||
|
|
{ field: "reply", title: "回复", width: 100, templet: '#hasReplyTpl' },
|
|||
|
|
{ field: "submitTime", title: "提交时间", width: 160, templet: function(d) {
|
|||
|
|
return formatDateTime(d.submitTime);
|
|||
|
|
}},
|
|||
|
|
{ width: 180, title: "操作", align: "center", fixed: "right", toolbar: "#table-feedback-bar" }
|
|||
|
|
]],
|
|||
|
|
text: "对不起,加载出现异常!",
|
|||
|
|
response: {
|
|||
|
|
statusName: 'code',
|
|||
|
|
statusCode: 0,
|
|||
|
|
msgName: 'info',
|
|||
|
|
countName: 'count',
|
|||
|
|
dataName: 'data'
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 监听工具条
|
|||
|
|
table.on("tool(LAY-feedback-manage)", function (e) {
|
|||
|
|
var l = e.data;
|
|||
|
|
|
|||
|
|
if ("detail" === e.event) {
|
|||
|
|
showFeedbackDetail(l);
|
|||
|
|
} else if ("reply" === e.event) {
|
|||
|
|
showReplyDialog(l);
|
|||
|
|
} else if ("del" === e.event) {
|
|||
|
|
layer.confirm('确定删除该反馈吗?', function (idx) {
|
|||
|
|
admin.req({
|
|||
|
|
url: setter.baseurl + 'adminapi/FeedbackManage/Delete',
|
|||
|
|
data: { id: l.id },
|
|||
|
|
done: function (res) {
|
|||
|
|
layer.close(idx);
|
|||
|
|
if (res.code === 0) {
|
|||
|
|
layer.msg('删除成功');
|
|||
|
|
table.reload('LAY-feedback-manage');
|
|||
|
|
} else {
|
|||
|
|
layer.msg(res.info || '删除失败');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 显示反馈详情
|
|||
|
|
function showFeedbackDetail(feedback) {
|
|||
|
|
var typeNames = {1:'功能建议',2:'bug反馈',3:'其他问题',4:'充值问题',5:'游戏问题'};
|
|||
|
|
var statusNames = {0:'待处理',1:'处理中',2:'已回复',3:'已解决',4:'已关闭'};
|
|||
|
|
|
|||
|
|
var content =
|
|||
|
|
'<div style="padding: 20px;">' +
|
|||
|
|
'<fieldset class="layui-elem-field">' +
|
|||
|
|
'<legend>用户信息</legend>' +
|
|||
|
|
'<div class="layui-field-box">' +
|
|||
|
|
'<p><strong>用户编号:</strong>' + (feedback.userNumber || '-') + '</p>' +
|
|||
|
|
'<p><strong>用户昵称:</strong>' + (feedback.userName || '-') + '</p>' +
|
|||
|
|
'<p><strong>联系方式:</strong>' + (feedback.contact || '-') + '</p>' +
|
|||
|
|
'<p><strong>QQ:</strong>' + (feedback.qq || '-') + '</p>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</fieldset>' +
|
|||
|
|
'<fieldset class="layui-elem-field">' +
|
|||
|
|
'<legend>反馈信息</legend>' +
|
|||
|
|
'<div class="layui-field-box">' +
|
|||
|
|
'<p><strong>类型:</strong>' + (typeNames[feedback.type] || '未知') + '</p>' +
|
|||
|
|
'<p><strong>标题:</strong>' + (feedback.title || '-') + '</p>' +
|
|||
|
|
'<p><strong>内容:</strong></p>' +
|
|||
|
|
'<div style="background:#f5f5f5;padding:10px;border-radius:4px;margin-top:5px;">' + (feedback.content || '-') + '</div>' +
|
|||
|
|
'<p style="margin-top:10px;"><strong>提交时间:</strong>' + formatDateTime(feedback.submitTime) + '</p>' +
|
|||
|
|
'<p><strong>当前状态:</strong>' + (statusNames[feedback.status] || '未知') + '</p>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</fieldset>';
|
|||
|
|
|
|||
|
|
if (feedback.reply) {
|
|||
|
|
content +=
|
|||
|
|
'<fieldset class="layui-elem-field layui-field-green">' +
|
|||
|
|
'<legend>回复信息</legend>' +
|
|||
|
|
'<div class="layui-field-box">' +
|
|||
|
|
'<p><strong>回复内容:</strong></p>' +
|
|||
|
|
'<div style="background:#f5f5f5;padding:10px;border-radius:4px;margin-top:5px;">' + feedback.reply + '</div>' +
|
|||
|
|
'<p style="margin-top:10px;"><strong>回复时间:</strong>' + formatDateTime(feedback.replyTime) + '</p>' +
|
|||
|
|
'<p><strong>回复人:</strong>' + (feedback.replyAdminName || '-') + '</p>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</fieldset>';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
content += '</div>';
|
|||
|
|
|
|||
|
|
layer.open({
|
|||
|
|
type: 1,
|
|||
|
|
title: '反馈详情',
|
|||
|
|
area: ['700px', '600px'],
|
|||
|
|
content: content
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 显示回复弹窗
|
|||
|
|
function showReplyDialog(feedback) {
|
|||
|
|
var statusNames = {0:'待处理',1:'处理中',2:'已回复',3:'已解决',4:'已关闭'};
|
|||
|
|
|
|||
|
|
layer.open({
|
|||
|
|
type: 1,
|
|||
|
|
title: '回复反馈',
|
|||
|
|
area: ['600px', '450px'],
|
|||
|
|
content: '<div style="padding:20px;">' +
|
|||
|
|
'<form class="layui-form" lay-filter="reply-form">' +
|
|||
|
|
'<div class="layui-form-item">' +
|
|||
|
|
'<label class="layui-form-label">当前状态</label>' +
|
|||
|
|
'<div class="layui-input-block">' +
|
|||
|
|
'<select name="status" lay-filter="status-select">' +
|
|||
|
|
'<option value="0" ' + (feedback.status === 0 ? 'selected' : '') + '>待处理</option>' +
|
|||
|
|
'<option value="1" ' + (feedback.status === 1 ? 'selected' : '') + '>处理中</option>' +
|
|||
|
|
'<option value="2" ' + (feedback.status === 2 ? 'selected' : '') + '>已回复</option>' +
|
|||
|
|
'<option value="3" ' + (feedback.status === 3 ? 'selected' : '') + '>已解决</option>' +
|
|||
|
|
'<option value="4" ' + (feedback.status === 4 ? 'selected' : '') + '>已关闭</option>' +
|
|||
|
|
'</select>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'<div class="layui-form-item layui-form-text">' +
|
|||
|
|
'<label class="layui-form-label">回复内容</label>' +
|
|||
|
|
'<div class="layui-input-block">' +
|
|||
|
|
'<textarea name="reply" placeholder="请输入回复内容" class="layui-textarea" style="min-height:150px;">' + (feedback.reply || '') + '</textarea>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'<div class="layui-form-item">' +
|
|||
|
|
'<div class="layui-input-block">' +
|
|||
|
|
'<button class="layui-btn" lay-submit lay-filter="reply-submit">提交回复</button>' +
|
|||
|
|
'<button type="button" class="layui-btn layui-btn-primary" onclick="layer.closeAll();">取消</button>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'</form>' +
|
|||
|
|
'</div>',
|
|||
|
|
success: function(layero, index) {
|
|||
|
|
form.render('select', 'reply-form');
|
|||
|
|
|
|||
|
|
form.on('submit(reply-submit)', function(data) {
|
|||
|
|
admin.req({
|
|||
|
|
url: setter.baseurl + 'adminapi/FeedbackManage/Reply',
|
|||
|
|
contentType: 'application/json',
|
|||
|
|
method: 'post',
|
|||
|
|
data: JSON.stringify({
|
|||
|
|
id: feedback.id,
|
|||
|
|
reply: data.field.reply,
|
|||
|
|
status: parseInt(data.field.status)
|
|||
|
|
}),
|
|||
|
|
done: function(res) {
|
|||
|
|
if (res.code === 0) {
|
|||
|
|
layer.close(index);
|
|||
|
|
layer.msg('回复成功');
|
|||
|
|
table.reload('LAY-feedback-manage');
|
|||
|
|
} else {
|
|||
|
|
layer.msg(res.info || '回复失败');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return false;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function formatDateTime(date) {
|
|||
|
|
if (!date) return '-';
|
|||
|
|
var d = new Date(date);
|
|||
|
|
var year = d.getFullYear();
|
|||
|
|
var month = ('0' + (d.getMonth() + 1)).slice(-2);
|
|||
|
|
var day = ('0' + d.getDate()).slice(-2);
|
|||
|
|
var hour = ('0' + d.getHours()).slice(-2);
|
|||
|
|
var minute = ('0' + d.getMinutes()).slice(-2);
|
|||
|
|
var second = ('0' + d.getSeconds()).slice(-2);
|
|||
|
|
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
</script>
|