From 752a754d45fdefbe2b30d393bb3df8e6c8b84cf6 Mon Sep 17 00:00:00 2001 From: WindowBird <13870814+windows-bird@user.noreply.gitee.com> Date: Sat, 22 Nov 2025 16:35:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=AE=A1=E7=90=860.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/task/manage/index.vue | 301 +++++++++++++++++++----------------- utils/request/index.js | 2 +- 2 files changed, 162 insertions(+), 141 deletions(-) diff --git a/pages/task/manage/index.vue b/pages/task/manage/index.vue index 4313c8d..fcb6593 100644 --- a/pages/task/manage/index.vue +++ b/pages/task/manage/index.vue @@ -168,12 +168,13 @@ @scrolltolower="handleScrollToLower" > - + @@ -186,37 +187,40 @@ :plain="false" :custom-style="getTagCustomStyle(task.status)" > - - {{ formatDate(task.expireTime) }} + {{ task.date }} + + + + + 立即处理 + + - 所属项目: {{ task.projectName || '未分配项目' }} - {{ truncateText(task.description, 80) }} + 所属项目: {{ task.project }} + {{truncateText(task.description)}} - 负责人: {{ getOwnerNames(task.memberList) || '未分配' }} - 创建人: {{ task.createName || '未知' }} + 负责人: {{ task.owner }} + 创建人: {{ task.createName }} - 发布时间: {{ formatDate(task.createTime) }} - + 发布时间: {{ task.releaseTime }} + 🕐 - + {{ task.remainingDays < 0 ? `已逾期${Math.abs(task.remainingDays)}天` : `剩余${task.remainingDays}天` }} - 通过时间: {{ formatDate(task.passTime) }} @@ -319,9 +323,11 @@ import { ref, computed, onMounted } from 'vue'; import { getTaskList, getProjectListAll, getUserList } from '@/api'; import { useDictStore } from '@/store/dict'; +import { useTaskStore } from '@/store/task'; import { usePagination } from '@/composables'; import { getDictLabel } from '@/utils/dict'; import { truncateText } from '@/utils/textSolve/truncateText'; +import { getStatusText, getTaskStatusType, getTaskStatusStyle } from '@/utils/taskConfig.js'; import FabPlus from '@/components/FabPlus.vue'; const dictStore = useDictStore(); @@ -448,6 +454,13 @@ const { defaultParams: {} }); +// 格式化日期:将 "2024-10-31 23:59:59" 转换为 "2024-10-31" +const formatDate = (dateStr) => { + if (!dateStr) return ''; + // 如果包含空格,取日期部分 + return dateStr.split(' ')[0]; +}; + // 计算剩余天数 const calculateRemainingDays = (expireTime) => { if (!expireTime) return null; @@ -460,16 +473,21 @@ const calculateRemainingDays = (expireTime) => { return diffDays; }; -// 根据过期时间和状态判断任务状态(用于卡片样式) -const determineTaskStatusForCard = (task) => { +// 提取负责人:从 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 determineTaskStatus = (item, expireTime) => { // 如果任务已完成(状态为4),直接返回 completed - const taskStatus = task.status; - if (taskStatus === 4 || taskStatus === '4') { + const taskStatusFromBackend = item.status; + if (taskStatusFromBackend === 4 || taskStatusFromBackend === 'completed') { return 'completed'; } - // 如果没有过期时间,返回 pending - const expireTime = task.expireTime; + // 如果没有过期时间,使用默认 pending if (!expireTime) { return 'pending'; } @@ -495,130 +513,101 @@ const determineTaskStatusForCard = (task) => { return 'pending'; }; -// 任务列表(添加状态和剩余天数) -const tasks = computed(() => { - return list.value.map(task => { - const expireTime = task.expireTime || ''; - const remainingDays = calculateRemainingDays(expireTime); - const cardStatus = determineTaskStatusForCard(task); - +// 将接口数据转换为页面需要的格式 +const transformTaskData = (item) => { + const expireTime = item.expireTime || item.expire_time || ''; + + // 最高优先级:判断任务状态 - status===4 或 status==='4' 直接返回completed,不做任何其他校验 + // 支持多种字段名和数据类型:status、taskStatus、statusId 等 + const taskStatus = item.status !== undefined ? item.status : + item.taskStatus !== undefined ? item.taskStatus : + item.statusId !== undefined ? item.statusId : null; + + // 检查是否已完成(支持数字4、字符串'4'、字符串'completed'等多种格式) + const isCompleted = taskStatus === 4 || + taskStatus === '4' || + taskStatus === 'completed' || + String(taskStatus) === '4'; + + // 如果已完成,直接返回完成状态,不做过期校验,不计算剩余天数 + if (isCompleted) { return { - ...task, - remainingDays, - cardStatus + id: item.id || '', + status: 'completed', // 固定为completed,确保显示灰色样式 + createName: item.createName || '', + 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: null // 已完成任务不计算剩余天数 }; - }); + } + + // 未完成的任务才计算剩余天数并进行过期校验 + const remainingDays = calculateRemainingDays(expireTime); + const finalStatus = determineTaskStatus(item, expireTime); + + return { + id: item.id || '', + status: finalStatus, + createName: item.createName || '', + 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 + }; +}; + +// 将分页器的 list 转换为任务列表格式 +const tasks = computed(() => { + return list.value.map(item => transformTaskData(item)); }); -// 获取状态文本(根据数字状态) -const getStatusText = (status) => { - if (!status && status !== 0) return '未知'; - // 从字典获取状态文本 - const dictLabel = getDictLabel('task_status', String(status)); - if (dictLabel && dictLabel !== String(status)) { - return dictLabel; - } - // 默认映射 - const statusMap = { - '1': '待接收', - '2': '进行中', - '3': '已提交', - '4': '已完成', - '5': '已驳回', - '6': '已取消', - '7': '逾期完成', - '10': '待完成' - }; - return statusMap[String(status)] || `状态${status}`; -}; - -// 获取状态类型(用于标签颜色) -const getTaskStatusType = (status) => { - if (!status && status !== 0) return 'primary'; - // 从字典获取listClass,映射到uv-tags的type - const statusDict = dictStore.getDictByType('task_status'); - const statusItem = statusDict.find(item => item.dictValue === String(status)); - if (statusItem) { - const listClassMap = { - 'primary': 'primary', - 'success': 'success', - 'warning': 'warning', - 'danger': 'error', - 'info': 'info' - }; - return listClassMap[statusItem.listClass] || 'primary'; - } - // 默认映射 - const typeMap = { - '1': 'info', // 待接收 - '2': 'warning', // 进行中 - '3': 'primary', // 已提交 - '4': 'success', // 已完成 - '5': 'error', // 已驳回 - '6': 'error', // 已取消 - '7': 'warning', // 逾期完成 - '10': 'primary' // 待完成 - }; - return typeMap[String(status)] || 'primary'; -}; - -// 获取标签自定义样式 +// 使用全局配置获取标签自定义样式 const getTagCustomStyle = (status) => { - const statusDict = dictStore.getDictByType('task_status'); - const statusItem = statusDict.find(item => item.dictValue === String(status)); - - // 默认样式 - const defaultStyle = { - backgroundColor: '#909399', - color: '#fff', - borderColor: '#909399' + const styleConfig = getTaskStatusStyle(status); + return { + backgroundColor: styleConfig.backgroundColor, + color: styleConfig.color, + borderColor: styleConfig.borderColor }; - - if (!statusItem) { - return defaultStyle; - } - - // 根据listClass设置颜色 - const colorMap = { - 'primary': { backgroundColor: '#2885ff', color: '#fff', borderColor: '#2885ff' }, - 'success': { backgroundColor: '#67c23a', color: '#fff', borderColor: '#67c23a' }, - 'warning': { backgroundColor: '#ff9800', color: '#fff', borderColor: '#ff9800' }, - 'danger': { backgroundColor: '#f56c6c', color: '#fff', borderColor: '#f56c6c' }, - 'info': { backgroundColor: '#909399', color: '#fff', borderColor: '#909399' } - }; - - return colorMap[statusItem.listClass] || defaultStyle; }; // 获取卡片样式类 -const getTaskCardClass = (task) => { +const getTaskCardClass = (status) => { return { - 'task-card-imminent': task.cardStatus === 'imminent', - 'task-card-pending': task.cardStatus === 'pending', - 'task-card-completed': task.cardStatus === 'completed', - 'task-card-overdue': task.cardStatus === 'overdue' + '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 = (cardStatus) => { +const getCountdownClass = (status) => { return { - 'countdown-warning': cardStatus === 'imminent', - 'countdown-primary': cardStatus === 'pending', - 'countdown-error': cardStatus === 'overdue' + 'countdown-warning': status === 'imminent', + 'countdown-primary': status === 'pending', + 'countdown-error': status === 'overdue' }; }; -// 格式化日期 -const formatDate = (dateStr) => { - if (!dateStr) return ''; - return dateStr.split(' ')[0]; -}; - -// 获取负责人名称 -const getOwnerNames = (memberList) => { - if (!Array.isArray(memberList) || memberList.length === 0) return ''; - return memberList.map(member => member.userName || member.name || '').filter(name => name).join('、'); +// 处理任务 +const handleTask = (task) => { + goToTaskDetail(task); }; // 打开选择器 @@ -791,8 +780,26 @@ const handleScrollToLower = () => { } }; -// 跳转到任务详情 +// 跳转到任务详情页 const goToTaskDetail = (task) => { + // 使用 Pinia store 存储任务详情数据 + const taskStore = useTaskStore(); + taskStore.setTaskDetail({ + 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: task.createName, + responsible: task.owner || '张珊珊、李志', + publishTime: task.releaseTime || '2025-10-17', + content: task.description || '任务内容任务。这里是详细的任务描述,可以包含多行文本。根据实际需求,这里可以展示任务的详细要求、步骤说明、注意事项等。任务内容应该清晰明了,便于负责人理解和执行。', + submitRecords: [] + }); + uni.navigateTo({ url: `/pages/task/detail/index?id=${task.id}` }); @@ -1049,21 +1056,34 @@ onMounted(() => { align-items: center; gap: 4px; padding: 4px 12px; - background: #f5f5f5; - border-radius: 16px; - font-size: 13px; + background: transparent; + border-radius: 0; + font-size: 14px; color: #666; transition: all 0.2s; white-space: nowrap; cursor: pointer; + position: relative; &:active { opacity: 0.7; } &.active { - background: #2885ff; - color: #fff; + background: transparent; + color: #2885ff; + font-weight: 500; + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 12px; + right: 12px; + height: 2px; + background-color: #2885ff; + border-radius: 1px; + } } .count { @@ -1107,3 +1127,4 @@ onMounted(() => { @import '@/styles/task-card.scss'; + diff --git a/utils/request/index.js b/utils/request/index.js index 329e31f..668858f 100644 --- a/utils/request/index.js +++ b/utils/request/index.js @@ -11,7 +11,7 @@ export const Request = () => { uni.$uv.http.setConfig((config) => { /* config 为默认全局配置*/ config.baseURL = 'http://192.168.1.4:4001'; /* 根域名 */ - config.baseURL = 'https://pm.ccttiot.com/prod-api'; /* 根域名 */ + // config.baseURL = 'https://pm.ccttiot.com/prod-api'; /* 根域名 */ return config })