最近開發一個商城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中文網的一篇文章,也踩坑挺多,還是上一下原文鏈接把鏈接
