Studyplan.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\wap\controller;
  12. use app\admin\model\study\Plan;
  13. use app\admin\model\study\PlanBuy;
  14. use app\admin\model\study\PlanSteps;
  15. use app\admin\model\study\PlanItems;
  16. use app\wap\model\special\Special as SpecialModel;
  17. use app\wap\model\special\SpecialWatch as SpecialWatch;
  18. use app\wap\model\special\SpecialTask;
  19. use app\admin\model\questions\Relation;
  20. use app\wap\model\topic\ExaminationRecord;
  21. use app\wap\model\topic\CertificateRelated;
  22. use app\wap\model\topic\CertificateRecord;
  23. use app\wap\model\special\SpecialSource;
  24. use app\wap\model\store\StoreOrder;
  25. use service\JsonService;
  26. use think\Url;
  27. /**商品控制器
  28. * Class Store
  29. * @package app\wap\controller
  30. */
  31. class Studyplan extends AuthController{
  32. /*
  33. * 白名单
  34. * */
  35. public static function WhiteList(){
  36. return [
  37. 'index',
  38. 'detail',
  39. ];
  40. }
  41. public function index($page = 1, $limit = 20, $op = ''){
  42. if ($op == 'list') {
  43. $model = Plan::alias('p')->where('p.is_del', 0)->page((int)$page, (int)$limit);
  44. $model = $model->join('PlanBuy pb', 'pb.uid = ' . $this->uid .' and pb.planid = p.id ', 'left');
  45. $orderList = $model->order('p.shelf_time DESC')->field('p.*, pb.id as isbuy')->select();
  46. $orderList = count($orderList) > 0 ? $orderList->toArray() : [];
  47. return JsonService::successful($orderList);
  48. }
  49. //微信支付
  50. $user_level = !$this->uid ? 0 : $this->userInfo;
  51. $this->assign('is_member', isset($user_level['level']) ? $user_level['level'] : 0);
  52. return $this->fetch();
  53. }
  54. public function details($id = 0) {
  55. if (!$id) $this->failed('缺少参数,无法访问', Url::build('index/index'));
  56. $planinfo = Plan::get($id);
  57. if (!$planinfo) $this->failed('参数错误,无法访问', Url::build('index/index'));
  58. $planinfo['introduction'] = htmlspecialchars_decode($planinfo['introduction']);
  59. $steps = PlanSteps::where('is_del', 0)->where('pid', $id)->order('sort asc')->select()->toArray();
  60. $stepids = [];
  61. $isPay = 0;
  62. $buyinfo = PlanBuy::where('planid', $id)->where('uid', $this->uid)->where('is_del', 0)->find();
  63. if ($buyinfo) {
  64. $isPay = 1;
  65. }
  66. $stepsList = [];
  67. $itemsList = [];
  68. foreach($steps as $v){
  69. $stepsList[$v['id']] = $v;
  70. $itemsList[$v['id']] = [];
  71. $stepids[] = $v['id'];
  72. }
  73. $join = [
  74. ['special s', 's.id = it.cid and s.is_del = 0 and s.status = 1']
  75. ];
  76. $items = PlanItems::alias('it')->field('s.*, it.stepsid,it.pid')
  77. ->join($join)
  78. ->where('pid', $id)
  79. ->where('stepsid', 'in', $stepids)
  80. ->order('sort asc')
  81. ->select();
  82. //$specialids = [];
  83. foreach ($items as $v) {
  84. $v['count'] = SpecialModel::numberChapters($v['type'], $v['id']);
  85. $itemsList[$v['stepsid']][] = $v->toArray();
  86. //$specialids[] = $v['id'];
  87. }
  88. //标记计划步骤是否完成学习
  89. $isopen = 1;
  90. foreach ($itemsList as $key => &$v) {
  91. $isend = 1;
  92. foreach($v as $k1 => &$v1) {
  93. //
  94. $join = [
  95. ['SpecialWatch sw', 'sw.special_id = ss.special_id and sw.task_id = ss.source_id and sw.uid = ' . $this->uid, 'left'],
  96. ];
  97. $order = 'sort desc,id desc';
  98. if ($v1['sort_order']) {
  99. $order = 'sort asc, id asc';
  100. }
  101. $specialWatchList = SpecialSource::alias('ss')->field('ss.*, sw.viewing_time,sw.percentage')
  102. ->join($join)
  103. ->where('ss.special_id', '=', $v1['id'])
  104. ->order($order)
  105. ->select();
  106. foreach($specialWatchList as $v2){
  107. $v1['tasklist'][$v2['special_id']][] = $v2->toArray();
  108. if ($v2['percentage'] < 95 && $isend == 1) $isend = 0;
  109. }
  110. //echo $isend . '---' . $v1['id'];
  111. if ($isend == 1) {
  112. //判断是否有考试
  113. $join = [
  114. ['ExaminationRecord er', 'er.test_id = r.relation_id and er.uid = ' . $this->uid, 'left'],
  115. ];
  116. $examlist = Relation::alias('r')->where('r.relationship_id', $v1['id'])->where('r.relationship', 2)
  117. ->field('r.relation_id as test_id, MAX(er.score) as score')->join($join)->group('r.relation_id')->select();
  118. if ($examlist) {
  119. foreach ($examlist as $item) {
  120. if ($item['score'] < 60) {
  121. $isend = 0;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. $stepsList[$key]['isopen'] = $isopen;
  128. if ($isend == 0) {
  129. $isopen = 0;
  130. }
  131. //$stepsList[$key]['isend'] = $isend;
  132. }
  133. $stepsList = array_values($stepsList);
  134. //微信支付相关代码
  135. $user_level = !$this->uid ? 0 : $this->userInfo;
  136. $this->assign('is_member', isset($user_level['level']) ? $user_level['level'] : 0);
  137. $this->assign('isPay', $isPay);
  138. $this->assign('steps', json_encode($stepsList));
  139. $this->assign('itemsList', json_encode($itemsList));
  140. $this->assign('planinfo', json_encode($planinfo));
  141. return $this->fetch();
  142. }
  143. /**
  144. * 创建专题支付订单
  145. * @param int $special_id 专题id
  146. * @param int $pay_type 购买类型 1=礼物,2=普通购买,3=开团或者拼团
  147. * @throws \think\db\exception\DataNotFoundException
  148. * @throws \think\db\exception\ModelNotFoundException
  149. * @throws \think\exception\DbException
  150. */
  151. public function create_order($special_id, $pay_type_num, $payType, $pinkId = 0, $total_num = 1, $link_pay_uid = 0, $from = 'weixin')
  152. {
  153. if (!$special_id) return JsonService::fail('缺少购买参数');
  154. if ($pay_type_num == -1) return JsonService::fail('选择购买方式');
  155. $Plan = Plan::where('is_del', 0)->where('is_show', 1)->find($special_id);
  156. if (!$Plan) return JsonService::status('ORDER_ERROR', '购买的学习计划不存在');
  157. $order = StoreOrder::createPlanOrder($Plan, $pinkId, $pay_type_num, $this->uid, $payType, $link_pay_uid, $total_num);
  158. $orderId = $order['order_id'];
  159. $info = compact('orderId');
  160. if ($orderId) {
  161. $orderInfo = StoreOrder::where('order_id', $orderId)->find();
  162. if (!$orderInfo || !isset($orderInfo['paid'])) return JsonService::status('pay_error', '支付订单不存在!');
  163. if ($orderInfo['paid']) return JsonService::status('pay_error', '支付已支付!');
  164. if (bcsub((float)$orderInfo['pay_price'], 0, 2) <= 0) {
  165. if (StoreOrder::jsPayPlanPrice($orderId, $this->uid))
  166. return JsonService::status('success', '支付成功', $info);
  167. else
  168. return JsonService::status('pay_error', StoreOrder::getErrorInfo());
  169. } else {
  170. switch ($payType) {
  171. case 'weixin':
  172. try {
  173. if ($from == 'weixinh5') {
  174. $jsConfig = StoreOrder::h5PlanPay($orderId);
  175. } else {
  176. $jsConfig = StoreOrder::jsPlanPay($orderId);
  177. }
  178. } catch (\Exception $e) {
  179. return JsonService::status('pay_error', $e->getMessage(), $info);
  180. }
  181. $info['jsConfig'] = $jsConfig;
  182. if ($from == 'weixinh5') {
  183. return JsonService::status('wechat_h5_pay', '订单创建成功', $info);
  184. } else {
  185. return JsonService::status('wechat_pay', '订单创建成功', $info);
  186. }
  187. break;
  188. case 'yue':
  189. if (StoreOrder::yuePlanPay($orderId, $this->uid))
  190. return JsonService::status('success', '余额支付成功', $info);
  191. else
  192. return JsonService::status('pay_error', StoreOrder::getErrorInfo());
  193. break;
  194. case 'zhifubao':
  195. $info['pay_price'] = $orderInfo['pay_price'];
  196. $info['orderName'] = '购买学习计划';
  197. return JsonService::status('zhifubao_pay', '订单创建成功', base64_encode(json_encode($info)));
  198. break;
  199. }
  200. }
  201. } else {
  202. return JsonService::fail(StoreOrder::getErrorInfo('订单生成失败!'));
  203. }
  204. }
  205. public function gotoStudy($id){
  206. if (!$id) $this->failed('缺少参数,无法访问', Url::build('index/index'));
  207. $planinfo = Plan::get($id);
  208. if (!$planinfo) $this->failed('参数错误,无法访问', Url::build('index/index'));
  209. $buyinfo = PlanBuy::where('planid', $id)->where('uid', $this->uid)->where('is_del', 0)->find();
  210. if (!$buyinfo) {
  211. $this->failed('课程尚未购买,非法访问', Url::build('index/index'));
  212. }
  213. $planinfo['introduction'] = htmlspecialchars_decode($planinfo['introduction']);
  214. $steps = PlanSteps::where('is_del', 0)->where('pid', $id)->order('sort asc')->select();
  215. foreach($steps as $v){
  216. $stepids[] = $v['id'];
  217. }
  218. $join = [
  219. ['special s', 's.id = it.cid and s.is_del = 0 and s.status = 1'],
  220. ];
  221. $items = PlanItems::alias('it')->field('s.*, it.stepsid,it.pid, it.cid')
  222. ->join($join)
  223. ->where('pid', $id)
  224. ->where('stepsid', 'in', $stepids)
  225. ->order('sort asc')
  226. ->select();
  227. //$spids = [];
  228. $itemsList = [];
  229. $tasklist = [];
  230. foreach ($items as $v) {
  231. $v['count'] = SpecialModel::numberChapters($v['type'], $v['id']);
  232. $itemsList[$v['stepsid']][] = $v->toArray();
  233. //$spids[] = $v['cid'];
  234. $join = [
  235. ['SpecialWatch sw', 'sw.special_id = ss.special_id and sw.task_id = ss.source_id and sw.uid = ' . $this->uid, 'left'],
  236. ];
  237. $order = 'sort desc,id desc';
  238. if ($v['sort_order']) {
  239. $order = 'sort asc, id asc';
  240. }
  241. $specialWatchList = SpecialSource::alias('ss')->field('ss.*, sw.viewing_time,sw.percentage')
  242. ->join($join)
  243. ->where('ss.special_id', '=', $v['cid'])
  244. ->order($order)
  245. ->select();
  246. foreach($specialWatchList as $v){
  247. $tasklist[$v['special_id']][] = $v->toArray();
  248. }
  249. }
  250. $nowspid = 0;
  251. $nowtaskid = 0;
  252. $viewing_time= 0;
  253. foreach ($itemsList as $v) {
  254. foreach ($v as $v1) {
  255. //判断课程是否学习完成
  256. if ($tasklist[$v1['id']] && is_array($tasklist[$v1['id']])) {
  257. foreach ($tasklist[$v1['id']] as $v2) {
  258. if ($v2['percentage'] < 100) {
  259. $nowspid = $v1['id'];
  260. $nowtaskid = $v2['source_id'];
  261. $viewing_time = $v2['viewing_time'];
  262. break;
  263. }
  264. }
  265. }
  266. if ($nowspid) break;
  267. //判断是否有考试
  268. $join = [
  269. ['ExaminationRecord er', 'er.test_id = r.relation_id and er.uid = ' . $this->uid, 'left'],
  270. ];
  271. $examlist = Relation::alias('r')->where('r.relationship_id', $v1['id'])->where('r.relationship', 2)
  272. ->field('r.relation_id as test_id, er.score')->join($join)->select();
  273. if ($examlist) {
  274. foreach ($examlist as $item) {
  275. if ($item['score'] < 60) {
  276. $this->redirect('wap/special/question_index', ['id' => $item['test_id'], 'planid' => $id, ]);
  277. }
  278. }
  279. }
  280. }
  281. if ($nowspid) break;
  282. }
  283. if (!$nowspid) {
  284. $nowspid = $items[0]['id'];
  285. $nowtaskid = $tasklist[$nowspid][0]['source_id'];
  286. }
  287. //id=206&specialId=37&viewing_time=0
  288. $this->redirect('wap/special/task_info', ['id' => $nowtaskid, 'specialId' => $nowspid, 'viewing_time' => $viewing_time, 'planid' => $id, ]);
  289. }
  290. /**
  291. * 购买失败删除订单
  292. * @param string $orderId 订单id
  293. * @return json
  294. * */
  295. public function del_order($orderId = '') {
  296. if (StoreOrder::where('order_id', $orderId)->update(['is_del' => 1]))
  297. return JsonService::successful();
  298. else
  299. return JsonService::fail();
  300. }
  301. /**
  302. * 学习计划检测是否达到领取证书标准
  303. * $plan_id 学习计划ID
  304. */
  305. public function inspect($plan_id = 0)
  306. {
  307. if (!$this->uid) return JsonService::fail('err');
  308. if (!$plan_id) $this->failed('缺少参数,无法访问', Url::build('index/index'));
  309. $planinfo = Plan::get($plan_id);
  310. if (!$planinfo) $this->failed('参数错误,无法访问', Url::build('index/index'));
  311. $buyinfo = PlanBuy::where('planid', $plan_id)->where('uid', $this->uid)->where('is_del', 0)->find();
  312. if (!$buyinfo) {
  313. $this->failed('课程尚未购买,非法访问', Url::build('index/index'));
  314. }
  315. //查询是否关联证书
  316. $certinfo = CertificateRelated::where(['related' => $plan_id, 'obtain' => 3, 'is_show' => 1])->find();
  317. if (!$certinfo) $this->failed('该学习计划未绑定证书');
  318. //查询是否以获得证书
  319. $certinfo = CertificateRecord::where(['source_id' => $plan_id, 'obtain' => 3, 'status' => 1, 'uid' => $this->uid])->find();
  320. if ($certinfo) $this->failed('学习计划证书已获取完成');
  321. $steps = PlanSteps::where('is_del', 0)->where('pid', $plan_id)->order('sort asc')->select();
  322. foreach($steps as $v){
  323. $stepids[] = $v['id'];
  324. }
  325. $join = [
  326. ['special s', 's.id = it.cid and s.is_del = 0 and s.status = 1'],
  327. ];
  328. $items = PlanItems::alias('it')->field('s.*, it.stepsid,it.pid, it.cid')
  329. ->join($join)
  330. ->where('pid', $plan_id)
  331. ->where('stepsid', 'in', $stepids)
  332. ->order('sort asc')
  333. ->select();
  334. //$spids = [];
  335. $flag = 1;
  336. $itemsList = [];
  337. $tasklist = [];
  338. foreach ($items as $v) {
  339. $v['count'] = SpecialModel::numberChapters($v['type'], $v['id']);
  340. $itemsList[$v['stepsid']][] = $v->toArray();
  341. //$spids[] = $v['cid'];
  342. $join = [
  343. ['SpecialWatch sw', 'sw.special_id = ss.special_id and sw.task_id = ss.source_id and sw.uid = ' . $this->uid, 'left'],
  344. ];
  345. $order = 'sort desc,id desc';
  346. if ($v['sort_order']) {
  347. $order = 'sort asc, id asc';
  348. }
  349. $specialWatchList = SpecialSource::alias('ss')->field('ss.*, sw.viewing_time,sw.percentage')
  350. ->join($join)
  351. ->where('ss.special_id', '=', $v['cid'])
  352. ->order($order)
  353. ->select();
  354. foreach($specialWatchList as $v){
  355. $tasklist[$v['special_id']][] = $v->toArray();
  356. }
  357. }
  358. $nowspid = 0;
  359. foreach ($itemsList as $v) {
  360. foreach ($v as $v1) {
  361. //判断课程是否学习完成
  362. if ($tasklist[$v1['id']] && is_array($tasklist[$v1['id']])) {
  363. foreach ($tasklist[$v1['id']] as $v2) {
  364. if ($v2['percentage'] < 100) {
  365. $nowspid = $v1['id'];
  366. $flag = 0;
  367. break;
  368. }
  369. }
  370. }
  371. if ($nowspid) break;
  372. //判断是否有考试
  373. $join = [
  374. ['ExaminationRecord er', 'er.test_id = r.relation_id and er.uid = ' . $this->uid, 'left'],
  375. ];
  376. $examlist = Relation::alias('r')->where('r.relationship_id', $v1['id'])->where('r.relationship', 2)
  377. ->field('r.relation_id as test_id, er.score')->join($join)->select();
  378. if ($examlist) {
  379. foreach ($examlist as $item) {
  380. if ($item['score'] < 60) {
  381. $flag = 0;
  382. }
  383. }
  384. }
  385. }
  386. if ($nowspid) break;
  387. }
  388. if ($flag) {
  389. return JsonService::successful('ok');
  390. } else {
  391. return JsonService::fail('err');
  392. }
  393. }
  394. /**用户领取证书
  395. * $special_id 专题ID
  396. */
  397. public function getTheCertificate($plan_id)
  398. {
  399. $res = CertificateRecord::getUserTheCertificate($plan_id, 3, $this->uid);
  400. if ($res) return JsonService::successful($res);
  401. else return JsonService::fail('领取失败');
  402. }
  403. }