feat: 솔루션 포털 홈페이지 이식 + 솔루션 소개 최신화 + 통합 메신저앱 QR 페이지 추가
This commit is contained in:
parent
95f8106f82
commit
bb6bc69c68
@ -18,6 +18,7 @@ import TagBindingList from './pages/TagBindingList'
|
||||
import UpdateQueueList from './pages/UpdateQueueList'
|
||||
import AuditLog from './pages/AuditLog'
|
||||
import SystemSettings from './pages/SystemSettings'
|
||||
import MobileApp from './pages/MobileApp'
|
||||
import WorklogList from './pages/uiws/WorklogList'
|
||||
import ScheduleCalendar from './pages/uiws/ScheduleCalendar'
|
||||
import MessageBox from './pages/uiws/MessageBox'
|
||||
@ -52,6 +53,7 @@ export default function App() {
|
||||
<Route path="/schedules" element={<ScheduleCalendar />} />
|
||||
<Route path="/messages" element={<MessageBox />} />
|
||||
<Route path="/work-stats" element={<StatsPivot />} />
|
||||
<Route path="/mobile-app" element={<MobileApp />} />
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/dashboard" replace />} />
|
||||
</Routes>
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
LayoutDashboard, Store, FileText, RefreshCw,
|
||||
Bell, Cpu, ClipboardList, Zap, Users, Package, Building2, Brain,
|
||||
Link2, ListOrdered, NotebookPen, CalendarDays, Mail, BarChart3,
|
||||
ScrollText, Settings
|
||||
ScrollText, Settings, Smartphone
|
||||
} from 'lucide-react'
|
||||
|
||||
const nav = [
|
||||
@ -27,6 +27,7 @@ const nav = [
|
||||
{ to: '/schedules', icon: CalendarDays, label: '일정 관리' },
|
||||
{ to: '/messages', icon: Mail, label: '쪽지' },
|
||||
{ to: '/work-stats', icon: BarChart3, label: '업무 통계' },
|
||||
{ to: '/mobile-app', icon: Smartphone, label: '모바일 앱 설치' },
|
||||
]
|
||||
|
||||
export default function Sidebar() {
|
||||
|
||||
123
frontend/src/pages/MobileApp.tsx
Normal file
123
frontend/src/pages/MobileApp.tsx
Normal file
@ -0,0 +1,123 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Smartphone, Download, Copy, Check, ExternalLink, RefreshCw } from 'lucide-react'
|
||||
|
||||
// 중앙 APK 저장소(ITSM)의 공개 엔드포인트 — 인증 불필요·CORS 허용 (읽기전용)
|
||||
// 업로드·버전 관리는 GUARDiA Manager/ITSM에서 일원화. 본 화면은 표시 전용.
|
||||
const ITSM_APP_BASE = 'https://zioinfo.co.kr:8443'
|
||||
|
||||
interface AppInfo {
|
||||
has_version: boolean
|
||||
app_name?: string
|
||||
version?: string
|
||||
platform?: string
|
||||
file_size_mb?: number
|
||||
release_notes?: string
|
||||
download_count?: number
|
||||
qr_url?: string
|
||||
landing_url?: string
|
||||
download_url?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export default function MobileApp() {
|
||||
const [info, setInfo] = useState<AppInfo | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [err, setErr] = useState('')
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const load = () => {
|
||||
setLoading(true); setErr('')
|
||||
fetch(`${ITSM_APP_BASE}/api/app/public-latest`)
|
||||
.then(r => r.json())
|
||||
.then((d: AppInfo) => setInfo(d))
|
||||
.catch(() => setErr('버전 정보를 불러올 수 없습니다. (중앙 앱 저장소 연결 실패)'))
|
||||
.finally(() => setLoading(false))
|
||||
}
|
||||
useEffect(() => { load() }, [])
|
||||
|
||||
const copyLink = async () => {
|
||||
if (!info?.landing_url) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(info.landing_url)
|
||||
setCopied(true); setTimeout(() => setCopied(false), 2000)
|
||||
} catch { /* clipboard 권한 없을 때 무시 */ }
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Smartphone className="text-brand" size={22} />
|
||||
<h1 className="text-xl font-bold">GUARDiA 통합 메신저 앱 설치</h1>
|
||||
</div>
|
||||
<button onClick={load} className="flex items-center gap-1.5 px-3 py-2 rounded-lg bg-card border border-edge text-sm text-slate-300 hover:text-brand">
|
||||
<RefreshCw size={15} /> 새로고침
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-slate-400 mb-6">
|
||||
QR 코드를 스캔하면 <span className="text-brand font-semibold">GUARDiA Messenger</span> 앱 설치 페이지로 이동합니다.
|
||||
앱스토어 설치가 필요 없으며, 앱 업로드·버전 관리는 GUARDiA Manager에서 일원화되어 있습니다.
|
||||
</p>
|
||||
|
||||
{loading && <div className="text-slate-400 text-sm">불러오는 중…</div>}
|
||||
{err && <div className="bg-card border border-edge rounded-xl p-6 text-rose-400 text-sm">{err}</div>}
|
||||
|
||||
{!loading && !err && info && !info.has_version && (
|
||||
<div className="bg-card border border-edge rounded-xl p-8 text-center text-slate-400">
|
||||
<Smartphone size={36} className="mx-auto mb-3 text-slate-600" />
|
||||
아직 등록된 앱 버전이 없습니다.<br />
|
||||
<span className="text-xs">GUARDiA Manager에서 APK를 업로드하면 여기에 QR이 표시됩니다.</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!loading && !err && info?.has_version && (
|
||||
<div className="bg-card border border-edge rounded-xl p-6 grid md:grid-cols-[200px_1fr] gap-6 items-start">
|
||||
<div className="bg-white rounded-xl p-3 flex items-center justify-center">
|
||||
<img src={info.qr_url} alt="앱 설치 QR" className="w-44 h-44" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span className="text-lg font-bold">{info.app_name || 'GUARDiA Messenger'}</span>
|
||||
<span className="px-2 py-0.5 rounded-md bg-brand2 text-white text-xs font-semibold">v{info.version}</span>
|
||||
</div>
|
||||
<div className="text-xs text-slate-400 mb-4">
|
||||
{info.platform} · {info.file_size_mb ? `${info.file_size_mb}MB` : ''}
|
||||
{info.download_count != null && ` · 다운로드 ${info.download_count}회`}
|
||||
</div>
|
||||
|
||||
{info.release_notes && (
|
||||
<div className="mb-4">
|
||||
<div className="text-[11px] font-semibold text-slate-500 uppercase tracking-wider mb-1">변경점</div>
|
||||
<div className="text-sm text-slate-300 whitespace-pre-line bg-ink border border-edge rounded-lg p-3 max-h-32 overflow-auto">
|
||||
{info.release_notes}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<a href={info.landing_url} target="_blank" rel="noreferrer"
|
||||
className="flex items-center gap-1.5 px-3 py-2 rounded-lg bg-brand text-ink text-sm font-semibold">
|
||||
<ExternalLink size={15} /> 설치 페이지 열기
|
||||
</a>
|
||||
<a href={info.download_url} target="_blank" rel="noreferrer"
|
||||
className="flex items-center gap-1.5 px-3 py-2 rounded-lg bg-card border border-edge text-sm text-slate-300 hover:text-brand">
|
||||
<Download size={15} /> APK 직접 다운로드
|
||||
</a>
|
||||
<button onClick={copyLink}
|
||||
className="flex items-center gap-1.5 px-3 py-2 rounded-lg bg-card border border-edge text-sm text-slate-300 hover:text-brand">
|
||||
{copied ? <Check size={15} className="text-accent" /> : <Copy size={15} />}
|
||||
{copied ? '복사됨' : '다운로드 링크 복사'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 text-[12px] text-slate-500 leading-relaxed">
|
||||
📱 Android: APK 다운로드 후 설정 → 보안 → "알 수 없는 소스" 허용 → 설치.
|
||||
앱스토어 등록이 필요 없습니다.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user