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中文网的一篇文章,也踩坑挺多,还是上一下原文链接把链接