diff --git a/frontend/src/views/TaskHall.vue b/frontend/src/views/TaskHall.vue index 94b8538..3cc3b85 100644 --- a/frontend/src/views/TaskHall.vue +++ b/frontend/src/views/TaskHall.vue @@ -2455,7 +2455,34 @@ const completedPagination = reactive({ const getTaskTypeName = (typeId: number, taskTypeName?: string) => { // 如果有直接传入的类型名称,优先使用 if (taskTypeName) return taskTypeName + + // 确保demandTypes已加载 + if (!demandTypes.value || demandTypes.value.length === 0) { + // 如果store中没有,尝试重新加载 + if (!configStore.loading) { + configStore.loadDemandTypes() + } + return '加载中...' + } + const type = demandTypes.value.find(t => t.id === typeId) + + // 尝试递归查找(如果是树形结构) + if (!type) { + const findInTree = (items: any[]): any => { + for (const item of items) { + if (item.id === typeId) return item + if (item.children) { + const found = findInTree(item.children) + if (found) return found + } + } + return null + } + const found = findInTree(demandTypes.value) + if (found) return found.name + } + return type?.name || '未知类型' } @@ -5309,5 +5336,280 @@ onUnmounted(() => { :deep(.approve-modal) .ant-btn-text.ant-btn-danger:hover { background-color: rgba(255, 77, 79, 0.1); } + +/* 新版卡片样式 */ +.card-new-layout { + height: 100%; + display: flex; + flex-direction: column; + border-radius: 12px; + overflow: hidden; + background: #1e1e1e; + border: 1px solid #333; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); + + &:hover { + transform: translateY(-4px); + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4); + border-color: #444; + + .card-title { + color: #31f08b; + } + } +} + +.preview-cover { + position: relative; + height: 160px; + overflow: hidden; + background: #141414; + + img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1); + } + + .preview-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(to bottom, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.4) 100%); + opacity: 0.8; + transition: opacity 0.3s ease; + } + + &:hover { + img { + transform: scale(1.08); + } + .preview-overlay { + opacity: 0.6; + } + } +} + +.floating-badges { + position: absolute; + top: 12px; + left: 12px; + display: flex; + gap: 6px; + flex-wrap: wrap; + z-index: 2; +} + +.badge-mini { + padding: 4px 10px; + border-radius: 6px; + font-size: 11px; + font-weight: 600; + color: #fff; + background: rgba(0, 0, 0, 0.65); + backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.1); + letter-spacing: 0.5px; + + &.subtask { background: rgba(24, 144, 255, 0.85); border-color: rgba(24, 144, 255, 0.3); } + &.new { background: rgba(49, 240, 139, 0.85); color: #000; border-color: rgba(49, 240, 139, 0.3); } + &.urgent { background: rgba(245, 34, 45, 0.85); border-color: rgba(245, 34, 45, 0.3); } +} + +.card-body { + padding: 20px; + flex: 1; + display: flex; + flex-direction: column; +} + +.header-badges { + display: flex; + gap: 8px; + margin-bottom: 12px; + flex-wrap: wrap; +} + +.badge-tag { + padding: 2px 8px; + border-radius: 4px; + font-size: 11px; + font-weight: 500; + letter-spacing: 0.3px; + + &.subtask { background: rgba(24, 144, 255, 0.1); color: #40a9ff; border: 1px solid rgba(24, 144, 255, 0.2); } + &.new { background: rgba(49, 240, 139, 0.1); color: #31f08b; border: 1px solid rgba(49, 240, 139, 0.2); } + &.urgent { background: rgba(245, 34, 45, 0.1); color: #ff4d4f; border: 1px solid rgba(245, 34, 45, 0.2); } + &.high-score { background: rgba(250, 173, 20, 0.1); color: #ffc53d; border: 1px solid rgba(250, 173, 20, 0.2); } +} + +.card-title { + font-size: 16px; + font-weight: 600; + color: #fff; + line-height: 1.5; + margin: 0 0 20px; + // 限制2行 + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + min-height: 48px; + transition: color 0.3s ease; + letter-spacing: 0.2px; +} + +.metrics-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 14px 16px; + background: #262626; + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid #333; +} + +.metric { + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + position: relative; + + &.divider { + width: 1px; + height: 24px; + background: #3a3a3a; + flex: 0 0 1px; + margin: 0 12px; + } + + .label { + font-size: 11px; + color: #888; + margin-bottom: 6px; + text-transform: uppercase; + letter-spacing: 0.5px; + } + + .value { + font-size: 13px; + color: #e0e0e0; + font-weight: 500; + max-width: 90px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + line-height: 1.2; + + &.score { + color: #31f08b; + font-size: 18px; + font-weight: 700; + text-shadow: 0 0 10px rgba(49, 240, 139, 0.2); + } + + &.type { + color: #fff; + } + } +} + +.details-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px 16px; + margin-bottom: 24px; +} + +.detail-item { + display: flex; + align-items: center; + gap: 8px; + font-size: 12px; + color: #999; + min-width: 0; // 防止溢出 + + .icon { + color: #555; + flex-shrink: 0; + } + + .text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + line-height: 1.4; + } + + .text-ellipsis { + flex: 1; + } +} + +.card-actions { + display: flex; + gap: 12px; + margin-top: auto; + + .action-btn { + flex: 1; + height: 40px; + border-radius: 6px; + font-size: 13px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + border: none; + letter-spacing: 0.5px; + + &.secondary { + background: #2a2a2a; + color: #ccc; + border: 1px solid #3a3a3a; + + &:hover { + background: #333; + color: #fff; + border-color: #444; + } + } + + &.primary { + background: #31f08b; + color: #000; + box-shadow: 0 2px 8px rgba(49, 240, 139, 0.2); + + &:hover { + background: #4de19b; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(49, 240, 139, 0.3); + } + + &:active { + transform: translateY(0); + } + + &.disabled { + background: #333; + color: #666; + cursor: not-allowed; + border: 1px solid #444; + box-shadow: none; + + &:hover { + transform: none; + background: #333; + } + } + } + } +}