Industrial-image-management.../src/views/task/task-approval/TaskApproval.vue

350 lines
8.0 KiB
Vue
Raw Normal View History

2025-08-13 10:07:11 +08:00
<template>
<GiPageLayout>
<div class="task-approval-page">
<div class="page-header">
<h2>任务审批</h2>
<p class="page-description">审批转交的任务</p>
</div>
2025-08-13 10:24:24 +08:00
<!-- 状态汇总改为左边文字右边数字布局 -->
2025-08-13 10:07:11 +08:00
<div class="status-summary">
<div
class="status-item pending"
@click="activeTab = 'pending'"
:class="{ active: activeTab === 'pending' }"
>
<span class="status-text">待审批</span>
<span class="count">{{ pendingCount }}</span>
</div>
<div
class="status-item approved"
@click="activeTab = 'approved'"
:class="{ active: activeTab === 'approved' }"
>
<span class="status-text">已通过</span>
<span class="count">{{ approvedCount }}</span>
</div>
<div
class="status-item rejected"
@click="activeTab = 'rejected'"
:class="{ active: activeTab === 'rejected' }"
>
<span class="status-text">已拒绝</span>
<span class="count">{{ rejectedCount }}</span>
</div>
</div>
<div class="content">
<div class="task-list">
<!-- 根据激活的标签渲染对应状态的任务 -->
<div
class="task-item"
v-for="task in filteredTasks"
:key="task.id"
>
<div class="task-header">
<h3>{{ task.title }}</h3>
<span
class="task-status"
:class="task.status"
>
{{
task.status === 'pending' ? '待审批' :
task.status === 'approved' ? '已通过' : '已拒绝'
}}
</span>
</div>
<p class="task-description">{{ task.description }}</p>
<div class="transfer-info">
<div class="info-item">
<span class="label">转交人:</span>
<span>{{ task.from }}</span>
</div>
<div class="info-item">
<span class="label">接收人:</span>
<span>{{ task.to }}</span>
</div>
<div class="info-item">
<span class="label">部门:</span>
<span>{{ task.department }}</span>
</div>
<div class="info-item">
<span class="label">转交日期:</span>
<span>{{ task.transferDate }}</span>
</div>
<div class="info-item">
<span class="label">转交原因:</span>
<span>{{ task.reason }}</span>
</div>
</div>
<div class="action-buttons" v-if="task.status === 'pending'">
<button class="approve-btn" @click="handleApprove(task.id)">通过</button>
<button class="reject-btn" @click="handleReject(task.id)">拒绝</button>
</div>
</div>
</div>
</div>
</div>
</GiPageLayout>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
// 模拟所有任务数据
const allTasks = ref([
{
id: '1',
title: '前端页面重构',
description: '重构用户管理页面,优化交互体验',
from: '张三',
to: '李四',
department: '前端开发部',
transferDate: '2025-08-10',
reason: '原负责人工作负荷过大',
status: 'pending'
},
{
id: '2',
title: 'API接口开发',
description: '开发用户管理相关API接口',
from: '王五',
to: '赵六',
department: '后端开发部',
transferDate: '2025-08-11',
reason: '技术栈更匹配',
status: 'pending'
},
{
id: '3',
title: '数据库设计',
description: '设计用户管理模块的数据库表结构',
from: '钱七',
to: '孙八',
department: '数据库组',
transferDate: '2025-08-12',
reason: '专业领域更对口',
status: 'pending'
}
]);
// 激活的标签,默认待审批
const activeTab = ref('pending');
// 计算各状态任务数量
const pendingCount = computed(() => allTasks.value.filter(t => t.status === 'pending').length);
const approvedCount = computed(() => allTasks.value.filter(t => t.status === 'approved').length);
const rejectedCount = computed(() => allTasks.value.filter(t => t.status === 'rejected').length);
// 根据激活标签筛选任务
const filteredTasks = computed(() => {
return allTasks.value.filter(task => task.status === activeTab.value);
});
// 审批操作
const handleApprove = (taskId: string) => {
const task = allTasks.value.find(t => t.id === taskId);
if (task) {
task.status = 'approved';
}
};
// 拒绝操作
const handleReject = (taskId: string) => {
const task = allTasks.value.find(t => t.id === taskId);
if (task) {
task.status = 'rejected';
}
};
</script>
<style scoped>
.task-approval-page {
height: 100%;
padding: 20px;
display: flex;
flex-direction: column;
}
.page-header {
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0;
}
.page-description {
color: #666;
margin-top: 8px;
font-size: 14px;
}
/* 状态汇总区域 */
.status-summary {
display: flex;
gap: 20px;
margin-bottom: 24px;
}
.status-item {
flex: 1;
display: flex;
justify-content: space-between; /* 让文字居左、数字居右 */
align-items: center;
padding: 16px;
border-radius: 8px;
cursor: pointer; /* 鼠标悬浮变手型,提示可点击 */
transition: all 0.2s ease;
border-top: 4px solid transparent; /* 预留顶部边框位置 */
}
/* 待审批状态样式 */
.status-item.pending {
border-top-color: #f59e0b;
background-color: rgba(245, 158, 11, 0.1); /* 浅橙色背景 */
}
.status-item.pending .count {
color: #f59e0b;
}
/* 已通过状态样式 */
.status-item.approved {
border-top-color: #10b981;
background-color: rgba(16, 185, 129, 0.1); /* 浅绿色背景 */
}
.status-item.approved .count {
color: #10b981;
}
/* 已拒绝状态样式 */
.status-item.rejected {
border-top-color: #ef4444;
background-color: rgba(239, 68, 68, 0.1); /* 浅红色背景 */
}
.status-item.rejected .count {
color: #ef4444;
}
/* 状态文字样式 */
.status-text {
font-size: 14px;
color: #333;
}
/* 数字样式 */
.count {
font-size: 20px;
font-weight: bold;
}
/* 激活态样式(可选,点击后高亮) */
.status-item.active {
transform: scale(1.02);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.content {
flex: 1;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
padding: 20px;
overflow: auto;
}
.task-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.task-item {
padding: 16px;
border: 1px solid #e5e7eb;
border-radius: 8px;
background-color: #fff;
}
.task-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.task-header h3 {
margin: 0;
font-size: 16px;
color: #1f2937;
}
.task-status {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.task-status.pending {
background-color: #fef3c7;
color: #92400e;
}
.task-status.approved {
background-color: #d1fae5;
color: #065f46;
}
.task-status.rejected {
background-color: #fee2e2;
color: #991b1b;
}
.task-description {
margin: 0 0 12px 0;
color: #6b7280;
font-size: 14px;
}
.transfer-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
margin-bottom: 16px;
}
.info-item {
display: flex;
gap: 8px;
font-size: 14px;
}
.info-item .label {
color: #6b7280;
}
.action-buttons {
display: flex;
gap: 8px;
justify-content: flex-end;
}
.approve-btn, .reject-btn {
padding: 6px 12px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
.approve-btn {
background-color: #10b981;
color: white;
border: none;
}
.reject-btn {
background-color: #ef4444;
color: white;
border: none;
}
</style>