|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册 
×
- <?php
- /**
- * 每日签到插件 - 核心函数库
- */
- if(!defined('IN_DISCUZ')) {
- exit('Access Denied');
- }
- /* ---------------- 设置 ---------------- */
- function bbgn_set_default() {
- return array(
- 'open' => '1', // 启用开关
- 'btntext' => '', // 签到按钮文字
- 'retro_open' => '1', // 允许补签
- 'retro_credit' => 'extcredits2', // 补签消耗积分类型
- 'retro_num' => '10', // 补签消耗数值 0=免费
- 'retro_max' => '3', // 周期(自然月)内补签次数上限 0=禁用
- 'remind_open' => '0', // 定时提醒开关
- 'remind_hour' => '20', // 提醒触发时段 0-23
- 'rank_cache' => '3600', // 榜单缓存时长(秒)
- 'notice_open' => '1', // 签到成功站内通知
- 'base_credit' => 'extcredits2', // 奖励积分类型
- 'base_num' => '2', // 基础奖励数值
- 'random_open' => '0', // 随机积分奖励开关
- 'random_min' => '1',
- 'random_max' => '5',
- 'rank_limit' => '20', // 榜单上榜人数
- );
- }
- function bbgn_set_all($refresh = false) {
- static $set = null;
- if($set === null || $refresh) {
- $set = array();
- $query = DB::query("SELECT skey, svalue FROM ".DB::table('lymsouqd_bbgn_set'));
- while($row = DB::fetch($query)) {
- $set[$row['skey']] = $row['svalue'];
- }
- $set = array_merge(bbgn_set_default(), $set);
- }
- return $set;
- }
- function bbgn_set_save($key, $value) {
- DB::insert('lymsouqd_bbgn_set', array('skey' => $key, 'svalue' => $value), false, true);
- }
- /* ---------------- 工具 ---------------- */
- function bbgn_today() {
- return dgmdate(TIMESTAMP, 'Y-m-d');
- }
- function bbgn_creditname($credittype) {
- global $_G;
- $id = intval(str_replace('extcredits', '', $credittype));
- if($id >= 1 && $id <= 8 && !empty($_G['setting']['extcredits'][$id]['title'])) {
- return $_G['setting']['extcredits'][$id]['title'];
- }
- return $credittype;
- }
- /* 站点已启用的扩展积分列表 */
- function bbgn_creditlist() {
- global $_G;
- $list = array();
- for($i = 1; $i <= 8; $i++) {
- if(!empty($_G['setting']['extcredits'][$i]['title'])) {
- $list['extcredits'.$i] = $_G['setting']['extcredits'][$i]['title'];
- }
- }
- return $list;
- }
- function bbgn_json($data) {
- header('Content-Type: application/json; charset=utf-8');
- echo json_encode($data, JSON_UNESCAPED_UNICODE);
- exit;
- }
- /* ---------------- 用户统计 ---------------- */
- function bbgn_user_get($uid) {
- global $_G;
- $user = DB::fetch_first("SELECT * FROM ".DB::table('lymsouqd_bbgn_user')." WHERE uid=%d", array($uid));
- if(!$user) {
- $username = ($_G['uid'] == $uid) ? $_G['username'] : DB::result_first("SELECT username FROM ".DB::table('common_member')." WHERE uid=%d", array($uid));
- $data = array(
- 'uid' => $uid,
- 'username' => $username,
- 'totaldays' => 0,
- 'contin' => 0,
- 'maxcontin' => 0,
- 'reward_total' => 0,
- 'lastday' => '',
- 'lasttime' => 0,
- 'retro_num' => 0,
- 'retro_month' => '',
- 'updatetime' => TIMESTAMP,
- );
- DB::insert('lymsouqd_bbgn_user', $data, false, true);
- $user = $data;
- }
- return $user;
- }
- function bbgn_signed_today($uid) {
- return DB::result_first("SELECT COUNT(*) FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND qdday=%s AND status=1", array($uid, bbgn_today()));
- }
- /* 重新计算连续签到天数(从今天或昨天向前追溯) */
- function bbgn_recalc_contin($uid) {
- $map = array();
- $query = DB::query("SELECT DISTINCT qdday FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND status=1", array($uid));
- while($row = DB::fetch($query)) {
- $map[$row['qdday']] = 1;
- }
- $today = bbgn_today();
- $cursor = isset($map[$today]) ? $today : dgmdate(TIMESTAMP - 86400, 'Y-m-d');
- $contin = 0;
- while(isset($map[$cursor])) {
- $contin++;
- $cursor = dgmdate(strtotime($cursor) - 86400, 'Y-m-d');
- }
- return $contin;
- }
- /* 全量重算用户统计(撤销记录后调用) */
- function bbgn_recalc_user($uid) {
- $totaldays = DB::result_first("SELECT COUNT(DISTINCT qdday) FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND status=1", array($uid));
- $reward_total = DB::result_first("SELECT IFNULL(SUM(reward),0) FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND status=1", array($uid));
- $lastday = DB::result_first("SELECT IFNULL(MAX(qdday),'') FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND status=1", array($uid));
- $contin = bbgn_recalc_contin($uid);
- $user = bbgn_user_get($uid);
- $maxcontin = max($user['maxcontin'], $contin);
- DB::update('lymsouqd_bbgn_user', array(
- 'totaldays' => $totaldays,
- 'reward_total' => $reward_total,
- 'lastday' => $lastday,
- 'contin' => $contin,
- 'maxcontin' => $maxcontin,
- 'updatetime' => TIMESTAMP,
- ), "uid='".intval($uid)."'");
- }
- /* 当月已用补签次数 */
- function bbgn_retro_count($uid) {
- $user = bbgn_user_get($uid);
- $month = dgmdate(TIMESTAMP, 'Y-m');
- if($user['retro_month'] != $month) {
- return 0;
- }
- return intval($user['retro_num']);
- }
- /* ---------------- 奖励 ---------------- */
- /* 计算签到奖励:基础 + 随机 + 连签区间 + 阶段 */
- function bbgn_reward_calc($contin, $set) {
- $total = 0;
- $detail = array();
- $base = intval($set['base_num']);
- if($base > 0) {
- $total += $base;
- $detail[] = '基础奖励 +'.$base;
- }
- if($set['random_open']) {
- $min = max(0, intval($set['random_min']));
- $max = max($min, intval($set['random_max']));
- $r = mt_rand($min, $max);
- if($r > 0) {
- $total += $r;
- $detail[] = '随机奖励 +'.$r;
- }
- }
- $query = DB::query("SELECT * FROM ".DB::table('lymsouqd_bbgn_reward')." WHERE status=1 ORDER BY sort, id");
- while($rule = DB::fetch($query)) {
- $num = intval($rule['num']);
- if($num <= 0) continue;
- if($rule['rtype'] == 'contin' && $contin >= intval($rule['daymin']) && $contin <= intval($rule['daymax'])) {
- $total += $num;
- $detail[] = '连签'.$rule['daymin'].'-'.$rule['daymax'].'天奖励 +'.$num;
- } elseif($rule['rtype'] == 'stage' && $contin == intval($rule['day'])) {
- $total += $num;
- $detail[] = '连签'.$rule['day'].'天阶段奖励 +'.$num;
- }
- }
- return array($total, $detail);
- }
- /* 下一阶段奖励进度 */
- function bbgn_nextstage($contin) {
- $stage = DB::fetch_first("SELECT day, num FROM ".DB::table('lymsouqd_bbgn_reward')." WHERE rtype='stage' AND status=1 AND day>%d ORDER BY day ASC LIMIT 1", array($contin));
- if(!$stage) {
- return null;
- }
- $prev = DB::result_first("SELECT IFNULL(MAX(day),0) FROM ".DB::table('lymsouqd_bbgn_reward')." WHERE rtype='stage' AND status=1 AND day<=%d", array($contin));
- $span = max(1, $stage['day'] - $prev);
- $done = max(0, $contin - $prev);
- return array(
- 'day' => $stage['day'],
- 'num' => $stage['num'],
- 'need' => $stage['day'] - $contin,
- 'progress' => min(100, round($done / $span * 100)),
- );
- }
- /* ---------------- 签到 / 补签 ---------------- */
- /* 执行签到,返回 array(code, msg, data) */
- function bbgn_dosign($uid) {
- global $_G;
- $set = bbgn_set_all();
- if(!$set['open']) {
- return array(1, '签到功能已关闭');
- }
- if(bbgn_signed_today($uid)) {
- return array(1, '今日已完成签到,请勿重复操作');
- }
- $user = bbgn_user_get($uid);
- $today = bbgn_today();
- $yesterday = dgmdate(TIMESTAMP - 86400, 'Y-m-d');
- $contin = ($user['lastday'] == $yesterday) ? $user['contin'] + 1 : 1;
- list($total, $detail) = bbgn_reward_calc($contin, $set);
- $credit = $set['base_credit'];
- if($total > 0) {
- updatemembercount($uid, array($credit => $total), 1, 'BGN', 0, '', '每日签到奖励');
- }
- DB::insert('lymsouqd_bbgn_log', array(
- 'uid' => $uid,
- 'username' => $user['username'],
- 'qdday' => $today,
- 'dateline' => TIMESTAMP,
- 'qtype' => 1,
- 'credit' => $credit,
- 'reward' => $total,
- 'detail' => implode(',', $detail),
- 'status' => 1,
- ));
- DB::update('lymsouqd_bbgn_user', array(
- 'totaldays' => $user['totaldays'] + 1,
- 'contin' => $contin,
- 'maxcontin' => max($user['maxcontin'], $contin),
- 'reward_total' => $user['reward_total'] + $total,
- 'lastday' => $today,
- 'lasttime' => TIMESTAMP,
- 'updatetime' => TIMESTAMP,
- ), "uid='".intval($uid)."'");
- if($set['notice_open']) {
- $msg = '签到成功!连续签到 '.$contin.' 天';
- if($total > 0) {
- $msg .= ',获得 '.bbgn_creditname($credit).' +'.$total.'('.implode(',', $detail).')';
- }
- notification_add($uid, 'system', $msg, array(), 1);
- }
- return array(0, '签到成功', array(
- 'contin' => $contin,
- 'totaldays' => $user['totaldays'] + 1,
- 'reward' => $total,
- 'reward_total' => $user['reward_total'] + $total,
- 'detail' => $detail,
- 'nextstage' => bbgn_nextstage($contin),
- ));
- }
- /* 执行补签($isadmin=true 时跳过开关/次数/积分校验),返回 array(code, msg, data) */
- function bbgn_doretro($uid, $date, $isadmin = false) {
- global $_G;
- $set = bbgn_set_all();
- if(!$set['open']) {
- return array(1, '签到功能已关闭');
- }
- if(!$isadmin && !$set['retro_open']) {
- return array(1, '补签功能已关闭');
- }
- if(!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) || !strtotime($date)) {
- return array(1, '补签日期无效');
- }
- $today = bbgn_today();
- if($date >= $today) {
- return array(1, '只能补签今天之前的日期');
- }
- if(!$isadmin && dgmdate(TIMESTAMP, 'Y-m') != substr($date, 0, 7)) {
- return array(1, '仅支持补签本月漏签日期');
- }
- $exists = DB::result_first("SELECT COUNT(*) FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND qdday=%s AND status=1", array($uid, $date));
- if($exists) {
- return array(1, '该日期已有签到记录');
- }
- if(!$isadmin) {
- $max = intval($set['retro_max']);
- if($max <= 0) {
- return array(1, '补签功能已关闭');
- }
- if(bbgn_retro_count($uid) >= $max) {
- return array(1, '本周期补签次数已达上限');
- }
- $cost = intval($set['retro_num']);
- $credit = $set['retro_credit'];
- if($cost > 0) {
- $cid = intval(str_replace('extcredits', '', $credit));
- $field = ($cid >= 1 && $cid <= 8) ? 'extcredits'.$cid : 'extcredits2';
- $balance = DB::result_first("SELECT `".$field."` FROM ".DB::table('common_member_count')." WHERE uid=%d", array($uid));
- if($balance < $cost) {
- return array(1, bbgn_creditname($credit).'不足,无法完成补签');
- }
- updatemembercount($uid, array($credit => -$cost), 1, 'BGR', 0, '', '签到补签消耗');
- }
- /* 更新本月补签计数 */
- $user = bbgn_user_get($uid);
- $month = dgmdate(TIMESTAMP, 'Y-m');
- $num = ($user['retro_month'] == $month) ? $user['retro_num'] + 1 : 1;
- DB::update('lymsouqd_bbgn_user', array('retro_num' => $num, 'retro_month' => $month), "uid='".intval($uid)."'");
- }
- $user = bbgn_user_get($uid);
- DB::insert('lymsouqd_bbgn_log', array(
- 'uid' => $uid,
- 'username' => $user['username'],
- 'qdday' => $date,
- 'dateline' => TIMESTAMP,
- 'qtype' => $isadmin ? 3 : 2,
- 'credit' => '',
- 'reward' => 0,
- 'detail' => $isadmin ? '管理员补签' : '积分补签',
- 'status' => 1,
- ));
- /* 连签天数自动接续:重算统计 */
- bbgn_recalc_user($uid);
- $user = bbgn_user_get($uid);
- return array(0, '补签成功', array(
- 'contin' => $user['contin'],
- 'totaldays' => $user['totaldays'],
- 'nextstage' => bbgn_nextstage($user['contin']),
- ));
- }
- /* ---------------- 榜单 ---------------- */
- function bbgn_rank($type) {
- $set = bbgn_set_all();
- $cache = bbgn_set_all();
- $key = 'rankcache_'.$type;
- $now = TIMESTAMP;
- $cached = isset($cache[$key]) ? json_decode($cache[$key], true) : null;
- if($cached && !empty($cached['list']) && $now - intval($cached['time']) < max(60, intval($set['rank_cache']))) {
- return $cached['list'];
- }
- $limit = max(1, intval($set['rank_limit']));
- $list = array();
- if($type == 'total') {
- $query = DB::query("SELECT uid, username, totaldays AS score FROM ".DB::table('lymsouqd_bbgn_user')." WHERE totaldays>0 ORDER BY totaldays DESC, updatetime ASC LIMIT ".$limit);
- } elseif($type == 'contin') {
- $query = DB::query("SELECT uid, username, contin AS score FROM ".DB::table('lymsouqd_bbgn_user')." WHERE contin>0 ORDER BY contin DESC, updatetime ASC LIMIT ".$limit);
- } else {
- $month = dgmdate(TIMESTAMP, 'Y-m');
- $query = DB::query("SELECT uid, username, COUNT(DISTINCT qdday) AS score FROM ".DB::table('lymsouqd_bbgn_log')." WHERE status=1 AND qdday LIKE %s GROUP BY uid ORDER BY score DESC, uid ASC LIMIT ".$limit, array($month.'%'));
- }
- while($row = DB::fetch($query)) {
- $list[] = $row;
- }
- bbgn_set_save($key, json_encode(array('time' => $now, 'list' => $list)));
- return $list;
- }
- /* 当前用户名次 */
- function bbgn_rank_self($uid, $type) {
- if($type == 'total') {
- $my = bbgn_user_get($uid);
- $score = $my['totaldays'];
- if($score <= 0) return 0;
- return DB::result_first("SELECT COUNT(*) FROM ".DB::table('lymsouqd_bbgn_user')." WHERE totaldays>%d", array($score)) + 1;
- } elseif($type == 'contin') {
- $my = bbgn_user_get($uid);
- $score = $my['contin'];
- if($score <= 0) return 0;
- return DB::result_first("SELECT COUNT(*) FROM ".DB::table('lymsouqd_bbgn_user')." WHERE contin>%d", array($score)) + 1;
- } else {
- $month = dgmdate(TIMESTAMP, 'Y-m');
- $score = DB::result_first("SELECT COUNT(DISTINCT qdday) FROM ".DB::table('lymsouqd_bbgn_log')." WHERE uid=%d AND status=1 AND qdday LIKE %s", array($uid, $month.'%'));
- if($score <= 0) return 0;
- return DB::result_first("SELECT COUNT(*) FROM (SELECT uid FROM ".DB::table('lymsouqd_bbgn_log')." WHERE status=1 AND qdday LIKE %s GROUP BY uid HAVING COUNT(DISTINCT qdday)>%d) t", array($month.'%', $score)) + 1;
- }
- }
- /* 清空榜单缓存 */
- function bbgn_rank_clear() {
- DB::query("DELETE FROM ".DB::table('lymsouqd_bbgn_set')." WHERE skey LIKE 'rankcache_%'");
- }
复制代码
|

|