fix: 添加isAdmin字段到UserInfoVO,修复管理员抢单权限

This commit is contained in:
Your Name 2026-01-04 10:03:40 +08:00
parent 2a91ffd908
commit 3161ebfd59
4 changed files with 104 additions and 10 deletions

View File

@ -942,10 +942,11 @@ public class UserService {
.roles(roleCodes)
.status(user.getStatus())
.isDepartmentLeader(isDepartmentLeader)
.isAdmin(user.getIsAdmin())
.build();
log.info("getUserInfoByToken - 返回VO: id={}, deptId={}, deptName={}, roleIds={}, roles={}, isDepartmentLeader={}",
userInfoVO.getId(), userInfoVO.getDeptId(), userInfoVO.getDeptName(), userInfoVO.getRoleIds(), roleCodes, isDepartmentLeader);
log.info("getUserInfoByToken - 返回VO: id={}, deptId={}, deptName={}, roleIds={}, roles={}, isDepartmentLeader={}, isAdmin={}",
userInfoVO.getId(), userInfoVO.getDeptId(), userInfoVO.getDeptName(), userInfoVO.getRoleIds(), roleCodes, isDepartmentLeader, user.getIsAdmin());
return userInfoVO;
}

View File

@ -80,5 +80,10 @@ public class UserInfoVO {
* 是否为部门负责人:0-否 1-是
*/
private Integer isDepartmentLeader;
/**
* 是否为管理员:0-否 1-是
*/
private Integer isAdmin;
}

View File

@ -211,7 +211,7 @@
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'rank'">
<span class="rank-badge" :class="getRankClass(index + 1)">
{{ index === 0 ? '🥇' : index === 1 ? '🥈' : index === 2 ? '🥉' : index + 1 }}
{{ index + 1 }}
</span>
</template>
<template v-else-if="column.key === 'onTimeRate'">
@ -803,8 +803,85 @@ const getWarningActionText = (type: string) => {
}
}
// 导出数据为 CSV
const exportData = () => {
message.info('导出功能开发中...')
const monthStr = selectedMonth.value || dayjs().format('YYYY-MM')
let csvContent = '\uFEFF' // BOM for UTF-8 encoding
// 1. 概览数据
csvContent += '【核心指标概览】\n'
csvContent += '指标,数值\n'
csvContent += `总任务数,${overview.value.totalDemands}\n`
csvContent += `待处理,${overview.value.pendingDemands}\n`
csvContent += `进行中,${inProgressCount.value}\n`
csvContent += `已完成,${overview.value.completedDemands}\n`
csvContent += `完成率,${completionRate.value}%\n`
csvContent += `准时率,${onTimeRate.value}%\n`
csvContent += '\n'
// 2. 用户需求统计
if (statistics.userStats && statistics.userStats.length > 0) {
csvContent += '【用户需求统计】\n'
csvContent += '排名,用户名,部门,发起数,完成数,总积分,完成率\n'
statistics.userStats.forEach((user: any, index: number) => {
const rate = user.totalDemands > 0 ? ((user.completedDemands / user.totalDemands) * 100).toFixed(1) : '0.0'
csvContent += `${index + 1},${user.userName || '-'},${user.deptName || '-'},${user.totalDemands},${user.completedDemands},${user.totalScore || 0},${rate}%\n`
})
csvContent += '\n'
}
// 3. 部门需求统计
if (statistics.deptStats && statistics.deptStats.length > 0) {
csvContent += '【部门需求统计】\n'
csvContent += '排名,部门名称,发起数,完成数,完成率\n'
statistics.deptStats.forEach((dept: any, index: number) => {
const rate = dept.totalDemands > 0 ? ((dept.completedDemands / dept.totalDemands) * 100).toFixed(1) : '0.0'
csvContent += `${index + 1},${dept.deptName || '-'},${dept.totalDemands},${dept.completedDemands},${rate}%\n`
})
csvContent += '\n'
}
// 4. 设计师绩效
if (designerPerformance.designerStats && designerPerformance.designerStats.length > 0) {
csvContent += '【设计师绩效】\n'
csvContent += '排名,设计师,部门,接单量,完成量,完成率,准时率,评分\n'
designerPerformance.designerStats.forEach((designer: any, index: number) => {
csvContent += `${index + 1},${designer.realName || '-'},${designer.deptName || '-'},${designer.receivedCount || 0},${designer.completedCount || 0},${designer.completionRate || 0}%,${designer.onTimeRate || 0}%,${designer.avgRating?.toFixed(1) || '-'}\n`
})
csvContent += '\n'
}
// 5. 流程效率指标
csvContent += '【流程效率指标】\n'
csvContent += '指标,本周,上周,本月,目标\n'
efficiencyTableData.value.forEach((row: any) => {
csvContent += `${row.metric},${row.week},${row.lastWeek},${row.month},${row.target}\n`
})
csvContent += '\n'
// 6. 预警任务
if (warningTasks.value && warningTasks.value.length > 0) {
csvContent += '【预警任务】\n'
csvContent += '级别,任务名称,处理人,预警原因\n'
warningTasks.value.forEach((task: any) => {
const level = task.warningLevel === 'urgent' ? '紧急' : task.warningLevel === 'warning' ? '警告' : '正常'
csvContent += `${level},${task.taskTitle || '-'},${task.receiverName || '-'},${task.warningReason || '-'}\n`
})
csvContent += '\n'
}
// 创建并下载文件
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `数据分析报表_${monthStr}.csv`
link.style.display = 'none'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(link.href)
message.success('报表导出成功')
}
onMounted(() => {
@ -1194,10 +1271,10 @@ onMounted(() => {
.ant-table-thead > tr > th {
background: transparent !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.05) !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.02) !important;
color: $text-secondary !important;
font-weight: 500;
padding: 16px;
padding: 16px 24px;
&::before {
display: none !important; // 移除表头分割线
@ -1205,14 +1282,20 @@ onMounted(() => {
}
.ant-table-tbody > tr > td {
border-bottom: 1px solid rgba(255, 255, 255, 0.02) !important;
padding: 16px;
border-bottom: none !important; // 彻底移除分割线
padding: 16px 24px;
color: $text-primary;
transition: background 0.3s;
transition: background 0.3s ease;
}
// 极柔和的悬停效果,避免闪白
.ant-table-tbody > tr:hover > td {
background: rgba(255, 255, 255, 0.03) !important;
background: rgba(255, 255, 255, 0.02) !important;
}
// 偶数行增加极淡的背景,形成斑马纹,替代分割线
.ant-table-tbody > tr:nth-child(even) > td {
background: rgba(255, 255, 255, 0.005);
}
// 移除所有垂直边框

View File

@ -3564,6 +3564,11 @@ const canGrabTask = (task: TaskOrSubTask) => {
const userDeptId = userInfo.deptId
const userDeptType = userInfo.deptType // 'demand' 或 'receiving'
// 管理员拥有所有权限,可以直接抢单
if (userInfo.isAdmin === 1 || userInfo.isAdmin === true) {
return { canGrab: true, reason: '' }
}
// 检查1:没有部门不能抢单
if (!userDeptId) {
return { canGrab: false, reason: '您未分配部门,无法接单' }