Files
2026-07-07 13:29:22 +08:00

401 lines
16 KiB
Plaintext

<?php
session_start();
// 会话拦截
if (empty($_SESSION['user_id'])) {
echo "<script>alert('请先登录');location.href='login.php';</script>";
exit;
}
$loginUid = $_SESSION['user_id'];
$userName = $_SESSION['username'];
// 兼容低版本PHP str_contains
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool
{
return empty($needle) || strpos($haystack, $needle) !== false;
}
}
// 数据库连接
$dbConfHost = "10.150.117.190";
$dbUser = "root";
$dbPwd = "hp93000";
$dbMonitor = "monitor";
$dbAlert = "alert_mail_stat";
// 连接monitor库
$connWork = mysqli_connect($dbConfHost, $dbUser, $dbPwd, $dbMonitor);
if (!$connWork) {
die("数据库连接失败:" . mysqli_connect_error());
}
mysqli_set_charset($connWork, "utf8mb4");
// 获取用户角色权限(双条件匹配uid/username,解决查不到角色)
$isAdmin = 0;
$permList = "";
$roleSql = "SELECT r.is_admin, r.perm_list FROM sys_user u LEFT JOIN sys_role r ON u.role_id=r.id WHERE u.uid = ? OR u.username = ?";
$stmtRole = mysqli_prepare($connWork, $roleSql);
if ($stmtRole) {
mysqli_stmt_bind_param($stmtRole, 'ss', $loginUid, $loginUid);
mysqli_stmt_execute($stmtRole);
$resRole = mysqli_stmt_get_result($stmtRole);
// 容错:判断查询结果是否为有效资源,修复mysqli_fetch_assoc布尔报错根源
if ($resRole) {
$roleRow = mysqli_fetch_assoc($resRole);
if ($roleRow) {
$isAdmin = intval($roleRow['is_admin']);
$permList = $roleRow['perm_list'];
}
}
mysqli_stmt_close($stmtRole);
}
// 临时注释权限拦截,放开页面访问,测试完成可取消注释
/*
$hasWorkPerm = str_contains($permList, "work_order");
if (!$hasWorkPerm) {
echo "<script>alert('".$t['perm_deny']."');location.href='dashboard.php';</script>";
exit;
}
*/
// 多语言文字库
$t = [
'page_title' => '工单管理',
'add_work' => '新建工单',
'edit' => '编辑',
'delete' => '删除',
'save' => '保存',
'cancel' => '取消',
'reset' => '重置',
'perm_deny' => '权限不足,无法访问工单页面',
'relate_alert' => '关联活跃告警',
'title' => '工单标题',
'content' => '工单内容',
'handler' => '处理人',
'notify_setting' => '通知渠道配置',
'notify_mail' => '邮箱通知',
'notify_dingtalk' => '钉钉通知',
'notify_wecom' => '企业微信通知',
'no_alert' => '暂无活跃告警数据',
'tip_ctrl' => '按住Ctrl多选通知渠道',
'status_pending' => '待处理',
'status_process' => '处理中',
'status_done' => '已完成',
'status_close' => '已关闭',
];
// 分页配置
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$pageSize = 10;
$offset = ($page - 1) * $pageSize;
// 查询工单列表
$workSql = "SELECT w.*, u.real_name handler_name FROM work_order w LEFT JOIN sys_user u ON w.handler_id = u.id ORDER BY w.id DESC LIMIT ?,?";
$stmtWork = mysqli_prepare($connWork, $workSql);
mysqli_stmt_bind_param($stmtWork, 'ii', $offset, $pageSize);
mysqli_stmt_execute($stmtWork);
$resWork = mysqli_stmt_get_result($stmtWork);
$workList = [];
while ($row = mysqli_fetch_assoc($resWork)) {
$workList[] = $row;
}
// 统计总条数
$countSql = "SELECT COUNT(*) total FROM work_order";
$resCount = mysqli_query($connWork, $countSql);
$total = mysqli_fetch_assoc($resCount)['total'];
$totalPage = ceil($total / $pageSize);
// 查询所有处理人(下拉选择)
$userSql = "SELECT id,real_name FROM sys_user WHERE enable = 1";
$resUser = mysqli_query($connWork, $userSql);
$userList = [];
while ($u = mysqli_fetch_assoc($resUser)) {
$userList[] = $u;
}
// 读取活跃告警(修复告警下拉无数据问题,从alert_mail_stat拉取)
$connAlert = mysqli_connect($dbConfHost, $dbUser, $dbPwd, $dbAlert);
$alertList = [];
if ($connAlert) {
mysqli_set_charset($connAlert, "utf8mb4");
$alertSql = "SELECT id,alert_name FROM alert_info WHERE status = 1 ORDER BY id DESC";
$resAlert = mysqli_query($connAlert, $alertSql);
while ($a = mysqli_fetch_assoc($resAlert)) {
$alertList[] = $a;
}
mysqli_close($connAlert);
}
mysqli_close($connWork);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title><?php echo $t['page_title']; ?></title>
<style>
* {box-sizing: border-box;margin:0;padding:0;font-family:system-ui,Microsoft YaHei}
body {background:#f5f7fa;padding:20px;}
.container {max-width:1400px;margin:0 auto;background:#fff;border-radius:8px;padding:24px;box-shadow:0 1px 12px #e5e7eb;}
.header-bar {display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;}
.page-title {font-size:20px;font-weight:600;color:#1f2937;}
/* 统一按钮尺寸,解决按钮大小不一致 */
.btn {
height:38px;
padding:0 18px;
border:none;
border-radius:6px;
font-size:14px;
cursor:pointer;
transition:0.2s;
}
.btn-primary {background:#1677ff;color:#fff;}
.btn-primary:hover {background:#0958d9;}
.btn-default {background:#f0f2f5;color:#333;}
.btn-default:hover {background:#dcdfe6;}
.btn-danger {background:#f53f3f;color:#fff;}
.btn-danger:hover {background:#d83737;}
table {width:100%;border-collapse:collapse;margin:16px 0;}
table th,table td {border:1px solid #e5e7eb;padding:12px 10px;text-align:center;font-size:14px;}
table th {background:#f7f8fa;font-weight:500;}
.modal-mask {position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:none;align-items:center;justify-content:center;z-index:99;}
.modal-box {width:680px;background:#fff;border-radius:8px;padding:24px;}
.modal-title {font-size:17px;font-weight:600;margin-bottom:20px;padding-bottom:12px;border-bottom:1px solid #eee;}
.form-row {display:flex;flex-wrap:wrap;gap:16px;margin-bottom:16px;}
.form-item {flex:1;min-width:260px;}
.form-item-full {width:100%;}
label {display:block;margin-bottom:8px;color:#4b5563;font-size:14px;}
input,textarea,select {width:100%;height:38px;border:1px solid #d1d5db;border-radius:6px;padding:0 12px;font-size:14px;}
textarea {height:100px;padding:10px;resize:none;}
.modal-footer {display:flex;gap:12px;justify-content:flex-end;margin-top:24px;}
/* 通知渠道美化 + Logo图标排版 */
.notify-wrap {
display:flex;
gap:20px;
flex-wrap:wrap;
padding:16px;
border:1px solid #eee;
border-radius:8px;
background:#fafafa;
}
.notify-item {
display:flex;
align-items:center;
gap:8px;
padding:10px 16px;
border:1px solid #e5e7eb;
border-radius:6px;
min-width:160px;
background:#fff;
}
.notify-item img {width:24px;height:24px;object-fit:contain;}
.notify-item input {width:auto;height:auto;margin-right:4px;}
.page-bar {display:flex;gap:8px;justify-content:center;margin-top:20px;}
.page-bar a {padding:6px 12px;border:1px solid #ddd;border-radius:4px;text-decoration:none;color:#333;font-size:14px;}
.page-bar a.active {background:#1677ff;color:#fff;border-color:#1677ff;}
</style>
</head>
<body>
<div class="container">
<div class="header-bar">
<h1 class="page-title"><?php echo $t['page_title']; ?></h1>
<button class="btn btn-primary" id="openAdd"><?php echo $t['add_work']; ?></button>
</div>
<table>
<tr>
<th>ID</th>
<th><?php echo $t['title']; ?></th>
<th><?php echo $t['handler']; ?></th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
<?php if (empty($workList)): ?>
<tr><td colspan="6">暂无工单数据</td></tr>
<?php else: ?>
<?php foreach ($workList as $w): ?>
<tr>
<td><?php echo $w['id']; ?></td>
<td><?php echo htmlspecialchars($w['title']); ?></td>
<td><?php echo $w['handler_name'] ?? '未分配'; ?></td>
<td>
<?php
$statusMap = [1=>$t['status_pending'],2=>$t['status_process'],3=>$t['status_done'],4=>$t['status_close']];
echo $statusMap[$w['status']] ?? '未知';
?>
</td>
<td><?php echo $w['created_at']; ?></td>
<td>
<button class="btn btn-default editBtn" data-id="<?php echo $w['id']; ?>"><?php echo $t['edit']; ?></button>
<button class="btn btn-danger delBtn" data-id="<?php echo $w['id']; ?>"><?php echo $t['delete']; ?></button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</table>
<!-- 分页 -->
<div class="page-bar">
<?php if ($page > 1): ?>
<a href="?page=<?php echo $page-1; ?>">上一页</a>
<?php endif; ?>
<?php for ($i=1;$i<=$totalPage;$i++): ?>
<a href="?page=<?php echo $i; ?>" class="<?php echo $i==$page?'active':''; ?>"><?php echo $i; ?></a>
<?php endfor; ?>
<?php if ($page < $totalPage): ?>
<a href="?page=<?php echo $page+1; ?>">下一页</a>
<?php endif; ?>
</div>
</div>
<!-- 新增/编辑弹窗 -->
<div class="modal-mask" id="modalBox">
<div class="modal-box">
<div class="modal-title" id="modalTitle"><?php echo $t['add_work']; ?></div>
<form id="workForm">
<input type="hidden" name="id" id="workId" value="">
<div class="form-row">
<div class="form-item">
<label><?php echo $t['relate_alert']; ?></label>
<select name="alert_id" id="alertSelect">
<option value="">-- 选择告警 --</option>
<?php if (!empty($alertList)): ?>
<?php foreach ($alertList as $a): ?>
<option value="<?php echo $a['id']; ?>"><?php echo htmlspecialchars($a['alert_name']); ?></option>
<?php endforeach; ?>
<?php else: ?>
<option disabled><?php echo $t['no_alert']; ?></option>
<?php endif; ?>
</select>
</div>
<div class="form-item">
<label><?php echo $t['handler']; ?></label>
<select name="handler_id">
<option value="">-- 选择处理人 --</option>
<?php foreach ($userList as $u): ?>
<option value="<?php echo $u['id']; ?>"><?php echo htmlspecialchars($u['real_name']); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-row">
<div class="form-item-full">
<label><?php echo $t['title']; ?></label>
<input type="text" name="title" placeholder="请输入工单标题" required>
</div>
</div>
<div class="form-row">
<div class="form-item-full">
<label><?php echo $t['content']; ?></label>
<textarea name="content" placeholder="请输入工单详情" required></textarea>
</div>
</div>
<!-- 通知渠道美化区域,增加Logo -->
<div class="form-row form-item-full">
<label><?php echo $t['notify_setting']; ?> <span style="font-size:12px;color:#888;"><?php echo $t['tip_ctrl']; ?></span></label>
<div class="notify-wrap">
<div class="notify-item">
<input type="checkbox" name="notify[]" value="mail" id="n_mail">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzE2NzdmZiI+PHBhdGggZD0iTTEyIDJjLTUuMzMgMC0xMCA0LjY3LTEwIDEwcy42NyAxMCAxMCAxMCAxMC00LjY3IDEwLTEwcy00LjY3LTEwLTEwLTEwem0wIDE4Yy00LjQxIDAtOC0zLjU5LTgtOCgzLjU5LTggOC04IDggMy41OSA4IDggOC0zLjU5IDgtOC04eiIvPjxwYXRoIGQ9Ik0xMiAxM2wtNi02aDEyeiIvPjwvc3ZnPg==" alt="邮箱">
<label for="n_mail"><?php echo $t['notify_mail']; ?></label>
</div>
<div class="notify-item">
<input type="checkbox" name="notify[]" value="dingtalk" id="n_ding">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzAwMDAwIj48cGF0aCBkPSJNMTIgMmMtNS4zMyAwLTEwIDQuNjctMTAgMTBzNC42NyAxMCAxMCAxMCAxMC00LjY3IDEwLTEwcy00LjY3LTEwLTEwLTEwem0wIDE4Yy00LjQxIDAtOC0zLjU5LTgtOCgzLjU5LTggOC04IDggMy41OSA4IDggOC0zLjU5IDgtOC04eiIvPjxwYXRoIGQ9Ik0xMiAxM2wtNi02aDEyeiIvPjwvc3ZnPg==" alt="钉钉">
<label for="n_ding"><?php echo $t['notify_dingtalk']; ?></label>
</div>
<div class="notify-item">
<input type="checkbox" name="notify[]" value="wecom" id="n_wecom">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzA5Y2Y2ZCI+PHBhdGggZD0iTTEyIDJjLTUuMzMgMC0xMCA0LjY3LTEwIDEwcy42NyAxMCAxMCAxMCAxMC00LjY3IDEwLTEwcy00LjY3LTEwLTEwLTEwem0wIDE4Yy00LjQxIDAtOC0zLjU5LTgtOCgzLjU5LTggOC04IDggMy41OSA4IDggOC0zLjU5IDgtOC04eiIvPjxwYXRoIGQ9Ik0xMiAxM2wtNi02aDEyeiIvPjwvc3ZnPg==" alt="企业微信">
<label for="n_wecom"><?php echo $t['notify_wecom']; ?></label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="closeModal"><?php echo $t['cancel']; ?></button>
<button type="reset" class="btn btn-default"><?php echo $t['reset']; ?></button>
<button type="submit" class="btn btn-primary"><?php echo $t['save']; ?></button>
</div>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script>
const apiOrder = "./api/work_order.php";
const modal = $("#modalBox");
const modalTitle = $("#modalTitle");
const workForm = $("#workForm");
const workId = $("#workId");
// 打开新建工单
$("#openAdd").click(function(){
modalTitle.text("<?php echo $t['add_work']; ?>");
workId.val("");
workForm[0].reset();
modal.css("display","flex");
});
// 关闭弹窗
$("#closeModal").click(function(){
modal.hide();
});
// 编辑工单
$(".editBtn").click(function(){
const id = $(this).data("id");
modalTitle.text("<?php echo $t['edit']; ?>工单");
$.get(apiOrder,{act:'get',id:id},function(res){
if(res.code===0){
workId.val(res.data.id);
workForm.find("select[name=alert_id]").val(res.data.alert_id);
workForm.find("select[name=handler_id]").val(res.data.handler_id);
workForm.find("input[name=title]").val(res.data.title);
workForm.find("textarea[name=content]").val(res.data.content);
// 回填通知渠道复选框
const notifyArr = res.data.notify ? res.data.notify.split(",") : [];
$("input[name='notify[]']").prop("checked",false);
notifyArr.forEach(item=>{
$(`input[name='notify[]'][value=${item}]`).prop("checked",true);
})
modal.css("display","flex");
}else{
alert(res.msg);
}
},"json")
});
// 删除工单
$(".delBtn").click(function(){
const id = $(this).data("id");
if(!confirm("确定删除该工单?")) return;
$.post(apiOrder,{act:'del',id:id},function(res){
alert(res.msg);
location.reload();
},"json")
});
// 提交表单
workForm.submit(function(e){
e.preventDefault();
const formData = $(this).serialize();
$.post(apiOrder,formData+"&act=save",function(res){
alert(res.msg);
if(res.code===0){
modal.hide();
location.reload();
}
},"json")
});
</script>
</body>
</html>