feat: 公共表更名 common/member 前缀 + 插件命令自动加载 + 版本 1.1.1

- 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
This commit is contained in:
ywxapp
2026-08-20 20:19:15 +08:00
parent 303f548664
commit 1d49e6f5ee
395 changed files with 13342 additions and 2012 deletions
+180
View File
@@ -0,0 +1,180 @@
<?php
/*
* @Author: YwxApp <ywx@ywxapp.cn>
* @Date: 2026-08-07 10:22:47
* @LastEditors: YwxApp <ywx@ywxapp.cn>
* @LastEditTime: 2026-08-20 00:36:36
* @Description:
* @FilePath: \ywxapp_dev\ywxapp\model\CommonCard.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 CommonCard extends BaseModel
{
use SoftDelete;
protected function getOptions(): array
{
return [
'strict' => false,
'autoWriteTimestamp' => 'int',
'createTime' => 'create_at',
'updateTime' => 'update_at',
'deleteTime' => 'delete_at',
'defaultSoftDelete' => 0,
'append' => ['target'],
'hidden' => ['create_at', 'update_at', 'delete_at'],
'readonly' => ['id'],
];
}
// 卡密状态
const STATUS_UNSOLD = 0; // 未售
const STATUS_SOLD = 1; // 已售
const STATUS_USED = 2; // 已用(已兑换)
/**
* 运行时自愈:确保 card 主表存在(install.sql 为事实源)。
*/
public static function ensureSchema(): void
{
BaseModel::ensureTableFromInstall(BaseModel::currentPrefix(), 'common_card');
}
/**
* 初始化:自愈建表,避免远程库缺失 wxapp_card 导致 1146。
*/
protected function initialize()
{
parent::initialize();
self::ensureSchema();
}
/**
* 兑换卡密(会员用卡号+密码充值余额)
*
* @param int $uid 会员ID
* @param string $cardno 卡号
* @param string $password 密码
* @return array ['success'=>bool,'msg'=>string,'data'=>array]
*/
public static function redeem(int $uid, string $cardno, string $password): array
{
if ($uid <= 0 || $cardno === '' || $password === '') {
return ['success' => false, 'msg' => '参数不完整'];
}
$card = self::where('cardno', $cardno)->find();
if (empty($card)) {
return ['success' => false, 'msg' => '卡密不存在'];
}
if ($card->delete_at > 0) {
return ['success' => false, 'msg' => '卡密已失效'];
}
if ((int)$card->status === self::STATUS_USED) {
return ['success' => false, 'msg' => '该卡密已被使用'];
}
// 密码校验(存储若为明文,按需改为 password_verify)
if ((string)$card->password !== (string)$password) {
return ['success' => false, 'msg' => '卡号或密码错误'];
}
$amount = (float)$card->amount;
if ($amount <= 0) {
return ['success' => false, 'msg' => '卡密面值异常'];
}
Db::startTrans();
try {
// 1) 卡密标记已用,绑定会员
$card->status = self::STATUS_USED;
$card->use_time = time();
$card->uid = $uid;
$card->save();
// 2) 会员钱包加余额 + 累计充值(无钱包则自动创建)
$wallet = Db::name('member_wallet')->where('uid', $uid)->find();
if (empty($wallet)) {
Db::name('member_wallet')->insert([
'uid' => $uid,
'balance' => $amount,
'total_recharge' => $amount,
'create_at' => time(),
'update_at' => time(),
]);
} else {
Db::name('member_wallet')
->where('uid', $uid)
->inc('balance', $amount)
->inc('total_recharge', $amount)
->update(['update_at' => time()]);
}
// 3) 充值流水
Db::name('member_bill')->insert([
'uid' => $uid,
'type' => 1, // 充值
'amount' => $amount,
'currency' => 1, // 人民币
'channel' => 'card',
'order_no' => 'CARD' . date('YmdHis') . $uid . mt_rand(100, 999),
'status' => 1, // 成功
'description' => '卡密充值:' . $cardno,
'create_at' => time(),
'update_at' => time(),
]);
Db::commit();
return [
'success' => true,
'msg' => '兑换成功,已充值 ¥' . number_format($amount, 2),
'data' => ['amount' => $amount],
];
} catch (\Throwable $e) {
Db::rollback();
throw $e;
}
}
/**
* 批量生成卡密
*
* @param int $count 生成数量
* @param float $amount 面值
* @param string $prefix 卡号前缀(如 YX)
* @return array 生成的卡号列表
*/
public static function generateBatch(int $count, float $amount, string $prefix = ''): array
{
$count = max(1, min(200, $count)); // 单次上限保护
$batchNo = date('YmdHis') . mt_rand(1000, 9999);
$list = [];
$rows = [];
for ($i = 0; $i < $count; $i++) {
$cardno = ($prefix ?: 'YX') . strtoupper(substr(md5(uniqid((string)mt_rand(), true)), 0, 16));
$password = strtoupper(substr(md5(uniqid((string)mt_rand(), true)), 0, 8));
$list[] = ['cardno' => $cardno, 'password' => $password];
$rows[] = [
'cardno' => $cardno,
'password' => $password,
'amount' => $amount,
'status' => self::STATUS_UNSOLD,
'batch_no' => $batchNo,
'create_at' => time(),
'update_at' => time(),
];
}
self::insertAll($rows);
return $list;
}
}