Initial commit
This commit is contained in:
385
app/Http/Controllers/Admin/DocumentController.php
Normal file
385
app/Http/Controllers/Admin/DocumentController.php
Normal file
@@ -0,0 +1,385 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AuditLog;
|
||||
use App\Models\Document;
|
||||
use App\Models\DocumentCategory;
|
||||
use App\Models\DocumentVersion;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DocumentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of documents
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = Document::with(['category', 'currentVersion', 'createdBy'])
|
||||
->orderBy('created_at', 'desc');
|
||||
|
||||
// Filter by category
|
||||
if ($request->filled('category')) {
|
||||
$query->where('document_category_id', $request->category);
|
||||
}
|
||||
|
||||
// Filter by access level
|
||||
if ($request->filled('access_level')) {
|
||||
$query->where('access_level', $request->access_level);
|
||||
}
|
||||
|
||||
// Filter by status
|
||||
if ($request->filled('status')) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
// Search
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('title', 'like', "%{$search}%")
|
||||
->orWhere('document_number', 'like', "%{$search}%")
|
||||
->orWhere('description', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
$documents = $query->paginate(20);
|
||||
$categories = DocumentCategory::orderBy('sort_order')->get();
|
||||
|
||||
return view('admin.documents.index', compact('documents', 'categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new document
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$categories = DocumentCategory::orderBy('sort_order')->get();
|
||||
return view('admin.documents.create', compact('categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created document with initial version
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'document_category_id' => 'required|exists:document_categories,id',
|
||||
'title' => 'required|string|max:255',
|
||||
'document_number' => 'nullable|string|max:255|unique:documents,document_number',
|
||||
'description' => 'nullable|string',
|
||||
'access_level' => 'required|in:public,members,admin,board',
|
||||
'file' => 'required|file|max:10240', // 10MB max
|
||||
'version_notes' => 'nullable|string',
|
||||
]);
|
||||
|
||||
// Upload file
|
||||
$file = $request->file('file');
|
||||
$path = $file->store('documents', 'private');
|
||||
|
||||
// Create document
|
||||
$document = Document::create([
|
||||
'document_category_id' => $validated['document_category_id'],
|
||||
'title' => $validated['title'],
|
||||
'document_number' => $validated['document_number'],
|
||||
'description' => $validated['description'],
|
||||
'access_level' => $validated['access_level'],
|
||||
'status' => 'active',
|
||||
'created_by_user_id' => auth()->id(),
|
||||
'version_count' => 0,
|
||||
]);
|
||||
|
||||
// Add first version
|
||||
$document->addVersion(
|
||||
filePath: $path,
|
||||
originalFilename: $file->getClientOriginalName(),
|
||||
mimeType: $file->getMimeType(),
|
||||
fileSize: $file->getSize(),
|
||||
uploadedBy: auth()->user(),
|
||||
versionNotes: $validated['version_notes'] ?? '初始版本'
|
||||
);
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.created',
|
||||
'description' => "建立文件:{$document->title}",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return redirect()
|
||||
->route('admin.documents.show', $document)
|
||||
->with('status', '文件已成功建立');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified document
|
||||
*/
|
||||
public function show(Document $document)
|
||||
{
|
||||
$document->load(['category', 'versions.uploadedBy', 'createdBy', 'lastUpdatedBy', 'accessLogs.user']);
|
||||
$versionHistory = $document->getVersionHistory();
|
||||
|
||||
return view('admin.documents.show', compact('document', 'versionHistory'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the document metadata
|
||||
*/
|
||||
public function edit(Document $document)
|
||||
{
|
||||
$categories = DocumentCategory::orderBy('sort_order')->get();
|
||||
return view('admin.documents.edit', compact('document', 'categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the document metadata (not the file)
|
||||
*/
|
||||
public function update(Request $request, Document $document)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'document_category_id' => 'required|exists:document_categories,id',
|
||||
'title' => 'required|string|max:255',
|
||||
'document_number' => 'nullable|string|max:255|unique:documents,document_number,' . $document->id,
|
||||
'description' => 'nullable|string',
|
||||
'access_level' => 'required|in:public,members,admin,board',
|
||||
]);
|
||||
|
||||
$document->update([
|
||||
...$validated,
|
||||
'last_updated_by_user_id' => auth()->id(),
|
||||
]);
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.updated',
|
||||
'description' => "更新文件資訊:{$document->title}",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return redirect()
|
||||
->route('admin.documents.show', $document)
|
||||
->with('status', '文件資訊已成功更新');
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a new version of the document
|
||||
*/
|
||||
public function uploadNewVersion(Request $request, Document $document)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'file' => 'required|file|max:10240', // 10MB max
|
||||
'version_notes' => 'required|string',
|
||||
]);
|
||||
|
||||
// Upload file
|
||||
$file = $request->file('file');
|
||||
$path = $file->store('documents', 'private');
|
||||
|
||||
// Add new version
|
||||
$version = $document->addVersion(
|
||||
filePath: $path,
|
||||
originalFilename: $file->getClientOriginalName(),
|
||||
mimeType: $file->getMimeType(),
|
||||
fileSize: $file->getSize(),
|
||||
uploadedBy: auth()->user(),
|
||||
versionNotes: $validated['version_notes']
|
||||
);
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.version_uploaded',
|
||||
'description' => "上傳新版本:{$document->title} (版本 {$version->version_number})",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return back()->with('status', "新版本 {$version->version_number} 已成功上傳");
|
||||
}
|
||||
|
||||
/**
|
||||
* Promote an old version to current
|
||||
*/
|
||||
public function promoteVersion(Document $document, DocumentVersion $version)
|
||||
{
|
||||
if ($version->document_id !== $document->id) {
|
||||
return back()->with('error', '版本不符合');
|
||||
}
|
||||
|
||||
$document->promoteVersion($version, auth()->user());
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.version_promoted',
|
||||
'description' => "提升版本為當前版本:{$document->title} (版本 {$version->version_number})",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return back()->with('status', "版本 {$version->version_number} 已設為當前版本");
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a specific version
|
||||
*/
|
||||
public function downloadVersion(Document $document, DocumentVersion $version)
|
||||
{
|
||||
if ($version->document_id !== $document->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
if (!$version->fileExists()) {
|
||||
abort(404, '檔案不存在');
|
||||
}
|
||||
|
||||
// Log access
|
||||
$document->logAccess('download', auth()->user());
|
||||
|
||||
return Storage::disk('private')->download(
|
||||
$version->file_path,
|
||||
$version->original_filename
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Archive a document
|
||||
*/
|
||||
public function archive(Document $document)
|
||||
{
|
||||
$document->archive();
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.archived',
|
||||
'description' => "封存文件:{$document->title}",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return back()->with('status', '文件已封存');
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore an archived document
|
||||
*/
|
||||
public function restore(Document $document)
|
||||
{
|
||||
$document->unarchive();
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.restored',
|
||||
'description' => "恢復文件:{$document->title}",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return back()->with('status', '文件已恢復');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a document permanently
|
||||
*/
|
||||
public function destroy(Document $document)
|
||||
{
|
||||
$title = $document->title;
|
||||
|
||||
// Delete all version files
|
||||
foreach ($document->versions as $version) {
|
||||
if ($version->fileExists()) {
|
||||
Storage::disk('private')->delete($version->file_path);
|
||||
}
|
||||
}
|
||||
|
||||
$document->delete();
|
||||
|
||||
// Audit log
|
||||
AuditLog::create([
|
||||
'user_id' => auth()->id(),
|
||||
'action' => 'document.deleted',
|
||||
'description' => "刪除文件:{$title}",
|
||||
'ip_address' => request()->ip(),
|
||||
]);
|
||||
|
||||
return redirect()
|
||||
->route('admin.documents.index')
|
||||
->with('status', '文件已永久刪除');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display document statistics dashboard
|
||||
*/
|
||||
public function statistics()
|
||||
{
|
||||
// Check if statistics feature is enabled
|
||||
$settings = app(\App\Services\SettingsService::class);
|
||||
if (!$settings->isFeatureEnabled('statistics')) {
|
||||
abort(404, '統計功能未啟用');
|
||||
}
|
||||
|
||||
// Check user permission
|
||||
if (!auth()->user()->can('view_document_statistics')) {
|
||||
abort(403, '您沒有檢視文件統計的權限');
|
||||
}
|
||||
|
||||
$stats = [
|
||||
'total_documents' => Document::where('status', 'active')->count(),
|
||||
'total_versions' => \App\Models\DocumentVersion::count(),
|
||||
'total_downloads' => Document::sum('download_count'),
|
||||
'total_views' => Document::sum('view_count'),
|
||||
'archived_documents' => Document::where('status', 'archived')->count(),
|
||||
];
|
||||
|
||||
// Documents by category
|
||||
$documentsByCategory = DocumentCategory::withCount(['activeDocuments'])
|
||||
->orderBy('active_documents_count', 'desc')
|
||||
->get();
|
||||
|
||||
// Most viewed documents
|
||||
$mostViewed = Document::with(['category', 'currentVersion'])
|
||||
->where('status', 'active')
|
||||
->orderBy('view_count', 'desc')
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
// Most downloaded documents
|
||||
$mostDownloaded = Document::with(['category', 'currentVersion'])
|
||||
->where('status', 'active')
|
||||
->orderBy('download_count', 'desc')
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
// Recent activity (last 30 days)
|
||||
$recentActivity = \App\Models\DocumentAccessLog::with(['user', 'document'])
|
||||
->where('accessed_at', '>=', now()->subDays(30))
|
||||
->latest('accessed_at')
|
||||
->limit(50)
|
||||
->get();
|
||||
|
||||
// Monthly upload trends (last 6 months)
|
||||
$uploadTrends = Document::selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month, COUNT(*) as count')
|
||||
->where('created_at', '>=', now()->subMonths(6))
|
||||
->groupBy('month')
|
||||
->orderBy('month', 'desc')
|
||||
->get();
|
||||
|
||||
// Access level distribution
|
||||
$accessLevelStats = Document::selectRaw('access_level, COUNT(*) as count')
|
||||
->where('status', 'active')
|
||||
->groupBy('access_level')
|
||||
->get();
|
||||
|
||||
return view('admin.documents.statistics', compact(
|
||||
'stats',
|
||||
'documentsByCategory',
|
||||
'mostViewed',
|
||||
'mostDownloaded',
|
||||
'recentActivity',
|
||||
'uploadTrends',
|
||||
'accessLevelStats'
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user