fix: 添加isAdmin字段到UserInfoVO,修复管理员抢单权限
This commit is contained in:
parent
2a91ffd908
commit
3161ebfd59
@ -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;
|
||||
}
|
||||
|
||||
@ -80,5 +80,10 @@ public class UserInfoVO {
|
||||
* 是否为部门负责人:0-否 1-是
|
||||
*/
|
||||
private Integer isDepartmentLeader;
|
||||
|
||||
/**
|
||||
* 是否为管理员:0-否 1-是
|
||||
*/
|
||||
private Integer isAdmin;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
// 移除所有垂直边框
|
||||
|
||||
@ -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: '您未分配部门,无法接单' }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user