Clockin.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php namespace App\Models\Score;
  2. use Illuminate\Database\Eloquent\Factories\HasFactory;
  3. use Illuminate\Database\Eloquent\Model;
  4. use App\Facades\Servers\Redis\Redis;
  5. use App\Models\CustomScore;
  6. use Illuminate\Support\Carbon;
  7. use Illuminate\Support\Facades\DB;
  8. /**
  9. * 打卡任务模型
  10. *
  11. */
  12. class Clockin extends Model
  13. {
  14. use HasFactory;
  15. // 与模型关联的表名
  16. protected $table = 'score_clockin';
  17. // 是否主动维护时间戳
  18. public $timestamps = false;
  19. /**
  20. * 添加数据
  21. *
  22. */
  23. public function add($data)
  24. {
  25. // 时间
  26. $data['insert_time'] = time();
  27. $data['update_time'] = time();
  28. // 写入数据表
  29. $id = $this->query()->insertGetId($data);
  30. // 如果操作失败
  31. if( !$id ) return ['error'=>'新增失败'];
  32. // 更新缓存
  33. $this->getList(true);
  34. // 返回结果
  35. return $id;
  36. }
  37. /**
  38. * 添加数据
  39. *
  40. */
  41. public function edit($id,$data)
  42. {
  43. // 更新时间
  44. $data['update_time'] = time();
  45. // 写入数据表
  46. $result = $this->query()->where(['id'=>$id])->update($data);
  47. // 如果操作失败
  48. if( !$result ) return ['error'=>'修改失败'];
  49. // 更新缓存
  50. $this->getList(true);
  51. // 返回结果
  52. return $result;
  53. }
  54. /**
  55. * 获取列表
  56. * @param bool $force 是否强制更新
  57. *
  58. */
  59. public function getList($force=false)
  60. {
  61. // 结果数据
  62. $list = $force ? [] : cache('score:clockin:list');
  63. // 不存在数据
  64. if ( !$list ) {
  65. // 从数据库获取数据
  66. $data = $this->query()->where([['status','=',0]])->orderBy('what_day')->orderBy('id')->get(['id','what_day','status','reward']);
  67. // 是否有数据
  68. $data = $data ? $data->toArray() : [];
  69. // 循环处理数据
  70. $list = [];
  71. // 进行更新
  72. foreach ($data as $value) {
  73. // 重组数据
  74. $list[$value['what_day']] = $value;
  75. }
  76. // 存起来
  77. cache(['score:clockin:list'=>$list]);
  78. }
  79. // 返回结果
  80. return $list;
  81. }
  82. /**
  83. * 根据天数获取
  84. *
  85. */
  86. public function getOne($whatDay,$field=''){
  87. // 获取列表数据
  88. $list = $this->getList();
  89. // 获取数据
  90. $one = isset($list[$whatDay]) ? $list[$whatDay] : [];
  91. // 返回值
  92. return empty($field) ? $one : ( isset($one[$field]) ? $one[$field] : null);
  93. }
  94. /**
  95. * 今日是否已签到
  96. *
  97. * @param int $uid 用户ID
  98. *
  99. */
  100. public function isMarkClock($uid){
  101. // 如果没有id
  102. if( !$uid ) return ['is_clockin'=>0,'finish_day'=>0];
  103. // 获取缓存
  104. $record = cache('score:clockin:mark:uid:'.$uid,[]);
  105. // 返回结果
  106. if( $record ) return $record;
  107. // 模型实例
  108. $Record = new Record();
  109. // 通过查询今日打卡积分记录
  110. $record = $Record->query()->where([['custom_uid','=',$uid],['buy_type','=',2],['status','=',1],['pay_time','>=',Carbon::now()->startOfDay()->getTimestamp()]])->first(['id','pay_type','pay_time']);
  111. // 如果没有记录
  112. $record = $record ? ['is_clockin'=>1,'finish_day'=>$record['pay_type']] : ['is_clockin'=>0,'finish_day'=>0];
  113. // 如果没有打卡天数
  114. if( !$record['finish_day'] ) {
  115. // 获取昨天的打卡记录。以获取已打卡天数
  116. $record['finish_day'] = (int) $Record->query()->where([['custom_uid','=',$uid],['buy_type','=',2],['status','=',1],['pay_time','>=',Carbon::now()->addDays(-1)->startOfDay()->getTimestamp()],['pay_time','<=',Carbon::now()->addDays(-1)->endOfDay()->getTimestamp()]])->value('pay_type');
  117. }
  118. // 标记
  119. $this->setMarkClock($uid,$record);
  120. // 返回结果
  121. return $record;
  122. }
  123. /**
  124. * 设置打卡
  125. *
  126. * @param int $uid 用户ID
  127. *
  128. */
  129. public function setMarkClock($uid,$record){
  130. // 存起来
  131. cache(['score:clockin:mark:uid:'.$uid=>$record],now()->endOfDay());
  132. // 返回结果
  133. return $record;
  134. }
  135. /**
  136. * 获取最大的打卡天数
  137. *
  138. */
  139. public function getMaxDay(){
  140. // 查询数据
  141. $data = $this->getList();
  142. // 获取天数字段
  143. $days = array_column($data,'what_day');
  144. // 获取第一个
  145. $maxDay = $days ? max($days) : 0;
  146. // 返回结果
  147. return (int) $maxDay;
  148. }
  149. /**
  150. * 打卡操作
  151. *
  152. * @param int $uid 用户ID
  153. *
  154. */
  155. public function finish($uid)
  156. {
  157. // 获取打卡任务列表,并获取最大天数
  158. $maxDay = $this->getMaxDay();
  159. // 如果是0,没有需要签到的任务
  160. if( !$maxDay ) return ['error'=>'无签到任务'];
  161. // 是否已签到
  162. $isMark = $this->isMarkClock($uid);
  163. // 如果已经签到,不进行后续操作,返回已打卡
  164. if( $isMark['is_clockin'] ) return ['error'=>'今日已打卡'];
  165. // 如果当前已签到天数大于最大天数,从1开始计算签到天数
  166. $finishDay = $isMark['finish_day'] >= $maxDay ? 1 : $isMark['finish_day'] +1;
  167. // 通过今日天数查找对应的打卡奖励
  168. $reward = $this->getOne($finishDay,'reward');
  169. // 组合数据,写入订单表,子表
  170. DB::beginTransaction();
  171. // 写入数据
  172. try {
  173. // 成功继续
  174. $result = (new CustomScore())->trade($uid,0,$reward,2,$finishDay);
  175. // 失败结束
  176. if( isset($result['error']) ) {
  177. // 回退数据
  178. DB::rollBack();
  179. // 下单失败提示
  180. return ['error'=>$result['error']];
  181. }
  182. // 提交数据
  183. DB::commit();
  184. // 打卡通过
  185. $isMark['is_clockin'] = 1;
  186. $isMark['finish_day'] = $finishDay;
  187. // 标记
  188. $this->setMarkClock($uid,$isMark);
  189. // 奖励返回
  190. $isMark['reward'] = $reward;
  191. // 返回打卡结果与奖励
  192. return $isMark;
  193. } catch (\Throwable $th) {
  194. // 回退数据
  195. DB::rollBack();
  196. // 下单失败提示
  197. return ['error'=>'打卡失败'];
  198. }
  199. }
  200. /**
  201. * 获取活动打卡列表
  202. *@param int $active_id 打卡活动id
  203. *
  204. */
  205. public function getActiveList($active_id=0,$force=true)
  206. {
  207. // 结果数据
  208. $list = $force ? [] : cache('score:clockin:list:'.$active_id);
  209. $where = [
  210. 'status'=>0,
  211. 'active_id'=>$active_id
  212. ];
  213. // 不存在数据
  214. if ( !$list ) {
  215. // 从数据库获取数据
  216. $data = $this->query()
  217. ->where($where)
  218. ->orderBy('what_day')
  219. ->orderBy('id')
  220. ->get(['id','what_day','status','reward','active_id','coupon_id']);
  221. // 是否有数据
  222. $data = $data ? $data->toArray() : [];
  223. // 循环处理数据
  224. $list = [];
  225. // 进行更新
  226. foreach ($data as $value) {
  227. // 重组数据
  228. $list[$value['what_day']] = $value;
  229. }
  230. // 存起来
  231. cache(['score:clockin:list:'.$active_id=>$list]);
  232. }
  233. // 返回结果
  234. return $list;
  235. }
  236. }