Initial commit

This commit is contained in:
2025-11-20 23:21:05 +08:00
commit 13bc6db529
378 changed files with 54527 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
<?php
namespace App\Http\Controllers;
use App\Models\Document;
use App\Models\DocumentCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class PublicDocumentController extends Controller
{
/**
* Display the document library (public + member access)
*/
public function index(Request $request)
{
$query = Document::with(['category', 'currentVersion'])
->where('status', 'active');
// Filter based on user's access level
$user = auth()->user();
if (!$user) {
// Only public documents for guests
$query->where('access_level', 'public');
} elseif (!$user->is_admin && !$user->hasRole('admin')) {
// Members can see public + members-only
$query->whereIn('access_level', ['public', 'members']);
}
// Admins can see all documents
// Filter by category
if ($request->filled('category')) {
$query->where('document_category_id', $request->category);
}
// Search
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('title', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
$documents = $query->orderBy('created_at', 'desc')->paginate(20);
// Get categories with document counts (based on user's access)
$categories = DocumentCategory::withCount([
'activeDocuments' => function($query) use ($user) {
if (!$user) {
$query->where('access_level', 'public');
} elseif (!$user->is_admin && !$user->hasRole('admin')) {
$query->whereIn('access_level', ['public', 'members']);
}
}
])->orderBy('sort_order')->get();
return view('documents.index', compact('documents', 'categories'));
}
/**
* Show a document via its public UUID
*/
public function show(string $uuid)
{
$document = Document::where('public_uuid', $uuid)
->where('status', 'active')
->with(['category', 'currentVersion', 'versions.uploadedBy'])
->firstOrFail();
// Check access permission
$user = auth()->user();
if (!$document->canBeViewedBy($user)) {
if (!$user) {
return redirect()->route('login')->with('error', '請先登入以檢視此文件');
}
abort(403, '您沒有權限檢視此文件');
}
// Log access
$document->logAccess('view', $user);
return view('documents.show', compact('document'));
}
/**
* Download the current version of a document
*/
public function download(string $uuid)
{
$document = Document::where('public_uuid', $uuid)
->where('status', 'active')
->firstOrFail();
// Check access permission
$user = auth()->user();
if (!$document->canBeViewedBy($user)) {
if (!$user) {
return redirect()->route('login')->with('error', '請先登入以下載此文件');
}
abort(403, '您沒有權限下載此文件');
}
$currentVersion = $document->currentVersion;
if (!$currentVersion || !$currentVersion->fileExists()) {
abort(404, '檔案不存在');
}
// Log access
$document->logAccess('download', $user);
return Storage::disk('private')->download(
$currentVersion->file_path,
$currentVersion->original_filename
);
}
/**
* Download a specific version (if user has access)
*/
public function downloadVersion(string $uuid, int $versionId)
{
$document = Document::where('public_uuid', $uuid)
->where('status', 'active')
->firstOrFail();
// Check access permission
$user = auth()->user();
if (!$document->canBeViewedBy($user)) {
abort(403, '您沒有權限下載此文件');
}
$version = $document->versions()->findOrFail($versionId);
if (!$version->fileExists()) {
abort(404, '檔案不存在');
}
// Log access
$document->logAccess('download', $user);
return Storage::disk('private')->download(
$version->file_path,
$version->original_filename
);
}
/**
* Generate and download QR code for document
*/
public function downloadQRCode(string $uuid)
{
// Check if QR code feature is enabled
$settings = app(\App\Services\SettingsService::class);
if (!$settings->isFeatureEnabled('qr_codes')) {
abort(404, 'QR Code 功能未啟用');
}
// Check user permission
$user = auth()->user();
if ($user && !$user->can('use_qr_codes')) {
abort(403, '您沒有使用 QR Code 功能的權限');
}
$document = Document::where('public_uuid', $uuid)->firstOrFail();
// Check document access
if (!$document->canBeViewedBy($user)) {
abort(403);
}
// Use default size from system settings
$qrCode = $document->generateQRCodePNG();
return response($qrCode, 200)
->header('Content-Type', 'image/png')
->header('Content-Disposition', 'attachment; filename="qrcode-' . $document->id . '.png"');
}
}