php七天簽到功能及表設計


最近開發一個商城app項目,需求表有個功能是寫個七天簽到功能,網上找了一圈才找到一個勉強可用的。

經修改應用到項目后,記錄一下需求開發流程及相關思路

先看設計稿:

功能需求如下:

1.顯示七天簽到列表,每簽到一天得到一積分,兩天兩積分,以此類推。在第八天的時候,重置歸零為第一天

2.顯示連續簽到天數、積分值

3.簽到日歷中,已簽到高亮顯示

4.切換年月,可以查詢到那天簽到的

 

數據表設計:

1.首先看數據庫表的設計,因為預計這個商城項目用戶量估計不大,所以采用了單表設計,數據量上去再說吧~

2.我這邊用戶功能會有個打卡視頻視頻功能,不需要的話可以把這兩個字段清除

CREATE TABLE `cy_user_sign_log` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '序號',
  `uid` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用戶id',
  `days` int(10) DEFAULT '0' COMMENT '連續簽到天數',
  `sign_time` int(10) DEFAULT NULL COMMENT '簽到時間',
  `is_sign` tinyint(4) DEFAULT '0' COMMENT '是否簽到過',
  `video` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '簽到視頻',
  `video_cover` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '簽到視頻封面',
  `create_time` int(10) NOT NULL COMMENT '新增時間',
  `update_time` int(10) DEFAULT NULL COMMENT '更新時間',
  `delete_time` int(10) DEFAULT NULL COMMENT '用來識別軟刪除\n只要這個字段的值不為NULL\n則視為已刪除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用戶簽到記錄表';

 

php框架公司使用的是tp6,這里我就直接上控制器和模型的代碼了

控制器:

1.涉及積分的功能,此處我就不上我的代碼了,如果有需要直接寫一個 方法就行了addScore($uid, $score);

2.這里注意一下,接口返回的月份數據,time和sign對應的意思

 'days'   =>  '日期',
 'sign'  =>  '0=未簽到,1=已簽到',
 'time'   =>  '0=過去,1=現在,2=未來',

 

/**
 * 用戶簽到列表
 * @return array 日期列表
 * @return array(
 *  'days'   =>  '天數',
 *  'sign'  =>  '0=未簽到,1=已簽到',
 *  'time'   =>  '0=過去,1=現在,2=未來',
 * );
 */
public function getUserSignList()
{
  $year = input('year', '');
  $month = input('month', '');
  $uid = request()->uid;
  // 日歷列表
  if ($year && $month) {
    $monthSign = UserSignLog::build()->getMonthSign($year, $month);
    $dayList = UserSignLog::build()->showDays($monthSign, $year, $month);
  } else {
    $monthSign = UserSignLog::build()->getMonthSign();
    $dayList = UserSignLog::build()->showDays($monthSign);
  }

  $data['dayList'] = $dayList;
  // 今天簽到數據
  $data['isSign'] = 0;
  $todayData = UserSignLog::build()->todayData();
  if ($todayData) {
    $data['isSign'] = 1;
  }
  $daysData = UserSignLog::build()->getInsertData($uid);
  $data['days'] = $daysData['days']; // 連續簽到天數
  return json_success('用戶簽到列表', $data);
}

/**
 * 執行當天簽到
 * @return json
 */
public function userSign()
{
  $todayData = UserSignLog::build()->todayData();
  if ($todayData['is_sign'] == 1) {
    return json_error('已簽到,請勿重復提交');
  } else {
    $uid = request()->uid;
    $daysData = UserSignLog::build()->getInsertData($uid);
    try {
      // 無今天數據
      if ($todayData == NULL) {
        $daysData['uid'] = $uid;
        $daysData['create_time'] = time();
        UserSignLog::build()->create($daysData);
      } else {
        UserSignLog::build()->where("id = {$todayData['id']}")->save($daysData);
      }
      $score = UserSignLog::build()->getTodayScores($daysData['days']);
      // 為該用戶添加積分
      // addScore($uid, $score);
    } catch (\Exception $e) {
      return json_error($e->getMessage());
    }
    $data['score'] = $score;  // 積分
    $data['days'] = $daysData['days']; // 連續簽到天數
    return json_success('簽到成功', $data);
  }
}

 

模型代碼:

<?php

declare(strict_types=1);

namespace app\model\user;

use think\Model;
use \think\facade\Db;
use think\model\concern\SoftDelete;

/**
 * @mixin think\Model
 */
class UserSignLog extends \app\model\BaseModel
{
  use SoftDelete;

  public static function build()
  {
    return new self();
  }


