加入操作記錄與介面 20250512
This commit is contained in:
parent
b0325aef79
commit
78bf426459
97
app/Livewire/Admin/ActivityLogTable.php
Normal file
97
app/Livewire/Admin/ActivityLogTable.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Admin;
|
||||
|
||||
use App\Models\ActivityLog;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use PowerComponents\LivewirePowerGrid\Column;
|
||||
use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
||||
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
|
||||
final class ActivityLogTable extends PowerGridComponent
|
||||
{
|
||||
public string $tableName = 'activity-log-table';
|
||||
|
||||
public function setUp(): array
|
||||
{
|
||||
$this->showCheckBox();
|
||||
|
||||
return [
|
||||
PowerGrid::header()
|
||||
->showSearchInput(),
|
||||
PowerGrid::footer()
|
||||
->showPerPage()
|
||||
->showRecordCount(),
|
||||
];
|
||||
}
|
||||
|
||||
public function datasource(): Builder
|
||||
{
|
||||
return Activity::with(['causer'])->latest();
|
||||
}
|
||||
|
||||
public function relationSearch(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function fields(): PowerGridFields
|
||||
{
|
||||
return PowerGrid::fields()
|
||||
->add('id')
|
||||
->add('created_at_formatted', fn (Activity $model) => Carbon::parse($model->created_at)->format('Y-m-d H:i:s'))
|
||||
->add('causer_name', fn (Activity $model) => optional($model->causer)->name)
|
||||
->add('subject_type_label', fn (Activity $model) => class_basename($model->subject_type))
|
||||
->add('subject_type')
|
||||
->add('subject_id')
|
||||
->add('description')
|
||||
->add('log_name')
|
||||
->add('changes', function (Activity $model) {
|
||||
$old = $model->properties['old'] ?? [];
|
||||
$new = $model->properties['attributes'] ?? [];
|
||||
|
||||
$changes = [];
|
||||
|
||||
foreach ($new as $key => $newValue) {
|
||||
if (in_array($key, ['updated_at', 'created_at'])) continue;
|
||||
$oldValue = $old[$key] ?? '(空)';
|
||||
if ($newValue != $oldValue) {
|
||||
$changes[] = "<strong>{$key}</strong>: {$oldValue} → {$newValue}";
|
||||
}
|
||||
}
|
||||
|
||||
return implode('<br>', $changes);
|
||||
})
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
$column=[];
|
||||
$column[]=Column::make('時間', 'created_at_formatted', 'created_at')->sortable()->searchable();
|
||||
$column[]=Column::make('操作者', 'causer.name')->sortable()->searchable()->bodyAttribute('whitespace-nowrap');
|
||||
$column[]=Column::make('模型', 'subject_type_label')->sortable()->searchable();
|
||||
$column[]=Column::make('模型 ID', 'subject_id')->sortable()->searchable();
|
||||
$column[]=Column::make('動作', 'description')->sortable()->searchable();
|
||||
$column[]=Column::make('變更內容', 'changes')->sortable(false)->searchable(false)->bodyAttribute('whitespace-normal text-sm text-gray-700');
|
||||
$column[]=Column::make('Log 名稱', 'log_name')->sortable()->searchable();
|
||||
return $column;
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
Filter::datetimepicker('created_at'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -6,12 +6,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Helpers\ChineseNameConverter;
|
||||
use App\Helpers\ChineseStrokesConverter;
|
||||
|
||||
use App\Traits\LogsModelActivity;
|
||||
|
||||
class Artist extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ArtistFactory> */
|
||||
use HasFactory;
|
||||
use HasFactory, LogsModelActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'category',
|
||||
|
@ -4,15 +4,17 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Traits\LogsModelActivity;
|
||||
|
||||
class Branch extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ArtistFactory> */
|
||||
use HasFactory;
|
||||
use HasFactory, LogsModelActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'external_ip',
|
||||
'enable',
|
||||
];
|
||||
|
||||
public function rooms() {
|
||||
|
@ -4,11 +4,12 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Traits\LogsModelActivity;
|
||||
|
||||
class Room extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ArtistFactory> */
|
||||
use HasFactory;
|
||||
use HasFactory, LogsModelActivity;
|
||||
|
||||
protected $casts = [
|
||||
'started_at' => 'datetime',
|
||||
|
@ -6,11 +6,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Helpers\ChineseNameConverter;
|
||||
use App\Helpers\ChineseStrokesConverter;
|
||||
use App\Traits\LogsModelActivity;
|
||||
|
||||
class Song extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\SongFactory> */
|
||||
use HasFactory;
|
||||
use HasFactory, LogsModelActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'id',
|
||||
|
@ -7,11 +7,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
use App\Traits\LogsModelActivity;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable, HasRoles;
|
||||
use HasFactory, Notifiable, HasRoles, LogsModelActivity;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
23
app/Traits/LogsModelActivity.php
Normal file
23
app/Traits/LogsModelActivity.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
trait LogsModelActivity
|
||||
{
|
||||
use LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->useLogName(strtolower(class_basename(static::class)))
|
||||
->logOnly($this->getFillable())
|
||||
->logOnlyDirty()
|
||||
->dontSubmitEmptyLogs()
|
||||
->setDescriptionForEvent(function (string $eventName) {
|
||||
return class_basename(static::class) . " 已 {$eventName}";
|
||||
});
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
"overtrue/php-opencc": "^1.2",
|
||||
"overtrue/pinyin": "^5.3",
|
||||
"power-components/livewire-powergrid": "^6.3",
|
||||
"spatie/laravel-activitylog": "^4.10",
|
||||
"spatie/laravel-permission": "^6.17",
|
||||
"wire-elements/modal": "^2.0",
|
||||
"wireui/wireui": "^2.4"
|
||||
|
93
composer.lock
generated
93
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d5d6344c1be46378bdaa0bfecd2e300e",
|
||||
"content-hash": "54bbfde233e690f726d54157b29f12a3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
@ -4346,6 +4346,97 @@
|
||||
],
|
||||
"time": "2024-04-27T21:32:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-activitylog",
|
||||
"version": "4.10.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/laravel-activitylog.git",
|
||||
"reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/466f30f7245fe3a6e328ad5e6812bd43b4bddea5",
|
||||
"reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/config": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"illuminate/database": "^8.69 || ^9.27 || ^10.0 || ^11.0 || ^12.0",
|
||||
"illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"php": "^8.1",
|
||||
"spatie/laravel-package-tools": "^1.6.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"orchestra/testbench": "^6.23 || ^7.0 || ^8.0 || ^9.0 || ^10.0",
|
||||
"pestphp/pest": "^1.20 || ^2.0 || ^3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Spatie\\Activitylog\\ActivitylogServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Spatie\\Activitylog\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Freek Van der Herten",
|
||||
"email": "freek@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian De Deyne",
|
||||
"email": "sebastian@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Tom Witkowski",
|
||||
"email": "dev.gummibeer@gmail.com",
|
||||
"homepage": "https://gummibeer.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A very simple activity logger to monitor the users of your website or application",
|
||||
"homepage": "https://github.com/spatie/activitylog",
|
||||
"keywords": [
|
||||
"activity",
|
||||
"laravel",
|
||||
"log",
|
||||
"spatie",
|
||||
"user"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/laravel-activitylog/issues",
|
||||
"source": "https://github.com/spatie/laravel-activitylog/tree/4.10.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://spatie.be/open-source/support-us",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/spatie",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-10T15:38:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-package-tools",
|
||||
"version": "1.92.4",
|
||||
|
52
config/activitylog.php
Normal file
52
config/activitylog.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
* If set to false, no activities will be saved to the database.
|
||||
*/
|
||||
'enabled' => env('ACTIVITY_LOGGER_ENABLED', true),
|
||||
|
||||
/*
|
||||
* When the clean-command is executed, all recording activities older than
|
||||
* the number of days specified here will be deleted.
|
||||
*/
|
||||
'delete_records_older_than_days' => 365,
|
||||
|
||||
/*
|
||||
* If no log name is passed to the activity() helper
|
||||
* we use this default log name.
|
||||
*/
|
||||
'default_log_name' => 'default',
|
||||
|
||||
/*
|
||||
* You can specify an auth driver here that gets user models.
|
||||
* If this is null we'll use the current Laravel auth driver.
|
||||
*/
|
||||
'default_auth_driver' => null,
|
||||
|
||||
/*
|
||||
* If set to true, the subject returns soft deleted models.
|
||||
*/
|
||||
'subject_returns_soft_deleted_models' => false,
|
||||
|
||||
/*
|
||||
* This model will be used to log activity.
|
||||
* It should implement the Spatie\Activitylog\Contracts\Activity interface
|
||||
* and extend Illuminate\Database\Eloquent\Model.
|
||||
*/
|
||||
'activity_model' => \Spatie\Activitylog\Models\Activity::class,
|
||||
|
||||
/*
|
||||
* This is the name of the table that will be created by the migration and
|
||||
* used by the Activity model shipped with this package.
|
||||
*/
|
||||
'table_name' => env('ACTIVITY_LOGGER_TABLE_NAME', 'activity_log'),
|
||||
|
||||
/*
|
||||
* This is the database connection that will be used by the migration and
|
||||
* the Activity model shipped with this package. In case it's not set
|
||||
* Laravel's database.default will be used instead.
|
||||
*/
|
||||
'database_connection' => env('ACTIVITY_LOGGER_DB_CONNECTION'),
|
||||
];
|
@ -42,17 +42,6 @@ return [
|
||||
'synchronous' => null,
|
||||
],
|
||||
|
||||
'KTVsqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'url' => env('DB_URL'),
|
||||
'database' => env('SQLITE_DB', database_path('KSongDatabase.db')),
|
||||
'prefix' => '',
|
||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||
'busy_timeout' => null,
|
||||
'journal_mode' => null,
|
||||
'synchronous' => null,
|
||||
],
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DB_URL'),
|
||||
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->create(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('log_name')->nullable();
|
||||
$table->text('description');
|
||||
$table->nullableMorphs('subject', 'subject');
|
||||
$table->nullableMorphs('causer', 'causer');
|
||||
$table->json('properties')->nullable();
|
||||
$table->timestamps();
|
||||
$table->index('log_name');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->dropIfExists(config('activitylog.table_name'));
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddEventColumnToActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->string('event')->nullable()->after('subject_type');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->dropColumn('event');
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddBatchUuidColumnToActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->uuid('batch_uuid')->nullable()->after('properties');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->dropColumn('batch_uuid');
|
||||
});
|
||||
}
|
||||
}
|
4
resources/views/livewire/admin/activity-log.blade.php
Normal file
4
resources/views/livewire/admin/activity-log.blade.php
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
<x-layouts.admin>
|
||||
<livewire:admin.activity-log-table />
|
||||
</x-layouts.admin>
|
@ -3,6 +3,7 @@
|
||||
|
||||
$menus = [
|
||||
['label' => 'Dashboard', 'route' => 'admin.dashboard', 'icon' => 'home', 'permission' => null],
|
||||
['label' => 'ActivityLog', 'route' => 'admin.activity-log', 'icon' => 'clock', 'permission' => null],
|
||||
['label' => 'Role', 'route' => 'admin.roles', 'icon' => 'user-circle', 'permission' => 'role-list'],
|
||||
['label' => 'User', 'route' => 'admin.users', 'icon' => 'user-circle', 'permission' => 'user-list'],
|
||||
['label' => 'Artist', 'route' => 'admin.artists', 'icon' => 'musical-note', 'permission' => 'song-list'],
|
||||
|
@ -21,7 +21,7 @@ require __DIR__.'/auth.php';
|
||||
|
||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
||||
Route::get('/dashboard', AdminDashboard::class)->name('dashboard');
|
||||
|
||||
Route::get('/activity-log', function () {return view('livewire.admin.activity-log');})->name('activity-log');
|
||||
Route::get('/roles', function () {return view('livewire.admin.roles');})->name('roles');
|
||||
Route::get('/users', function () {return view('livewire.admin.users');})->name('users');
|
||||
Route::get('/artists', function () {return view('livewire.admin.artists');})->name('artists');
|
||||
|
8
開發手冊.ini
8
開發手冊.ini
@ -61,6 +61,7 @@ npm install && npm run build
|
||||
php artisan convert:unihan-strokes \
|
||||
--input=resources/data/Unihan_IRGSources.txt \
|
||||
--output=resources/data/unihan_strokes.php
|
||||
|
||||
php artisan cache:forget unihan_strokes
|
||||
|
||||
|
||||
@ -75,6 +76,13 @@ php artisan vendor:publish --tag=livewire-powergrid-config
|
||||
composer require overtrue/php-opencc -vvv
|
||||
composer require overtrue/pinyin
|
||||
|
||||
操作記錄
|
||||
composer require spatie/laravel-activitylog
|
||||
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations"
|
||||
php artisan migrate
|
||||
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-config"
|
||||
php artisan make:model ActivityLog
|
||||
|
||||
建立分頁table
|
||||
php artisan powergrid:create
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user