修复权限管理,角色认证,更新工单认领系统,增加表格导出支持区间选择,增加docker管理(开发中

This commit is contained in:
2026-07-09 10:06:44 +08:00
parent 0c2fe393df
commit 3b84698fd3
25 changed files with 8975 additions and 102 deletions
+87 -29
View File
@@ -4,6 +4,8 @@ header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache");
header("Expires: Thu, 01 Jan 1970 00:00:00 GMT");
require_once 'auth.php';
// 兼容低PHP版本 str_contains
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
@@ -21,6 +23,8 @@ $_SESSION['login_time'] = time();
$userName = htmlspecialchars($_SESSION['username']);
$userRoleId = $_SESSION['role_id'];
$loginUid = $_SESSION['user_id'];
// 修复:auth.php 必须输出 $roleRealName,若无则临时赋值避免报错
$roleRealName = $_SESSION['roleRealName'] ?? '';
// 全局配置库连接
$dbConfigHost = "10.150.117.190";
@@ -116,7 +120,9 @@ $langMap = [
'no_user_data' => '无可用用户',
'perm_deny' => '权限不足,禁止访问',
'unread_ticket' => '未读工单',
'mark_all_read' => '全部标记已读'
'mark_all_read' => '全部标记已读',
'claim_ticket' => '认领工单',
'claim_man' => '认领人'
],
'en' => [
'html_lang' => 'en',
@@ -177,7 +183,9 @@ $langMap = [
'no_user_data' => 'No available users',
'perm_deny' => 'Permission denied',
'unread_ticket' => 'Unread Tickets',
'mark_all_read' => 'Mark All Read'
'mark_all_read' => 'Mark All Read',
'claim_ticket' => 'Claim Ticket',
'claim_man' => 'Claimer'
]
];
$t = $langMap[$currentLang];
@@ -210,7 +218,9 @@ mysqli_set_charset($connWork, "utf8mb4");
// 获取用户角色权限
$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 = ?";
$roleId = 0;
$allowPages = [];
$roleSql = "SELECT r.is_admin, r.perm_list, u.role_id FROM sys_user u LEFT JOIN sys_role r ON u.role_id=r.id WHERE u.uid = ?";
$stmtRole = mysqli_prepare($connWork, $roleSql);
if($stmtRole){
mysqli_stmt_bind_param($stmtRole, 's', $loginUid);
@@ -221,10 +231,23 @@ if($stmtRole){
if ($roleRow) {
$isAdmin = intval($roleRow['is_admin']);
$permList = $roleRow['perm_list'];
$roleId = intval($roleRow['role_id'] ?? 0);
}
}
}
// 读取当前角色页面权限列表(修复分发下拉判断缺失变量)
if ($roleId > 0) {
$permSql = "SELECT page_key FROM sys_role_perm WHERE role_id = ?";
$stmtPerm = mysqli_prepare($connWork, $permSql);
mysqli_stmt_bind_param($stmtPerm, 'i', $roleId);
mysqli_stmt_execute($stmtPerm);
$pRes = mysqli_stmt_get_result($stmtPerm);
while ($p = mysqli_fetch_assoc($pRes)) {
$allowPages[] = $p['page_key'];
}
}
// 权限校验临时注释,如需开启取消注释
//$hasWorkPerm = str_contains($permList, "work_order");
//if (!$hasWorkPerm) {
@@ -258,22 +281,16 @@ $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$pageSize = intval($sysConfig['page_size'] ?? 20);
if ($pageSize < 1) $pageSize = 20;
$offset = ($page - 1) * $pageSize;
// ========== 修复1:数据权限过滤 普通用户仅展示创建/分配给自己工单,参数绑定修复 ==========
if ($isAdmin === 1) {
$whereSql = " 1=1 ";
} else {
$whereSql = " (create_uid = ? OR assign_uid = ?) ";
}
// 所有人查看全部工单,不再按uid过滤
$whereSql = " 1=1 ";
$bindType = "ii";
$bindData = [$offset, $pageSize];
// 统计工单总数
$cntSql = "SELECT COUNT(*) total FROM work_order WHERE " . $whereSql;
$stmtCnt = mysqli_prepare($connWork, $cntSql);
$total = 0;
if($stmtCnt){
if ($isAdmin !== 1) {
mysqli_stmt_bind_param($stmtCnt, 'ss', $loginUid, $loginUid);
}
mysqli_stmt_execute($stmtCnt);
$cntRes = mysqli_stmt_get_result($stmtCnt);
if ($cntRes instanceof mysqli_result) {
@@ -283,21 +300,20 @@ if($stmtCnt){
}
$totalPage = $pageSize <= 0 ? 1 : ceil($total / $pageSize);
// 查询工单列表带出is_read未读标记)
$listSql = "SELECT wo.*, uc.real_name create_name, ua.real_name assign_name
// 查询工单列表带出认领人信息
$listSql = "SELECT wo.*,
uc.real_name create_name,
ua.real_name assign_name,
uu.real_name claim_name
FROM work_order wo
LEFT JOIN sys_user uc ON wo.create_uid = uc.uid
LEFT JOIN sys_user ua ON wo.assign_uid = ua.uid
LEFT JOIN sys_user uu ON wo.claim_uid = uu.uid
WHERE " . $whereSql . " ORDER BY create_time DESC LIMIT ?, ?";
$stmtList = mysqli_prepare($connWork, $listSql);
$orderList = [];
if($stmtList){
if ($isAdmin === 1) {
mysqli_stmt_bind_param($stmtList, 'ii', $offset, $pageSize);
} else {
// 修复参数绑定:2个字符串uid + 2个数字分页参数
mysqli_stmt_bind_param($stmtList, 'ssii', $loginUid, $loginUid, $offset, $pageSize);
}
mysqli_stmt_bind_param($stmtList, $bindType, ...$bindData);
mysqli_stmt_execute($stmtList);
$listResult = mysqli_stmt_get_result($stmtList);
if ($listResult instanceof mysqli_result) {
@@ -453,7 +469,7 @@ tr.unread-row{background:#fff3f3 !important;}
<i class="fa fa-bell-o"></i>
<?php if($unreadCount > 0):?><span><?php echo $unreadCount; ?></span><?php endif;?>
</span>
<span class="user-info"><i class="fa fa-user-circle"></i><?php echo $t['current_user']; ?><?php echo $userName; ?></span>
<span class="user-info"><i class="fa fa-user-circle"></i><?php echo $t['current_user']; ?><?php echo $userName; ?><?php echo $roleRealName; ?></span>
<span class="time-info"><i class="fa fa-clock-o"></i><span id="nowTime">--</span></span>
<div class="lang-box">
<select id="langSwitch">
@@ -486,13 +502,14 @@ tr.unread-row{background:#fff3f3 !important;}
<th><i class="fa fa-tag"></i><?php echo $t['work_status']; ?></th>
<th><i class="fa fa-calendar-o"></i><?php echo $t['create_time']; ?></th>
<th><i class="fa fa-clock-o"></i><?php echo $t['update_time']; ?></th>
<th><i class="fa fa-user-circle-o"></i><?php echo $t['claim_man']; ?></th>
<th>OP</th>
</tr>
</thead>
<tbody>
<?php if (count($orderList) === 0): ?>
<tr>
<td colspan="9">
<td colspan="10">
<div class="empty-tip">
<i class="fa fa-ticket"></i>
<div><?php echo $t['no_work_data']; ?></div>
@@ -510,6 +527,8 @@ tr.unread-row{background:#fff3f3 !important;}
case 4:$statusText=$t['status_4'];$statusClass='tag-closed';break;
}
$rowClass = $item['is_read'] == 0 && $item['assign_uid'] == $loginUid ? 'unread-row' : '';
// 操作权限:管理员 或 当前登录用户是认领人
$canOperate = ($isAdmin === 1 || $item['claim_uid'] === $loginUid);
?>
<tr class="<?php echo $rowClass; ?>"
data-id="<?php echo $item['id']; ?>"
@@ -529,20 +548,33 @@ tr.unread-row{background:#fff3f3 !important;}
<td><span class="status-tag <?php echo $statusClass; ?>"><?php echo $statusText; ?></span></td>
<td><?php echo $item['create_time']; ?></td>
<td><?php echo $item['update_time'] ?? '-'; ?></td>
<td style="display:flex;gap:6px;align-items:center;">
<?php if ($isAdmin === 1): ?>
<!-- 认领人列 -->
<td><?php echo $item['claim_name'] ?? '-'; ?></td>
<!-- 操作栏 -->
<td style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;">
<?php if ($isAdmin === 1 || in_array("system_manage", $allowPages)): ?>
<select class="assign-user select-sm">
<option value="">--</option>
<?php echo $userOptions; ?>
</select>
<?php endif; ?>
<select class="status-select select-sm">
<?php if (empty($item['claim_uid'])): ?>
<button class="btn-base btn-sm btn-success claim-order" data-id="<?php echo $item['id']; ?>">
<i class="fa fa-hand-paper-o"></i><?php echo $t['claim_ticket']; ?>
</button>
<?php endif; ?>
<select class="status-select select-sm" <?php if(!$canOperate) echo "disabled"; ?>>
<option value="1" <?php echo $item['status']==1?'selected':''; ?>><?php echo $t['status_1']; ?></option>
<option value="2" <?php echo $item['status']==2?'selected':''; ?>><?php echo $t['status_2']; ?></option>
<option value="3" <?php echo $item['status']==3?'selected':''; ?>><?php echo $t['status_3']; ?></option>
<option value="4" <?php echo $item['status']==4?'selected':''; ?>><?php echo $t['status_4']; ?></option>
</select>
<button class="btn-base btn-outline btn-sm edit-order"><i class="fa fa-edit"></i><?php echo $t['work_edit']; ?></button>
<button class="btn-base btn-outline btn-sm edit-order" <?php if(!$canOperate) echo "disabled"; ?>>
<i class="fa fa-edit"></i><?php echo $t['work_edit']; ?>
</button>
</td>
</tr>
<?php endforeach; ?>
@@ -734,7 +766,7 @@ function loadFiringAlert(selSelector, bindId=""){
const sel = $(selSelector);
sel.html(`<option value="">-- <?php echo $t['no_alert_option']; ?> --</option>`);
list.forEach(item=>{
const aid = `${item.alert_name}|${item.instance}`;
const aid = `${item.alert_name}_${item.instance}`;
sel.append(`<option value="${aid}" data-name="${item.alert_name}" data-ip="${item.instance}">
[${item.instance}] ${item.alert_name}
</option>`);
@@ -781,6 +813,7 @@ $("#closeEditModal,#cancelEdit").click(function(){
$("#editModal").hide();
});
// 编辑工单弹窗填充
$(document).on("click", ".edit-order", function(){
const tr = $(this).closest("tr");
$("#editOrderId").val(tr.data("id"));
@@ -801,6 +834,8 @@ $(document).on("click", ".edit-order", function(){
loadFiringAlert("#editRelateAlertSelect", relateAid);
$("#editModal").css("display","flex");
});
// 新建工单提交
$("#submitOrder").click(function(){
const title = $("#orderTitle").val().trim();
const content = $("#orderContent").val().trim();
@@ -898,7 +933,7 @@ $(document).on("change", ".status-select", function(){
});
});
// 管理员分发工单(修复只修改当前行单条ID,不再匹配标题批量更新)
// 管理员分发工单
$(document).on("change", ".assign-user", function(){
const tr = $(this).closest("tr");
const orderId = tr.data("id");
@@ -920,6 +955,29 @@ $(document).on("change", ".assign-user", function(){
});
});
// 工单认领
$(document).on("click", ".claim-order", function(){
const orderId = $(this).data("id");
if(!confirm(currentLang==="zh"?"确认认领该工单?":"Confirm claim this order?")) return;
$.ajax({
url: apiOrder + "?action=claim_work",
method: "POST",
contentType: "application/json",
data: JSON.stringify({
id: orderId,
uid: loginUid
}),
dataType: "json",
success(res){
alert(res.msg);
if(res.code === 0) location.reload();
},
error(){
alert(currentLang==='zh'?"认领请求失败":"Claim failed");
}
});
});
// 一键标记全部当前用户待处理工单为已读
$("#markAllRead").click(function(){
$.ajax({