feat: 프로젝트 문서의 AI 반영 상태 배지 표시

AI 추천이 문서 내용을 반영하지 못해도(추출 실패·미지원 형식) 추천은
정상 응답되어 사용자가 인지할 수 없던 문제를 해소한다. 문서 목록에
반영 상태 배지를 노출한다.

- ProjectAttachmentResponse.aiStatus 추가(ready/failed/unsupported)
  · ready: 추출 성공(반영 가능) · failed: 지원 형식이나 추출 실패
  · unsupported: 미지원 형식(이미지·xlsx·ppt·zip 등)
- isExtractableType + deriveAiStatus 로 상태 산출
  (추출 본문은 응답에 노출하지 않고 상태 판별에만 사용)
- listFiles 에서 extracted_text 를 명시적으로 선택(select:false 우회)
- 공용 AttachmentAiBadge 컴포넌트 추가 → 프로젝트 상세·설정 문서 목록에 적용

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-23 15:10:20 +09:00
parent d964f9101a
commit e719829f0b
6 changed files with 124 additions and 6 deletions
@@ -0,0 +1,72 @@
<script setup lang="ts">
// 프로젝트 문서의 AI 추천 반영 상태 배지
// ready: 반영 가능 / failed: 추출 실패 / unsupported: 미지원 형식
import { computed } from 'vue'
interface Props {
status: 'ready' | 'failed' | 'unsupported'
}
const props = defineProps<Props>()
// 상태별 라벨·툴팁·스타일 클래스
const META: Record<Props['status'], { label: string; title: string; cls: string }> = {
ready: {
label: 'AI 반영',
title: 'AI 업무 추천에 이 문서 내용이 반영됩니다.',
cls: 'ok',
},
failed: {
label: '추출 실패',
title: '문서에서 텍스트를 추출하지 못해 AI 추천에 반영되지 않습니다.',
cls: 'warn',
},
unsupported: {
label: 'AI 반영 불가',
title: '미지원 형식이라 AI 추천에 반영되지 않습니다. (txt·csv·pdf·docx 지원)',
cls: 'muted',
},
}
const meta = computed(() => META[props.status])
</script>
<template>
<span
class="ai-badge"
:class="meta.cls"
:title="meta.title"
>
{{ meta.label }}
</span>
</template>
<style scoped>
.ai-badge {
flex-shrink: 0;
display: inline-flex;
align-items: center;
height: 1.25rem;
padding: 0 0.4375rem;
border-radius: 0.3125rem;
border: 1px solid transparent;
font-size: 0.6875rem;
font-weight: 600;
white-space: nowrap;
cursor: default;
}
.ai-badge.ok {
color: var(--green);
background: var(--green-weak);
border-color: var(--green-border);
}
.ai-badge.warn {
color: var(--amber);
background: var(--amber-weak);
border-color: var(--amber-border);
}
.ai-badge.muted {
color: var(--text-3);
background: #f3f4f6;
border-color: var(--border);
}
</style>