OfficeSystem/pages/task-list/index.vue
2025-11-05 15:06:23 +08:00

451 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="task-list-page">
<scroll-view class="task-scroll" scroll-y>
<view class="task-container">
<!-- 任务卡片列表 -->
<view
class="task-card"
v-for="task in filteredTasks"
:key="task.id"
:class="getTaskCardClass(task.status)"
@click="goToTaskDetail(task)"
>
<!-- 状态标签和日期 -->
<view class="task-header">
<view class="task-badge-wrapper">
<uv-tags
:text="getStatusText(task.status)"
:type="getStatusType(task.status)"
size="mini"
></uv-tags>
</view>
<view class="task-date-wrapper">
<text class="task-date">{{ task.date }}</text>
</view>
</view>
<!-- 任务内容 -->
<view class="task-content">
<text class="task-project">所属项目: {{ task.project }}</text>
<text class="task-description">{{ task.description }}</text>
<view class="task-meta">
<text class="task-owner">负责人: {{ task.owner }}</text>
<view class="task-time-row">
<text class="task-time">发布时间: {{ task.releaseTime }}</text>
<view class="task-countdown" v-if="task.status !== 'completed'">
<text class="countdown-icon">🕐</text>
<text class="countdown-text" :class="getCountdownClass(task.status)">
剩余{{ task.remainingDays }}天
</text>
</view>
</view>
</view>
</view>
<!-- 立即处理按钮 -->
<view class="task-action" v-if="task.status !== 'completed'">
<uv-button
:type="getButtonType(task.status)"
size="small"
@click.stop="handleTask(task)"
>
立即处理
</uv-button>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="filteredTasks.length === 0">
<text class="empty-text">暂无{{ getStatusText(statusFilter) }}任务</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
// 获取页面参数
const statusFilter = ref('');
// 任务状态映射
const statusMap = {
'completed': '完成任务',
'pending': '待完成任务',
'imminent': '即将预期',
'overdue': '逾期任务'
};
// 反向映射(从中文到英文)
const statusReverseMap = {
'完成任务': 'completed',
'待完成任务': 'pending',
'即将预期': 'imminent',
'逾期任务': 'overdue'
};
// 任务列表数据
const tasks = ref([
// 即将逾期任务
{
id: 1,
status: 'imminent',
date: '2025-10-15',
project: '创特项目管理系统',
description: '项目内容项目内容项目内容项目内容项目内容项目...',
owner: '张珊珊、李志',
releaseTime: '2025-03-21',
remainingDays: 12
},
{
id: 2,
status: 'imminent',
date: '2025-10-16',
project: '客户管理系统',
description: '完成客户管理系统的需求分析和功能设计...',
owner: '王五',
releaseTime: '2025-03-20',
remainingDays: 13
},
// 待完成任务
{
id: 3,
status: 'pending',
date: '2025-10-15',
project: '创特项目管理系统',
description: '项目内容项目内容项目内容项目内容项目内容项目...',
owner: '张珊珊、李志',
releaseTime: '2025-03-21',
remainingDays: 12
},
{
id: 4,
status: 'pending',
date: '2025-10-18',
project: '财务管理系统',
description: '财务模块的数据统计和报表生成功能开发...',
owner: '赵六',
releaseTime: '2025-03-22',
remainingDays: 15
},
{
id: 5,
status: 'pending',
date: '2025-10-20',
project: '人事管理系统',
description: '人事档案管理模块的优化和升级...',
owner: '孙七',
releaseTime: '2025-03-25',
remainingDays: 17
},
// 已完成任务
{
id: 6,
status: 'completed',
date: '2025-10-15',
project: '创特项目管理系统',
description: '项目内容项目内容项目内容项目内容项目内容项目...',
owner: '张珊珊、李志',
releaseTime: '2025-03-21'
},
{
id: 7,
status: 'completed',
date: '2025-10-10',
project: '数据分析平台',
description: '数据分析平台的报表功能开发已完成...',
owner: '周八',
releaseTime: '2025-03-15'
},
// 逾期任务
{
id: 8,
status: 'overdue',
date: '2025-10-15',
project: '创特项目管理系统',
description: '项目内容项目内容项目内容项目内容项目内容项目...',
owner: '张珊珊、李志',
releaseTime: '2025-03-21',
remainingDays: -5
}
]);
// 根据状态过滤任务
const filteredTasks = computed(() => {
if (!statusFilter.value) {
return tasks.value;
}
return tasks.value.filter(task => task.status === statusFilter.value);
});
// 获取状态文本
const getStatusText = (status) => {
const statusTextMap = {
'imminent': '即将逾期',
'pending': '待完成',
'completed': '已完成',
'overdue': '逾期'
};
return statusTextMap[status] || status;
};
// 获取状态类型用于uv-tags
const getStatusType = (status) => {
const typeMap = {
'imminent': 'warning',
'pending': 'primary',
'completed': 'info',
'overdue': 'error'
};
return typeMap[status] || 'primary';
};
// 获取卡片样式类
const getTaskCardClass = (status) => {
return {
'task-card-imminent': status === 'imminent',
'task-card-pending': status === 'pending',
'task-card-completed': status === 'completed',
'task-card-overdue': status === 'overdue'
};
};
// 获取按钮类型
const getButtonType = (status) => {
const typeMap = {
'imminent': 'warning',
'pending': 'primary',
'overdue': 'error'
};
return typeMap[status] || 'primary';
};
// 获取倒计时样式类
const getCountdownClass = (status) => {
return {
'countdown-warning': status === 'imminent',
'countdown-primary': status === 'pending',
'countdown-error': status === 'overdue'
};
};
// 处理任务
const handleTask = (task) => {
goToTaskDetail(task);
};
// 跳转到任务详情页
const goToTaskDetail = (task) => {
// 将任务数据存储到本地,供详情页使用
uni.setStorageSync('taskDetailData', {
id: task.id,
name: task.description || '待办任务名称',
project: task.project || '所属项目',
statusTags: task.status === 'overdue' ? ['已逾期', '紧急'] :
task.status === 'imminent' ? ['即将逾期'] :
task.status === 'pending' ? ['待完成'] :
['已完成'],
deadline: task.date || '2025-10-14 18:00',
creator: '张珊珊',
responsible: task.owner || '张珊珊、李志',
publishTime: task.releaseTime || '2025-10-17',
content: task.description || '任务内容任务。这里是详细的任务描述,可以包含多行文本。根据实际需求,这里可以展示任务的详细要求、步骤说明、注意事项等。任务内容应该清晰明了,便于负责人理解和执行。',
submitRecords: []
});
uni.navigateTo({
url: `/pages/task-detail/index?id=${task.id}`
});
};
// 页面加载时获取参数
onLoad((options) => {
// 获取状态参数
if (options.status) {
statusFilter.value = options.status;
} else if (options.label) {
// 如果传入的是中文标签,转换为英文状态
statusFilter.value = statusReverseMap[decodeURIComponent(options.label)] || '';
}
// 设置页面标题
if (statusFilter.value && statusMap[statusFilter.value]) {
uni.setNavigationBarTitle({
title: statusMap[statusFilter.value]
});
}
});
</script>
<style lang="scss" scoped>
.task-list-page {
width: 100%;
height: 100vh;
background: #f5f5f5;
}
.task-scroll {
width: 100%;
height: 100%;
}
.task-container {
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.task-card {
background: #fff;
border-radius: 12px;
padding: 16px;
display: flex;
flex-direction: column;
position: relative;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}
.task-card:active {
transform: scale(0.98);
opacity: 0.9;
}
// 即将逾期卡片样式
.task-card-imminent {
border-left: 4px solid #ff9800;
}
// 待完成卡片样式
.task-card-pending {
border-left: 4px solid #2885ff;
}
// 已完成卡片样式
.task-card-completed {
border-left: 4px solid #909399;
opacity: 0.85;
}
// 逾期卡片样式
.task-card-overdue {
background: linear-gradient(135deg, #fff5f5 0%, #ffe6e6 100%);
border-left: 4px solid #f56c6c;
box-shadow: 0 2px 12px rgba(255, 68, 68, 0.1);
}
.task-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.task-badge-wrapper {
flex-shrink: 0;
}
.task-date-wrapper {
background: rgba(0, 0, 0, 0.04);
border-radius: 4px;
padding: 4px 8px;
}
.task-date {
font-size: 14px;
color: #333;
font-weight: 500;
}
.task-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
.task-project {
font-size: 12px;
color: #666;
line-height: 1.5;
}
.task-description {
font-size: 14px;
color: #333;
line-height: 1.5;
margin-bottom: 4px;
}
.task-meta {
display: flex;
flex-direction: column;
gap: 4px;
}
.task-owner {
font-size: 12px;
color: #666;
}
.task-time-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.task-time {
font-size: 12px;
color: #666;
}
.task-countdown {
display: flex;
align-items: center;
gap: 4px;
}
.countdown-icon {
font-size: 14px;
}
.countdown-text {
font-size: 12px;
font-weight: 500;
}
.countdown-warning {
color: #ff9800;
}
.countdown-primary {
color: #2885ff;
}
.countdown-error {
color: #f56c6c;
}
.task-action {
margin-top: 12px;
display: flex;
justify-content: flex-end;
}
.empty-state {
padding: 60px 20px;
text-align: center;
}
.empty-text {
font-size: 14px;
color: #999;
}
</style>