add
This commit is contained in:
115
app/common/model/Attachment.php
Normal file
115
app/common/model/Attachment.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use Throwable;
|
||||
use think\Model;
|
||||
use think\facade\Event;
|
||||
use app\admin\model\Admin;
|
||||
use app\common\library\Upload;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* Attachment模型
|
||||
* @property string url 文件物理路径
|
||||
* @property int quote 上传(引用)次数
|
||||
* @property int last_upload_time 最后上传时间
|
||||
*/
|
||||
class Attachment extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
|
||||
protected $append = [
|
||||
'suffix',
|
||||
'full_url'
|
||||
];
|
||||
|
||||
/**
|
||||
* 上传类实例,可以通过它调用上传文件驱动,且驱动类具有静态缓存
|
||||
*/
|
||||
protected static Upload $upload;
|
||||
|
||||
protected static function init(): void
|
||||
{
|
||||
self::$upload = new Upload();
|
||||
}
|
||||
|
||||
public function getSuffixAttr($value, $row): string
|
||||
{
|
||||
if ($row['name']) {
|
||||
$suffix = strtolower(pathinfo($row['name'], PATHINFO_EXTENSION));
|
||||
return $suffix && preg_match("/^[a-zA-Z0-9]+$/", $suffix) ? $suffix : 'file';
|
||||
}
|
||||
return 'file';
|
||||
}
|
||||
|
||||
public function getFullUrlAttr($value, $row): string
|
||||
{
|
||||
$driver = self::$upload->getDriver($row['storage'], false);
|
||||
return $driver ? $driver->url($row['url']) : full_url($row['url']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增前
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected static function onBeforeInsert($model): bool
|
||||
{
|
||||
$repeat = $model->where([
|
||||
['sha1', '=', $model->sha1],
|
||||
['topic', '=', $model->topic],
|
||||
['storage', '=', $model->storage],
|
||||
])->find();
|
||||
if ($repeat) {
|
||||
$driver = self::$upload->getDriver($repeat->storage, false);
|
||||
if ($driver && !$driver->exists($repeat->url)) {
|
||||
$repeat->delete();
|
||||
return true;
|
||||
} else {
|
||||
$repeat->quote++;
|
||||
$repeat->last_upload_time = time();
|
||||
$repeat->save();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增后
|
||||
*/
|
||||
protected static function onAfterInsert($model): void
|
||||
{
|
||||
Event::trigger('AttachmentInsert', $model);
|
||||
|
||||
if (!$model->last_upload_time) {
|
||||
$model->quote = 1;
|
||||
$model->last_upload_time = time();
|
||||
$model->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除后
|
||||
*/
|
||||
protected static function onAfterDelete($model): void
|
||||
{
|
||||
Event::trigger('AttachmentDel', $model);
|
||||
|
||||
$driver = self::$upload->getDriver($model->storage, false);
|
||||
if ($driver && $driver->exists($model->url)) {
|
||||
$driver->delete($model->url);
|
||||
}
|
||||
}
|
||||
|
||||
public function admin(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Admin::class);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
150
app/common/model/BaseModel.php
Normal file
150
app/common/model/BaseModel.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
namespace app\common\model;
|
||||
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\db\BaseQuery;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
use think\Model;
|
||||
use think\db\Query;
|
||||
|
||||
class BaseModel extends Model
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 查询前处理数据库连接
|
||||
*/
|
||||
public static function findbefore($model, $where):string
|
||||
{
|
||||
return DatabaseRoute::getConnection($model->getTable(), $where, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 写入数据前处理数据库连接
|
||||
* @param array $data 写入的数据
|
||||
* @return void
|
||||
*/
|
||||
protected static function onBeforeInsert($data)
|
||||
{
|
||||
$connection = DatabaseRoute::getConnection($data->getTable(), $data, true);
|
||||
print_r($connection);
|
||||
$data->setConnection($connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据前处理数据库连接
|
||||
* @param array $data 更新的数据
|
||||
* @return void
|
||||
*/
|
||||
protected static function onBeforeUpdate($data)
|
||||
{
|
||||
$connection = DatabaseRoute::getConnection($data->getTable(), $data->getWhere(), true);
|
||||
$data->setConnection($connection);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从查询选项中提取分库键的值(深度解析版)
|
||||
*/
|
||||
private static function extractKeyFromOptions(array $options, string $keyField)
|
||||
{
|
||||
$dbKey = null;
|
||||
|
||||
// 1. 处理顶级 where 条件
|
||||
if (isset($options['where'])) {
|
||||
$dbKey = static::parseWhereCondition($options['where'], $keyField);
|
||||
if ($dbKey !== null) return $dbKey;
|
||||
}
|
||||
|
||||
// 2. 处理 whereOr 条件
|
||||
if (isset($options['whereOr'])) {
|
||||
$dbKey = static::parseWhereCondition($options['whereOr'], $keyField);
|
||||
if ($dbKey !== null) return $dbKey;
|
||||
}
|
||||
|
||||
// 3. 处理软删除条件
|
||||
if (isset($options['soft_delete']) && is_array($options['soft_delete'])) {
|
||||
if ($options['soft_delete'][0] === $keyField) {
|
||||
$dbKey = $options['soft_delete'][2] ?? null;
|
||||
Log::info("条件类型3: 软删除条件中匹配到 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 处理字段绑定(bind)
|
||||
if (isset($options['bind'][$keyField])) {
|
||||
$dbKey = $options['bind'][$keyField];
|
||||
Log::info("条件类型4: 绑定参数中匹配到 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
|
||||
// 5. 处理查询参数(param)
|
||||
if (isset($options['param'][$keyField])) {
|
||||
$dbKey = $options['param'][$keyField];
|
||||
Log::info("条件类型5: 查询参数中匹配到 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
|
||||
// 6. 处理数据(data)- 适用于更新操作
|
||||
if (isset($options['data'][$keyField])) {
|
||||
$dbKey = $options['data'][$keyField];
|
||||
Log::info("条件类型6: 数据中匹配到 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
|
||||
// 未找到分库键
|
||||
Log::warning("条件解析失败: 未找到 {$keyField} 的值");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 where 条件(处理 AND/OR 逻辑)
|
||||
*/
|
||||
private static function parseWhereCondition($where, string $keyField)
|
||||
{
|
||||
$dbKey = null;
|
||||
|
||||
// 处理数组形式的 where 条件
|
||||
if (is_array($where)) {
|
||||
foreach ($where as $index => $whereItem) {
|
||||
// 1. 处理 AND/OR 逻辑分组
|
||||
if (is_string($index) && in_array(strtoupper($index), ['AND', 'OR', 'NOT'])) {
|
||||
Log::info("条件类型1: 发现 {$index} 逻辑分组,开始递归解析");
|
||||
|
||||
// 递归解析逻辑分组中的条件
|
||||
$dbKey = static::parseWhereCondition($whereItem, $keyField);
|
||||
if ($dbKey !== null) {
|
||||
Log::info("条件类型1: {$index} 分组中匹配到 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
} // 2. 处理 ['user_id', '=', 123] 形式
|
||||
elseif (is_array($whereItem) && count($whereItem) >= 3) {
|
||||
if ($whereItem[0] === $keyField) {
|
||||
$dbKey = $whereItem[2];
|
||||
Log::info("条件类型2: 直接匹配 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
} // 3. 处理闭包条件: ['user_id', function($query){...}]
|
||||
elseif (is_array($whereItem) && isset($whereItem[1]) && $whereItem[1] instanceof \Closure) {
|
||||
Log::info("条件类型3: 发现闭包条件,开始递归解析");
|
||||
|
||||
// 创建临时查询对象执行闭包
|
||||
$subQuery = new Query();
|
||||
$whereItem[1]($subQuery);
|
||||
|
||||
// 递归解析闭包中的条件
|
||||
$dbKey = static::extractKeyFromOptions($subQuery->getOptions(), $keyField);
|
||||
if ($dbKey !== null) {
|
||||
Log::info("条件类型3: 闭包中匹配到 {$keyField}={$dbKey}");
|
||||
return $dbKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
125
app/common/model/Common.php
Normal file
125
app/common/model/Common.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\czg\model\SysCaptcha;
|
||||
use think\cache\driver\Redis;
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
use support\think\Cache;
|
||||
|
||||
class Common extends Model
|
||||
{
|
||||
|
||||
|
||||
// 统一处理分表表新增编辑查询(主表中没有的表)
|
||||
public static function saveDbData($table, $sale, $data, $operate = 'insertGetId', $where = [])
|
||||
{
|
||||
if(in_array($operate, ['insertGetId', 'insert']) || $operate == 'update') {
|
||||
$connect_name = DatabaseRoute::getConnection($table, $sale, true);
|
||||
}else {
|
||||
$connect_name = DatabaseRoute::getConnection($table, $sale);
|
||||
}
|
||||
$db = Db::connect($connect_name);
|
||||
if($operate == 'insert' || $operate == 'insertGetId') {
|
||||
return $db->name($table)->insertGetId($data);
|
||||
}elseif($operate == 'update') {
|
||||
return $db->name($table)->where($where)->update($data);
|
||||
}elseif ($operate == 'select') {
|
||||
return $db->name($table)->where($where)->select();
|
||||
}elseif ($operate == 'find') {
|
||||
return $db->name($table)->where($where)->find();
|
||||
}
|
||||
}
|
||||
|
||||
public static function db_count($table, $sale, $where)
|
||||
{
|
||||
$connect_name = DatabaseRoute::getConnection($table, $sale);
|
||||
$db = Db::connect($connect_name);
|
||||
return $db->name($table)->where($where)->count();
|
||||
|
||||
}
|
||||
|
||||
public static function getAppUseKv()
|
||||
{
|
||||
$info = Db::connect(config('database.search_library'))->name('common_info')->where(['is_app_use' => 1])->field('id, value')->select();
|
||||
$data = [];
|
||||
foreach ($info as $k => $v) {
|
||||
$data[$v['id']] = $v['value'];
|
||||
}
|
||||
return returnSuccessData($data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 检查是否允许访问(基于Redis的频率限制)
|
||||
* @param string $id 唯一标识(如用户ID、IP等)
|
||||
* @param string $key 操作类型(如"updateWeekCourseView")
|
||||
* @param int $count 允许的访问次数
|
||||
* @param int $seconds 时间窗口(秒)
|
||||
* @return bool 是否允许访问
|
||||
*/
|
||||
public static function isAccessAllowed($id, $key, $count, $seconds, $sys_data = false)
|
||||
{
|
||||
if($sys_data) {
|
||||
$redisKey = 'sys:data:' . $key . ':' . $id;
|
||||
}else {
|
||||
$redisKey = generateRedisKey($key, $id);
|
||||
}
|
||||
// 获取当前访问次数
|
||||
$currentCount = Cache::get($redisKey);
|
||||
|
||||
if ($currentCount === null) {
|
||||
// 首次访问:初始化计数器并设置过期时间
|
||||
Cache::set($redisKey, $seconds, 1);
|
||||
return true;
|
||||
}
|
||||
if ((int)$currentCount < $count) {
|
||||
// 未超过限制:增加计数
|
||||
Cache::set($redisKey,$currentCount + 1);
|
||||
return true;
|
||||
}
|
||||
// 已超过限制
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param int $courseId 课程ID
|
||||
* @return int 周播放量
|
||||
*/
|
||||
public static function getCourseWeekViewCount($courseId)
|
||||
{
|
||||
$key = "course:viewCount:{$courseId}";
|
||||
// 从Redis获取周播放量
|
||||
$viewCount = Cache::get($key);
|
||||
if (empty($viewCount)) {
|
||||
// 计算下周一的时间戳
|
||||
$now = time();
|
||||
$dayOfWeek = date('N', $now); // 1-7,1表示周一
|
||||
$daysToMonday = $dayOfWeek === 1 ? 7 : (1 - $dayOfWeek + 7) % 7;
|
||||
$nextMonday = $now + $daysToMonday * 86400;
|
||||
|
||||
// 计算剩余秒数并设置缓存
|
||||
$seconds = $nextMonday - $now;
|
||||
Cache::set($key, 1, $seconds);
|
||||
return 1;
|
||||
}
|
||||
// 播放量递增并返回
|
||||
$newCount = Cache::set($key, $viewCount + 1, -1);
|
||||
return $newCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
83
app/common/model/Config.php
Normal file
83
app/common/model/Config.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use Throwable;
|
||||
use think\Model;
|
||||
use app\admin\model\Config as adminConfigModel;
|
||||
|
||||
class Config extends Model
|
||||
{
|
||||
/**
|
||||
* 添加系统配置分组
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function addConfigGroup(string $key, string $value): bool
|
||||
{
|
||||
return self::addArrayItem('config_group', $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统配置分组
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function removeConfigGroup(string $key): bool
|
||||
{
|
||||
if (adminConfigModel::where('group', $key)->find()) return false;
|
||||
return self::removeArrayItem('config_group', $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加系统快捷配置入口
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function addQuickEntrance(string $key, string $value): bool
|
||||
{
|
||||
return self::addArrayItem('config_quick_entrance', $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统快捷配置入口
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function removeQuickEntrance(string $key): bool
|
||||
{
|
||||
return self::removeArrayItem('config_quick_entrance', $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为Array类型的配置项添加元素
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function addArrayItem(string $name, string $key, string $value): bool
|
||||
{
|
||||
$configRow = adminConfigModel::where('name', $name)->find();
|
||||
foreach ($configRow->value as $item) {
|
||||
if ($item['key'] == $key) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$configRow->value = array_merge($configRow->value, [['key' => $key, 'value' => $value]]);
|
||||
$configRow->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除Array类型配置项的一个元素
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function removeArrayItem(string $name, string $key): bool
|
||||
{
|
||||
$configRow = adminConfigModel::where('name', $name)->find();
|
||||
$configRowValue = $configRow->value;
|
||||
foreach ($configRowValue as $iKey => $item) {
|
||||
if ($item['key'] == $key) {
|
||||
unset($configRowValue[$iKey]);
|
||||
}
|
||||
}
|
||||
$configRow->value = $configRowValue;
|
||||
$configRow->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
14
app/common/model/CourseCollect.php
Normal file
14
app/common/model/CourseCollect.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
|
||||
use app\czg\model\SysCaptcha;
|
||||
use think\facade\Cache;
|
||||
|
||||
class CourseCollect extends BaseModel
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
80
app/common/model/SysUser.php
Normal file
80
app/common/model/SysUser.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\czg\model\SysCaptcha;
|
||||
use ba\Random;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Db;
|
||||
|
||||
class SysUser extends BaseModel
|
||||
{
|
||||
|
||||
public static function adda()
|
||||
{
|
||||
SysUser::create([
|
||||
'user_id' => rand(000000, 999999),
|
||||
'username' => '哎呀' . rand(000000, 999999),
|
||||
]);
|
||||
}
|
||||
|
||||
// 查询username
|
||||
public static function GetByusername($username)
|
||||
{
|
||||
// 全表扫描username
|
||||
$dbmap = config('database.db_map');
|
||||
foreach ($dbmap as $dbname) {
|
||||
if(!in_array($dbname, config('database.unset_db_map'))) {
|
||||
$connect = Db::connect($dbname);
|
||||
$data = $connect->name('sys_user')->where(['username' => $username])->find();
|
||||
if($data) {
|
||||
// 如果查到直接跳出循环并保存缓存
|
||||
Cache::set('admin_info_' . $username, $data['user_id']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public static function GetByQrcode($qd_rcode)
|
||||
{
|
||||
// 全表扫描username
|
||||
return DatabaseRoute::getAllDbData('sys_user', function ($query) use ($qd_rcode) {
|
||||
return $query->where([
|
||||
'qd_code' => $qd_rcode
|
||||
]);
|
||||
})->find();
|
||||
}
|
||||
|
||||
public static function updateSysMoney($userId, $money, $type)
|
||||
{
|
||||
$count = Db::name('sys_user_money')->where([
|
||||
'user_id' => $userId
|
||||
])->count();
|
||||
if (!$count) {
|
||||
Db::name('sys_user_money')->where([
|
||||
'user_id' => $userId
|
||||
])->insert([
|
||||
'id' => Random::generateRandomPrefixedId(19),
|
||||
'user_id' => $userId,
|
||||
'money' => 0
|
||||
]);
|
||||
}
|
||||
$model = Db::name('sys_user_money');
|
||||
if ($type) {
|
||||
$model->inc('money', floatval($money))->where([
|
||||
'user_id' => $userId
|
||||
])->update();
|
||||
}else{
|
||||
$model->dec('money', floatval($money))->where([
|
||||
'user_id' => $userId
|
||||
])->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
51
app/common/model/User.php
Normal file
51
app/common/model/User.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* 会员公共模型
|
||||
* @property int $id 会员ID
|
||||
* @property string $password 密码密文
|
||||
* @property string $salt 密码盐(废弃待删)
|
||||
* @property int $login_failure 登录失败次数
|
||||
* @property string $last_login_time 上次登录时间
|
||||
* @property string $last_login_ip 上次登录IP
|
||||
* @property string $email 会员邮箱
|
||||
* @property string $mobile 会员手机号
|
||||
* @property string $status 状态:enable=启用,disable=禁用,...(string存储,可自定义其他)
|
||||
*/
|
||||
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 resetPassword($uid, $newPassword): int|User
|
||||
{
|
||||
return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
|
||||
}
|
||||
|
||||
public function getMoneyAttr($value): string
|
||||
{
|
||||
return bcdiv($value, 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户的余额是不可以直接进行修改的,请通过 UserMoneyLog 模型插入记录来实现自动修改余额
|
||||
* 此处定义上 money 的修改器仅为防止直接对余额的修改造成数据错乱
|
||||
*/
|
||||
public function setMoneyAttr($value): string
|
||||
{
|
||||
return bcmul($value, 100, 2);
|
||||
}
|
||||
}
|
||||
41
app/common/model/UserMoneyLog.php
Normal file
41
app/common/model/UserMoneyLog.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use think\model;
|
||||
|
||||
class UserMoneyLog extends model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = 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);
|
||||
}
|
||||
}
|
||||
11
app/common/model/UserScoreLog.php
Normal file
11
app/common/model/UserScoreLog.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use think\model;
|
||||
|
||||
class UserScoreLog extends model
|
||||
{
|
||||
protected $autoWriteTimestamp = true;
|
||||
protected $updateTime = false;
|
||||
}
|
||||
Reference in New Issue
Block a user