diff --git a/app/Http/Controllers/AppVersionController.php b/app/Http/Controllers/AppVersionController.php new file mode 100644 index 00000000..a8f42528 --- /dev/null +++ b/app/Http/Controllers/AppVersionController.php @@ -0,0 +1,71 @@ +appVersionService->list(); + + return view('app-versions.index', compact('versions')); + } + + /** + * 새 버전 등록 + */ + public function store(Request $request): RedirectResponse + { + $request->validate([ + 'version_code' => 'required|integer|min:1|unique:app_versions,version_code', + 'version_name' => 'required|string|max:20', + 'platform' => 'required|in:android,ios', + 'release_notes' => 'nullable|string', + 'force_update' => 'nullable|boolean', + 'apk_file' => 'nullable|file|max:204800', // 200MB + ]); + + $this->appVersionService->store( + $request->only(['version_code', 'version_name', 'platform', 'release_notes', 'force_update']), + $request->file('apk_file') + ); + + return redirect()->route('app-versions.index') + ->with('success', '새 버전이 등록되었습니다.'); + } + + /** + * 활성 토글 + */ + public function toggleActive(int $id): RedirectResponse + { + $version = $this->appVersionService->toggleActive($id); + $status = $version->is_active ? '활성화' : '비활성화'; + + return redirect()->route('app-versions.index') + ->with('success', "v{$version->version_name}이 {$status}되었습니다."); + } + + /** + * 삭제 + */ + public function destroy(int $id): RedirectResponse + { + $this->appVersionService->destroy($id); + + return redirect()->route('app-versions.index') + ->with('success', '버전이 삭제되었습니다.'); + } +} diff --git a/app/Models/AppVersion.php b/app/Models/AppVersion.php new file mode 100644 index 00000000..4129a645 --- /dev/null +++ b/app/Models/AppVersion.php @@ -0,0 +1,36 @@ + 'integer', + 'apk_size' => 'integer', + 'force_update' => 'boolean', + 'is_active' => 'boolean', + 'download_count' => 'integer', + 'published_at' => 'datetime', + ]; +} diff --git a/app/Services/AppVersionService.php b/app/Services/AppVersionService.php new file mode 100644 index 00000000..b70439dd --- /dev/null +++ b/app/Services/AppVersionService.php @@ -0,0 +1,65 @@ +paginate($perPage); + } + + /** + * 새 버전 등록 + */ + public function store(array $data, ?UploadedFile $apkFile = null): AppVersion + { + if ($apkFile) { + $data['apk_original_name'] = $apkFile->getClientOriginalName(); + $data['apk_size'] = $apkFile->getSize(); + $data['apk_path'] = $apkFile->store('apk', 'app_releases'); + } + + $data['created_by'] = auth()->id(); + $data['published_at'] = $data['published_at'] ?? now(); + + return AppVersion::create($data); + } + + /** + * 활성 토글 + */ + public function toggleActive(int $id): AppVersion + { + $version = AppVersion::findOrFail($id); + $version->is_active = ! $version->is_active; + $version->updated_by = auth()->id(); + $version->save(); + + return $version; + } + + /** + * 삭제 + */ + public function destroy(int $id): void + { + $version = AppVersion::findOrFail($id); + + // APK 파일 삭제 + if ($version->apk_path && Storage::disk('app_releases')->exists($version->apk_path)) { + Storage::disk('app_releases')->delete($version->apk_path); + } + + $version->delete(); + } +} diff --git a/config/filesystems.php b/config/filesystems.php index 902cb1fa..6413fd2e 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -66,6 +66,14 @@ 'report' => false, ], + 'app_releases' => [ + 'driver' => 'local', + 'root' => env('APP_RELEASES_PATH', '/var/www/shared-storage/releases'), + 'visibility' => 'private', + 'throw' => false, + 'report' => false, + ], + 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), diff --git a/resources/views/app-versions/index.blade.php b/resources/views/app-versions/index.blade.php new file mode 100644 index 00000000..da81cc39 --- /dev/null +++ b/resources/views/app-versions/index.blade.php @@ -0,0 +1,169 @@ +@extends('layouts.app') + +@section('title', '앱 버전 관리') + +@section('content') +
| 버전 | +플랫폼 | +변경사항 | +강제 | +활성 | +다운로드 | +APK | +배포일 | +관리 | +
|---|---|---|---|---|---|---|---|---|
|
+ v{{ $version->version_name }}
+ code: {{ $version->version_code }}
+ |
+ + {{ strtoupper($version->platform) }} + | ++ {{ $version->release_notes ? \Illuminate\Support\Str::limit($version->release_notes, 60) : '-' }} + | ++ @if($version->force_update) + 필수 + @else + - + @endif + | ++ + | ++ {{ number_format($version->download_count) }} + | ++ @if($version->apk_path) + + {{ $version->apk_original_name ? \Illuminate\Support\Str::limit($version->apk_original_name, 20) : 'APK' }} + + @if($version->apk_size) + ({{ number_format($version->apk_size / 1024 / 1024, 1) }}MB) + @endif + @else + - + @endif + | ++ {{ $version->published_at?->format('Y-m-d') ?? '-' }} + | ++ + | +
| 등록된 버전이 없습니다. | +||||||||