  /**
   * 返回每次簽到要插入的數據
   *
   * @param int $uid 用戶id
   * @return array(
   *  'days'   =>  '天數',
   *  'is_sign'  =>  '是否簽到,用1表示已經簽到',
   *  'sign_time'   =>  '簽到時間',
   * );
   */
  public function getInsertData($uid)
  {
    // 昨天的連續簽到天數
    $start_time = strtotime(date('Y-m-d 0:0:0', time() - 86400)) - 1;
    $end_time  = strtotime(date('Y-m-d 23:59:59', time() - 86400)) + 1;
    $where[] = ['uid', '=', $uid];
    $where[] = ['sign_time', '>', $start_time];
    $where[] = ['sign_time', '<', $end_time];
    $yesterday = UserSignLog::build()->where($where)->find();
    $days = $yesterday['days'];
    if ($days) {
      $days++;
      // 七天簽到,大於七天按一天算
      if ($days > 7) {
        $days = 1;
      }
    } else {
      $days = 1;
    }
    return array(
      'days'    => $days,
      'is_sign'  => 1,
      'sign_time'   => time()
    );
  }

  /**
   * 用戶當天簽到的數據
   * @return array 簽到信息 is_sign,sign_time 等
   */
  public function todayData()
  {
    $uid = request()->uid;
    $time = time();
    $start_sign_time  = strtotime(date('Y-m-d 0:0:0', $time)) - 1;
    $end_sign_time = strtotime(date('Y-m-d 23:59:59', $time)) + 1;
    $where[] = ['uid', '=', $uid];
    $where[] = ['sign_time', '>', $start_sign_time];
    $where[] = ['sign_time', '<', $end_sign_time];
    $data = UserSignLog::build()->where($where)->find();
    return $data;
  }

  /**
   * 積分規則,返回連續簽到的天數對應的積分
   * @param int $days 當天應該得的分數
   * @return int 積分
   */
  public function getTodayScores($days)
  {
    switch ($days) {
      case 1:
        return 1;
        break;
      case 2:
        return 2;
        break;
      case 3:
        return 3;
        break;
      case 4:
        return 4;
        break;
      case 5:
        return 5;
        break;
      case 6:
        return 6;
        break;
      case 7:
        return 7;
        break;
      default:
        return 7;
        break;
    }
  }

  /**
   * 顯示簽到列表
   *
   * @param array  $signDays 某月簽到的日期 array(1,2,3,4,5,12,13)
   * @param int $year    可選,年份
   * @param int $month   可選,月份
   * @return string 日期列表1
   */
  public function showDays($signDays, $year = '', $month = '')
  {
    $time = time();
    $year = $year ? $year : date('Y', $time);
    $month = $month ? $month : date('m', $time);
    $yearMonth = $year . '-' . $month;
    $year = intval($year);
    $month = intval($month);
    $daysTotal = date('t', mktime(0, 0, 0, $month, 1, $year));
    $now = date('Y-m-d', $time);
    $str = [];
    // sign(0=未簽到,1=已簽到)
    // time(0=過去,1=現在,2=未來)
    for ($i = 0; $i < $daysTotal; $i++) {
      $j = $i + 1;
      $time = strtotime("$year-$month-$j");
      $someDay = date('Y-m-d', $time);
      // 小於今天的日期樣式
      if ($someDay <= $now) {
        // 是否為當天
        if ($someDay == $now) {
          // 當天簽到過的
          if (in_array($j, $signDays)) {
            $data['date'] = $yearMonth . '-' . $j;
            $data['sign'] = 1;
            $data['time'] = 1;
            $str[] = $data;
          } else {
            $data['date'] = $yearMonth . '-' . $j;
            $data['sign'] = 0;
            $data['time'] = 1;
            $str[] = $data;
          }
        } else {
          // 簽到過的日期
          if (in_array($j, $signDays)) {
            $data['date'] = $yearMonth . '-' . $j;
            $data['sign'] = 1;
            $data['time'] = 0;
            $str[] = $data;
          } else {
            $data['date'] = $yearMonth . '-' . $j;
            $data['sign'] = 0;
            $data['time'] = 0;
            $str[] = $data;
          }
        }
      } else {
        $data['date'] = $yearMonth . '-' . $j;
        $data['sign'] = 0;
        $data['time'] = 2;
        $str[] = $data;
      }

    }
    return $str;
  }

  /**
   * 獲取月簽到的天數
   * @return 月簽到日期 array(1,2,3,4,5,12,13)
   */
  public function getMonthSign($year = '', $month = '')
  {
    $uid = request()->uid;
    if (empty($year) && empty($month)) {
      $time  = time();
      $year  = date('Y', $time);
      $month = date('m', $time);
    }

    $day  = date("t", strtotime("$year-$month"));
    $start_sign_time  = strtotime("$year-$month-1 0:0:0") - 1;
    $end_sign_time = strtotime("$year-$month-$day 23:59:59") + 1;
    $where[] = ['uid', '=', $uid];
    $where[] = ['sign_time', '>', $start_sign_time];
    $where[] = ['sign_time', '<', $end_sign_time];
    $list = UserSignLog::build() ->where($where)->order('sign_time asc')->column('sign_time');
    foreach ($list as $key => $value) {
      $list[$key] = date('j', $value);
    }
    return $list;
  }

}

 

來源我是參考php中文網的一篇文章,也踩坑挺多,還是上一下原文鏈接把鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM