diff --git a/README.md b/README.md
index 4e6c6fb..beb62da 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,8 @@
```php
$permissions = [
- 'users' => ['name' => '用户管理', 'curd' => true],
+ 'users' => ['name' => '用户管理', 'curd' => true, 'children' => ['balance' => '变更余额']],
+ 'user-balance' => ['name' => '余额流水', 'curd' => ['index', 'show']],
];
```
@@ -31,8 +32,9 @@ $permissions = [
```php
$menus = [
- ['title' => '用户模块', 'icon' => 'feather icon-user', 'uri' => '/users', 'permission' => 'users', 'children' => [
- ['title' => '用户管理', 'icon' => '', 'uri' => '/users', 'permission' => 'users']
+ ['title' => '用户模块', 'icon' => 'feather icon-user', 'uri' => '/users', 'permission' => ['users', 'user_balance'], 'children' => [
+ ['title' => '用户管理', 'icon' => '', 'uri' => '/users', 'permission' => 'users'],
+ ['title' => '余额流水', 'icon' => '', 'uri' => '/user-balance', 'permission' => 'user_balance'],
]],
];
```
diff --git a/lang/zh_CN/user-balance.php b/lang/zh_CN/user-balance.php
index bf69d3b..9c3ed07 100644
--- a/lang/zh_CN/user-balance.php
+++ b/lang/zh_CN/user-balance.php
@@ -7,9 +7,14 @@ return [
],
'fields' => [
'user_id' => '用户',
+ 'user' => [
+ 'phone' => '用户',
+ ],
'cate' => '类别',
'amount' => '金额',
'description' => '描述',
'created_at' => '时间',
+ 'balance' => '剩余',
+ 'remarks' => '备注',
]
];
diff --git a/routes/admin.php b/routes/admin.php
index 780fc21..58078ff 100644
--- a/routes/admin.php
+++ b/routes/admin.php
@@ -11,4 +11,5 @@ Route::group([
Route::get('api/users', [UserController::class, 'list'])->name('dcat.admin.api.users');
Route::resource('users', UserController::class)->names('dcat.admin.users');
+ Route::resource('user-balance', UserBalanceController::class)->names('dcat.admin.user_balance');
});
diff --git a/src/Action/ShowBalance.php b/src/Action/ShowBalance.php
new file mode 100644
index 0000000..c67aa20
--- /dev/null
+++ b/src/Action/ShowBalance.php
@@ -0,0 +1,26 @@
+parent->model();
+ $form = BalanceForm::make()->payload(['balance' => $model->balance, 'id' => $model->id]);
+ return Modal::make()->lg()->title($this->title)->body($form)->button('');
+ }
+
+ protected function authorize($user): bool
+ {
+ return $user->can('dcat.admin.users.balance');
+ }
+}
diff --git a/src/Action/ShowRemark.php b/src/Action/ShowRemark.php
new file mode 100644
index 0000000..5c5fc82
--- /dev/null
+++ b/src/Action/ShowRemark.php
@@ -0,0 +1,21 @@
+parent->model();
+ $form = RemarkForm::make()->payload(['remarks' => $model->remarks ?: '', 'id' => $model->id]);
+ return Modal::make()->lg()->title($this->title)->body($form)->button('');
+ }
+}
diff --git a/src/Form/BalanceForm.php b/src/Form/BalanceForm.php
new file mode 100644
index 0000000..2a629bc
--- /dev/null
+++ b/src/Form/BalanceForm.php
@@ -0,0 +1,63 @@
+ false, 'submit' => true];
+
+ public function handle(array $input)
+ {
+ $amount = $input['amount'];
+ if ($amount == 0) {
+ $this->response()->error('数量不能为0');
+ }
+ $user = User::findOrFail($this->payload['id']);
+ if ($user->balance + $amount < 0) {
+ return $this->response()->error('余额不能小于0');
+ }
+ try {
+ DB::beginTransaction();
+ $user->increment('balance', $amount);
+
+ $admin = Admin::user();
+ $user->balanceLogs()->create([
+ 'amount' => $amount,
+ 'balance' => $user->balance,
+ 'cate' => $input['cate'],
+ 'description' => $input['description'],
+ 'source_id' => $admin->id,
+ 'source_type' => $admin->getMorphClass()
+ ]);
+ DB::commit();
+ return $this->response()->success('操作成功')->refresh();
+ } catch (\Exception $e) {
+ DB::rollBack();
+ return $this->response()->error($e->getMessage());
+ }
+ }
+
+ public function form()
+ {
+ $this->display('balance');
+ $this->number('amount', '数量')->help('正数为增加, 负数为减少')->default(0)->required();
+ $this->text('cate', '分类')->required();
+ $this->text('description', '描述')->required();
+ }
+
+ public function default()
+ {
+ return [
+ 'balance' => $this->payload['balance']
+ ];
+ }
+}
diff --git a/src/Form/RemarkForm.php b/src/Form/RemarkForm.php
new file mode 100644
index 0000000..6109a34
--- /dev/null
+++ b/src/Form/RemarkForm.php
@@ -0,0 +1,35 @@
+ false, 'submit' => true];
+
+ public function handle(array $input)
+ {
+ $info = UserBalance::findOrFail($this->payload['id']);
+ $info->update(['remarks' => $input['remarks']]);
+
+ return $this->response()->success('操作成功')->refresh();
+ }
+
+ public function form()
+ {
+ $this->text('remarks');
+ }
+
+ public function default()
+ {
+ return [
+ 'remarks' => $this->payload['remarks']
+ ];
+ }
+}
diff --git a/src/Http/Admin/UserBalanceController.php b/src/Http/Admin/UserBalanceController.php
new file mode 100644
index 0000000..8873154
--- /dev/null
+++ b/src/Http/Admin/UserBalanceController.php
@@ -0,0 +1,76 @@
+model()->sort();
+
+ $grid->column('user.phone');
+ $grid->column('cate');
+ $grid->column('description');
+ $grid->column('amount');
+ $grid->column('created_at');
+
+ $grid->disableCreateButton();
+ $grid->disableEditButton();
+ $grid->disableDeleteButton();
+
+ $grid->filter(function (Filter $filter) {
+ $filter->panel();
+
+ $filter->equal('user_id')->select()->ajax('api/users?_paginate=1')->model(User::class, 'id', 'phone')->width(3);
+ $filter->like('cate')->width(3);
+ $filter->whereBetween('created_at', function ($q) {
+ $start = data_get($this->input, 'start');
+ $start = $start ? Carbon::createFromFormat('Y-m-d', $start) : null;
+ $end = data_get($this->input, 'end');
+ $end = $end ? Carbon::createFromFormat('Y-m-d', $end) : null;
+ if ($start) {
+ if ($end) {
+ $q->whereBetween('created_at', [$start, $end]);
+ }
+ $q->where('created_at', '>=', $start);
+ } else if ($end) {
+ $q->where('created_at', '<=', $end);
+ }
+ })->date()->width(3);
+ });
+ });
+ }
+
+ protected function detail($id)
+ {
+ return Show::make($id, UserBalance::with(['user']), function (Show $show) {
+ $show->field('user.phone');
+ $show->field('cate');
+ $show->field('description');
+ $show->field('amount');
+ $show->field('balance');
+ $show->field('remarks');
+ $show->field('created_at');
+
+ $show->tools(function (Tools $tools) {
+ $tools->disableDelete();
+ $tools->disableEdit();
+ $tools->disableList();
+ $tools->append(new ShowRemark());
+ });
+ });
+ }
+}
diff --git a/src/Http/Admin/UserController.php b/src/Http/Admin/UserController.php
index 23d959d..e182eb4 100644
--- a/src/Http/Admin/UserController.php
+++ b/src/Http/Admin/UserController.php
@@ -19,6 +19,7 @@ use Illuminate\Validation\Rule;
use Peidikeji\User\Models\User;
use Peidikeji\User\Models\UserSocialite;
use Illuminate\Support\Str;
+use Peidikeji\User\Action\ShowBalance;
class UserController extends AdminController
{
@@ -146,8 +147,9 @@ class UserController extends AdminController
$show->field('profit');
$show->field('created_at');
$show->tools(function (Tools $tools) {
- $tools->disableBack();
- $tools->disableList(false);
+ $tools->disableList();
+
+ $tools->append(new ShowBalance());
});
$tab = new Tab();
diff --git a/src/Models/User.php b/src/Models/User.php
index f6bb921..6649327 100644
--- a/src/Models/User.php
+++ b/src/Models/User.php
@@ -6,7 +6,6 @@ use EloquentFilter\Filterable;
use Laravel\Sanctum\HasApiTokens;
use Peidikeji\User\Filters\UserFilter;
use Dcat\Admin\Traits\HasDateTimeFormatter;
-use Dcat\Admin\Traits\ModelTree;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Str;
@@ -54,6 +53,11 @@ class User extends Authenticatable
return $this->hasMany(UserSocialite::class, 'user_id');
}
+ public function balanceLogs()
+ {
+ return $this->hasMany(UserBalance::class, 'user_id');
+ }
+
public function scopeSort($q)
{
return $q->latest('id');
diff --git a/src/Models/UserBalance.php b/src/Models/UserBalance.php
new file mode 100644
index 0000000..01652d6
--- /dev/null
+++ b/src/Models/UserBalance.php
@@ -0,0 +1,30 @@
+belongsTo(User::class, 'user_id');
+ }
+
+ public function source()
+ {
+ return $this->morphTo();
+ }
+
+ public function scopeSort($q)
+ {
+ return $q->latest('created_at');
+ }
+}
diff --git a/src/UserServiceProvider.php b/src/UserServiceProvider.php
index 69c6f30..26a5392 100644
--- a/src/UserServiceProvider.php
+++ b/src/UserServiceProvider.php
@@ -31,6 +31,7 @@ class UserServiceProvider extends ServiceProvider
$menu->add([
['id' => 1, 'parent_id' => 0, 'title' => '用户模块', 'icon' => 'feather icon-user', 'uri' => ''],
['id' => 2, 'parent_id' => 1, 'title' => '用户管理', 'icon' => '', 'uri' => '/users'],
+ ['id' => 3, 'parent_id' => 1, 'title' => '余额流水', 'icon' => '', 'uri' => '/user-balance'],
]);
});
}