594 lines
17 KiB
HTML
594 lines
17 KiB
HTML
<form class="layui-form page-content p-4" lay-filter="webform">
|
||
<input type="hidden" name="id" id="id" value="<?php echo isset($detail['id']) ? $detail['id'] : ''; ?>" />
|
||
<h3 class="h3-title">处理工单</h3>
|
||
<table class="layui-table layui-table-form">
|
||
<tr>
|
||
<td class="layui-td-gray-2">分派处理人<font>*</font>
|
||
</td>
|
||
<td>
|
||
<select name="solve" lay-verify="required" lay-reqText="请选择处理人" class="layui-select" lay-search=""
|
||
lay-filter="solve" <?php if(isset($detail['status']) && ($detail['status']==2 || $detail['status']==3))
|
||
echo 'disabled' ; ?>>
|
||
<option value="">请选择处理人</option>
|
||
</select>
|
||
</td>
|
||
<td class="layui-td-gray-2">工单状态<font>*</font>
|
||
</td>
|
||
<td colspan="3">
|
||
<select name="status" lay-verify="required" lay-reqText="请选择工单状态" class="layui-select" id="status-select" <?php
|
||
if(isset($detail['status']) && $detail['status']==3) echo 'disabled' ; ?>>
|
||
<option value="">请选择工单状态</option>
|
||
<option value="1" <?php echo (isset($detail['status']) && $detail['status']==1) ? 'selected' : '' ; ?>>解决中
|
||
</option>
|
||
<option value="2" <?php echo (isset($detail['status']) && $detail['status']==2) ? 'selected' : '' ; ?>>已解决
|
||
</option>
|
||
<option value="3" <?php echo (isset($detail['status']) && $detail['status']==3) ? 'selected' : '' ; ?>>已关闭
|
||
</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<?php if (!isset($detail['status']) || $detail['status'] != 3): ?>
|
||
<div class="pt-1">
|
||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">
|
||
立即提交
|
||
</button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="wtjs-box">
|
||
<h3 class="h3-title">基础信息</h3>
|
||
<table class="layui-table layui-table-form">
|
||
<tr>
|
||
<td class="layui-td-gray-2">工单ID</td>
|
||
<td>
|
||
{$detail['id']}
|
||
</td>
|
||
<td class="layui-td-gray-2">项目工单ID</td>
|
||
<td>
|
||
{$detail['id']}
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="layui-td-gray-2">隶属项目</td>
|
||
<td>
|
||
{$detail['project_id']}
|
||
</td>
|
||
<td class="layui-td-gray-2">问题类型</td>
|
||
<td>
|
||
{$detail['problemtype']}
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="layui-td-gray-2">提交人</td>
|
||
<td>
|
||
{$detail['creater']}
|
||
</td>
|
||
<td class="layui-td-gray-2">联系电话</td>
|
||
<td>
|
||
{$detail['contact']}
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="layui-td-gray-2">电子邮箱</td>
|
||
<td>
|
||
{$detail['email']}
|
||
</td>
|
||
<td class="layui-td-gray-2">提交时间</td>
|
||
<td>
|
||
{$detail['sub_time']}
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="wtjs-box">
|
||
<h3 class="h3-title">问题</h3>
|
||
<div style="display: flex;gap: 15px;">
|
||
<div class="wtjs-content">
|
||
<h4>问题描述</h4>
|
||
<div id="workorder-content">
|
||
<?= $detail['content'] ?>
|
||
</div>
|
||
</div>
|
||
<div class="wtbz">
|
||
<h4>备注</h4>
|
||
<p>{$detail.remark}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="yhgt-box">
|
||
<h3 class="h3-title">用户沟通</h3>
|
||
<div style="display: flex;gap: 15px;">
|
||
<div class="yhgt-content">
|
||
<h4>用户留言</h4>
|
||
<div id="workorder-message">
|
||
<?= $detail['content'] ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- <table class="layui-table layui-table-form">
|
||
<tr>
|
||
<td class="layui-td-gray-2">项目问题</td>
|
||
<td>
|
||
<div id="workorder-content">
|
||
<?= $detail['content'] ?>
|
||
</div>
|
||
</td>
|
||
<td class="layui-td-gray-2">备注</td>
|
||
<td>{$detail.remark}</td>
|
||
</tr>
|
||
</table> -->
|
||
|
||
|
||
</form>
|
||
|
||
<script>
|
||
// 工具函数:获取URL参数
|
||
function getQueryParam(name) {
|
||
var params = new URLSearchParams(window.location.search);
|
||
return params.get(name) || '';
|
||
}
|
||
|
||
// 需要填充的字段
|
||
var fields = [
|
||
'id', 'project_id', 'problemtype', 'creater', 'contact', 'email', 'sub_time', 'remark', 'status'
|
||
];
|
||
|
||
// 页面内容填充
|
||
function fillFieldsFromUrl() {
|
||
fields.forEach(function (field) {
|
||
var value = getQueryParam(field);
|
||
var el = document.getElementById('workorder-' + field);
|
||
if (el) el.textContent = value;
|
||
// 隐藏input赋值
|
||
var inputEl = document.querySelector('input[name="' + field + '"]');
|
||
if (inputEl && !inputEl.value) inputEl.value = value;
|
||
});
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
fillFieldsFromUrl();
|
||
});
|
||
|
||
layui.use(['form', 'layer'], function () {
|
||
var form = layui.form,
|
||
layer = layui.layer;
|
||
|
||
// 1. 工单状态禁用逻辑
|
||
function handleStatusDisable() {
|
||
var status = getQueryParam('status') || "<?php echo isset($detail['status']) ? $detail['status'] : ''; ?>";
|
||
var statusNum = parseInt(status, 10);
|
||
|
||
// 仅当状态为3(已关闭)时才禁用下拉框
|
||
if (statusNum === 3) {
|
||
document.querySelector('select[name="status"]').disabled = true;
|
||
}
|
||
|
||
// 确保已解决状态可见
|
||
if (statusNum === 2) {
|
||
var statusSelect = document.getElementById('status-select');
|
||
Array.from(statusSelect.options).forEach(function (opt) {
|
||
opt.disabled = false;
|
||
opt.style.display = '';
|
||
});
|
||
}
|
||
}
|
||
|
||
// 2. 渲染处理人下拉框
|
||
function renderSolveSelect() {
|
||
fetch('/api/index/getallstaff')
|
||
.then((response) => response.json())
|
||
.then((data) => {
|
||
var select = document.querySelector('select[name="solve"]');
|
||
select.innerHTML = '<option value="">请选择处理人</option>';
|
||
var solveVal = getQueryParam('solve') || "<?php echo isset($detail['solve']) ? $detail['solve'] : ''; ?>";
|
||
var found = false;
|
||
data.data.forEach((solve) => {
|
||
var option = document.createElement('option');
|
||
option.value = solve.id;
|
||
option.innerText = solve.name;
|
||
if (String(solve.id) === String(solveVal)) {
|
||
option.selected = true;
|
||
found = true;
|
||
}
|
||
select.appendChild(option);
|
||
});
|
||
// 如果solve的值不在接口返回的列表中,手动添加一个option
|
||
if (solveVal && !found) {
|
||
var option = document.createElement('option');
|
||
option.value = solveVal;
|
||
// 这里可以显示solveVal本身,或者显示“未知处理人”
|
||
option.innerText = "<?php echo isset($detail['solve']) && isset($detail['solve_name']) ? $detail['solve_name'] : '未知处理人'; ?>";
|
||
option.selected = true;
|
||
select.appendChild(option);
|
||
}
|
||
form.render('select');
|
||
})
|
||
.catch((error) => {
|
||
console.error('Error fetching staff:', error);
|
||
});
|
||
}
|
||
|
||
// 3. 渲染工单状态
|
||
function renderStatusSelect() {
|
||
var statusVal = getQueryParam('status') || "<?php echo isset($detail['status']) ? $detail['status'] : ''; ?>";
|
||
if (statusVal) {
|
||
form.val('webform', {
|
||
status: String(statusVal)
|
||
});
|
||
}
|
||
}
|
||
|
||
// 4. 图片预览
|
||
layer.photos({
|
||
photos: '#workorder-content',
|
||
anim: 5
|
||
});
|
||
|
||
// 5. 初始化
|
||
handleStatusDisable();
|
||
renderSolveSelect();
|
||
renderStatusSelect();
|
||
|
||
// 6. 表单提交
|
||
form.on('submit(webform)', function (data) {
|
||
var id = getQueryParam('id');
|
||
fetch('/workorder/index/edit?id=' + id, {
|
||
method: 'POST',
|
||
body: JSON.stringify(data.field),
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
})
|
||
.then((response) => response.json())
|
||
.then((result) => {
|
||
layer.msg(result.msg);
|
||
if (result.code === 2) {
|
||
setTimeout(function () {
|
||
var index = parent.layer.getFrameIndex(window.name);
|
||
parent.layer.close(index);
|
||
parent.location.reload();
|
||
}, 1000);
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
});
|
||
|
||
//调取用户沟通信息
|
||
var order_id = getQueryParam('id') || "<?php echo isset($detail['id']) ? $detail['id'] : ''; ?>";
|
||
function loadUserMessages() {
|
||
if (!order_id) return;
|
||
fetch('/workorder/index/usermessagelist?order_id=' + order_id)
|
||
.then(response => response.json())
|
||
.then(res => {
|
||
var html = '';
|
||
if (res.code === 0 && Array.isArray(res.data)) {
|
||
res.data.forEach(function (msg) {
|
||
var who = '';
|
||
var labelClass = '';
|
||
var avatarClass = '';
|
||
var avatarText = '';
|
||
var userMsgClass = 'user-message';
|
||
if (msg.msgby == 1) {
|
||
who = '客户留言';
|
||
labelClass = 'msgby-customer';
|
||
avatarClass = 'avatar msgby-customer';
|
||
avatarText = '客';
|
||
// 客户留言不加 platform 类
|
||
} else if (msg.msgby == 0) {
|
||
who = '平台回复';
|
||
labelClass = 'msgby-platform';
|
||
avatarClass = 'avatar msgby-platform';
|
||
avatarText = '平';
|
||
userMsgClass += ' platform'; // 平台回复加 platform 类
|
||
} else {
|
||
who = '未知';
|
||
labelClass = '';
|
||
avatarClass = 'avatar';
|
||
avatarText = '?';
|
||
}
|
||
html += '<div class="' + userMsgClass + '">';
|
||
html += '<div class="msg-main">';
|
||
html += '<div><span class="msgby-label ' + labelClass + '">[' + who + ']</span>';
|
||
html += '<span class="msg-time">' + (msg.create_time || '') + '</span></div>';
|
||
html += '<div class="msg-content">' + (msg.content || '') + '</div>';
|
||
html += '<div class="msg-actions">';
|
||
if (msg.msgby == 1) {
|
||
html += '<button type="button" class="layui-btn layui-btn-xs reply-btn" data-msgid="' + msg.msg_id + '" data-orderid="' + msg.order_id + '">回复</button>';
|
||
}
|
||
if (msg.msgby == 0) {
|
||
html += '<button type="button" class="layui-btn layui-btn-xs layui-btn-danger delete-btn" data-msgid="' + msg.msg_id + '" data-orderid="' + msg.order_id + '">删除</button>';
|
||
}
|
||
html += '</div>';
|
||
html += '</div>';
|
||
html += '</div>';
|
||
});
|
||
}
|
||
if (!html) html = '<div style="color:#888;">暂无沟通信息</div>';
|
||
document.getElementById('workorder-message').innerHTML = html;
|
||
|
||
// 绑定回复按钮事件
|
||
var replyBtns = document.querySelectorAll('.reply-btn');
|
||
replyBtns.forEach(function (btn) {
|
||
btn.onclick = function () {
|
||
var msgid = this.getAttribute('data-msgid');
|
||
var orderid = this.getAttribute('data-orderid');
|
||
layer.prompt({ title: '回复客户', formType: 2 }, function (value, index) {
|
||
if (!value) {
|
||
layer.msg('回复内容不能为空');
|
||
return;
|
||
}
|
||
// 调用接口提交
|
||
fetch('/workorder/index/messageadd', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
order_id: orderid,
|
||
msg_id: msgid,
|
||
msgby: 0, // 平台回复
|
||
content: value
|
||
})
|
||
})
|
||
.then(res => res.json())
|
||
.then(resp => {
|
||
if (resp.code === 0) {
|
||
layer.msg('回复成功');
|
||
layer.close(index);
|
||
loadUserMessages();
|
||
} else {
|
||
layer.msg(resp.msg || '回复失败');
|
||
}
|
||
})
|
||
.catch(function () {
|
||
layer.msg('网络错误');
|
||
});
|
||
});
|
||
};
|
||
});
|
||
|
||
// 绑定删除按钮事件
|
||
var deleteBtns = document.querySelectorAll('.delete-btn');
|
||
deleteBtns.forEach(function (btn) {
|
||
btn.onclick = function () {
|
||
var msgid = this.getAttribute('data-msgid');
|
||
var order_id = this.getAttribute('data-orderid');
|
||
layer.confirm('确定要删除这条平台回复吗?', { icon: 3, title: '提示' }, function (index) {
|
||
fetch('/workorder/index/messagedel', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
msg_id: msgid,
|
||
order_id: order_id
|
||
})
|
||
})
|
||
.then(res => res.json())
|
||
.then(resp => {
|
||
if (resp.code === 0) {
|
||
layer.msg('删除成功');
|
||
loadUserMessages();
|
||
} else {
|
||
layer.msg(resp.msg || '删除失败');
|
||
}
|
||
})
|
||
.catch(function () {
|
||
layer.msg('网络错误');
|
||
});
|
||
layer.close(index);
|
||
});
|
||
};
|
||
});
|
||
})
|
||
.catch(function () {
|
||
document.getElementById('workorder-message').innerHTML = '<div style="color:#888;">加载沟通信息失败</div>';
|
||
});
|
||
}
|
||
|
||
// 页面加载时调用
|
||
loadUserMessages();
|
||
</script>
|
||
<style>
|
||
.page-content img {
|
||
padding: 15px 0;
|
||
}
|
||
|
||
.layui-layer-shade {
|
||
background-color: rgba(0, 0, 0, 0.5) !important;
|
||
}
|
||
|
||
.pt-1 {
|
||
margin-top: 15px;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 20px;
|
||
border-bottom: 1px solid #eee;
|
||
width: 100%;
|
||
}
|
||
|
||
.layui-table {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.wtjs-box,
|
||
.yhgt-box {
|
||
border: 1px solid #eee;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.wtjs-content {
|
||
border: 1px solid #eee;
|
||
width: 60%;
|
||
}
|
||
|
||
.yhgt-content {
|
||
border: 1px solid #eee;
|
||
width: 100%;
|
||
}
|
||
|
||
.wtbz {
|
||
border: 1px solid #eee;
|
||
width: 40%;
|
||
}
|
||
|
||
.wtjs-content,
|
||
.yhgt-content,
|
||
.wtbz {
|
||
padding: 15px;
|
||
background-color: #f8fafc;
|
||
}
|
||
|
||
.wtjs-box h4,
|
||
.yhgt-box h4 {
|
||
margin-bottom: 15px;
|
||
border-bottom: 1px solid #ddd;
|
||
padding-bottom: 15px;
|
||
color: #4b4b4b;
|
||
}
|
||
|
||
.user-message .msgby-label {
|
||
display: inline-block;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
margin-right: 8px;
|
||
}
|
||
|
||
.user-message .msgby-customer {
|
||
background: #e6f7ff;
|
||
color: #409eff;
|
||
}
|
||
|
||
.user-message .msgby-platform {
|
||
background: #f0f9eb;
|
||
color: #67c23a;
|
||
}
|
||
/* 留言区整体背景 */
|
||
.yhgt-content {
|
||
background: #f8fafc;
|
||
border-radius: 10px;
|
||
padding: 24px;
|
||
min-height: 120px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
||
}
|
||
|
||
/* 单条留言卡片 */
|
||
.user-message {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 16px;
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
|
||
padding: 16px 20px;
|
||
margin-bottom: 18px;
|
||
border: none;
|
||
position: relative;
|
||
transition: box-shadow 0.2s;
|
||
}
|
||
.user-message:hover {
|
||
box-shadow: 0 4px 16px rgba(0,0,0,0.10);
|
||
}
|
||
|
||
/* 气泡箭头 */
|
||
.user-message::before {
|
||
content: "";
|
||
display: block;
|
||
position: absolute;
|
||
left: -8px;
|
||
top: 24px;
|
||
width: 0;
|
||
height: 0;
|
||
border-top: 8px solid transparent;
|
||
border-bottom: 8px solid transparent;
|
||
border-right: 8px solid #fff;
|
||
}
|
||
|
||
/* 平台回复三角标在右 */
|
||
.user-message.platform {
|
||
flex-direction: row-reverse;
|
||
}
|
||
.user-message.platform::before {
|
||
left: auto;
|
||
right: -8px;
|
||
border-right: none;
|
||
border-left: 8px solid #fff;
|
||
}
|
||
.user-message.platform .avatar {
|
||
background: #f0f9eb;
|
||
color: #67c23a;
|
||
box-shadow: 0 1px 4px rgba(103,194,58,0.08);
|
||
}
|
||
|
||
/* 客户留言和平台回复头像 */
|
||
.user-message .avatar {
|
||
width: 38px;
|
||
height: 38px;
|
||
border-radius: 50%;
|
||
background: #e6f7ff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 18px;
|
||
color: #409eff;
|
||
font-weight: bold;
|
||
flex-shrink: 0;
|
||
box-shadow: 0 1px 4px rgba(64,158,255,0.08);
|
||
}
|
||
.user-message .msgby-platform.avatar {
|
||
background: #f0f9eb;
|
||
color: #67c23a;
|
||
box-shadow: 0 1px 4px rgba(103,194,58,0.08);
|
||
}
|
||
|
||
/* 留言内容主体 */
|
||
.user-message .msg-main {
|
||
flex: 1;
|
||
}
|
||
.user-message .msgby-label {
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
margin-right: 8px;
|
||
padding: 2px 10px;
|
||
border-radius: 12px;
|
||
vertical-align: middle;
|
||
}
|
||
.user-message .msgby-customer {
|
||
background: #e6f7ff;
|
||
color: #409eff;
|
||
}
|
||
.user-message .msgby-platform {
|
||
background: #f0f9eb;
|
||
color: #67c23a;
|
||
}
|
||
.user-message .msg-time {
|
||
color: #999;
|
||
font-size: 12px;
|
||
margin-bottom: 4px;
|
||
}
|
||
.user-message .msg-content {
|
||
font-size: 15px;
|
||
color: #333;
|
||
margin-bottom: 6px;
|
||
line-height: 1.7;
|
||
padding: 20px;
|
||
padding-left: 0;
|
||
}
|
||
|
||
/* 按钮区 */
|
||
.user-message .msg-actions {
|
||
margin-top: 8px;
|
||
}
|
||
.user-message .layui-btn-xs {
|
||
padding: 0 10px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.layui-td-gray, .layui-td-gray-2, .layui-td-gray-3, .layui-td-gray-4{
|
||
background-color:#f8fafc ;
|
||
}
|
||
</style> |