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 '用来识别软删除
只要这个字段的值不为NULL
则视为已删除',
  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 appmodeluser;

use thinkModel;
use 	hinkfacadeDb;
use thinkmodelconcernSoftDelete;

/**
 * @mixin thinkModel
 */
class UserSignLog extends appmodelBaseModel
{
  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中文网的一篇文章,也踩坑挺多,还是上一下原文链接把链接

原文地址:https://www.cnblogs.com/seanpan/p/14814277.html