DiverseYouthNightSchool/application/common/model/school/classes/ClassesLib.php

764 lines
24 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common\model\school\classes;
use app\common\library\Virtual;
use app\common\model\BaseModel;
use app\common\model\dyqc\ManystoreShop;
use app\common\model\school\classes\lib\Spec;
use app\common\model\User;
use think\Model;
use traits\model\SoftDelete;
class ClassesLib extends BaseModel
{
use SoftDelete;
// 表名
protected $name = 'school_classes_lib';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = 'deletetime';
protected $classes_lib_ids = [];
// 追加属性
protected $append = [
'add_type_text',
'type_text',
'address_type_text',
'status_text',
'auth_status_text',
'auth_time_text',
'recommend_text',
'hot_text',
'new_text',
'selfhot_text',
'distance_text',
];
public function getDistanceTextAttr($value, $data) {
$distance_text = '';
$distance = $data['distance'] ?? 0;
switch (true) {
case $distance >= 1000;
$distance_text = round(($distance / 1000), 2) . 'km';
break;
default :
$distance_text = $distance . 'm';
break;
}
return $distance_text;
}
protected static function init()
{
self::afterInsert(function ($row) {
if (!$row['weigh']) {
$pk = $row->getPk();
$row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]);
}
});
}
public function getAddTypeList()
{
return ['1' => __('Add_type 1'), '2' => __('Add_type 2')];
}
public function getTypeList()
{
return ['out' => __('Type out'), 'in' => __('Type in')];
}
public function getAddressTypeList()
{
return ['1' => __('Address_type 1'), '2' => __('Address_type 2')];
}
public function getStatusList()
{
return ['1' => __('Status 1'), '2' => __('Status 2'), '3' => __('Status 3')];
}
public function getAuthStatusList()
{
return ['0' => __('Auth_status 0'), '1' => __('Auth_status 1'), '2' => __('Auth_status 2')];
}
public function getRecommendList()
{
return ['0' => __('Recommend 0'), '1' => __('Recommend 1')];
}
public function getHotList()
{
return ['0' => __('Hot 0'), '1' => __('Hot 1')];
}
public function getNewList()
{
return ['0' => __('New 0'), '1' => __('New 1')];
}
public function getSelfhotList()
{
return ['0' => __('Selfhot 0'), '1' => __('Selfhot 1')];
}
public function getAddTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['add_type']) ? $data['add_type'] : '');
$list = $this->getAddTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['type']) ? $data['type'] : '');
$list = $this->getTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getAddressTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['address_type']) ? $data['address_type'] : '');
$list = $this->getAddressTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getAuthStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['auth_status']) ? $data['auth_status'] : '');
$list = $this->getAuthStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getAuthTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['auth_time']) ? $data['auth_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getRecommendTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['recommend']) ? $data['recommend'] : '');
$list = $this->getRecommendList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getHotTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['hot']) ? $data['hot'] : '');
$list = $this->getHotList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getNewTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['new']) ? $data['new'] : '');
$list = $this->getNewList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getSelfhotTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['selfhot']) ? $data['selfhot'] : '');
$list = $this->getSelfhotList();
return isset($list[$value]) ? $list[$value] : '';
}
protected function setAuthTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
public function getHeadimageAttr($value, $data)
{
if (!empty($value)) return cdnurl($value, true);
}
public function getImagesAttr($value, $data)
{
$imagesArray = [];
if (!empty($value)) {
$imagesArray = explode(',', $value);
foreach ($imagesArray as &$v) {
$v = cdnurl($v, true);
}
return $imagesArray;
}
return $imagesArray;
}
public function manystore()
{
return $this->belongsTo('app\admin\model\Manystore', 'manystore_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function shop()
{
return $this->belongsTo(ManystoreShop::class, 'shop_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function user()
{
return $this->belongsTo('app\common\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function admin()
{
return $this->belongsTo('app\admin\model\Admin', 'admin_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function teacher()
{
return $this->belongsTo('app\common\model\school\classes\Teacher', 'teacher_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function specs()
{
return $this->hasMany(ClassesSpec::class,'classes_lib_id');
}
/** 课程详情
* @param $id
* @return ClassesLib|null
* @throws \think\exception\DbException
*/
public function detail($id,$user_id=0){
$self = $this->get($id,['shop','teacher']);
//是否收藏
$self['is_collect'] = 0;
//是否购买
$self['have_buy'] = 0;
if($user_id){
//判断是否收藏
$self['is_collect'] = Collect::where("user_id",$user_id)->where("classes_lib_id",$id)->count();
//判断用户是否已报名
$self['have_buy'] = \app\common\model\school\classes\order\Order::where("classes_lib_id",$id)
->where("user_id",$user_id)
->where("status","in",["3","6","9"])
->count() ? 1 : 0 ;
//$self['virtual_people'] = $self['virtual_people'] + 1;
//有用户进来,参与人数+1
if(!$self['have_buy'])$self['virtual_people'] = $self['virtual_people'] + 1;
}
//下架判断
// if($self['status'] != '1'){
// $this->error("该课程已下架");
// }
//
//参与人数 = 虚拟人数 + 平台人数
return $self;
}
/**课程参与人员信息
* @param $id
*
*/
public function virtualParticipants($id,$user_id=0){
//虚拟用户生成数量
$v_num = 10;
$unpaid_user_data = $paid_user_data = [];
$selfuser = null;
if($user_id){
$selfuser = User::get($user_id);
}
$user_unpaid_order = $user_paid_order =null;
if($selfuser){
$user_unpaid_order = \app\common\model\school\classes\order\Order::where("classes_lib_id",$id)
->where("status","in",["0",'-3'])
->where("user_id",$user_id)
->order("createtime desc")
->value("createtime");
$user_paid_order = \app\common\model\school\classes\order\Order::where("classes_lib_id",$id)
->where("status","in",["3",'6','9'])
->where("user_id",$user_id)
->order("createtime desc")
->value("createtime");
}
//参与者头像
//先从订单里取出最新的10个未支付的用户不足的用虚拟用户填充
$user_ids = \app\common\model\school\classes\order\Order::where("classes_lib_id",$id)->where("status","in",["0",'-3'])->order("createtime desc")->limit($v_num)->column("createtime","user_id");
if($user_ids){
$users = User::where("id","in",array_keys($user_ids))->select();
foreach ($users as $user){
$unpaid_user_data[] = [
"nickname"=>$user['nickname'],
"head_image"=>$user['avatar'],
"classes_lib_id"=>$id,
"time"=>$user_ids[$user['id']],
"jointype"=>'1',
"havetype"=>'0'
];
}
}
if(!$user_paid_order && $selfuser){
if($user_unpaid_order){
$unpaid_user_data[] = [
"nickname"=>$selfuser['nickname'],
"head_image"=>$selfuser['avatar'],
"classes_lib_id"=>$id,
"time"=>$user_unpaid_order,
"jointype"=>'1',
"havetype"=>'0'
];
$user_ids[$selfuser['id']] = $user_unpaid_order;
}else{
$unpaid_user_data[] = [
"nickname"=>$selfuser['nickname'],
"head_image"=>$selfuser['avatar'],
"classes_lib_id"=>$id,
"time"=>time(),
"jointype"=>'1',
"havetype"=>'0'
];
$user_ids[$selfuser['id']] = time();
}
}
//计算需要生成的虚拟用户数量
$v_num = $v_num - count($user_ids);
if($v_num<0)$v_num =0;
if($v_num){
$unpaid_user = VirtualUser::where("classes_lib_id",$id)->where("jointype",'1')->order("time desc")->limit($v_num)->select();
$unpaid_user_data = array_merge($unpaid_user_data,$unpaid_user);
}
//再从订单里取出最新的10个使用中已完成 和 已退款 的用户,不足的用虚拟用户填充
$user_ids = \app\common\model\school\classes\order\Order::where("classes_lib_id",$id)->where("status","in",["3",'6','9'])->order("createtime desc")->limit($v_num)->column("createtime","user_id");
if($user_ids){
$users = User::where("id","in",array_keys($user_ids))->select();
foreach ($users as $user){
$paid_user_data[] = [
"nickname"=>$user['nickname'],
"head_image"=>$user['avatar'],
"classes_lib_id"=>$id,
"time"=>$user_ids[$user['id']],
"jointype"=>'0',
"havetype"=>'1'
];
}
}
//计算需要生成的虚拟用户数量
$v_num = 10;
$v_num = $v_num - count($user_ids);
if($v_num<0)$v_num =0;
if($v_num){
$unpaid_user = VirtualUser::where("classes_lib_id",$id)->where("havetype",'1')->order("time desc")->limit($v_num)->select();
$paid_user_data = array_merge($paid_user_data,$unpaid_user);
}
//进行昵称加*和按时间重新排序
array_multisort(array_column($unpaid_user_data, 'time'), SORT_ASC, $unpaid_user_data);
array_multisort(array_column($paid_user_data, 'time'), SORT_ASC, $paid_user_data);
foreach ($unpaid_user_data as &$userss){
//substr_replace($username, '****', 3, 4);
$userss["nickname"] = $this->nickname_filter($userss["nickname"]);
}
foreach ($paid_user_data as &$usersss){
//substr_replace($username, '****', 3, 4);
$usersss["nickname"] = $this->nickname_filter($usersss["nickname"]);
}
return compact("unpaid_user_data","paid_user_data");
}
public function nickname_filter($nickname){
$nickname_len = mb_strlen($nickname);
if($nickname_len<=2){
return $nickname;
}else{
return mb_substr($nickname,0,1).str_repeat("*",$nickname_len-2).mb_substr($nickname,-1);
}
}
/**课程规格
* @param $id
*
*/
public function spec($id){
//课程规格
$spec_data = ClassesSpec::where("classes_lib_id",$id)->where("status",'1')->order("weigh desc")->select();
return $spec_data;
}
/** 管理的课程ids
* @param $user_id
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getClassesAuthIds($user_id){
$classes_lib_ids = Verification::where("user_id",$user_id)->where("status",'1')->column("classes_lib_ids");
if($classes_lib_ids){
//遍历课程ids
foreach ($classes_lib_ids as $classes_lib_id){
$classes_lib_id_arr = explode(",",$classes_lib_id)?:[];
foreach ($classes_lib_id_arr as $v){
$this->classes_lib_ids[] = $v;
}
}
}
//判断是否有老师身份
$teacher = Teacher::where("user_id",$user_id)->find();
if($teacher){
$lib_ids = ClassesLib::where("teacher_id",$teacher['id'])->column('id');
$this->classes_lib_ids = array_merge($this->classes_lib_ids,$lib_ids);
}
$this->classes_lib_ids = array_unique($this->classes_lib_ids);
return $this->classes_lib_ids;
}
/**
* 获取所有课程列表
*/
public static function getVaildList($params) {
extract($params);
$a = (new self)->getWithAlisaName().'.';
// 查询自提点
if(isset($status) && in_array($status, ['1','2','3'])){
$selfetch = self::with(['teacher']);
}else{
$selfetch = self::with(['teacher'])->where($a.'status', '1')->where("{$a}auth_status",1);
}
$order = $order?? 'normal';
$per_page = $limit ?? 10;
$field = "{$a}id,{$a}shop_id,{$a}user_id,{$a}teacher_id,{$a}classes_cate_ids,{$a}classes_label_ids,{$a}self_label_tag,{$a}title,{$a}headimage,{$a}type,{$a}classes_date_text,{$a}classes_time_text,{$a}virtual_num,{$a}sale,{$a}price,{$a}underline_price,{$a}virtual_collect,{$a}status,{$a}auth_status,{$a}weigh,{$a}recommend,{$a}hot,{$a}new,{$a}selfhot,{$a}createtime,{$a}virtual_people,{$a}feel,{$a}limit_num,{$a}sign_num,{$a}verification_num";
//得到距离
if (isset($latitude) && isset($longitude) && $latitude && $longitude) {
$field .= ', '.getDistanceBuilder($latitude, $longitude);
}else{
$field .= ', 0 as distance';
}
//得到每个
$selfetch = $selfetch->field($field);
if (isset($keyword) && $keyword) {
$selfetch = $selfetch->where("{$a}title|{$a}address|{$a}address_detail|{$a}address_city", 'like', '%' . $keyword . '%');
}
if (isset($manystore_id) && $manystore_id) {
$selfetch = $selfetch->where("{$a}manystore_id", 'in', ''.$manystore_id);
}
if (isset($shop_id) && $shop_id) {
$selfetch = $selfetch->where("{$a}shop_id", 'in', ''.$shop_id);
}
if (isset($user_id) && $user_id) {
$selfetch = $selfetch->where("{$a}user_id", 'in', ''.$user_id);
}
if (isset($my) && $my && isset($my_user_id) && $my_user_id) {
$selfetch = $selfetch->where("{$a}user_id", 'in', ''.$my_user_id);
}
if (isset($teacher_id) && $teacher_id) {
$selfetch = $selfetch->where("{$a}teacher_id", 'in', ''.$teacher_id);
}
if (isset($type) && $type) {
$selfetch = $selfetch->where("{$a}type", 'in', ''.$type);
}
if (isset($address_type) && $address_type) {
$selfetch = $selfetch->where("{$a}address_type", 'in', ''.$address_type);
}
if (isset($recommend) && $recommend) {
$selfetch = $selfetch->where("{$a}recommend", 'in', ''.$recommend);
}
if (isset($hot) && $hot) {
$selfetch = $selfetch->where("{$a}hot", 'in', ''.$hot);
}
if (isset($new) && $new) {
$selfetch = $selfetch->where("{$a}new", 'in', ''.$new);
}
if (isset($feel) && $feel) {
$selfetch = $selfetch->where("{$a}feel", 'in', ''.$feel);
}
//区域搜索
if (isset($province) && $province) {
$selfetch = $selfetch->where("{$a}province", 'in', ''.$province);
}
if (isset($city) && $city) {
$selfetch = $selfetch->where("{$a}city", 'in', ''.$city);
}
if (isset($district) && $district) {
$selfetch = $selfetch->where("{$a}district", 'in', ''.$district);
}
if (isset($self_label_tag) && $self_label_tag) {
$self_label_tag = implode("|",explode(',',$self_label_tag));
$selfetch = $selfetch->whereRaw(" {$a}self_label_tag REGEXP '({$self_label_tag})'");
}
if (isset($classes_cate_ids) && $classes_cate_ids) {
$classes_cate_ids = implode("|",explode(',',$classes_cate_ids));
$selfetch = $selfetch->whereRaw(" {$a}classes_cate_ids REGEXP '({$classes_cate_ids})'");
}
if (isset($classes_label_ids) && $classes_label_ids) {
$classes_label_ids = implode("|",explode(',',$classes_label_ids));
$selfetch = $selfetch->whereRaw(" {$a}classes_label_ids REGEXP '({$classes_label_ids})'");
}
$collect_classes_lib_ids = [-1];
//需登录查询条件:
if(isset($my_user_id) && $my_user_id){
//得到我收藏的课程ids
$collect_classes_lib_ids = Collect::where("user_id",$my_user_id)->column("classes_lib_id");
//专查我的收藏
if(isset($collect) && $collect){
$selfetch = $selfetch->where("{$a}id","in",$collect_classes_lib_ids);
}
}
//排序
switch ($order) {
case "normal": //综合排序(推薦優先)
$selfetch = $selfetch->order("{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "distance": //距离优先 权重
$selfetch = $selfetch->order("distance asc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "hot": //熱門优先
$selfetch = $selfetch->order("{$a}hot desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "new": //平台最新优先
$selfetch = $selfetch->order("{$a}new desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "selfhot": //机构热门优先
$selfetch = $selfetch->order("{$a}selfhot desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc");
break;
case "sale": //銷量优先
$selfetch = $selfetch->order("{$a}sale desc,{$a}verification_num desc,{$a}sign_num desc,{$a}recommend desc,{$a}weigh desc");
break;
default:
throw new \Exception("不支持的排序类型");
}
if(isset($nearby) && $nearby) {
$selfetch = $selfetch->having("distance <= {$nearby}");
}
$selfetch = $selfetch->paginate($per_page);
//额外附加数据
foreach ($selfetch as $row) { //迭代器魔术方法遍历,填值自动引用传值
//设置是否已收藏
$row->is_collect = in_array($row->id,$collect_classes_lib_ids) ? 1 : 0;
}
return $selfetch;
}
public static function update_classes($classes_lib_id){
//更新课程规格库存
$classes_lib = self::get($classes_lib_id);
if($classes_lib){
//所有课时加起来
$classes_lib->limit_num = ClassesSpec::where("classes_lib_id",$classes_lib_id)->sum( "limit_num");
//更新虚拟用户数据
//得到课程所有虚拟参与者数量
$virtual_people = VirtualUser::where("jointype",'1')->where("classes_lib_id",$classes_lib_id)->count();
//如果课程虚拟参与者字段 数量小于 虚拟参与者实际数量 ,则等于虚拟参与者实际数量
$classes_lib->virtual_people = $classes_lib->virtual_people < $virtual_people ? $virtual_people : $classes_lib->virtual_people;
//得到课程所有虚拟报名者数量
$virtual_num = VirtualUser::where("havetype",'1')->where("classes_lib_id",$classes_lib_id)->count();
//如果课程虚拟报名者字段 数量小于 虚拟报名者实际数量 ,则等于虚拟报名者实际数量 havetype
$classes_lib->virtual_num = $classes_lib->virtual_num < $virtual_num ? $virtual_num : $classes_lib->virtual_num;
$classes_lib->save();
}
}
public static function add_virtual_init($classes_lib_id){
//更新课程规格库存
$classes_lib = self::get($classes_lib_id);
if($classes_lib){
//如果课程虚拟参与者字300-2000随机
$classes_lib->virtual_people = mt_rand(300, 2000);
//如果课程虚拟报名者字段
$classes_lib->virtual_num = 0;
$classes_lib->save();
//生成20个虚拟参与者
(new Virtual())->getVirtualUser(20,$classes_lib_id,time(),true);
}
}
/**设置收藏
* @param $id
* @param int $user_id
* @param int $collect 0取消收藏 1收藏
* @param bool $check
* @param bool $trans
* @throws \Exception
*/
public function collect($id,$user_id,$collect,$oper_type='user',$oper_id=0,$trans=false){
$classes_lib = self::where("id",$id)->find();
if(!$classes_lib)throw new \Exception("找不到课程!");
//判断逻辑
if($trans){
self::beginTrans();
}
try{
//事务逻辑
$where = [
"user_id"=>$user_id,
"classes_lib_id"=>$id,
"weigh"=>$classes_lib["weigh"],
];
//查询是否已收藏
$res1 = Collect::where($where)->find();
if($collect){
if(!$res1){
//未收藏,添加收藏
$res1 = new Collect();
$res1->allowField(true)->save($where);
}
}else{
//取消收藏
$res1 = Collect::where($where)->delete();
}
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
$where["is_collect"] = $collect;
return $where;
}
}