任务过滤显示
This commit is contained in:
parent
badefc18f1
commit
7e7e2f6c5a
|
|
@ -39,3 +39,36 @@ export const getDashboardBrief = ({ joinUserId, keys }) => {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取任务列表
|
||||
* @param {Object} params 请求参数
|
||||
* @param {boolean} params.overdue 是否获取逾期任务
|
||||
* @param {number[]} params.statusList 任务状态列表,4对应已完成
|
||||
* @param {string} params.expireTimeStart 过期时间开始范围(格式:yyyy-MM-dd HH:mm:ss)
|
||||
* @param {string} params.expireTimeEnd 过期时间结束范围(格式:yyyy-MM-dd HH:mm:ss)
|
||||
* @returns {Promise} 返回任务列表
|
||||
*/
|
||||
export const getTaskList = ({ overdue, statusList, expireTimeStart, expireTimeEnd }) => {
|
||||
const queryParams = [];
|
||||
if (overdue !== undefined) {
|
||||
queryParams.push(`overdue=${overdue}`);
|
||||
}
|
||||
if (statusList !== undefined && Array.isArray(statusList) && statusList.length > 0) {
|
||||
// 将数组转换为逗号分隔的字符串,例如 [4] => "4" 或 [1,2,3] => "1,2,3"
|
||||
queryParams.push(`statusList=${statusList.join(',')}`);
|
||||
}
|
||||
if (expireTimeStart !== undefined && expireTimeStart !== null && expireTimeStart !== '') {
|
||||
queryParams.push(`expireTimeStart=${encodeURIComponent(expireTimeStart)}`);
|
||||
}
|
||||
if (expireTimeEnd !== undefined && expireTimeEnd !== null && expireTimeEnd !== '') {
|
||||
queryParams.push(`expireTimeEnd=${encodeURIComponent(expireTimeEnd)}`);
|
||||
}
|
||||
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
|
||||
|
||||
return uni.$uv.http.get(`bst/task/list${queryString}`, {
|
||||
custom: {
|
||||
auth: true // 启用 token 认证
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
<!-- 逾期任务详情 -->
|
||||
<view class="overdue-section" v-if="overdueTasks.length > 0">
|
||||
<view class="overdue-card task-card-base task-card-overdue" v-for="task in overdueTasks" :key="task.id" @click="goToTaskDetail(task)">
|
||||
<view class="overdue-card task-card-base task-card-overdue" v-for="task in overdueTasks.slice(0, 1)" :key="task.id" @click="goToTaskDetail(task)">
|
||||
<view class="task-header">
|
||||
<view class="task-badge-wrapper">
|
||||
<uv-tags
|
||||
|
|
@ -67,11 +67,6 @@
|
|||
<uv-button type="error" size="small" @click.stop="handleOverdueTask(task)">立即处理</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="carousel-dots">
|
||||
<view class="dot" :class="{ active: true }"></view>
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 公告事项 -->
|
||||
|
|
@ -152,7 +147,7 @@
|
|||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getTaskStatusType, getTaskStatusStyle, getStatusText } from '@/utils/taskConfig.js';
|
||||
import { getDashboardBrief } from '@/common/api';
|
||||
import { getDashboardBrief, getTaskList } from '@/common/api';
|
||||
import { useUserStore } from '@/store/user';
|
||||
|
||||
// 任务统计
|
||||
|
|
@ -164,16 +159,7 @@ const taskStats = ref([
|
|||
]);
|
||||
|
||||
// 逾期任务
|
||||
const overdueTasks = ref([
|
||||
{
|
||||
id: 1,
|
||||
date: '2025-10-15',
|
||||
project: '创特项目管理系统',
|
||||
description: '项目内容项目内容项目内容项目内容项目内容项目...',
|
||||
owner: '张珊珊、李志',
|
||||
releaseTime: '2025-03-21'
|
||||
}
|
||||
]);
|
||||
const overdueTasks = ref([]);
|
||||
|
||||
// 公告事项
|
||||
const announcements = ref([
|
||||
|
|
@ -240,6 +226,71 @@ const mapApiDataToComponent = (apiData) => {
|
|||
// overdueTasks.value = [];
|
||||
};
|
||||
|
||||
// 格式化日期:将 "2024-10-31 23:59:59" 转换为 "2024-10-31"
|
||||
const formatDate = (dateStr) => {
|
||||
if (!dateStr) return '';
|
||||
// 如果包含空格,取日期部分
|
||||
return dateStr.split(' ')[0];
|
||||
};
|
||||
|
||||
// 提取负责人:从 memberList 中提取所有成员的名称
|
||||
const getOwnerNames = (memberList) => {
|
||||
if (!Array.isArray(memberList) || memberList.length === 0) return '';
|
||||
return memberList.map(member => member.userName || member.name || '').filter(name => name).join('、');
|
||||
};
|
||||
|
||||
// 加载逾期任务列表
|
||||
const loadOverdueTasks = async () => {
|
||||
try {
|
||||
const res = await getTaskList({ overdue: true });
|
||||
console.log('逾期任务列表加载成功:', res);
|
||||
|
||||
// 根据实际返回的数据结构:{ total: 27, rows: [...], code: 200, msg: "查询成功" }
|
||||
if (res && res.rows && Array.isArray(res.rows)) {
|
||||
overdueTasks.value = res.rows.map((item) => {
|
||||
return {
|
||||
id: item.id || '',
|
||||
date: formatDate(item.expireTime) || '',
|
||||
project: item.projectName || '',
|
||||
description: item.description || '',
|
||||
owner: getOwnerNames(item.memberList) || '',
|
||||
releaseTime: formatDate(item.createTime) || ''
|
||||
};
|
||||
});
|
||||
} else if (res && res.data && Array.isArray(res.data)) {
|
||||
// 兼容 data 字段
|
||||
overdueTasks.value = res.data.map((item) => {
|
||||
return {
|
||||
id: item.id || '',
|
||||
date: formatDate(item.expireTime) || '',
|
||||
project: item.projectName || '',
|
||||
description: item.description || '',
|
||||
owner: getOwnerNames(item.memberList) || '',
|
||||
releaseTime: formatDate(item.createTime) || ''
|
||||
};
|
||||
});
|
||||
} else if (res && Array.isArray(res)) {
|
||||
// 兼容直接返回数组的情况
|
||||
overdueTasks.value = res.map((item) => {
|
||||
return {
|
||||
id: item.id || '',
|
||||
date: formatDate(item.expireTime) || '',
|
||||
project: item.projectName || '',
|
||||
description: item.description || '',
|
||||
owner: getOwnerNames(item.memberList) || '',
|
||||
releaseTime: formatDate(item.createTime) || ''
|
||||
};
|
||||
});
|
||||
} else {
|
||||
overdueTasks.value = [];
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载逾期任务列表失败:', err);
|
||||
// 逾期任务加载失败不影响其他数据,只记录错误
|
||||
overdueTasks.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
// 加载看板数据
|
||||
const loadDashboardData = async () => {
|
||||
try {
|
||||
|
|
@ -273,6 +324,9 @@ const loadDashboardData = async () => {
|
|||
|
||||
console.log('看板数据加载成功:', res);
|
||||
mapApiDataToComponent(res);
|
||||
|
||||
// 加载逾期任务列表
|
||||
await loadOverdueTasks();
|
||||
} catch (err) {
|
||||
console.error('加载看板数据失败:', err);
|
||||
uni.showToast({
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
<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)"
|
||||
>
|
||||
<template v-if="!loading">
|
||||
<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">
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
<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'">
|
||||
<view class="task-countdown" v-if="task.status !== 'completed' && task.remainingDays !== null">
|
||||
<text class="countdown-icon">🕐</text>
|
||||
<text class="countdown-text" :class="getCountdownClass(task.status)">
|
||||
剩余{{ task.remainingDays }}天
|
||||
|
|
@ -54,11 +55,17 @@
|
|||
立即处理
|
||||
</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="empty-state" v-if="loading">
|
||||
<text class="empty-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="filteredTasks.length === 0">
|
||||
<text class="empty-text">暂无{{ getStatusText(statusFilter) }}任务</text>
|
||||
<view class="empty-state" v-else-if="filteredTasks.length === 0">
|
||||
<text class="empty-text">暂无{{ getStatusText(statusFilter) || '' }}任务</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
|
@ -69,9 +76,11 @@
|
|||
import { ref, computed } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { getStatusText, getTaskStatusType, getTaskStatusStyle } from '@/utils/taskConfig.js';
|
||||
import { getTaskList } from '@/common/api';
|
||||
|
||||
// 获取页面参数
|
||||
const statusFilter = ref('');
|
||||
const loading = ref(false);
|
||||
|
||||
// 任务状态映射
|
||||
const statusMap = {
|
||||
|
|
@ -90,90 +99,7 @@ const statusReverseMap = {
|
|||
};
|
||||
|
||||
// 任务列表数据
|
||||
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 tasks = ref([]);
|
||||
|
||||
// 根据状态过滤任务
|
||||
const filteredTasks = computed(() => {
|
||||
|
|
@ -251,6 +177,209 @@ const goToTaskDetail = (task) => {
|
|||
});
|
||||
};
|
||||
|
||||
// 格式化日期:将 "2024-10-31 23:59:59" 转换为 "2024-10-31"
|
||||
const formatDate = (dateStr) => {
|
||||
if (!dateStr) return '';
|
||||
// 如果包含空格,取日期部分
|
||||
return dateStr.split(' ')[0];
|
||||
};
|
||||
|
||||
// 格式化日期时间:格式化为 yyyy-MM-dd HH:mm:ss
|
||||
const formatDateTime = (date) => {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
const hours = String(d.getHours()).padStart(2, '0');
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(d.getSeconds()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
|
||||
// 获取即将逾期的时间范围(当前时间到3天后)
|
||||
const getImminentDateRange = () => {
|
||||
const now = new Date();
|
||||
const endDate = new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000);
|
||||
|
||||
return {
|
||||
expireTimeStart: formatDateTime(now),
|
||||
expireTimeEnd: formatDateTime(endDate)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 计算剩余天数
|
||||
const calculateRemainingDays = (expireTime) => {
|
||||
if (!expireTime) return null;
|
||||
const expireDate = new Date(expireTime);
|
||||
const now = new Date();
|
||||
now.setHours(0, 0, 0, 0);
|
||||
expireDate.setHours(0, 0, 0, 0);
|
||||
const diffTime = expireDate.getTime() - now.getTime();
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
return diffDays;
|
||||
};
|
||||
|
||||
// 提取负责人:从 memberList 中提取所有成员的名称
|
||||
const getOwnerNames = (memberList) => {
|
||||
if (!Array.isArray(memberList) || memberList.length === 0) return '';
|
||||
return memberList.map(member => member.userName || member.name || '').filter(name => name).join('、');
|
||||
};
|
||||
|
||||
// 将接口数据转换为页面需要的格式
|
||||
const transformTaskData = (item, status) => {
|
||||
const expireTime = item.expireTime || item.expire_time || '';
|
||||
const remainingDays = calculateRemainingDays(expireTime);
|
||||
|
||||
return {
|
||||
id: item.id || '',
|
||||
status: status,
|
||||
date: formatDate(expireTime) || '',
|
||||
project: item.projectName || item.project_name || '',
|
||||
description: item.description || item.task_name || '',
|
||||
owner: getOwnerNames(item.memberList || item.member_list || []),
|
||||
releaseTime: formatDate(item.createTime || item.create_time) || '',
|
||||
remainingDays: remainingDays
|
||||
};
|
||||
};
|
||||
|
||||
// 加载任务列表数据
|
||||
const loadTaskList = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
let res;
|
||||
|
||||
// 根据状态类型调用不同的接口
|
||||
if (statusFilter.value === 'completed') {
|
||||
// 已完成任务:使用 statusList=[4]
|
||||
res = await getTaskList({ statusList: [4] });
|
||||
} else if (statusFilter.value === 'overdue') {
|
||||
// 逾期任务:使用 overdue=true
|
||||
|
||||
res = await getTaskList({
|
||||
overdue: true,
|
||||
|
||||
});
|
||||
} else if (statusFilter.value === 'pending') {
|
||||
// 待完成任务:使用 statusList=[2]
|
||||
res = await getTaskList({ statusList: [2] });
|
||||
} else if (statusFilter.value === 'imminent') {
|
||||
// 即将逾期:使用 statusList=[2] 和过期时间范围参数(3天内)
|
||||
const dateRange = getImminentDateRange();
|
||||
res = await getTaskList({
|
||||
statusList: [2],
|
||||
expireTimeStart: dateRange.expireTimeStart,
|
||||
expireTimeEnd: dateRange.expireTimeEnd
|
||||
});
|
||||
} else {
|
||||
// 其他情况:获取所有任务
|
||||
res = await getTaskList({});
|
||||
}
|
||||
|
||||
console.log('任务列表加载成功:', res);
|
||||
|
||||
// 处理返回的数据
|
||||
let taskList = [];
|
||||
if (res && res.rows && Array.isArray(res.rows)) {
|
||||
taskList = res.rows;
|
||||
} else if (res && res.data && Array.isArray(res.data)) {
|
||||
taskList = res.data;
|
||||
} else if (res && Array.isArray(res)) {
|
||||
taskList = res;
|
||||
}
|
||||
|
||||
// 转换数据格式
|
||||
tasks.value = taskList.map((item) => {
|
||||
// 根据状态判断任务的status
|
||||
let taskStatus = statusFilter.value;
|
||||
|
||||
// 如果没有明确的状态过滤,根据任务的实际状态判断
|
||||
if (!taskStatus) {
|
||||
// 判断是否已完成(假设状态字段为 status 或 taskStatus,值为4表示已完成)
|
||||
const itemStatus = item.status || item.taskStatus || item.task_status;
|
||||
if (itemStatus === 4) {
|
||||
taskStatus = 'completed';
|
||||
} else if (itemStatus === 2) {
|
||||
// 状态为2表示待完成,根据到期时间判断是否逾期或即将逾期
|
||||
const remainingDays = calculateRemainingDays(item.expireTime || item.expire_time);
|
||||
if (remainingDays === null) {
|
||||
taskStatus = 'pending';
|
||||
} else if (remainingDays < 0) {
|
||||
taskStatus = 'overdue';
|
||||
} else if (remainingDays <= 7) {
|
||||
taskStatus = 'imminent';
|
||||
} else {
|
||||
taskStatus = 'pending';
|
||||
}
|
||||
} else {
|
||||
// 其他状态默认为待完成
|
||||
const remainingDays = calculateRemainingDays(item.expireTime || item.expire_time);
|
||||
if (remainingDays === null) {
|
||||
taskStatus = 'pending';
|
||||
} else if (remainingDays < 0) {
|
||||
taskStatus = 'overdue';
|
||||
} else if (remainingDays <= 7) {
|
||||
taskStatus = 'imminent';
|
||||
} else {
|
||||
taskStatus = 'pending';
|
||||
}
|
||||
}
|
||||
} else if (statusFilter.value === 'pending' || statusFilter.value === 'imminent') {
|
||||
// 对于待完成和即将逾期,确保任务状态为待完成(值为2)
|
||||
const itemStatus = item.status || item.taskStatus || item.task_status;
|
||||
if (itemStatus === 2) {
|
||||
// 如果是即将逾期,需要再次判断剩余天数
|
||||
if (statusFilter.value === 'imminent') {
|
||||
const remainingDays = calculateRemainingDays(item.expireTime || item.expire_time);
|
||||
if (remainingDays !== null && remainingDays > 0 && remainingDays <= 7) {
|
||||
taskStatus = 'imminent';
|
||||
} else {
|
||||
// 不符合即将逾期条件,设置为pending(后续会被过滤掉)
|
||||
taskStatus = 'pending';
|
||||
}
|
||||
} else {
|
||||
// 待完成任务,根据剩余天数判断是否逾期
|
||||
const remainingDays = calculateRemainingDays(item.expireTime || item.expire_time);
|
||||
if (remainingDays !== null && remainingDays < 0) {
|
||||
taskStatus = 'overdue';
|
||||
} else {
|
||||
taskStatus = 'pending';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果状态不是2,设置为pending(后续会被过滤掉)
|
||||
taskStatus = 'pending';
|
||||
}
|
||||
}
|
||||
|
||||
return transformTaskData(item, taskStatus);
|
||||
});
|
||||
|
||||
// 如果指定了状态过滤,还需要再次过滤(以防接口返回的数据不准确)
|
||||
if (statusFilter.value === 'overdue') {
|
||||
tasks.value = tasks.value.filter(task => task.status === 'overdue');
|
||||
} else if (statusFilter.value === 'completed') {
|
||||
tasks.value = tasks.value.filter(task => task.status === 'completed');
|
||||
} else if (statusFilter.value === 'imminent') {
|
||||
tasks.value = tasks.value.filter(task => task.status === 'imminent');
|
||||
} else if (statusFilter.value === 'pending') {
|
||||
tasks.value = tasks.value.filter(task => task.status === 'pending');
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('加载任务列表失败:', err);
|
||||
uni.showToast({
|
||||
title: '加载数据失败',
|
||||
icon: 'none'
|
||||
});
|
||||
tasks.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时获取参数
|
||||
onLoad((options) => {
|
||||
// 获取状态参数
|
||||
|
|
@ -267,6 +396,9 @@ onLoad((options) => {
|
|||
title: statusMap[statusFilter.value]
|
||||
});
|
||||
}
|
||||
|
||||
// 加载任务列表数据
|
||||
loadTaskList();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user