WORKSPACE / DEVELOPER

Upload và quản lý APK

Chưa Public? Upload lại nhiều lần cùng version để fix bug, giữ nguyên QR cho tester.

{{ strtoupper(substr(auth()->user()->name ?? 'D', 0, 1)) }} Đang xem với vai trò {{ auth()->user()->role ?? 'Developer' }} {{ auth()->user()->name ?? 'Developer' }}
↻
Build mới, không tạo version mới

Với cùng package, Version Name, Version Code và kênh, hệ thống tự tăng Build #, trả trạng thái về Chờ test và không đổi QR.

Đẩy APK mới / upload bản fix bug

Tải file .apk từ máy bạn, nhập thông tin release rồi gửi test.

Dev portal
{{-- Widget Giám Sát Dung Lượng Cloudflare R2 (Hạn mức 10GB Miễn Phí) --}} @if (auth()->user()->role == 'Admin')
Cloudflare R2 Đang kiểm tra dung lượng...
Lưu trữ đường dẫn: {ST_APP}/{Version}/{file} · Miễn phí 10 GB 🟢 An toàn
@endif
@csrf
{{-- Custom searchable select --}}
+ Ứng dụng mới
{{-- Hidden select để giữ tương thích với JS cũ đang lắng nghe #demoSelectApp --}}
Cùng version chưa Public → tự tạo build tiếp theo.
{{-- Progress Bar Chunk Upload --}}

Version & lịch sử build

Chỉ hiển thị các version do Developer đang chọn phụ trách.

@forelse ($releases as $rel) @php $app = $rel->appAndroid ?? $rel->appIos; $appName = $app?->app_name ?? '?'; $stApp = $app?->st_app ?? '?'; $initial = strtoupper(mb_substr($appName, 0, 1)); $colors = [ '#6366F1', '#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#14B8A6', ]; $bgColor = $colors[$rel->id % count($colors)]; $latestBuild = $rel->builds->first(); $buildCount = $rel->builds->count(); $statusMap = [ 'waiting' => ['label' => 'Chờ test', 'css' => 'waiting'], 'testing' => ['label' => 'Đang test', 'css' => 'testing'], 'failed' => ['label' => 'Cần sửa', 'css' => 'failed'], 'passed' => ['label' => 'Pass', 'css' => 'passed'], ]; $st = $rel->isPublished() ? ['label' => 'Published', 'css' => 'published'] : $statusMap[$rel->test_status] ?? [ 'label' => $rel->test_status, 'css' => 'waiting', ]; // Lấy thông tin tester: Người đã test (từ reports) hoặc Tester được phân công phụ trách app $testedBy = $rel->reports->pluck('tester.name')->filter()->unique()->implode(', '); $assignedTesters = ''; if (empty($testedBy) && !empty($app?->tester_ids)) { if (isset($testerUsers)) { $assignedTesters = collect($app->tester_ids) ->map(fn($uid) => $testerUsers[$uid] ?? null) ->filter() ->unique() ->implode(', '); } elseif (method_exists($app, 'getTestersAttribute')) { $assignedTesters = $app->testers->pluck('name')->implode(', '); } } $testerDisplay = $testedBy ?: $assignedTesters; @endphp {{-- Ứng dụng --}} {{-- Version & lượt upload --}} {{-- QA --}} {{-- Lần cập nhật --}} {{-- Thao tác --}} @empty @endforelse
Ứng dụng Version & lượt upload QA Lần cập nhật Thao tác
@php $devPkg = $app?->package ?? ''; @endphp @if (!empty($devPkg))
{{ $appName }} {{ $initial }}
@else {{ $initial }} @endif
{{ $stApp }} - {{ $appName }}
{{ $app?->package }}
v{{ $rel->version_name }} @if ($latestBuild) Build #{{ $latestBuild->revision }} @endif
{{--
@if ($rel->version_code) Code {{ $rel->version_code }} · @endif QA
--}} {{-- Lịch sử thu gọn --}} @if ($buildCount > 0)
▶ {{ $buildCount }} lần upload
    @foreach ($rel->builds as $b)
  • #{{ $b->revision }} {{ $b->created_at?->format('d/m H:i') }} @if ($b->notes) · {{ Str::limit($b->notes, 60) }} @endif
  • @endforeach
@endif
{{ $st['label'] }} @if ($rel->isPublished() && ($rel->publisher || $rel->published_at))
Public: {{ $rel->publisher?->name ?? 'Admin' }}
@endif @if ($testerDisplay)
{{ $testerDisplay }}
@else
Chưa phân công
@endif
{{ $rel->updated_at?->format('d/m H:i') }} @if ($rel->uploader)
{{ $rel->uploader->name }}
@endif
{{-- QR / Link --}} {{-- Upload lại --}} @if (!$rel->isPublished()) @endif {{-- Tải bản APK thông thường --}} @if ($latestBuild) ↓ Tải @endif {{-- Tải & Upload bản No-Ads (Chỉ hiển thị khi đã Published, mỗi app chỉ 1 file duy nhất hoặc APK hoặc AAB) --}} @if ($rel->isPublished()) @php $noadsFile = $rel->noads_apk_path ?: $rel->noads_aab_path; $noadsExt = $noadsFile ? strtoupper(pathinfo($noadsFile, PATHINFO_EXTENSION)) : ''; @endphp @if ($noadsFile) ↓ {{ $noadsExt }} No-Ads @endif @endif {{-- Public (chỉ Admin, khi passed) --}} @if (!$rel->isPublished() && ($isAdmin ?? false) && $rel->test_status === 'passed')
@csrf
@endif
Chưa có bản upload nào. Dùng form bên trên để upload APK đầu tiên.
@if ($releases->count()) {{ $releases->count() }} version · {{ $releases->sum(fn($r) => $r->builds->count()) }} build @endif
{{-- Modal Upload Bản APK / AAB Không Có Ads (No-Ads) --}}