初始化
This commit is contained in:
72
app/admin/model/Admin.php
Normal file
72
app/admin/model/Admin.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* Admin模型
|
||||
* @property int $id 管理员ID
|
||||
* @property string $username 管理员用户名
|
||||
* @property string $nickname 管理员昵称
|
||||
* @property string $email 管理员邮箱
|
||||
* @property string $mobile 管理员手机号
|
||||
* @property string $last_login_ip 上次登录IP
|
||||
* @property string $last_login_time 上次登录时间
|
||||
* @property int $login_failure 登录失败次数
|
||||
* @property string $password 密码密文
|
||||
* @property string $salt 密码盐(废弃待删)
|
||||
* @property string $status 状态:enable=启用,disable=禁用,...(string存储,可自定义其他)
|
||||
*/
|
||||
class Admin extends Model
|
||||
{
|
||||
/**
|
||||
* @var string 自动写入时间戳
|
||||
*/
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
/**
|
||||
* 追加属性
|
||||
*/
|
||||
protected $append = [
|
||||
'group_arr',
|
||||
'group_name_arr',
|
||||
];
|
||||
|
||||
public function getGroupArrAttr($value, $row): array
|
||||
{
|
||||
return Db::name('admin_group_access')
|
||||
->where('uid', $row['id'])
|
||||
->column('group_id');
|
||||
}
|
||||
|
||||
public function getGroupNameArrAttr($value, $row): array
|
||||
{
|
||||
$groupAccess = Db::name('admin_group_access')
|
||||
->where('uid', $row['id'])
|
||||
->column('group_id');
|
||||
return AdminGroup::whereIn('id', $groupAccess)->column('name');
|
||||
}
|
||||
|
||||
public function getAvatarAttr($value): string
|
||||
{
|
||||
return full_url($value, false, config('buildadmin.default_avatar'));
|
||||
}
|
||||
|
||||
public function setAvatarAttr($value): string
|
||||
{
|
||||
return $value == full_url('', false, config('buildadmin.default_avatar')) ? '' : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
* @param int|string $uid 管理员ID
|
||||
* @param string $newPassword 新密码
|
||||
* @return int|Admin
|
||||
*/
|
||||
public function resetPassword(int|string $uid, string $newPassword): int|Admin
|
||||
{
|
||||
return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
|
||||
}
|
||||
}
|
||||
13
app/admin/model/AdminGroup.php
Normal file
13
app/admin/model/AdminGroup.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* AdminGroup模型
|
||||
*/
|
||||
class AdminGroup extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
}
|
||||
160
app/admin/model/AdminLog.php
Normal file
160
app/admin/model/AdminLog.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use Throwable;
|
||||
use think\Model;
|
||||
use app\admin\library\Auth;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* AdminLog模型
|
||||
*/
|
||||
class AdminLog extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
/**
|
||||
* 自定义日志标题
|
||||
* @var string
|
||||
*/
|
||||
protected string $title = '';
|
||||
|
||||
/**
|
||||
* 自定义日志内容
|
||||
* @var string|array
|
||||
*/
|
||||
protected string|array $data = '';
|
||||
|
||||
/**
|
||||
* 忽略的链接正则列表
|
||||
* @var array
|
||||
*/
|
||||
protected array $urlIgnoreRegex = [
|
||||
'/^(.*)\/(select|index|logout)$/i',
|
||||
];
|
||||
|
||||
protected array $desensitizationRegex = [
|
||||
'/(password|salt|token)/i'
|
||||
];
|
||||
|
||||
public static function instance()
|
||||
{
|
||||
$request = request();
|
||||
if (!isset($request->adminLog)) {
|
||||
$request->adminLog = new static();
|
||||
}
|
||||
return $request->adminLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置标题
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle(string $title): void
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日志内容
|
||||
* @param string|array $data
|
||||
*/
|
||||
public function setData(string|array $data): void
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置忽略的链接正则列表
|
||||
* @param array|string $regex
|
||||
*/
|
||||
public function setUrlIgnoreRegex(array|string $regex = []): void
|
||||
{
|
||||
$regex = is_array($regex) ? $regex : [$regex];
|
||||
$this->urlIgnoreRegex = array_merge($this->urlIgnoreRegex, $regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要进行数据脱敏的正则列表
|
||||
* @param array|string $regex
|
||||
*/
|
||||
public function setDesensitizationRegex(array|string $regex = []): void
|
||||
{
|
||||
$regex = is_array($regex) ? $regex : [$regex];
|
||||
$this->desensitizationRegex = array_merge($this->desensitizationRegex, $regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据脱敏(只数组,根据数组 key 脱敏)
|
||||
* @param array|string $data
|
||||
* @return array|string
|
||||
*/
|
||||
protected function desensitization(array|string $data): array|string
|
||||
{
|
||||
if (!is_array($data) || !$this->desensitizationRegex) {
|
||||
return $data;
|
||||
}
|
||||
foreach ($data as $index => &$item) {
|
||||
foreach ($this->desensitizationRegex as $reg) {
|
||||
if (preg_match($reg, $index)) {
|
||||
$item = "***";
|
||||
} elseif (is_array($item)) {
|
||||
$item = $this->desensitization($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入日志
|
||||
* @param string $title
|
||||
* @param string|array|null $data
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function record(string $title = '', string|array|null $data = null): void
|
||||
{
|
||||
$auth = Auth::instance();
|
||||
$adminId = $auth->isLogin() ? $auth->id : 0;
|
||||
$username = $auth->isLogin() ? $auth->username : request()->param('username', __('Unknown'));
|
||||
|
||||
$controller = str_replace('.', '/', request()->controller(true));
|
||||
$action = request()->action(true);
|
||||
$path = $controller . '/' . $action;
|
||||
if ($this->urlIgnoreRegex) {
|
||||
foreach ($this->urlIgnoreRegex as $item) {
|
||||
if (preg_match($item, $path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$data = $data ?: $this->data;
|
||||
if (!$data) {
|
||||
$data = request()->param('', null, 'trim,strip_tags,htmlspecialchars');
|
||||
}
|
||||
$data = $this->desensitization($data);
|
||||
$title = $title ?: $this->title;
|
||||
if (!$title) {
|
||||
$controllerTitle = AdminRule::where('name', $controller)->value('title');
|
||||
$title = AdminRule::where('name', $path)->value('title');
|
||||
$title = $title ?: __('Unknown') . '(' . $action . ')';
|
||||
$title = $controllerTitle ? ($controllerTitle . '-' . $title) : $title;
|
||||
}
|
||||
self::create([
|
||||
'admin_id' => $adminId,
|
||||
'username' => $username,
|
||||
'url' => substr(request()->url(), 0, 1500),
|
||||
'title' => $title,
|
||||
'data' => !is_scalar($data) ? json_encode($data) : $data,
|
||||
'ip' => request()->ip(),
|
||||
'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
|
||||
]);
|
||||
}
|
||||
|
||||
public function admin(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Admin::class);
|
||||
}
|
||||
}
|
||||
21
app/admin/model/AdminRule.php
Normal file
21
app/admin/model/AdminRule.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* AdminRule 模型
|
||||
* @property int $status 状态:0=禁用,1=启用
|
||||
*/
|
||||
class AdminRule extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
public function setComponentAttr($value)
|
||||
{
|
||||
if ($value) $value = str_replace('\\', '/', $value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
133
app/admin/model/Config.php
Normal file
133
app/admin/model/Config.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use Throwable;
|
||||
use think\Model;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* 系统配置模型
|
||||
* @property mixed $content
|
||||
* @property mixed $rule
|
||||
* @property mixed $extend
|
||||
* @property mixed $allow_del
|
||||
*/
|
||||
class Config extends Model
|
||||
{
|
||||
public static string $cacheTag = 'sys_config';
|
||||
|
||||
protected $append = [
|
||||
'value',
|
||||
'content',
|
||||
'extend',
|
||||
'input_extend',
|
||||
];
|
||||
|
||||
protected array $jsonDecodeType = ['checkbox', 'array', 'selects'];
|
||||
protected array $needContent = ['radio', 'checkbox', 'select', 'selects'];
|
||||
|
||||
/**
|
||||
* 入库前
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function onBeforeInsert(Config $model): void
|
||||
{
|
||||
if (!in_array($model->getData('type'), $model->needContent)) {
|
||||
$model->content = null;
|
||||
} else {
|
||||
$model->content = json_encode(str_attr_to_array($model->getData('content')));
|
||||
}
|
||||
if (is_array($model->rule)) {
|
||||
$model->rule = implode(',', $model->rule);
|
||||
}
|
||||
if ($model->getData('extend') || $model->getData('inputExtend')) {
|
||||
$extend = str_attr_to_array($model->getData('extend'));
|
||||
$inputExtend = str_attr_to_array($model->getData('inputExtend'));
|
||||
if ($inputExtend) $extend['baInputExtend'] = $inputExtend;
|
||||
if ($extend) $model->extend = json_encode($extend);
|
||||
}
|
||||
$model->allow_del = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入后
|
||||
*/
|
||||
public static function onAfterWrite(): void
|
||||
{
|
||||
// 清理配置缓存
|
||||
Cache::tag(self::$cacheTag)->clear();
|
||||
}
|
||||
|
||||
public function getValueAttr($value, $row)
|
||||
{
|
||||
if (!isset($row['type']) || $value == '0') return $value;
|
||||
if (in_array($row['type'], $this->jsonDecodeType)) {
|
||||
return empty($value) ? [] : json_decode($value, true);
|
||||
} elseif ($row['type'] == 'switch') {
|
||||
return (bool)$value;
|
||||
} elseif ($row['type'] == 'editor') {
|
||||
return !$value ? '' : htmlspecialchars_decode($value);
|
||||
} elseif (in_array($row['type'], ['city', 'remoteSelects'])) {
|
||||
if (!$value) return [];
|
||||
if (!is_array($value)) return explode(',', $value);
|
||||
return $value;
|
||||
} else {
|
||||
return $value ?: '';
|
||||
}
|
||||
}
|
||||
|
||||
public function setValueAttr(mixed $value, $row): mixed
|
||||
{
|
||||
if (in_array($row['type'], $this->jsonDecodeType)) {
|
||||
return $value ? json_encode($value) : '';
|
||||
} elseif ($row['type'] == 'switch') {
|
||||
return $value ? '1' : '0';
|
||||
} elseif ($row['type'] == 'time') {
|
||||
return $value ? date('H:i:s', strtotime($value)) : '';
|
||||
} elseif ($row['type'] == 'city') {
|
||||
if ($value && is_array($value)) {
|
||||
return implode(',', $value);
|
||||
}
|
||||
return $value ?: '';
|
||||
} elseif (is_array($value)) {
|
||||
return implode(',', $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getContentAttr($value, $row)
|
||||
{
|
||||
if (!isset($row['type'])) return '';
|
||||
if (in_array($row['type'], $this->needContent)) {
|
||||
$arr = json_decode($value, true);
|
||||
return $arr ?: [];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public function getExtendAttr($value)
|
||||
{
|
||||
if ($value) {
|
||||
$arr = json_decode($value, true);
|
||||
if ($arr) {
|
||||
unset($arr['baInputExtend']);
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getInputExtendAttr($value, $row)
|
||||
{
|
||||
if ($row && $row['extend']) {
|
||||
$arr = json_decode($row['extend'], true);
|
||||
if ($arr && isset($arr['baInputExtend'])) {
|
||||
return $arr['baInputExtend'];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
24
app/admin/model/CrudLog.php
Normal file
24
app/admin/model/CrudLog.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* Log
|
||||
*/
|
||||
class CrudLog extends Model
|
||||
{
|
||||
// 表名
|
||||
protected $name = 'crud_log';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
protected $type = [
|
||||
'table' => 'array',
|
||||
'fields' => 'array',
|
||||
];
|
||||
|
||||
}
|
||||
15
app/admin/model/DataRecycle.php
Normal file
15
app/admin/model/DataRecycle.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* DataRecycle 模型
|
||||
*/
|
||||
class DataRecycle extends Model
|
||||
{
|
||||
protected $name = 'security_data_recycle';
|
||||
|
||||
protected $autoWriteTimestamp = true;
|
||||
}
|
||||
27
app/admin/model/DataRecycleLog.php
Normal file
27
app/admin/model/DataRecycleLog.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* DataRecycleLog 模型
|
||||
*/
|
||||
class DataRecycleLog extends Model
|
||||
{
|
||||
protected $name = 'security_data_recycle_log';
|
||||
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
public function recycle(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DataRecycle::class, 'recycle_id');
|
||||
}
|
||||
|
||||
public function admin(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Admin::class, 'admin_id');
|
||||
}
|
||||
}
|
||||
19
app/admin/model/SensitiveData.php
Normal file
19
app/admin/model/SensitiveData.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* SensitiveData 模型
|
||||
*/
|
||||
class SensitiveData extends Model
|
||||
{
|
||||
protected $name = 'security_sensitive_data';
|
||||
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
protected $type = [
|
||||
'data_fields' => 'array',
|
||||
];
|
||||
}
|
||||
27
app/admin/model/SensitiveDataLog.php
Normal file
27
app/admin/model/SensitiveDataLog.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* SensitiveDataLog 模型
|
||||
*/
|
||||
class SensitiveDataLog extends Model
|
||||
{
|
||||
protected $name = 'security_sensitive_data_log';
|
||||
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
public function sensitive(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(SensitiveData::class, 'sensitive_id');
|
||||
}
|
||||
|
||||
public function admin(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Admin::class, 'admin_id');
|
||||
}
|
||||
}
|
||||
52
app/admin/model/User.php
Normal file
52
app/admin/model/User.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* User 模型
|
||||
* @property int $id 用户ID
|
||||
* @property string password 密码密文
|
||||
*/
|
||||
class User extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
public function getAvatarAttr($value): string
|
||||
{
|
||||
return full_url($value, false, config('buildadmin.default_avatar'));
|
||||
}
|
||||
|
||||
public function setAvatarAttr($value): string
|
||||
{
|
||||
return $value == full_url('', false, config('buildadmin.default_avatar')) ? '' : $value;
|
||||
}
|
||||
|
||||
public function getMoneyAttr($value): string
|
||||
{
|
||||
return bcdiv($value, 100, 2);
|
||||
}
|
||||
|
||||
public function setMoneyAttr($value): string
|
||||
{
|
||||
return bcmul($value, 100, 2);
|
||||
}
|
||||
|
||||
public function userGroup(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(UserGroup::class, 'group_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
* @param int|string $uid 用户ID
|
||||
* @param string $newPassword 新密码
|
||||
* @return int|User
|
||||
*/
|
||||
public function resetPassword(int|string $uid, string $newPassword): int|User
|
||||
{
|
||||
return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
|
||||
}
|
||||
}
|
||||
13
app/admin/model/UserGroup.php
Normal file
13
app/admin/model/UserGroup.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* UserGroup 模型
|
||||
*/
|
||||
class UserGroup extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
}
|
||||
80
app/admin/model/UserMoneyLog.php
Normal file
80
app/admin/model/UserMoneyLog.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use Throwable;
|
||||
use think\model;
|
||||
use think\Exception;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* UserMoneyLog 模型
|
||||
* 1. 创建余额日志自动完成会员余额的添加
|
||||
* 2. 创建余额日志时,请开启事务
|
||||
*/
|
||||
class UserMoneyLog extends model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
/**
|
||||
* 入库前
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function onBeforeInsert($model): void
|
||||
{
|
||||
$user = User::where('id', $model->user_id)->lock(true)->find();
|
||||
if (!$user) {
|
||||
throw new Exception("The user can't find it");
|
||||
}
|
||||
if (!$model->memo) {
|
||||
throw new Exception("Change note cannot be blank");
|
||||
}
|
||||
$model->before = $user->money;
|
||||
|
||||
$user->money += $model->money;
|
||||
$user->save();
|
||||
|
||||
$model->after = $user->money;
|
||||
}
|
||||
|
||||
public static function onBeforeDelete(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getMoneyAttr($value): string
|
||||
{
|
||||
return bcdiv($value, 100, 2);
|
||||
}
|
||||
|
||||
public function setMoneyAttr($value): string
|
||||
{
|
||||
return bcmul($value, 100, 2);
|
||||
}
|
||||
|
||||
public function getBeforeAttr($value): string
|
||||
{
|
||||
return bcdiv($value, 100, 2);
|
||||
}
|
||||
|
||||
public function setBeforeAttr($value): string
|
||||
{
|
||||
return bcmul($value, 100, 2);
|
||||
}
|
||||
|
||||
public function getAfterAttr($value): string
|
||||
{
|
||||
return bcdiv($value, 100, 2);
|
||||
}
|
||||
|
||||
public function setAfterAttr($value): string
|
||||
{
|
||||
return bcmul($value, 100, 2);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
26
app/admin/model/UserRule.php
Normal file
26
app/admin/model/UserRule.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\model;
|
||||
|
||||
/**
|
||||
* UserRule 模型
|
||||
* @property int $status 状态:0=禁用,1=启用
|
||||
*/
|
||||
class UserRule extends model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
protected static function onAfterInsert($model): void
|
||||
{
|
||||
$pk = $model->getPk();
|
||||
$model->where($pk, $model[$pk])->update(['weigh' => $model[$pk]]);
|
||||
}
|
||||
|
||||
public function setComponentAttr($value)
|
||||
{
|
||||
if ($value) $value = str_replace('\\', '/', $value);
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
50
app/admin/model/UserScoreLog.php
Normal file
50
app/admin/model/UserScoreLog.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use Throwable;
|
||||
use think\model;
|
||||
use think\Exception;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* UserScoreLog 模型
|
||||
* 1. 创建积分日志自动完成会员积分的添加
|
||||
* 2. 创建积分日志时,请开启事务
|
||||
*/
|
||||
class UserScoreLog extends model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
/**
|
||||
* 入库前
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function onBeforeInsert($model): void
|
||||
{
|
||||
$user = User::where('id', $model->user_id)->lock(true)->find();
|
||||
if (!$user) {
|
||||
throw new Exception("The user can't find it");
|
||||
}
|
||||
if (!$model->memo) {
|
||||
throw new Exception("Change note cannot be blank");
|
||||
}
|
||||
$model->before = $user->score;
|
||||
|
||||
$user->score += $model->score;
|
||||
$user->save();
|
||||
|
||||
$model->after = $user->score;
|
||||
}
|
||||
|
||||
public static function onBeforeDelete(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user