初始化项目:添加后端代码、ThinkPHP框架、前端资源

This commit is contained in:
amb
2026-09-03 12:42:39 +08:00
commit 482bece22e
3726 changed files with 416708 additions and 0 deletions
@@ -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;
}
}
+37
View File
@@ -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);
}
}
+156
View File
@@ -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
]);
}
}
+89
View File
@@ -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]);
}
}
+112
View File
@@ -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);
}
}
+101
View File
@@ -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
]);
}
}
+64
View File
@@ -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;
}
}
+91
View File
@@ -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 = [
];
}
+33
View File
@@ -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 = [
];
}
+169
View File
@@ -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;
}
}
+75
View File
@@ -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 = [
];
}