初始化项目:添加后端代码、ThinkPHP框架、前端资源
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\activity;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\activity\Ticket;
|
||||
use app\common\exception\Exception;
|
||||
use app\api\model\app\activity\UserTicket;
|
||||
use fast\Random;
|
||||
class Activity extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_activity';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
|
||||
/**
|
||||
* 获取支付信息
|
||||
* @param $ticket
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPayDetail($ticketId,$count,$formId){
|
||||
//计算商品总价
|
||||
|
||||
//这里保证每张卡券都来自同一个活动
|
||||
|
||||
$ticketInfo = Ticket::where(['id'=>$ticketId])->find();
|
||||
if(!$ticketInfo){
|
||||
throw new \think\Exception("未获取到票券信息");
|
||||
}
|
||||
|
||||
|
||||
if($ticketInfo['inventory'] && ($ticketInfo['sales'] + $count) > $ticketInfo['inventory']){
|
||||
throw new \think\Exception("票券'{$ticketInfo['name']}'库存不足");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$activityInfo = self::getActivityDetail($ticketInfo['activity_id']);
|
||||
|
||||
if(!$activityInfo || (!$activityInfo['status'] && !$activityInfo['apply_status'])){
|
||||
throw new \think\Exception("当前活动暂不可用,请刷新后重试");
|
||||
}
|
||||
|
||||
|
||||
|
||||
$activityInfo['price_marking'] = $activityInfo['price'] = $ticketInfo['price'];
|
||||
|
||||
$activityInfo['name'] .= "【{$ticketInfo['name']}】";
|
||||
$activityInfo['ticket_id'] = $ticketInfo['id'];
|
||||
|
||||
$activityInfo['form_user_id'] = \app\api\model\app\activity\Form::getFormUser($formId);
|
||||
if(!$activityInfo['form_user_id']){
|
||||
throw new \think\Exception("报名信息错误,请返回重试");
|
||||
}
|
||||
|
||||
if(!\app\api\model\app\activity\BindCourse::checkJoinAuth($activityInfo['form_user_id'],$ticketInfo['activity_id'])){
|
||||
throw new \think\Exception("请先订阅关联课程");
|
||||
}
|
||||
|
||||
if($ticketInfo['limit_buy']){
|
||||
if($count > $ticketInfo['limit_buy']){
|
||||
throw new \think\Exception("票券'{$ticketInfo['name']}'超出限购数量");
|
||||
}
|
||||
|
||||
//判断限购
|
||||
$userBuyCount = \app\api\model\app\activity\UserTicket::getUserBuyCount($activityInfo['form_user_id'],$ticketInfo['id']);
|
||||
if(($userBuyCount + $count) > $ticketInfo['limit_buy']){
|
||||
throw new \think\Exception("票券'{$ticketInfo['name']}'超出限购数量");
|
||||
}
|
||||
}
|
||||
|
||||
$activityInfo['apply_info_id'] = $formId;
|
||||
$activityInfo['status'] = 1;
|
||||
$activityInfo['is_virtual_pay'] = \app\common\library\pay\VirtualPayService::isUseVirtualPay('activity');
|
||||
return $activityInfo;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 向用户发放票券
|
||||
* @param $userId
|
||||
* @param $activityId
|
||||
* @param $ticketId
|
||||
* @param $formId
|
||||
* @param $count
|
||||
* @param $price
|
||||
* @param $orderNo
|
||||
* @return void
|
||||
*/
|
||||
public static function setUserTicket($userId,$activityId,$ticketId,$formId,$count,$price,$orderNo,$ticket_no = ''){
|
||||
if(!$ticket_no){
|
||||
$ticket_no = Random::numeric(14);
|
||||
}
|
||||
for($i=0;$i<$count;$i++){
|
||||
UserTicket::insert([
|
||||
'uniacid'=>UNIACID,
|
||||
'user_id'=>$userId,
|
||||
'apply_info_id'=>$formId,
|
||||
'activity_id'=>$activityId,
|
||||
'ticket_id'=>$ticketId,
|
||||
'order_no'=>$orderNo,
|
||||
'price'=>$price,
|
||||
'ticket_no'=>$ticket_no,
|
||||
'status'=>1,
|
||||
'createtime'=>time()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取活动详情
|
||||
* @param $id
|
||||
* @return false
|
||||
*/
|
||||
public static function getActivityDetail($id){
|
||||
$data = self::where([
|
||||
'id'=>$id
|
||||
])->find();
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
// $data['apply_info_form'] = $this->formModel->getFromField($id);
|
||||
|
||||
//报名时间
|
||||
|
||||
if($data['apply_time_type'] == 1){
|
||||
$data['apply_start_time'] = $data['activity_start_time'];
|
||||
$data['apply_end_time'] = $data['activity_end_time'];
|
||||
}
|
||||
|
||||
$data['detail'] = \addons\alivod\library\Alivod::parseContentAliovdTag($data['detail']);
|
||||
|
||||
$data['type'] = 'activity';
|
||||
//判断活动状态
|
||||
|
||||
//判断活动是否进行中
|
||||
$data['status'] = (time() > $data['activity_start_time'] && time() < $data['activity_end_time']) ? 1 : 0;
|
||||
|
||||
//判断报名时间
|
||||
$data['apply_status'] = (time() > $data['apply_start_time'] && time() < $data['apply_end_time'] ) ? 1 : 0;
|
||||
|
||||
|
||||
//获取报名人数
|
||||
|
||||
if($data['apply_member_show']){
|
||||
$data['apply_user_count'] = \app\api\model\app\activity\UserTicket::getApplyUserCount($id);
|
||||
}else{
|
||||
$data['apply_user_count'] = 0;
|
||||
}
|
||||
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 增加浏览量
|
||||
* @param $activityId
|
||||
* @return void
|
||||
*/
|
||||
public static function incViews($activityId){
|
||||
self::where([
|
||||
'id'=>$activityId
|
||||
])->setInc('views');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查绑定课程权限
|
||||
* @return void
|
||||
*/
|
||||
public function checkBindCourse(){
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\activity;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\activity\Ticket;
|
||||
use app\common\exception\Exception;
|
||||
use app\api\model\app\activity\UserTicket;
|
||||
use fast\Random;
|
||||
|
||||
/**
|
||||
* 线下活动-绑定课程
|
||||
*/
|
||||
class BindCourse extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_activity_course';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('\app\api\model\course\Course', 'course_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户参与权限
|
||||
* @return void
|
||||
*/
|
||||
public static function checkJoinAuth($userId,$activityId){
|
||||
|
||||
$list = self::with(['course'])
|
||||
->where([
|
||||
'activity_id'=>$activityId,
|
||||
'course.status'=>1
|
||||
])
|
||||
->field("course_id")
|
||||
->select();
|
||||
|
||||
if(!$list){
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($list as $item){
|
||||
if(!\app\common\model\user\Subscription::getSubscriptionAuth($userId,$item['course_id'])){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\activity;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\activity\Ticket;
|
||||
use app\common\exception\Exception;
|
||||
use app\api\model\app\activity\UserTicket;
|
||||
use fast\Random;
|
||||
|
||||
/**
|
||||
* 线下活动-自定义表单
|
||||
*/
|
||||
class Form extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_activity_apply_form';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
|
||||
/**
|
||||
* 获取表单所属用户
|
||||
* @param $userId
|
||||
* @param $formId
|
||||
* @return void
|
||||
*/
|
||||
public static function getFormUser($formId){
|
||||
$formInfo = self::where([
|
||||
'id'=>$formId
|
||||
])->find();
|
||||
|
||||
if(!$formInfo){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $formInfo['user_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表单字段
|
||||
* @param $activityId
|
||||
* @return array|array[]
|
||||
*/
|
||||
public function getFromField($activityId){
|
||||
$activityData = \app\api\model\app\activity\Activity::getActivityDetail($activityId);
|
||||
|
||||
if(!$activityData){
|
||||
return false;
|
||||
}
|
||||
|
||||
$activityData['apply_info_form'] = json_decode($activityData['apply_info_form'],true);
|
||||
|
||||
$mustField = [
|
||||
[
|
||||
"required"=>true,
|
||||
"name"=>"姓名",
|
||||
"type"=>"input"
|
||||
],
|
||||
[
|
||||
"required"=>true,
|
||||
"name"=>"手机号",
|
||||
"type"=>"input"
|
||||
]
|
||||
];
|
||||
|
||||
if($activityData['apply_info_collet'] == 1){
|
||||
$mustField = array_merge($mustField,$activityData['apply_info_form']);
|
||||
}
|
||||
|
||||
return $mustField;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\activity;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\activity\Ticket;
|
||||
use app\common\exception\Exception;
|
||||
use app\api\model\app\activity\UserTicket;
|
||||
use fast\Random;
|
||||
|
||||
/**
|
||||
* 线下活动-自定义表单
|
||||
*/
|
||||
class Signin extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_activity_signin';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
|
||||
/**
|
||||
* 签到
|
||||
* @param $ticketNo
|
||||
* @param $type
|
||||
* @return bool
|
||||
*/
|
||||
public static function signin($ticketNo,$type='scan'){
|
||||
|
||||
$result = \app\api\model\app\activity\UserTicket::where([
|
||||
'ticket_no'=>$ticketNo
|
||||
])->update([
|
||||
'sign'=>1,
|
||||
'use_time'=>time()
|
||||
]);
|
||||
|
||||
|
||||
//消息推送收集
|
||||
\app\admin\library\app\msgpush\Msg::collect('activity_sing_in',['ticket_no'=>$ticketNo]);
|
||||
|
||||
if($result){
|
||||
self::insert([
|
||||
'uniacid'=>UNIACID,
|
||||
'ticket_no'=>$ticketNo,
|
||||
'type'=>$type,
|
||||
'createtime'=>time()
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 取消签到
|
||||
* @param $ticketNo
|
||||
* @return bool
|
||||
*/
|
||||
public static function cancel($ticketNo){
|
||||
$result = \app\api\model\app\activity\UserTicket::where([
|
||||
'ticket_no'=>$ticketNo
|
||||
])->update([
|
||||
'sign'=>0,
|
||||
'use_time'=>''
|
||||
]);
|
||||
|
||||
if($result){
|
||||
self::where([
|
||||
'ticket_no'=>$ticketNo
|
||||
])->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\activity;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
|
||||
class Ticket extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_activity_ticket';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\activity;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\activity\Ticket;
|
||||
use app\common\exception\Exception;
|
||||
class UserTicket extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_activity_user_ticket';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
/**
|
||||
* 获取报名人数
|
||||
* @return void
|
||||
*/
|
||||
public static function getApplyUserCount($activityId){
|
||||
return self::where([
|
||||
'activity_id'=>$activityId,
|
||||
'status'=>['<>',2]
|
||||
])->count();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户购买次数
|
||||
* @return void
|
||||
*/
|
||||
public static function getUserBuyCount($userId,$ticketId){
|
||||
return self::where([
|
||||
'ticket_id'=>$ticketId,
|
||||
'user_id'=>$userId
|
||||
])->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户票券
|
||||
* @param $where
|
||||
* @param $limit
|
||||
* @param $page
|
||||
* @param $sort
|
||||
* @return void
|
||||
*/
|
||||
public function getUserTicket($where,$limit,$page,$sort='desc'){
|
||||
$orderField = 'ut.createtime';
|
||||
|
||||
$field = ['ut.activity_id','ut.sign','ut.status','a.name as activity_name','at.name as ticket_name','ut.use_time','ut.price','ut.createtime','ut.ticket_no','form.mobile','form.name','form.other'];
|
||||
|
||||
$list = self::alias('ut')
|
||||
->join(\app\api\model\app\activity\Activity::getTable().' a','ut.activity_id=a.id','LEFT')
|
||||
->join(\app\api\model\app\activity\Ticket::getTable().' at','ut.ticket_id=at.id')
|
||||
->join(\app\api\model\app\activity\Form::getTable().' form','ut.apply_info_id=form.id')
|
||||
->where($where)
|
||||
->limit($limit)->page($page)
|
||||
->order($orderField,$sort)
|
||||
->field($field)
|
||||
->select();
|
||||
|
||||
if(!empty($list)){
|
||||
foreach ($list as &$item){
|
||||
$item['other'] = json_decode($item['other']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户票券
|
||||
* @param $where
|
||||
* @param $limit
|
||||
* @param $page
|
||||
* @param $sort
|
||||
* @return void
|
||||
*/
|
||||
public function getTicketDetail($ticketNo){
|
||||
|
||||
$field = ['ut.activity_id','ut.status','a.name as activity_name','at.name as ticket_name','ut.use_time','ut.price','ut.createtime','ut.ticket_no','form.mobile','form.name','form.other'];
|
||||
|
||||
$data = self::alias('ut')
|
||||
->join(\app\api\model\app\activity\Activity::getTable().' a','ut.activity_id=a.id')
|
||||
->join(\app\api\model\app\activity\Ticket::getTable().' at','ut.ticket_id=at.id')
|
||||
->join(\app\api\model\app\activity\Form::getTable().' form','ut.apply_info_id=form.id')
|
||||
->where([
|
||||
'ut.ticket_no'=>$ticketNo
|
||||
])
|
||||
->field($field)
|
||||
->find();
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 分佣
|
||||
*/
|
||||
class Commission extends Model
|
||||
{
|
||||
|
||||
public function handle($order)
|
||||
{
|
||||
//计算佣金
|
||||
|
||||
|
||||
|
||||
$orderItemList = (new Item())->getItemList($order->order_no);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class Condition extends Model
|
||||
{
|
||||
/**
|
||||
* 检查条件是否满足
|
||||
* @return void
|
||||
*/
|
||||
public static function checkCondition($userId,$type,$value){
|
||||
$value = floatval($value);
|
||||
$data = 0;
|
||||
switch ($type){
|
||||
case 'agent':
|
||||
$data = self::getAgent($userId);
|
||||
break;
|
||||
case 'customer':
|
||||
$data = self::getCustomer($userId);
|
||||
break;
|
||||
case 'customer_pay':
|
||||
$data = self::getCustomerPay($userId);
|
||||
break;
|
||||
case 'self_pay':
|
||||
$data = self::getSelfPay($userId);
|
||||
break;
|
||||
}
|
||||
|
||||
return $data >= $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取自购金额
|
||||
* @param $userId
|
||||
* @return void
|
||||
*/
|
||||
public static function getSelfPay($userId){
|
||||
$value = \app\common\model\order\Order::where([
|
||||
'status'=>\app\common\constant\order\Status::STATUS_SUCCESS,
|
||||
'user_id'=>$userId
|
||||
])->sum('real_pay_price');
|
||||
|
||||
if(!$value){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推广金额
|
||||
* @param $userId
|
||||
* @return void
|
||||
*/
|
||||
public static function getCustomerPay($userId){
|
||||
$value = \app\common\model\app\agent\Order::where([
|
||||
'status'=>1,
|
||||
'beneficiary_user_id'=>$userId
|
||||
])->sum('brokerage_price');
|
||||
|
||||
if(!$value){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户数量
|
||||
* @param $userId
|
||||
* @return int
|
||||
*/
|
||||
public static function getAgent($userId){
|
||||
$value = \app\common\model\app\agent\Relation::where([
|
||||
'status'=>1,
|
||||
'parent_id'=>$userId
|
||||
])->count();
|
||||
|
||||
if(!$value){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下级分销员
|
||||
* @param $userId
|
||||
* @return int
|
||||
*/
|
||||
public static function getCustomer($userId){
|
||||
|
||||
$value = \app\common\model\app\agent\Relation::alias('relation')
|
||||
->join(\app\common\model\app\agent\Member::getTable().' member','relation.user_id = member.user_id')
|
||||
->where([
|
||||
'relation.status'=>1,
|
||||
'member.status'=>1,
|
||||
'relation.parent_id'=>$userId
|
||||
])->count();
|
||||
|
||||
if(!$value){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class Goods extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_agent_goods';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
//禁止uniacid绑定
|
||||
protected $uniacid = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\course\Course', 'goods_id', 'id', [], 'RIGHT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 分销等级
|
||||
*/
|
||||
class Level extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取用户当前等级
|
||||
* @param $userId
|
||||
* @return void
|
||||
*/
|
||||
public function getUserLevel($userId){
|
||||
$levelList = \app\common\model\app\agent\Level::getLevelList();
|
||||
|
||||
if(empty($levelList)){
|
||||
return false;
|
||||
}
|
||||
|
||||
$memberModel = new \app\common\model\app\agent\Member();
|
||||
|
||||
$member = $memberModel->getMember($userId);
|
||||
|
||||
if(!$member || $member['status'] != 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($levelList as $item){
|
||||
|
||||
if( isset($item['id']) && $member['level'] == $item['id']){
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $levelList[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的下一等级
|
||||
* @param $userId
|
||||
* @return void
|
||||
*/
|
||||
public function getUserNextLevel($userId){
|
||||
$levelList = \app\common\model\app\agent\Level::getLevelList();
|
||||
|
||||
$memberModel = new \app\common\model\app\agent\Member();
|
||||
$member = $memberModel->getMember($userId);
|
||||
|
||||
if(!$member){
|
||||
return false;
|
||||
}
|
||||
|
||||
$levelIndex = 0;
|
||||
//当前的等级下标
|
||||
$nowLevelIndex = 0;
|
||||
|
||||
foreach ($levelList as $item){
|
||||
$data[] = $item;
|
||||
if( isset($item['id']) && $member['level'] == $item['id']){
|
||||
$nowLevelIndex = $levelIndex;
|
||||
}
|
||||
$levelIndex++;
|
||||
}
|
||||
|
||||
if(isset($data[$nowLevelIndex+1])){
|
||||
return $data[$nowLevelIndex+1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查升级
|
||||
* @param $userId
|
||||
* @return void
|
||||
*/
|
||||
public function handle($userId){
|
||||
|
||||
$nextLevelId = $this->checkLevelCondtion($userId);
|
||||
|
||||
if($nextLevelId !== false){
|
||||
$this->upLevel($userId,$nextLevelId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否满足升级条件
|
||||
* @param $userId 用户ID
|
||||
* @return false 满足则返回升级等级ID 否则false
|
||||
*/
|
||||
public function checkLevelCondtion($userId)
|
||||
{
|
||||
$config = \app\common\model\app\Config::getConfig('agent');
|
||||
$upLevel = $this->getUserNextLevel($userId);
|
||||
|
||||
if(!$upLevel){
|
||||
return false;
|
||||
}
|
||||
//判断是否满足条件
|
||||
$satisfy = false;
|
||||
foreach ($upLevel['condition'] as $type => $item){
|
||||
if($item['status'] == 1){
|
||||
|
||||
//判断自定条件
|
||||
$temp = \app\api\model\app\agent\Condition::checkCondition($userId,$type,$item['value']);
|
||||
|
||||
if($config['upgrade'] == 2){
|
||||
//满足一个即可
|
||||
if($temp){
|
||||
$satisfy = true;
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
//需要全部满足
|
||||
if(!$temp){
|
||||
$satisfy = false;
|
||||
break;
|
||||
}else{
|
||||
$satisfy = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($satisfy){
|
||||
return $upLevel['id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级
|
||||
* @param $userId 用户ID
|
||||
* @param $toLevelId 要升级的等级ID
|
||||
* @return void
|
||||
*/
|
||||
public function upLevel($userId,$toLevelId){
|
||||
|
||||
$memberModel = new \app\common\model\app\agent\Member();
|
||||
|
||||
return $memberModel->where([
|
||||
'user_id'=>$userId
|
||||
])->update([
|
||||
'level'=>$toLevelId
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
class Money extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_agent_member_money_log';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 变更资金
|
||||
* @param $type 资金类型
|
||||
* @param $userId 用户ID
|
||||
* @param $money 变更金额
|
||||
* @param $isFreeze 是否冻结 $type=money 有效
|
||||
* @param $memo 备注
|
||||
* @return bool
|
||||
*/
|
||||
public static function changeMoney($userId,$type,$money,$isFreeze = false,$memo = ''){
|
||||
$user = \app\common\model\app\agent\Member::lock(true)->where([
|
||||
'user_id'=>$userId
|
||||
])->find();
|
||||
if (!$user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$before = $user->money;
|
||||
if($type == 'money'){
|
||||
$after = function_exists('bcadd') ? bcadd($user->money, $money, 2) : $user->money + $money;
|
||||
if($money > 0){
|
||||
$totalMoney = function_exists('bcadd') ? bcadd($user->money_total, $money, 2) : $user->money_total + $money;
|
||||
$changeParams['money_total'] = $totalMoney;
|
||||
}
|
||||
if($isFreeze){
|
||||
$freezeMoney = function_exists('bcadd') ? bcadd($user->money_freeze, ($money * -1), 2) : $user->money_freeze + ($money * -1);
|
||||
$changeParams['money_freeze'] = $freezeMoney;
|
||||
}
|
||||
}else{
|
||||
$after = $before;
|
||||
}
|
||||
|
||||
$totalMoney = function_exists('bcadd') ? bcadd($user->$type, $money, 2) : $user->$type + $money;
|
||||
$changeParams[$type] = $totalMoney;
|
||||
|
||||
$user->save($changeParams);
|
||||
//写入日志
|
||||
if($memo !== false){
|
||||
if($type != 'money'){
|
||||
$money = 0;
|
||||
}
|
||||
self::addLog($userId,$money,$before,$after,$memo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加日志
|
||||
* @param $userId
|
||||
* @param $money
|
||||
* @param $before
|
||||
* @param $after
|
||||
* @param $memo
|
||||
* @return void
|
||||
*/
|
||||
public static function addLog($userId,$money,$before,$after,$memo = '')
|
||||
{
|
||||
self::create(['user_id' => $userId, 'money' => $money, 'before' => $before, 'after' => $after, 'memo' => $memo,'uniacid'=>UNIACID]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* 分销订单
|
||||
*/
|
||||
class Order extends Model
|
||||
{
|
||||
|
||||
// 表名,不含前缀
|
||||
protected $name = 'app_agent_order';
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = false;
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取统计数据
|
||||
* @param $userId
|
||||
* @return int[]
|
||||
*/
|
||||
public function getTotal($userId,$type='',$time=[]){
|
||||
|
||||
$data = [
|
||||
|
||||
'price_waiting'=>0,//待结算收益(元)
|
||||
'sales_waiting'=>0,//待结算销售额(元)
|
||||
'sales_success'=>0,//已结算销售额(元)
|
||||
|
||||
'price_success'=>0,//已结算收益/累计佣金(元)
|
||||
'price_goods'=>0,//商品佣金(元)
|
||||
'price_invite'=>0,//邀请佣金(元)
|
||||
'order_count'=>0//订单数
|
||||
];
|
||||
|
||||
$where = [
|
||||
'beneficiary_user_id'=>$userId
|
||||
];
|
||||
if($type){
|
||||
$where['type'] = $type;
|
||||
}
|
||||
|
||||
if($time){
|
||||
$where['createtime'] = ['BETWEEN',[$time['start'], $time['end']]];
|
||||
}
|
||||
|
||||
$data['order_count'] = self::where($where)->count();
|
||||
|
||||
$data['price_success'] = self::where($where)->where(['status'=>1])->sum('brokerage_price');
|
||||
$data['price_waiting'] = self::where($where)->where(['status'=>0])->sum('brokerage_price');
|
||||
$data['price_total'] = self::where($where)->sum('brokerage_price');
|
||||
//
|
||||
$data['sales_success'] = self::where($where)->where(['status'=>1])->sum('price');
|
||||
$data['sales_waiting'] = self::where($where)->where(['status'=>0])->sum('price');
|
||||
$data['sales_total'] = self::where($where)->sum('price');
|
||||
|
||||
$priceGoodsWhere = $priceInviteWhere = [
|
||||
'status'=>1
|
||||
];
|
||||
if(!isset($where['type'])){
|
||||
$priceInviteWhere['type'] = $priceGoodsWhere['type'] = 'commission';
|
||||
}
|
||||
|
||||
$data['price_goods'] = self::where($where)->where($priceGoodsWhere)->sum('brokerage_price');
|
||||
$data['price_invite'] = self::where($where)->where($priceInviteWhere)->sum('brokerage_price');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下级用户订单统计数据
|
||||
* @param $userId
|
||||
* @return void
|
||||
*/
|
||||
public function getChildUserOrder($userId){
|
||||
$data = [];
|
||||
$where = [
|
||||
'order_user_id'=>$userId
|
||||
];
|
||||
$data['price_success'] = self::where($where)->where(['status'=>1])->sum('brokerage_price');
|
||||
$data['price_waiting'] = self::where($where)->where(['status'=>0])->sum('brokerage_price');
|
||||
$data['order_count'] = self::where($where)->count();
|
||||
$data['order_success_count'] = self::where($where)->where(['status'=>1])->count();
|
||||
$data['order_waiting_count'] = self::where($where)->where(['status'=>0])->count();
|
||||
$lastOrder = self::where($where)->order('createtime','desc')->find();
|
||||
if($lastOrder){
|
||||
$data['order_last_time'] = $lastOrder['createtime'];
|
||||
}else{
|
||||
$data['order_last_time'] = '';
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function item()
|
||||
{
|
||||
return $this->belongsTo('app\common\model\order\Item', 'order_item_id', 'id', [])->setEagerlyType(0);
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('app\common\model\User', 'order_user_id', 'id',[],'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* 分销关系
|
||||
*/
|
||||
class Relation extends Model
|
||||
{
|
||||
|
||||
// 表名,不含前缀
|
||||
protected $name = 'app_agent_relation';
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = false;
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('app\common\model\User', 'user_id', 'id')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取统计数据
|
||||
* @param $userId
|
||||
* @return int[]
|
||||
*/
|
||||
public function getUserTotal($userId,$status='',$time=[]){
|
||||
|
||||
$data = [
|
||||
];
|
||||
|
||||
$where = [
|
||||
'parent_id'=>$userId
|
||||
];
|
||||
if($status){
|
||||
$where['status'] = $status;
|
||||
}
|
||||
|
||||
if($time){
|
||||
$where['createtime'] = ['BETWEEN',[$time['start'], $time['end']]];
|
||||
}
|
||||
|
||||
$data['count'] = self::where($where)->count(); //下级数量
|
||||
$data['normal'] = self::where($where)->where(['status'=>1])->count(); //正常数量
|
||||
$data['hidden'] = self::where($where)->where(['status'=>0])->count(); //解绑数量
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\common\model\app\agent\Member;
|
||||
class Withdraw extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_agent_withdraw';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
public function handle($userId,$money,$cardInfo=[]){
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class WithdrawCard extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_agent_withdraw_card';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'updatetime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
public function getCard($userId){
|
||||
$data = self::where([
|
||||
'user_id'=>$userId
|
||||
])->field(['name','card_no','address'])->find();
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\agent;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\common\model\app\agent\Member;
|
||||
|
||||
/**
|
||||
* 提现记录
|
||||
*/
|
||||
class WithdrawLog extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_agent_withdraw_log';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'updatetime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\exam\WarehouseQuestion;
|
||||
class Exercises extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exam_exercises';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\course\Course', 'bind_course', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取练习包含的题目数量
|
||||
* @param $exercisesId
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExercisesQuestionCount($exercisesId){
|
||||
$notInExercisesGroupIds = \app\api\model\app\exam\ExercisesBindWarehouseGroup::getNotInExercisesGroupIds($exercisesId);
|
||||
|
||||
return WarehouseQuestion::where([
|
||||
'group_id'=>['NOT IN',$notInExercisesGroupIds]
|
||||
])->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单中的会员卡与规格对应的信息
|
||||
* @param $cardIdSku 格式 ID_SKU
|
||||
* @return false
|
||||
*/
|
||||
public static function getPayDetail($exercisesId){
|
||||
|
||||
$data = self::where([
|
||||
'id'=>$exercisesId,
|
||||
'status'=>1,
|
||||
'sales_type'=>2
|
||||
])->field('detail',true)->find();
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $data->toArray();
|
||||
|
||||
|
||||
$data['price_marking'] = $data['price'] = $data['pay_price'];
|
||||
$data['type'] = 'exercises';
|
||||
|
||||
$extendInfo = \app\common\model\goods\Handle::parseGoodsExtendInfo($data['id'],'exercises');
|
||||
|
||||
$data = array_merge($data,$extendInfo);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
|
||||
use think\Model;
|
||||
use app\api\model\app\exam\WarehouseGroup;
|
||||
class ExercisesBindWarehouseGroup extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exam_exercises_bind_warehouse_group';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 获取练习绑定的题库分组
|
||||
* @param $exercisesId
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getExercisesBindWarehouseGroupIds($exercisesId){
|
||||
return self::where([
|
||||
'exercises_id'=>$exercisesId
|
||||
])->field('warehouse_group_id')->column('warehouse_group_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取没有被练习绑定的分组ID
|
||||
* 为什么要查这个?
|
||||
* 当分组被删除时,绑定被删除的分组的题目的分组ID未变更,
|
||||
* 当练习绑定了未分组的题目集合是,仅搜索分组为0的数据查不到上面情景的题目,故获取该类型的分组ID进行not in 反查询
|
||||
* @return void
|
||||
*/
|
||||
public static function getNotInExercisesGroupIds($exercisesId){
|
||||
$bindIds = self::getExercisesBindWarehouseGroupIds($exercisesId);
|
||||
|
||||
$group = WarehouseGroup::where([
|
||||
'id'=>['not in',$bindIds]
|
||||
])->field('id')->column('id');
|
||||
|
||||
if(!in_array('0',$bindIds)){
|
||||
$group[] = 0;
|
||||
}
|
||||
|
||||
return $group;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\exam\WarehouseQuestion;
|
||||
class ExercisesGroup extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exam_exercises_group';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
public function getList(){
|
||||
return self::where([
|
||||
'status'=>1
|
||||
])
|
||||
->order('sort','asc')->order('createtime','desc')->select();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
use think\Model;
|
||||
use app\api\model\app\exam\Exercises;
|
||||
use app\api\model\app\exam\WarehouseQuestion;
|
||||
use app\api\model\app\exam\ExercisesBindWarehouseGroup;
|
||||
/**
|
||||
* 题库练习记录
|
||||
*/
|
||||
class ExercisesLog extends Model
|
||||
{
|
||||
// 表名,不含前缀
|
||||
protected $name = 'app_exam_exercises_log';
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = false;
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 出题
|
||||
* @return void
|
||||
*/
|
||||
public function buildLog($userId,$exercisesId)
|
||||
{
|
||||
//获取出题配置
|
||||
$exercisesInfo = Exercises::where([
|
||||
'id'=>$exercisesId,
|
||||
'status'=>1
|
||||
])->find();
|
||||
|
||||
if(!$exercisesInfo){
|
||||
return false;
|
||||
}
|
||||
|
||||
$questionData = $this->getQuestionIds($userId,$exercisesId,$exercisesInfo['question_mode'],$exercisesInfo['question_count']);
|
||||
|
||||
if(!$questionData['ids']){
|
||||
return false;
|
||||
}
|
||||
|
||||
$logId = self::insertGetId([
|
||||
'user_id'=>$userId,
|
||||
'uniacid'=>UNIACID,
|
||||
'exercises_id'=>$exercisesId,
|
||||
'question_ids'=>implode(",",$questionData['ids']),
|
||||
'data_index'=>$questionData['data_index'],
|
||||
'question_count'=>count($questionData['ids']),
|
||||
'result_true_count'=>0,
|
||||
'createtime'=>time()
|
||||
]);
|
||||
|
||||
if(!$logId){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $logId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取练习记录的问题列表
|
||||
* @param $logId
|
||||
* @return false
|
||||
*/
|
||||
public function getQuestionList($logId){
|
||||
//获取出题配置
|
||||
$logData = self::where([
|
||||
'id'=>$logId
|
||||
])->find();
|
||||
|
||||
if(!$logData){
|
||||
return false;
|
||||
}
|
||||
|
||||
$logData['question_ids'] = explode(",",$logData['question_ids']);
|
||||
|
||||
$questionList = $this->idsGetQestion($logData['question_ids']);
|
||||
|
||||
return $questionList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过问题ID集合获取问题列表
|
||||
* @param $questionIds
|
||||
* @return false
|
||||
*/
|
||||
public function idsGetQestion($questionIds){
|
||||
|
||||
$questionList = WarehouseQuestion::where([
|
||||
'id'=>['in',$questionIds]
|
||||
])->orderRaw("find_in_set(id,'".implode(",",$questionIds)."')")->select();
|
||||
|
||||
if(!$questionList){
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($questionList as &$item){
|
||||
$item->option = json_decode($item->option,true);
|
||||
|
||||
switch ($item['type']){
|
||||
case 'multiple':
|
||||
case 'indefinite':
|
||||
$item->answer = explode(",",$item->answer);
|
||||
break;
|
||||
case 'fillblank':
|
||||
$item->answer = json_decode($item->answer,true);
|
||||
break;
|
||||
case 'essay':
|
||||
// 问答题答案为富文本字符串,保持原样
|
||||
break;
|
||||
default:
|
||||
$item->answer = intval($item->answer);
|
||||
}
|
||||
}
|
||||
|
||||
return $questionList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取问题集合ID
|
||||
* @param $userId
|
||||
* @param $exercisesId
|
||||
* @param $mode
|
||||
* @param $count
|
||||
* @return false
|
||||
*/
|
||||
public function getQuestionIds($userId,$exercisesId,$mode,$count){
|
||||
|
||||
// 判断是否已经过题了
|
||||
$exercisesLog = self::where([
|
||||
'exercises_id'=>$exercisesId,
|
||||
'user_id'=>$userId
|
||||
])->order('createtime','desc')->find();
|
||||
|
||||
|
||||
$dataIndex = 0;
|
||||
if($exercisesLog){
|
||||
$dataIndex = $exercisesLog['data_index'];
|
||||
}
|
||||
|
||||
if($mode == 'random'){
|
||||
$questionData = $this->getRandomQuestion($exercisesId,$dataIndex,$count);
|
||||
}else{
|
||||
$questionData = $this->getSortQuestion($exercisesId,$dataIndex,$count);
|
||||
}
|
||||
|
||||
if(!$questionData['ids']){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $questionData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 随机出题
|
||||
* @return void
|
||||
*/
|
||||
public function getRandomQuestion($exercisesId,$dataIndex,$count){
|
||||
$groupIds = ExercisesBindWarehouseGroup::getExercisesBindWarehouseGroupIds($exercisesId);
|
||||
$where = [];
|
||||
if($groupIds){
|
||||
$where = ['group_id'=>['in',$groupIds]];
|
||||
}
|
||||
|
||||
$questionIds = WarehouseQuestion::where($where)->orderRaw('rand()')->limit($count)->field('id')->column('id');
|
||||
|
||||
if($questionIds){
|
||||
shuffle($questionIds);
|
||||
}
|
||||
|
||||
return ['ids'=>$questionIds,'data_index'=>$dataIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* 顺序出题
|
||||
* @param $exercisesId 练习
|
||||
* @param $dataIndex 上次查询的下标
|
||||
* @param $count 获取数量
|
||||
* @return void
|
||||
*/
|
||||
public function getSortQuestion($exercisesId,$dataIndex,$count){
|
||||
$groupIds = ExercisesBindWarehouseGroup::getExercisesBindWarehouseGroupIds($exercisesId);
|
||||
|
||||
$where = [];
|
||||
if($groupIds){
|
||||
$where = ['group_id'=>['in',$groupIds]];
|
||||
}
|
||||
|
||||
$questionIds = WarehouseQuestion::where($where)->limit("{$dataIndex},$count")->field('id')->column('id');
|
||||
|
||||
if(count($questionIds) < $count){
|
||||
//说明问题不够了 需要重头再来
|
||||
$patchCount = $count - count($questionIds);
|
||||
|
||||
$dataIndex = $patchCount;
|
||||
|
||||
$patchQuestionIds = WarehouseQuestion::where($where)->limit("0,$patchCount")->field('id')->column('id');
|
||||
|
||||
if($patchQuestionIds){
|
||||
$questionIds = array_merge($questionIds,$patchQuestionIds);
|
||||
}
|
||||
|
||||
$questionIds = array_unique($questionIds);
|
||||
}else{
|
||||
$dataIndex += $count;
|
||||
}
|
||||
|
||||
return ['ids'=>$questionIds,'data_index'=>$dataIndex];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取做过的题目数量
|
||||
* @return void
|
||||
*/
|
||||
public function getCompleteQuestionCount($exercisesId){
|
||||
$questioIds = self::where([
|
||||
'exercises_id'=>$exercisesId
|
||||
])->field('question_ids')->column('question_ids');
|
||||
|
||||
if(!$questioIds){
|
||||
return 0;
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
|
||||
foreach ($questioIds as $questioId){
|
||||
$ids = array_merge($ids,explode(",",$questioId));
|
||||
}
|
||||
|
||||
$ids = array_unique($ids);
|
||||
|
||||
return count($ids);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
use think\Model;
|
||||
use app\api\model\app\exam\Exercises;
|
||||
use app\api\model\app\exam\WarehouseQuestion;
|
||||
use app\api\model\app\exam\ExercisesBindWarehouseGroup;
|
||||
/**
|
||||
* 题库练习记录答案
|
||||
*/
|
||||
class ExercisesLogAnswer extends Model
|
||||
{
|
||||
// 表名,不含前缀
|
||||
protected $name = 'app_exam_exercises_log_answer';
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = false;
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = false;
|
||||
protected $updateTime = false;
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 效验答案
|
||||
* @param $logId
|
||||
* @param $questionList 问题列表
|
||||
* @param $answerList 用户答案
|
||||
* @return void
|
||||
*/
|
||||
public function checkAnswer($questionList,$answerList){
|
||||
|
||||
if(empty($answerList) || empty($questionList)){
|
||||
return [];
|
||||
}
|
||||
|
||||
$questionKeyVals = [];
|
||||
foreach ($questionList as $question){
|
||||
$questionKeyVals[$question['id']] = $question;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
|
||||
$questionKeys = array_keys($questionKeyVals);
|
||||
|
||||
$trueCount = 0;
|
||||
$errorCount = 0;
|
||||
|
||||
foreach ($answerList as $key => $answer){
|
||||
//判断答案的题目ID 是不是全在问题列表里
|
||||
if(!in_array($key,$questionKeys)){
|
||||
throw new \app\common\exception\Exception('答案数据异常');
|
||||
}
|
||||
|
||||
$type = $questionKeyVals[$key]['type'];
|
||||
//判断答案的范围是否正确
|
||||
switch ($type){
|
||||
case 'judge':
|
||||
if($answer > 1 || $answer < 0){
|
||||
throw new \app\common\exception\Exception('判断题答案数据异常');
|
||||
}
|
||||
break;
|
||||
case 'single':
|
||||
if($answer > (count($questionKeyVals[$key]['option']) - 1) || $answer < 0){
|
||||
throw new \app\common\exception\Exception('单选题答案数据异常');
|
||||
}
|
||||
break;
|
||||
case 'multiple':
|
||||
case 'indefinite':
|
||||
if(!is_array($answer)){
|
||||
throw new \app\common\exception\Exception('多选题答案数据异常');
|
||||
}
|
||||
foreach ($answer as $option){
|
||||
if($option > (count($questionKeyVals[$key]['option']) - 1) || $option < 0){
|
||||
throw new \app\common\exception\Exception('多选题答案数据异常');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'fillblank':
|
||||
if(!is_array($answer)){
|
||||
throw new \app\common\exception\Exception('填空题答案数据异常');
|
||||
}
|
||||
break;
|
||||
case 'essay':
|
||||
break;
|
||||
}
|
||||
|
||||
$temp = [
|
||||
'question_id'=>$key,
|
||||
'createtime'=>time()
|
||||
];
|
||||
|
||||
$isCorrect = false;
|
||||
|
||||
switch ($type){
|
||||
case 'single':
|
||||
case 'judge':
|
||||
$temp['right_answer'] = $questionKeyVals[$key]['answer'];
|
||||
$temp['user_answer'] = $answer;
|
||||
$isCorrect = ($temp['right_answer'] == $temp['user_answer']);
|
||||
break;
|
||||
case 'multiple':
|
||||
case 'indefinite':
|
||||
$rightAnswer = $this->normalizeChoiceAnswer($questionKeyVals[$key]['answer']);
|
||||
$answer = $this->normalizeChoiceAnswer($answer);
|
||||
$temp['right_answer'] = implode(",",$rightAnswer);
|
||||
$temp['user_answer'] = implode(",",$answer);
|
||||
$isCorrect = ($rightAnswer == $answer);
|
||||
break;
|
||||
case 'fillblank':
|
||||
$rightAnswer = is_array($questionKeyVals[$key]['answer']) ? $questionKeyVals[$key]['answer'] : json_decode($questionKeyVals[$key]['answer'],true);
|
||||
$temp['right_answer'] = json_encode($rightAnswer,JSON_UNESCAPED_UNICODE);
|
||||
$temp['user_answer'] = json_encode($answer,JSON_UNESCAPED_UNICODE);
|
||||
$isCorrect = $this->checkFillblankAnswer($answer,$rightAnswer);
|
||||
break;
|
||||
case 'essay':
|
||||
$temp['right_answer'] = $questionKeyVals[$key]['answer'];
|
||||
$temp['user_answer'] = (is_array($answer) || is_object($answer))
|
||||
? json_encode($answer, JSON_UNESCAPED_UNICODE)
|
||||
: $answer;
|
||||
$isCorrect = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if($isCorrect){
|
||||
$trueCount++;
|
||||
$temp['result'] = 1;
|
||||
$temp['error_book_show'] = 0;
|
||||
}else{
|
||||
$temp['result'] = 0;
|
||||
// 问答题属于主观题,不纳入错题本
|
||||
$temp['error_book_show'] = ($type == 'essay') ? 2 : 1;
|
||||
if($type != 'essay'){
|
||||
$errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$result[] = $temp;
|
||||
}
|
||||
|
||||
return [
|
||||
'answer_list'=>$result,
|
||||
'error_count'=>$errorCount,
|
||||
'true_count'=>$trueCount,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验填空题答案
|
||||
* @param array $userAnswer 用户答案
|
||||
* @param array $rightAnswer 正确答案
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkFillblankAnswer($userAnswer,$rightAnswer){
|
||||
|
||||
if(empty($rightAnswer) || empty($userAnswer)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(count($userAnswer) != count($rightAnswer)){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($rightAnswer as $index => $acceptedAnswers){
|
||||
$userBlankAnswer = isset($userAnswer[$index]) ? trim($userAnswer[$index]) : '';
|
||||
$blankCorrect = false;
|
||||
if(!is_array($acceptedAnswers)){
|
||||
$acceptedAnswers = [$acceptedAnswers];
|
||||
}
|
||||
foreach ($acceptedAnswers as $acceptedAnswer){
|
||||
if(strcasecmp(trim($acceptedAnswer),$userBlankAnswer) === 0){
|
||||
$blankCorrect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$blankCorrect){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化选择题答案,避免多选/不定项因顺序不同误判。
|
||||
* @param mixed $answer
|
||||
* @return array
|
||||
*/
|
||||
protected function normalizeChoiceAnswer($answer)
|
||||
{
|
||||
if(!is_array($answer)){
|
||||
$answer = ($answer === '' || $answer === null) ? [] : explode(",",$answer);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($answer as $item){
|
||||
if($item === '' || $item === null){
|
||||
continue;
|
||||
}
|
||||
$result[] = intval($item);
|
||||
}
|
||||
|
||||
$result = array_values(array_unique($result));
|
||||
sort($result, SORT_NUMERIC);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 博阿村答案
|
||||
* @param $userId
|
||||
* @param $logId
|
||||
* @param $answerList
|
||||
* @return void
|
||||
*/
|
||||
public function saveAnswer($userId,$exercisesId,$logId,$answerList){
|
||||
|
||||
foreach ($answerList as &$item){
|
||||
$item['createtime'] = time();
|
||||
$item['exercises_log_id'] = $logId;
|
||||
$item['exercises_id'] = $exercisesId;
|
||||
$item['user_id'] = $userId;
|
||||
$item['uniacid'] = UNIACID;
|
||||
}
|
||||
|
||||
return self::insertAll($answerList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户提交的答案
|
||||
* @param $userId
|
||||
* @param $exercisesId
|
||||
* @param $logId
|
||||
* @return array
|
||||
*/
|
||||
public function getUserAnswer($userId,$exercisesId,$logId = 0){
|
||||
|
||||
$where = [
|
||||
'user_id'=>$userId
|
||||
];
|
||||
|
||||
if($exercisesId){
|
||||
$where['exercises_id'] = $exercisesId;
|
||||
}
|
||||
|
||||
if($logId){
|
||||
$where['exercises_log_id'] = $logId;
|
||||
}
|
||||
|
||||
$list = self::with(['warehouse_question'])->where($where)->group('question_id')->order('id','desc')->select();
|
||||
|
||||
$data = [];
|
||||
if(!$list){
|
||||
return $data;
|
||||
}
|
||||
|
||||
$list = collection($list)->toArray();
|
||||
foreach ($list as $item){
|
||||
$type = isset($item['warehouse_question']['type']) ? $item['warehouse_question']['type'] : '';
|
||||
switch ($type){
|
||||
case 'multiple':
|
||||
case 'indefinite':
|
||||
$data[$item['question_id']] = [];
|
||||
foreach (explode(",",$item['user_answer']) as $option){
|
||||
$data[$item['question_id']][] = intval($option);
|
||||
}
|
||||
break;
|
||||
case 'fillblank':
|
||||
$data[$item['question_id']] = json_decode($item['user_answer'],true);
|
||||
break;
|
||||
case 'essay':
|
||||
$decoded = json_decode($item['user_answer'], true);
|
||||
$data[$item['question_id']] = is_array($decoded) ? $decoded : $item['user_answer'];
|
||||
break;
|
||||
default:
|
||||
$data[$item['question_id']] = intval($item['user_answer']);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function warehouseQuestion()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\app\exam\WarehouseQuestion', 'question_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
class ExercisesSubscribe extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exam_exercises_subscribe';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
|
||||
|
||||
public function exercises()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\app\exam\Exercises', 'exercises_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
|
||||
use think\Model;
|
||||
|
||||
|
||||
class WarehouseGroup extends Model
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exam_warehouse_group';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有的分组ID
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getAllGroupIds(){
|
||||
return self::field('id')->column('id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exam;
|
||||
|
||||
use think\Model;
|
||||
|
||||
|
||||
class WarehouseQuestion extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exam_warehouse_question';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exchange;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class Batch extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exchange_batch';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 检查是否超出批次兑换限制
|
||||
* @param $userId
|
||||
* @param $code
|
||||
* @return void true=未超限制;false=超出限制
|
||||
*/
|
||||
public function checkLimit($userId,$batchId){
|
||||
|
||||
$batchInfo = self::where([
|
||||
'id'=>$batchId
|
||||
])->find();
|
||||
|
||||
if(!$batchInfo){
|
||||
return false;
|
||||
}
|
||||
|
||||
//不限制
|
||||
if(!$batchInfo['use_limit']){
|
||||
return true;
|
||||
}
|
||||
|
||||
$exchangeCount = \app\api\model\app\exchange\UseLog::getExchangeCount($userId,$batchId);
|
||||
|
||||
if($exchangeCount < $batchInfo['use_limit']){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exchange;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class Code extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exchange_code';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 检查兑换码
|
||||
* @param $code
|
||||
* @return void
|
||||
*/
|
||||
public function checkCode($code)
|
||||
{
|
||||
|
||||
//判断有没有
|
||||
$data = self::with(['batch'])->where([
|
||||
'code'=>$code,
|
||||
'code.status'=>1,
|
||||
'batch.status'=>1,
|
||||
'batch.starttime'=>['<',time()],
|
||||
'batch.endtime'=>['>',time()]
|
||||
])->find();
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function batch()
|
||||
{
|
||||
return $this->belongsTo('Batch', 'batch_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 兑换
|
||||
* @param $userId 用户
|
||||
* @param $goodsId 商品
|
||||
* @return bool
|
||||
*/
|
||||
public function exchange($userId,$batchId,$code)
|
||||
{
|
||||
$goods = \app\api\model\app\exchange\Goods::getBatchGoods($batchId);
|
||||
|
||||
if($goods){
|
||||
$subscriptionModel = new \app\common\model\user\Subscription();
|
||||
foreach ($goods as $item){
|
||||
$subscriptionModel->setUserCourse($userId,$item['goods_id'],'exchange');
|
||||
|
||||
\app\api\model\app\exchange\UseLog::insert([
|
||||
'user_id'=>$userId,
|
||||
'uniacid'=>UNIACID,
|
||||
'goods_id'=>$item['goods_id'],
|
||||
'code'=>$code,
|
||||
'batch_id'=>$batchId,
|
||||
'createtime'=>time()
|
||||
]);
|
||||
|
||||
self::where([
|
||||
'code'=>$code,
|
||||
'batch_id'=>$batchId
|
||||
])->update([
|
||||
'user_id'=>$userId,
|
||||
'use_time'=>time(),
|
||||
'status'=>2
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exchange;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class Goods extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exchange_batch_goods';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 获取批次包含的商品
|
||||
* @return void
|
||||
*/
|
||||
public static function getBatchGoods($batchId){
|
||||
return self::with('course')->where([
|
||||
'batch_id'=>$batchId
|
||||
])->select();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\course\Course', 'goods_id', 'id', [], 'RIGHT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\exchange;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class UseLog extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_exchange_use_log';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 获取兑换次数
|
||||
* @param $userId 用户
|
||||
* @param $batchId 批次
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getExchangeCount($userId,$batchId){
|
||||
return self::where([
|
||||
'user_id'=>$userId,
|
||||
'batch_id'=>$batchId
|
||||
])->group('code')->count();
|
||||
}
|
||||
|
||||
public function batch()
|
||||
{
|
||||
return $this->belongsTo('Batch', 'batch_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\course\Course', 'goods_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\pc;
|
||||
|
||||
use think\Model;
|
||||
/**
|
||||
* PC登录
|
||||
*/
|
||||
class Login extends Model
|
||||
{
|
||||
// 表名
|
||||
protected $name = 'app_pc_login';
|
||||
|
||||
protected $vaild_time = 120;
|
||||
|
||||
|
||||
public function getTicketState($ticket){
|
||||
$ticket = self::where([
|
||||
'uniacid'=>UNIACID,
|
||||
'ticket'=>$ticket,
|
||||
'status'=>1,
|
||||
'createtime'=>['>',time()-$this->vaild_time]
|
||||
])->find();
|
||||
|
||||
if(!$ticket){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查 ticket是否可用
|
||||
* @param $ticket
|
||||
* @return void
|
||||
*/
|
||||
public function checkTicketCanUse($ticket){
|
||||
$data = self::where([
|
||||
'uniacid'=>UNIACID,
|
||||
'ticket'=>$ticket,
|
||||
'status'=>0,
|
||||
'createtime'=>['>',time()-$this->vaild_time]
|
||||
])->find();
|
||||
|
||||
if($data){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 ticket
|
||||
* @return mixed
|
||||
*/
|
||||
public function buildTicket(){
|
||||
$ticket = \fast\Random::alnum(10);
|
||||
|
||||
self::insert([
|
||||
'uniacid'=>UNIACID,
|
||||
'ticket'=>$ticket,
|
||||
'status'=>0,
|
||||
'createtime'=>time()
|
||||
]);
|
||||
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁 ticket
|
||||
* @param $ticket
|
||||
* @return mixed
|
||||
*/
|
||||
public function destroyTicket($ticket){
|
||||
return self::where([
|
||||
'uniacid'=>UNIACID,
|
||||
'ticket'=>$ticket,
|
||||
])->update([
|
||||
'status'=>2
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 登录成功
|
||||
* @param $ticket
|
||||
* @param $userId
|
||||
* @param $token
|
||||
* @return mixed
|
||||
*/
|
||||
public function successTicket($ticket,$userId,$token){
|
||||
return self::where([
|
||||
'uniacid'=>UNIACID,
|
||||
'ticket'=>$ticket,
|
||||
])->update([
|
||||
'status'=>1,
|
||||
'user_id'=>$userId,
|
||||
'token'=>$token
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\pc;
|
||||
|
||||
use think\Model;
|
||||
/**
|
||||
* PC页面装修
|
||||
*/
|
||||
class Page extends Model
|
||||
{
|
||||
// 表名
|
||||
protected $name = 'app_pc_page';
|
||||
|
||||
|
||||
/**
|
||||
* 获取主页
|
||||
* @return false
|
||||
*/
|
||||
public function getIndexData(){
|
||||
$data = self::where([
|
||||
'is_index'=>1,
|
||||
'status'=>1
|
||||
])->find();
|
||||
|
||||
if($data){
|
||||
return $data;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取页面数据
|
||||
* @param $id
|
||||
* @return false
|
||||
*/
|
||||
public function getPageData($id){
|
||||
$where = [
|
||||
'status'=>1
|
||||
];
|
||||
if($id){
|
||||
$where['id'] = $id;
|
||||
$data = self::where($where)->find();
|
||||
if(!$data){
|
||||
$data = $this->getIndexData();
|
||||
}
|
||||
}else{
|
||||
$data = $this->getIndexData();
|
||||
}
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
//之前的变量名疏忽写错了,暂时这样
|
||||
$data['compontents'] = $data['components'];
|
||||
$data = (new \app\common\model\page\Decorate())->parseData($data,'pc');
|
||||
$data['components'] = $data['compontents'];
|
||||
unset($data['compontents']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\pc;
|
||||
|
||||
use think\Model;
|
||||
/**
|
||||
* SEO
|
||||
*/
|
||||
class Seo extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取 seo meta 信息
|
||||
* @param $type
|
||||
* @param $id
|
||||
* @return void
|
||||
*/
|
||||
public function getMeta($type = null,$id = null){
|
||||
$seoConfig = \app\common\model\app\Config::getConfig('pc_seo');
|
||||
$systemConfig = \app\common\model\config\System::getConfig('system');
|
||||
|
||||
$meta = [
|
||||
'title'=>'',
|
||||
'keywords'=>'',
|
||||
'description'=>''
|
||||
];
|
||||
|
||||
if($seoConfig){
|
||||
if($type == 'page' && $seoConfig['page_tdk_status'] == 1){
|
||||
//获取页面
|
||||
$pagedata = \app\api\model\app\pc\Page::where(['id'=>$id])->field(["seo_title","seo_description","seo_keyword"])->find();
|
||||
if($pagedata){
|
||||
$meta['title'] = $pagedata['seo_title'];
|
||||
$meta['keywords'] = $pagedata['seo_keyword'];
|
||||
$meta['description'] = $pagedata['seo_description'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($seoConfig['detail_tdk_status'] == 1 && $type != 'page'){
|
||||
switch ($type){
|
||||
case "goods":
|
||||
case "live":
|
||||
$goodsdata = \app\api\model\course\Course::where(['id'=>$id])->field(["name","briefing"])->find();
|
||||
if($goodsdata){
|
||||
$meta['title'] = $goodsdata['name'];
|
||||
$meta['description'] = $goodsdata['briefing'];
|
||||
}
|
||||
break;
|
||||
case "evaluation":
|
||||
$evaluationdata = \app\api\model\app\exam\Exercises::where(['id'=>$id])->field(["name"])->find();
|
||||
if($evaluationdata){
|
||||
$meta['title'] = $evaluationdata['name'];
|
||||
}
|
||||
break;
|
||||
case "search":
|
||||
$meta['title'] = $id."的搜索结果";
|
||||
break;
|
||||
case "vipcard":
|
||||
$vipcarddata = \app\api\model\app\vip\Card::where(['id'=>$id])->field(["title","subtitle"])->find();
|
||||
if($vipcarddata){
|
||||
$meta['title'] = $vipcarddata['title'];
|
||||
$meta['description'] = $vipcarddata['subtitle'];
|
||||
}
|
||||
break;
|
||||
case "activity":
|
||||
$activitydata = \app\api\model\app\activity\Activity::where(['id'=>$id])->field(["name","location"])->find();
|
||||
if($activitydata){
|
||||
$meta['title'] = $activitydata['name'];
|
||||
$meta['description'] = "活动地点:".$activitydata['location'];
|
||||
}
|
||||
break;
|
||||
case "user":
|
||||
$meta['title'] = $id == 'record' ? '学习记录' : ($id == 'info' ? "个人中心" : '我的课程');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($seoConfig['default_tdk_status'] == 1){
|
||||
$meta['title'] = empty($meta['title']) ? $seoConfig['default_tdk_title'] : $meta['title'];
|
||||
$meta['keywords'] = empty($meta['keywords']) ?implode(",",$seoConfig['default_tdk_keywords']) : $meta['keywords'];
|
||||
$meta['description'] = empty($meta['description']) ? $seoConfig['default_tdk_describe'] : $meta['description'];
|
||||
}
|
||||
}
|
||||
|
||||
$meta['title'] = empty($meta['title']) ? $systemConfig['name'] : $meta['title'];
|
||||
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\physical;
|
||||
|
||||
use think\Model;
|
||||
use app\admin\model\app\physical\SkuPrice;
|
||||
|
||||
class Goods extends Model
|
||||
{
|
||||
protected $name = 'app_physical_goods';
|
||||
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $deleteTime = false;
|
||||
|
||||
protected $append = [
|
||||
'status_text',
|
||||
'spec_type_text'
|
||||
];
|
||||
|
||||
public function getStatusList()
|
||||
{
|
||||
return [1 => '上架', 0 => '下架'];
|
||||
}
|
||||
|
||||
public function getSpecTypeList()
|
||||
{
|
||||
return ['single' => '单规格', 'multi' => '多规格'];
|
||||
}
|
||||
|
||||
public function getStatusTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
|
||||
$list = $this->getStatusList();
|
||||
return isset($list[$value]) ? $list[$value] : '';
|
||||
}
|
||||
|
||||
public function getSpecTypeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['spec_type']) ? $data['spec_type'] : '');
|
||||
$list = $this->getSpecTypeList();
|
||||
return isset($list[$value]) ? $list[$value] : '';
|
||||
}
|
||||
|
||||
public function getCarouselAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['carousel']) ? $data['carousel'] : '');
|
||||
if (empty($value)) {
|
||||
return [];
|
||||
}
|
||||
$carousel = json_decode($value, true);
|
||||
return is_array($carousel) ? $carousel : [];
|
||||
}
|
||||
|
||||
public function getParamsAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['params']) ? $data['params'] : '');
|
||||
if (empty($value)) {
|
||||
return [];
|
||||
}
|
||||
$params = json_decode($value, true);
|
||||
return is_array($params) ? $params : [];
|
||||
}
|
||||
|
||||
public function skus()
|
||||
{
|
||||
return $this->hasMany('app\admin\model\app\physical\Sku', 'goods_id', 'id');
|
||||
}
|
||||
|
||||
public function skuPrices()
|
||||
{
|
||||
return $this->hasMany('app\admin\model\app\physical\SkuPrice', 'goods_id', 'id');
|
||||
}
|
||||
|
||||
public static function getPayDetail($goodsIdSku, $count = 1, $extend = '')
|
||||
{
|
||||
$goodsIdSkuArr = explode('_', $goodsIdSku);
|
||||
$goodsId = $goodsIdSkuArr[0] ?? 0;
|
||||
$skuId = $goodsIdSkuArr[1] ?? 0;
|
||||
|
||||
$data = self::where([
|
||||
'id' => $goodsId,
|
||||
'status' => 1
|
||||
])->find();
|
||||
|
||||
if (!$data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $data->toArray();
|
||||
|
||||
$specType = $data['spec_type'] ?? 'single';
|
||||
|
||||
if ($specType == 'single') {
|
||||
$skuPrice = SkuPrice::where([
|
||||
'goods_id' => $goodsId,
|
||||
'uniacid' => UNIACID
|
||||
])->order('id', 'asc')->find();
|
||||
|
||||
if (!$skuPrice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$skuPrice = $skuPrice->toArray();
|
||||
$data['price'] = $skuPrice['price'];
|
||||
$data['price_marking'] = $skuPrice['original_price'] ?: $skuPrice['price'];
|
||||
$data['stock'] = $skuPrice['stock'];
|
||||
$data['sku_text'] = $skuPrice['goods_sku_text'] ?? '';
|
||||
} else {
|
||||
$skuPrice = SkuPrice::where([
|
||||
'id' => $skuId,
|
||||
'goods_id' => $goodsId,
|
||||
'uniacid' => UNIACID
|
||||
])->find();
|
||||
|
||||
if (!$skuPrice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$skuPrice = $skuPrice->toArray();
|
||||
$data['price'] = $skuPrice['price'];
|
||||
$data['price_marking'] = $skuPrice['original_price'] ?: $skuPrice['price'];
|
||||
$data['stock'] = $skuPrice['stock'];
|
||||
$data['sku_text'] = $skuPrice['goods_sku_text'] ?? '';
|
||||
}
|
||||
|
||||
$data['name'] = $data['name'];
|
||||
$data['title'] = $data['title'] ?? '';
|
||||
$data['type'] = 'physical';
|
||||
$data['count'] = $count;
|
||||
$data['extend'] = $extend;
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\recommend;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
use think\Cache;
|
||||
class Goods extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_recommend_goods';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 获取推荐商品列表
|
||||
* @param $count
|
||||
* @return void
|
||||
*/
|
||||
public function getGoodsList($count){
|
||||
|
||||
$cacheData = Cache::get(\app\common\constant\cache\Keys::COURSE_RECOMMEND);
|
||||
|
||||
if($cacheData){
|
||||
foreach ($cacheData as &$item) {
|
||||
$goodsType = $item['type'] ?? '';
|
||||
$isVirtualPay = \app\common\library\pay\VirtualPayService::isUseVirtualPay($goodsType);
|
||||
$item['is_virtual_pay'] = $isVirtualPay ? 1 : 0;
|
||||
if ($isVirtualPay && !isset($item['_virtual_converted'])) {
|
||||
$item = \app\common\library\pay\VirtualPayService::convertPriceFields($item, ['price', 'price_marking']);
|
||||
$item['_virtual_converted'] = true;
|
||||
}
|
||||
}
|
||||
unset($item);
|
||||
return $cacheData;
|
||||
}
|
||||
|
||||
$normalGoodsCondition = [
|
||||
'course.status'=>1,
|
||||
'sales_type'=>['like',"%alone%"],
|
||||
'hide'=>0
|
||||
];
|
||||
|
||||
$normalCount = self::with(['course'])->where($normalGoodsCondition)->count();
|
||||
$start = 0;
|
||||
|
||||
if(($normalCount - $count) > 0){
|
||||
$start = rand(0,(($normalCount - $count) - 1));
|
||||
}
|
||||
|
||||
$list = self::with(['course'])
|
||||
->where($normalGoodsCondition)
|
||||
->field(['course.name','course.cover','course.price','course.price_marking','course.pay_type','course.type','course.id'])
|
||||
->limit($start,$count)
|
||||
->select();
|
||||
|
||||
if ($list){
|
||||
|
||||
$vipAppConfig = \app\common\model\app\Config::getConfig('vip');
|
||||
|
||||
foreach ($list as &$item){
|
||||
unset($item['course']);
|
||||
|
||||
$item['is_vip_goods'] = false;
|
||||
if($vipAppConfig['status'] == 1){
|
||||
//判断是否为会员权益课程
|
||||
$item['is_vip_goods'] = \app\api\model\app\vip\CardPrivilege::checkVipGoods($item['id']);
|
||||
}
|
||||
|
||||
$goodsType = $item['type'] ?? '';
|
||||
$isVirtualPay = \app\common\library\pay\VirtualPayService::isUseVirtualPay($goodsType);
|
||||
$item['is_virtual_pay'] = $isVirtualPay ? 1 : 0;
|
||||
if ($isVirtualPay) {
|
||||
$item = \app\common\library\pay\VirtualPayService::convertPriceFields($item, ['price', 'price_marking']);
|
||||
$item['_virtual_converted'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
unset($item);
|
||||
|
||||
$list = collection($list)->toArray();
|
||||
}
|
||||
|
||||
Cache::tag(\app\common\constant\cache\Keys::COURSE_TAG)->set(\app\common\constant\cache\Keys::COURSE_RECOMMEND,$list);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\course\Course', 'goods_id', 'id', [], 'RIGHT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\score;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class GoodsGroup extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_score_goods_group';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\score;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class Goods extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_score_goods';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\api\model\course\Course', 'goods_id', 'id', [], 'right')->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\score;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\api\model\app\agent\Level;
|
||||
class GoodsGroup extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_score_goods_group';
|
||||
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\sign;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\common\model\User;
|
||||
class Log extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_sign_log';
|
||||
|
||||
|
||||
// 开启自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'int';
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $hidden = ['createtime', 'updatetime'];
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 获取签到记录
|
||||
public static function getList ($userId,$month = '') {
|
||||
|
||||
|
||||
$month = $month ? $month : date('Y-m');
|
||||
|
||||
// if ($month > date('Y-m')) {
|
||||
// throw new Exception('只能查看当前月之前的签到记录');
|
||||
// }
|
||||
|
||||
$sign = self::where('user_id', $userId)->where('date', 'like', $month . '%')->order('date', 'desc')->select();
|
||||
$sign_dates = array_column($sign, 'date');
|
||||
|
||||
$totime = time();
|
||||
$today = date('Y-m-d');
|
||||
// 要查询的是否是当前月
|
||||
$is_current = ($month == date('Y-m')) ? true : false;
|
||||
|
||||
// 所选月开始时间戳
|
||||
$month_start_time = strtotime($month);
|
||||
// 所选月总天数
|
||||
$month_days = date('t', $month_start_time);
|
||||
|
||||
$days = [];
|
||||
for($i = 1; $i <= $month_days; $i ++) {
|
||||
$for_time = $month_start_time + (($i - 1) * 86400);
|
||||
$for_date = date('Y-m-d', $for_time);
|
||||
|
||||
// 如果不是当前月,全是 before, 如果是当前月判断 日期是当前日期的 前面,还是后面
|
||||
$current = !$is_current ? ($month > date('Y-m') ? 'after' : 'before') :
|
||||
($for_date == $today ? 'today' :
|
||||
($for_date < $today ? 'before' : 'after'));
|
||||
|
||||
$days[] = [
|
||||
'is_sign' => in_array($for_date, $sign_dates), // 判断循环的日期,是否在查询的签到记录里面
|
||||
'date' => $for_date,
|
||||
'time' => $for_time,
|
||||
'day' => $i,
|
||||
'week' => date('w', $for_time),
|
||||
'current' => $current
|
||||
];
|
||||
}
|
||||
|
||||
$result = ['days' => $days];
|
||||
|
||||
// 如果是当前月,计算签到时长
|
||||
if ($is_current) {
|
||||
$continue_days = 0; // 连续签到天数
|
||||
$chunk = 0; // 第几次 chunk;
|
||||
$chunk_num = 10; // 每次查 10 条
|
||||
$sign = self::where('user_id', $userId)->chunk($chunk_num, function ($signs) use ($totime, &$continue_days, &$chunk, $chunk_num) {
|
||||
foreach ($signs as $key => $sign) {
|
||||
$pre_time = $totime - (86400 * ($key + ($chunk * $chunk_num)));
|
||||
$pre_date = date('Y-m-d', $pre_time);
|
||||
if ($sign->date == $pre_date) {
|
||||
$continue_days++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$chunk ++;
|
||||
}, 'date', 'desc'); // 如果 date 重复,有坑 (date < 2020-03-28)
|
||||
|
||||
$result['cuntinue_days'] = $continue_days;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
// 添加浏览记录
|
||||
public static function sign($userId,$month = '') {
|
||||
|
||||
$sign = self::where('user_id', $userId)->where('date', date('Y-m-d'))->find();
|
||||
|
||||
if ($sign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 当前时间戳,避免程序执行中间,刚好跨天
|
||||
$time = time();
|
||||
|
||||
// 获取积分规则
|
||||
$config = \app\common\model\app\Config::getConfig('sign');
|
||||
|
||||
if($config['status'] !=1){
|
||||
return false;
|
||||
}
|
||||
|
||||
$basic_score = $config['basic_score'];
|
||||
$continuity_score = $config['continuity_score'];
|
||||
$continuity_days = $config['continuity_days'];
|
||||
|
||||
// 查询签到记录,判断连续签到天数 只需要倒叙查询 $continuity_days 条记录
|
||||
$signs = self::where('user_id', $userId)->order('date', 'desc')->limit($continuity_days)->select();
|
||||
|
||||
$continue_days = 1;
|
||||
foreach ($signs as $key => $sign) {
|
||||
$pre_time = $time - (86400 * ($key + 1));
|
||||
$pre_date = date('Y-m-d', $pre_time);
|
||||
if ($sign->date == $pre_date) {
|
||||
$continue_days ++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 连续签到天数超出最大连续天数,按照最大连续天数计算
|
||||
$continue_effec_days = (($continue_days - 1) > $continuity_days) ? $continuity_days : ($continue_days - 1);
|
||||
|
||||
// 计算今天应得积分 连续签到两天,第二天所得积分为 $basic_score + ((2 - 1) * $continuity_score)
|
||||
$score = $basic_score;
|
||||
$until_add = $continue_effec_days * $continuity_score; // 连续签到累加必须大于 0 ,小于 0 舍弃
|
||||
if ($until_add > 0) { // 避免 continuity_days 填写小于 等于 0
|
||||
$score += $until_add;
|
||||
}
|
||||
|
||||
$sign = Db::transaction(function () use ($userId, $time, $score) {
|
||||
// 插入签到记录
|
||||
$sign = self::create([
|
||||
'uniacid'=>UNIACID,
|
||||
'user_id' => $userId,
|
||||
'date' => date('Y-m-d', $time),
|
||||
'score' => $score >= 0 ? $score : 0
|
||||
]);
|
||||
|
||||
// 赠送积分
|
||||
if ($score > 0) {
|
||||
User::score($score,$userId,'签到奖励');
|
||||
}
|
||||
|
||||
return $sign;
|
||||
});
|
||||
|
||||
return $sign;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\vip;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\common\model\User;
|
||||
use app\api\model\app\vip\CardUser;
|
||||
class Card extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_vip_card';
|
||||
|
||||
|
||||
// 开启自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'int';
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $hidden = ['createtime', 'updatetime'];
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取订单中的会员卡与规格对应的信息
|
||||
* @param $cardIdSku 格式 ID_SKU
|
||||
* @return false
|
||||
*/
|
||||
public static function getPayDetail($cardIdSku){
|
||||
$cardId = explode("_",$cardIdSku);
|
||||
|
||||
$data = self::where([
|
||||
'id'=>$cardId[0],
|
||||
'status'=>1
|
||||
])->find();
|
||||
|
||||
|
||||
|
||||
if(!$data){
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['sku'] = json_decode($data['sku'],true);
|
||||
|
||||
if(!$data['sku'] || !isset($cardId[1]) || !isset($data['sku'][$cardId[1]])){
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['price_marking'] = $data['price'] = $data['sku'][$cardId[1]]['price']; //价格
|
||||
$data['time'] = $data['sku'][$cardId[1]]['time']; //时长
|
||||
$data['limit'] = $data['sku'][$cardId[1]]['limit']; //限购
|
||||
$data['name'] = $data['title'];
|
||||
$data['type'] = 'vipcard';
|
||||
|
||||
if(\app\common\library\Platform::getSystemType() == 'single'){
|
||||
$data['cover'] = MODULE_URL.'/assets/image/vipcard.png';
|
||||
}else{
|
||||
$data['cover'] = MODULE_URL.'/public/assets/image/vipcard.png';
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\vip;
|
||||
|
||||
use think\Model;
|
||||
|
||||
|
||||
class CardPrivilege extends Model
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_vip_card_privilege';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* 获取批次包含的商品
|
||||
* @return void
|
||||
*/
|
||||
public function getPrivilegeGoods($cardId,$type){
|
||||
|
||||
|
||||
$list = self::with('course')->where([
|
||||
'card_id'=>$cardId,
|
||||
'card_privilege.type'=>$type,
|
||||
'course.status'=>1,
|
||||
'course.sales_type'=>['like',"%alone%"],
|
||||
'course.hide'=>0
|
||||
])->limit(6)->select();
|
||||
|
||||
$data = [];
|
||||
if(!empty($list)){
|
||||
foreach ($list as &$row){
|
||||
$row->course->visible(['name','cover','price','price_marking','pay_type','type','id','is_vip_goods']);
|
||||
$row->course->is_vip_goods = true;
|
||||
$data[] = $row->course;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取折扣后的商品价格
|
||||
* @param $price 价格
|
||||
* @param $discountVal 折扣
|
||||
* @return array
|
||||
*/
|
||||
public static function getDiscountPrice($price,$discountVal){
|
||||
|
||||
$data = [
|
||||
'price_marking' => $price
|
||||
];
|
||||
|
||||
$data['price'] = number_format(($price * $discountVal / 10), 2, '.', '');;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为会员权益商品
|
||||
* 1. 该商品被指定为某张启用中会员卡的指定课程权益
|
||||
* 2. 商品类型属于 article/video/audio/live/column,且存在启用了「全部课程」作用域的会员卡
|
||||
* @param $goodsId 商品ID
|
||||
* @return Boolean
|
||||
*/
|
||||
public static function checkVipGoods($goodsId){
|
||||
|
||||
$vipLog = self::with(['card'])->where([
|
||||
'card.status'=>1,
|
||||
'goods_id'=>$goodsId
|
||||
])->find();
|
||||
|
||||
if($vipLog){
|
||||
return true;
|
||||
}
|
||||
|
||||
//再判断「全部课程」作用域:只要存在启用中的卡,且课程类型受作用,则认为是 VIP 权益商品
|
||||
if (\app\common\model\app\vip\CardPrivilege::isCourseInScopeAll($goodsId)) {
|
||||
$cardModel = new \app\api\model\app\vip\Card();
|
||||
|
||||
$hasScopeAllCard = $cardModel->where('status', 1)
|
||||
->where('uniacid', UNIACID)
|
||||
->where(function ($query) {
|
||||
$query->where(['privilege_free' => 1, 'privilege_free_scope' => 'all'])
|
||||
->whereOr(['privilege_discount' => 1, 'privilege_discount_scope' => 'all']);
|
||||
})->find();
|
||||
|
||||
if ($hasScopeAllCard) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function card()
|
||||
{
|
||||
return $this->belongsTo('Card', 'card_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo('app\admin\model\Course', 'goods_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\app\vip;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use app\common\model\User;
|
||||
class CardUser extends Model
|
||||
{
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'app_vip_card_user';
|
||||
|
||||
|
||||
// 开启自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'int';
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $hidden = ['createtime', 'updatetime'];
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user