From 2fe44259ae6bad4964170799893d39b073f51928 Mon Sep 17 00:00:00 2001 From: WindowBird <13870814+windows-bird@user.noreply.gitee.com> Date: Mon, 17 Nov 2025 13:58:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8D=A1=E7=89=87=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/project/list/index.vue | 450 +++++++++++++++++++++++++++++------ 1 file changed, 373 insertions(+), 77 deletions(-) diff --git a/pages/project/list/index.vue b/pages/project/list/index.vue index ea96398..bd4857f 100644 --- a/pages/project/list/index.vue +++ b/pages/project/list/index.vue @@ -114,58 +114,86 @@ :key="project.id" @click="goToProjectDetail(project)" > - - - - + + + + {{ getStatusText(project.status) }} + + {{ getUrgentStatus(project) }} + - - 过期时间: - {{ formatDate(project.expireTime) }} + + 发布: {{ formatDate(project.createTime || project.releaseTime) }} + + + - - - {{ project.projectName }} - {{ project.description }} - - - 创建人: {{ project.createName }} - 负责人: {{ getOwnerNames(project.memberList) }} - - 提交: {{ project.submitCount || 0 }}次 - 接收: {{ project.receivedCount || 0 }}次 - + + {{ project.projectName }} + + + + + {{ getTagText(project) }} + + {{ project.description }} + + + + + + {{ tag }} + + + + + + + {{ formatDate(project.expireTime) }} + 🕐 + + {{ getTimeStatus(project) }} + - - - ⚠️ 已逾期 + + + + + {{ getAvatarText(member) }} + + + {{ formatMemberNames(project.memberList) }} - + 加载中... - + 暂无项目数据 - + 上拉加载更多 - + 没有更多数据了 @@ -348,6 +376,122 @@ const getOwnerNames = (memberList) => { return memberList.map(member => member.userName || member.name || '').filter(name => name).join('、'); }; +// 获取紧急状态标签 +const getUrgentStatus = (project) => { + if (!project.expireTime) return ''; + + const expireDate = new Date(project.expireTime); + const now = new Date(); + const diffTime = expireDate - now; + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays < 0) { + // 已逾期 + return ''; + } else if (diffDays <= 3) { + // 即将到期(3天内) + return '即将到期'; + } + return ''; +}; + +// 判断是否逾期 +const isOverdue = (project) => { + if (!project.expireTime) return false; + const expireDate = new Date(project.expireTime); + const now = new Date(); + return expireDate < now; +}; + +// 获取时间状态文本(剩余天数或逾期天数) +const getTimeStatus = (project) => { + if (!project.expireTime) return ''; + + const expireDate = new Date(project.expireTime); + const now = new Date(); + const diffTime = expireDate - now; + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays < 0) { + return `逾期${Math.abs(diffDays)}天`; + } else if (diffDays === 0) { + return '今天到期'; + } else { + return `剩余${diffDays}天`; + } +}; + +// 获取标签颜色(根据项目创建人或负责人) +const getTagColor = (project) => { + const colors = ['#87CEEB', '#FFB6C1', '#FFA500', '#98D8C8', '#DDA0DD']; + const name = project.createName || project.ownerName || ''; + if (!name) return colors[0]; + const index = name.charCodeAt(0) % colors.length; + return colors[index]; +}; + +// 获取标签文本(取创建人名字的第一个字) +const getTagText = (project) => { + const name = project.createName || project.ownerName || ''; + if (!name) return '项'; + return name.charAt(0); +}; + +// 获取显示成员(最多3个) +const getDisplayMembers = (memberList) => { + if (!Array.isArray(memberList)) return []; + return memberList.slice(0, 3); +}; + +// 格式化成员名称 +const formatMemberNames = (memberList) => { + if (!Array.isArray(memberList) || memberList.length === 0) return ''; + + const names = memberList.map(member => member.userName || member.name || '').filter(name => name); + + if (names.length <= 3) { + return names.join(''); + } else { + const firstThree = names.slice(0, 3).join(''); + return `${firstThree}等${names.length}人`; + } +}; + +// 获取头像颜色 +const getAvatarColor = (member, index) => { + const colors = ['#FFB6C1', '#87CEEB', '#DDA0DD', '#98D8C8', '#FFA500']; + return colors[index % colors.length]; +}; + +// 获取头像文本(取名字的第一个字) +const getAvatarText = (member) => { + const name = member.userName || member.name || ''; + if (!name) return '?'; + return name.charAt(0); +}; + +// 处理卡片菜单 +const handleCardMenu = (project) => { + uni.showActionSheet({ + itemList: ['修改', '删除', '+ 新增任务', '√ 开始开发'], + success: (res) => { + if (res.tapIndex === 0) { + // 修改 + uni.showToast({ title: '修改功能开发中', icon: 'none' }); + } else if (res.tapIndex === 1) { + // 删除 + uni.showToast({ title: '删除功能开发中', icon: 'none' }); + } else if (res.tapIndex === 2) { + // 新增任务 + uni.showToast({ title: '新增任务功能开发中', icon: 'none' }); + } else if (res.tapIndex === 3) { + // 开始开发 + uni.showToast({ title: '开始开发功能开发中', icon: 'none' }); + } + } + }); +}; + // 处理状态标签点击 const handleStatusTabClick = (value) => { activeStatusTab.value = value; @@ -383,7 +527,7 @@ const handleReset = () => { overdue: '' }; selectedMemberName.value = ''; - activeStatusTab.value = '2'; + activeStatusTab.value = 'IN_PROGRESS'; handleSearch(); }; @@ -563,90 +707,242 @@ onLoad(() => { .project-container { padding: 16px; - display: flex; - flex-direction: column; - gap: 12px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 16px; +} + +/* 移动端适配 */ +@media (max-width: 768px) { + .project-container { + grid-template-columns: repeat(2, 1fr); + gap: 12px; + padding: 12px; + } +} + +@media (max-width: 480px) { + .project-container { + grid-template-columns: 1fr; + } } .project-card { background: #fff; - border-radius: 12px; + border-radius: 8px; padding: 16px; display: flex; flex-direction: column; gap: 12px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + position: relative; + transition: all 0.3s ease; + cursor: pointer; } -.project-header { +.project-card:active { + transform: scale(0.98); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); +} + +/* 卡片头部 */ +.card-header { display: flex; - align-items: center; + align-items: flex-start; justify-content: space-between; + margin-bottom: 4px; } -.status-badge { - display: flex; - align-items: center; -} - -.expire-time { - display: flex; - align-items: center; - gap: 6px; -} - -.expire-label { - font-size: 12px; - color: #999; -} - -.expire-value { - font-size: 14px; - color: #333; -} - -.project-content { +.header-left { display: flex; flex-direction: column; + gap: 6px; + flex: 1; +} + +.status-tag { + display: inline-block; + padding: 4px 10px; + background: #E5E5E5; + border-radius: 4px; + font-size: 12px; + color: #333; + width: fit-content; +} + +.urgent-tag { + display: inline-block; + padding: 4px 10px; + background: #FF4444; + border-radius: 4px; + font-size: 12px; + color: #fff; + width: fit-content; +} + +.header-right { + display: flex; + align-items: center; gap: 8px; } -.project-name { +.release-date { + font-size: 12px; + color: #666; + white-space: nowrap; +} + +.action-menu { + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + padding: 4px; + border-radius: 4px; + transition: background-color 0.2s; +} + +.action-menu:active { + background-color: #f0f0f0; +} + +.menu-icon { + font-size: 18px; + color: #666; + line-height: 1; + transform: rotate(90deg); +} + +/* 项目标题 */ +.card-title { font-size: 16px; font-weight: 600; color: #333; + margin-top: 4px; } -.project-description { +/* 标签和描述行 */ +.card-tags-row { + display: flex; + align-items: center; + gap: 8px; + margin-top: 4px; +} + +.tag-circle { + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.tag-text { + font-size: 14px; + color: #fff; + font-weight: 500; +} + +.card-description { font-size: 14px; color: #666; - line-height: 1.5; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } -.project-meta { +/* 操作标签 */ +.action-tags { + display: flex; + gap: 8px; + flex-wrap: wrap; + margin-top: 4px; +} + +.action-tag { + padding: 4px 10px; + background: #E3F2FD; + border-radius: 4px; + font-size: 12px; + color: #1976D2; +} + +/* 卡片底部 */ +.card-footer { display: flex; flex-direction: column; - gap: 6px; + gap: 8px; margin-top: 8px; } -.meta-item { - font-size: 12px; - color: #999; -} - -.meta-row { +.date-info { display: flex; - gap: 16px; + align-items: center; + gap: 6px; } -.overdue-tip { - margin-top: 8px; +.date-text { + font-size: 14px; + color: #333; } -.overdue-text { +.time-icon { + font-size: 14px; +} + +.time-text { + font-size: 14px; + color: #666; + + &.overdue { + color: #FF4444; + } +} + +.member-info { + display: flex; + align-items: center; + gap: 8px; +} + +.member-avatars { + display: flex; + align-items: center; +} + +.member-avatar { + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + border: 2px solid #fff; + margin-left: -8px; + + &:first-child { + margin-left: 0; + } +} + +.avatar-text { + font-size: 10px; + color: #fff; + font-weight: 500; +} + +.member-text { font-size: 12px; - color: #ff4444; + color: #666; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .empty-state {