- 18 张公共表更名(addon/attachment/configure/links/spider_log/spider_stat/sms/notice/ad/task/prop/medal/help/card -> common_*,member_wallets->member_wallet,score_rule/score_log -> member_*,addon_config->common_addonconf),模型全部对齐新表名,Db 直引用清零 - Attachment 模型补 表名绑定,修复富文本上传查 wxapp_attachment 1146 隐患 - install.sql + 迁移 SQL:backend_admin/backend_role delete_at 默认 0,修复软删除(NULL != 0)误过滤导致后台菜单为空 - AppService::boot() 支持插件 info.php 声明 commands 自动注册插件命令(psr-4 自动加载,坏类名自动跳过) - 各插件(haonav/mqttbroker/wxchat/articles/blog/forum 等)字段与配置同步调整 - 框架版本 1.1.0 -> 1.1.1
133 lines
3.9 KiB
PHP
133 lines
3.9 KiB
PHP
<?php
|
||
/*
|
||
* @Author: YwxApp <ywx@ywxapp.cn>
|
||
* @Date: 2026-08-07 22:53:48
|
||
* @LastEditors: YwxApp <ywx@ywxapp.cn>
|
||
* @LastEditTime: 2026-08-19 21:12:33
|
||
* @Description:
|
||
* @FilePath: \ywxapp_dev\ywxapp\model\Score.php
|
||
* @CustomString: Copyright (c) 2026 YwxApp
|
||
*/
|
||
declare(strict_types=1);
|
||
namespace ywxapp\model;
|
||
|
||
use ywxapp\model\BaseModel;
|
||
|
||
use think\facade\Db;
|
||
use think\model\concern\SoftDelete;
|
||
|
||
/**
|
||
* 积分规则 & 积分流水
|
||
*/
|
||
class MebmberScore extends BaseModel
|
||
{
|
||
use SoftDelete;
|
||
|
||
/**
|
||
* 模型配置(BaseModel::applyOptions 约定)
|
||
*/
|
||
protected function getOptions(): array
|
||
{
|
||
return [
|
||
'strict' => true,
|
||
'autoWriteTimestamp' => 'int',
|
||
'createTime' => 'create_at',
|
||
'updateTime' => 'update_at',
|
||
'readonly' => ['view_count']
|
||
];
|
||
}
|
||
|
||
// 规则类型
|
||
const TYPE_GAIN = 1; // 获取
|
||
const TYPE_SPEND = 2; // 消费
|
||
|
||
public static function typeList(): array
|
||
{
|
||
return [
|
||
self::TYPE_GAIN => '获取',
|
||
self::TYPE_SPEND => '消费',
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 确保 score_rule / score_log 关联表已就绪(静态入口可能未实例化模型)
|
||
*/
|
||
public static function ensureSchema(): void
|
||
{
|
||
$prefix = BaseModel::currentPrefix();
|
||
BaseModel::ensureTableFromInstall($prefix, 'member_score_rule');
|
||
BaseModel::ensureTableFromInstall($prefix, 'member_score_log');
|
||
BaseModel::ensureColumn("{$prefix}member_user", 'score', "int unsigned NOT NULL DEFAULT 0 COMMENT '积分(做任务/互动获得)'");
|
||
}
|
||
|
||
/**
|
||
* 积分变动(带流水记录,事务安全)
|
||
* @param int $uid 用户ID
|
||
* @param int $type 1=收入 2=支出
|
||
* @param int $value 变动值(正数)
|
||
* @param string $remark 备注
|
||
* @param int $ruleId 关联规则ID(默认0)
|
||
* @return array [bool, string]
|
||
*/
|
||
public static function change(int $uid, int $type, int $value, string $remark = '', int $ruleId = 0): array
|
||
{
|
||
self::ensureSchema();
|
||
$uid = (int) $uid;
|
||
$value = (int) $value;
|
||
if ($uid <= 0 || $value <= 0) {
|
||
return [false, '参数错误'];
|
||
}
|
||
$type = $type === self::TYPE_SPEND ? self::TYPE_SPEND : self::TYPE_GAIN;
|
||
|
||
Db::startTrans();
|
||
try {
|
||
$user = Db::name('member_user')->where('uid', $uid)->lock(true)->find();
|
||
if (!$user) {
|
||
throw new \Exception('用户不存在');
|
||
}
|
||
if ($type === self::TYPE_SPEND && $user['score'] < $value) {
|
||
throw new \Exception('积分余额不足');
|
||
}
|
||
$balance = $type === self::TYPE_SPEND
|
||
? $user['score'] - $value
|
||
: $user['score'] + $value;
|
||
|
||
Db::name('member_user')->where('uid', $uid)->update(['score' => $balance]);
|
||
|
||
Db::name('member_score_log')->insert([
|
||
'uid' => $uid,
|
||
'rule_id' => $ruleId,
|
||
'type' => $type,
|
||
'value' => $value,
|
||
'balance' => $balance,
|
||
'remark' => $remark,
|
||
'create_at' => time(),
|
||
]);
|
||
|
||
Db::commit();
|
||
return [true, 'ok'];
|
||
} catch (\Throwable $e) {
|
||
Db::rollback();
|
||
return [false, $e->getMessage()];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 积分流水列表(后台查看)
|
||
*/
|
||
public static function logList(int $uid = 0, int $page = 1, int $limit = 15): array
|
||
{
|
||
self::ensureSchema();
|
||
$query = Db::name('member_score_log');
|
||
if ($uid > 0) {
|
||
$query->where('uid', $uid);
|
||
}
|
||
$count = $query->count();
|
||
$list = $query->order('id', 'desc')
|
||
->page($page, $limit)
|
||
->select()
|
||
->toArray();
|
||
return ['count' => $count, 'list' => $list];
|
||
}
|
||
}
|