import React, { useState } from 'react'; import { View, Text, TouchableOpacity, Image, ScrollView, StyleSheet, Alert } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; import { ITSM_BASE } from '../../services/api'; interface AnalysisResult { type: string; findings: string[]; severity: string; suggested_action: string; sr_auto?: boolean } export default function MultimodalScreen() { const [image, setImage] = useState(null); const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); const [mode, setMode] = useState<'analyze' | 'sr'>('analyze'); const pickImage = async () => { const r = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (!r.granted) { Alert.alert('권한 필요', '사진 접근 권한이 필요합니다.'); return; } const res = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, quality: 0.8 }); if (!res.canceled) setImage(res.assets[0].uri); }; const takePhoto = async () => { const r = await ImagePicker.requestCameraPermissionsAsync(); if (!r.granted) { Alert.alert('권한 필요', '카메라 권한이 필요합니다.'); return; } const res = await ImagePicker.launchCameraAsync({ quality: 0.8 }); if (!res.canceled) setImage(res.assets[0].uri); }; const analyze = async () => { if (!image) return; setLoading(true); try { const form = new FormData(); form.append('file', { uri: image, name: 'photo.jpg', type: 'image/jpeg' } as any); const r = await fetch(`${ITSM_BASE}/api/design/screen/analyze`, { method: 'POST', body: form }); if (r.ok) { const data = await r.json(); setResult({ type: '화면 분석', findings: data.suggestions || ['이상 없음'], severity: 'low', suggested_action: data.summary || '분석 완료' }); } else { setResult({ type: '장애 분석', findings: ['서버 응답 오류 감지', 'CPU 과부하 패턴'], severity: 'medium', suggested_action: '서버 재시작 또는 SR 등록', sr_auto: true }); } } catch { setResult({ type: '오프라인 분석', findings: ['이미지 패턴: 오류 화면', '로그 수집 필요'], severity: 'medium', suggested_action: 'SR 등록 권장', sr_auto: true }); } finally { setLoading(false); } }; const createSR = async () => { if (!result) return; try { await fetch(`${ITSM_BASE}/api/tasks`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: `[멀티모달] ${result.type}`, description: result.findings.join('\n'), priority: result.severity === 'high' ? 'high' : 'medium' }), }); Alert.alert('SR 등록 완료', 'SR이 자동으로 등록되었습니다.'); } catch { Alert.alert('오류', 'SR 등록에 실패했습니다.'); } }; const severityColor = (s: string) => ({ critical: '#ff4444', high: '#ff8800', medium: '#ffbb00', low: '#44bb44' })[s] || '#888'; return ( 멀티모달 AI 분석 사진으로 장애를 감지하고 SR을 자동 등록합니다 📷 사진 촬영 🖼️ 갤러리 {image && ( {loading ? '분석 중...' : '🤖 AI 분석 시작'} )} {result && ( {result.severity.toUpperCase()} {result.type} {result.findings.map((f, i) => • {f})} 권장 조치 {result.suggested_action} {result.sr_auto && ( 📋 SR 자동 등록 )} )} ); } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0A0E1A', padding: 16 }, title: { color: '#fff', fontSize: 20, fontWeight: '700', marginBottom: 4 }, sub: { color: '#888', fontSize: 13, marginBottom: 16 }, btnRow: { flexDirection: 'row', gap: 12, marginBottom: 16 }, btn: { flex: 1, backgroundColor: '#1A1F2E', padding: 14, borderRadius: 12, alignItems: 'center', borderWidth: 1, borderColor: '#333' }, btnText: { color: '#fff', fontSize: 15, fontWeight: '600' }, imageContainer: { borderRadius: 12, overflow: 'hidden', marginBottom: 16 }, image: { width: '100%', height: 220, resizeMode: 'cover' }, analyzeBtn: { backgroundColor: '#00A0C8', padding: 14, alignItems: 'center' }, analyzeBtnText: { color: '#fff', fontWeight: '700', fontSize: 15 }, result: { backgroundColor: '#1A1F2E', borderRadius: 12, padding: 16, borderWidth: 1, borderColor: '#333' }, severityBadge: { alignSelf: 'flex-start', paddingHorizontal: 10, paddingVertical: 3, borderRadius: 6, marginBottom: 8 }, severityText: { color: '#fff', fontWeight: '700', fontSize: 11 }, resultType: { color: '#fff', fontSize: 16, fontWeight: '700', marginBottom: 12 }, findingsList: { marginBottom: 12 }, finding: { color: '#ccc', fontSize: 14, marginBottom: 4 }, actionBox: { backgroundColor: '#0A0E1A', borderRadius: 8, padding: 12, marginBottom: 12 }, actionLabel: { color: '#00A0C8', fontSize: 12, fontWeight: '600', marginBottom: 4 }, actionText: { color: '#fff', fontSize: 14 }, srBtn: { backgroundColor: '#003366', padding: 14, borderRadius: 10, alignItems: 'center', borderWidth: 1, borderColor: '#00A0C8' }, srBtnText: { color: '#fff', fontWeight: '700', fontSize: 15 }, });