这是我的最终代码 有一个问题就是 目前是我手动测试的一个用户 给到他发放福利了 , 但是我希望是可以控制的 怎么优化? 例如某个用户生日当天没有给到积分 我来手动再给他一次:<?php
namespace app\command\admin;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
class Drawscore extends Command
{
protected $logFile;
protected $logPath;
protected function configure()
{
$this->setName('drawscore')
->setDescription('定时计划:计算工友生日和会员等级 生日/每年赠送相应积分');
}
protected function execute(Input $input, Output $output)
{
// 初始化日志系统
$this->initLogSystem();
$this->log("开始执行工匠福利积分发放...", true);
// 获取所有有效档位(按积分要求升序排列)
$this->log("查询有效福利档位...");
$fuli = Db::name("user_birthday_fuli")
->where("status", 1)
->order("chengzhang", "asc")
->select();
if(empty($fuli)) {
$this->log("没有配置福利档位,跳过执行", true);
return;
}
$this->log("找到 ".count($fuli)." 个有效福利档位");
// 获取最低积分要求
$minScore = $fuli[0]['chengzhang'];
// 获取今天的月-日格式(如:07-15)
$todayMD = date('m-d');
$this->log("最低积分要求: {$minScore}, 今天日期: {$todayMD}");
// 查询满足条件的工匠(积分达标且今天生日)
$this->log("查询符合条件的生日工匠...");
$users = Db::name("user")
->alias("u")
->join("user_gongjiang_log g", "g.user_id = u.id AND g.status = 1")
->where("u.score", ">=", $minScore)
->where("u.id", "=", 866) //Jin 测试
->where('u.birthday', '>', 0) // 确保birthday是有效时间戳
->whereRaw("DATE_FORMAT(FROM_UNIXTIME(u.birthday), '%m-%d') = ?", [$todayMD])
->field("u.id, u.mobile, u.score")
->select();
if(empty($users)) {
$this->log("今天没有符合条件的生日工匠", true);
return;
}
$this->log("找到 ".count($users)." 个符合条件的生日工匠");
// 构建积分档位映射表
$this->log("构建积分档位映射表...");
$scoreMap = [];
foreach ($fuli as $item) {
$scoreMap[$item['chengzhang']] = $item['zengsong'];
$this->log("档位: {$item['chengzhang']}分 => 赠送{$item['zengsong']}分");
}
krsort($scoreMap); // 按积分要求降序排列
// 当前年份的时间范围
$currentYear = date('Y');
$startTime = strtotime("{$currentYear}-01-01 00:00:00");
$endTime = strtotime("{$currentYear}-12-31 23:59:59");
$this->log("本年度时间范围: {$currentYear}-01-01 至 {$currentYear}-12-31");
$successCount = 0;
$skipCount = 0;
$failCount = 0;
$this->log("开始处理工匠用户...");
foreach ($users as $user) {
$this->log("处理用户 ID: {$user['id']}, 手机: {$user['mobile']}, 积分: {$user['score']}");
$shouldGet = 0;
// 从高到低匹配用户应得积分档位
foreach ($scoreMap as $required => $reward) {
if ($user['score'] >= $required) {
$shouldGet = $reward;
$this->log("匹配到档位: {$required}分 => 应得{$reward}分");
break;
}
}
if ($shouldGet <= 0) {
$this->log("无匹配档位,跳过");
$skipCount++;
continue;
}
// 检查本年度是否已发放
$this->log("检查本年度是否已发放...");
$hasGiven = Db::name("user_score_log")
->where([
'type_id' => 6, // 工匠福利
'user_id' => $user['id']
])
->where('create_time', 'between', [$startTime, $endTime])
->count();
if ($hasGiven > 0) {
$this->log("用户ID:{$user['id']} 本年度已发放积分,跳过");
$skipCount++;
continue;
}
// 发放积分
$remark = '工匠生日福利积分';
$this->log("发放积分: {$shouldGet}分...");
$drawScore = \app\user\model\ScoreLog::changeNoRedis(6, $user['id'], $shouldGet, 1, $remark);
if (!$drawScore) {
$this->log("用户ID:{$user['id']} 积分发放失败", true);
$failCount++;
} else {
$this->log("用户ID:{$user['id']} 发放 {$shouldGet} 积分成功", true);
$successCount++;
}
}
$this->log("工匠生日福利发放完成", true);
$this->log("统计: 成功 {$successCount} 人, 跳过 {$skipCount} 人, 失败 {$failCount} 人");
}
/**
* 初始化日志系统
*/
protected function initLogSystem()
{
// 创建日志目录(如果不存在)
$this->logPath = app()->getRuntimePath() . 'drawscore_logs/';
if (!is_dir($this->logPath)) {
mkdir($this->logPath, 0755, true);
}
// 按日期命名日志文件
$date = date('Y-m-d');
$this->logFile = $this->logPath . "drawscore_{$date}.log";
}
/**
* 记录日志(同时输出到控制台和文件)
*
* @param string $message 日志内容
* @param bool $toConsole 是否输出到控制台
*/
protected function log($message, $toConsole = false)
{
// 添加时间戳
$logMessage = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL;
// 写入文件
file_put_contents($this->logFile, $logMessage, FILE_APPEND | LOCK_EX);
// 输出到控制台
if ($toConsole) {
$this->output->writeln($message);
}
}
}