AddonsCourseDirectorys.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. <?php
  2. namespace addons\Course\common\models;
  3. use common\enums\StatusEnum;
  4. use Yii;
  5. /**
  6. * This is the model class for table "{{%addons_course_directorys}}".
  7. *
  8. * @property int $id
  9. * @property int $mall_id 商城id
  10. * @property int $course_id 课程id
  11. * @property int $parent_id 父级目录ID
  12. * @property int $level 目录等级 默认1
  13. * @property string $name 目录名称
  14. * @property int $sort 目录排序
  15. * @property int $status 状态 0禁用,1启用,-1是删除
  16. * @property int $created_at
  17. * @property int $updated_at
  18. */
  19. class AddonsCourseDirectorys extends \common\models\base\BaseActiveRecord
  20. {
  21. /**
  22. * {@inheritdoc}
  23. */
  24. public static function tableName()
  25. {
  26. return '{{%addons_course_directorys}}';
  27. }
  28. /**
  29. * {@inheritdoc}
  30. */
  31. public function rules()
  32. {
  33. return [
  34. [['mall_id', 'course_id', 'name', 'parent_id'], 'required'],
  35. [['mall_id', 'course_id', 'parent_id', 'level', 'sort', 'created_at', 'updated_at'], 'integer'],
  36. [['name'], 'string', 'max' => 50],
  37. ];
  38. }
  39. public function scenarios()
  40. {
  41. return [
  42. 'addDir' => ['course_id', 'name', 'level', 'sort', 'created_at', 'updated_at'],
  43. 'addSubDir' => ['course_id', 'name', 'parent_id', 'level', 'sort', 'created_at', 'updated_at'],
  44. 'rename' => ['id', 'name'],
  45. 'default' => [],
  46. ];
  47. }
  48. /**
  49. * {@inheritdoc}
  50. */
  51. public function attributeLabels()
  52. {
  53. return [
  54. 'id' => 'ID',
  55. 'mall_id' => '商城id',
  56. 'course_id' => '课程id',
  57. 'parent_id' => '父级目录ID',
  58. 'level' => '目录等级 默认1',
  59. 'name' => '目录名称',
  60. 'sort' => '目录排序',
  61. 'status' => '状态 0禁用,1启用,-1是删除',
  62. 'created_at' => 'Created At',
  63. 'updated_at' => 'Updated At',
  64. ];
  65. }
  66. public static function setData(int $mall_id, array $data, string $scenarios = 'default')
  67. {
  68. if (!empty($data['id'])) {
  69. $model = self::findOne(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'id' => $data['id']]);
  70. if (empty($model)) {
  71. self::$static_error = '数据异常';
  72. return false;
  73. }
  74. } else {
  75. $model = new self();
  76. $model->loadDefaultValues();
  77. $model->mall_id = $mall_id;
  78. $model->status = StatusEnum::ENABLED;
  79. }
  80. $model->scenario = $scenarios;
  81. foreach ($data as $key => $val) {
  82. $model->$key = $val;
  83. }
  84. if (!$model->save()) {
  85. self::$static_error = '保存数据失败:' . $model->getErrorMessage();
  86. return false;
  87. }
  88. return $model;
  89. }
  90. /**
  91. * @name:
  92. * @msg: 获取某一个课程下的目录列表
  93. * @param {int} $mall_id
  94. * @param {int} $course_id
  95. * @param {string} $field
  96. * @return {*}
  97. */
  98. public static function getList(int $mall_id, int $course_id, string $field = '*')
  99. {
  100. $list = self::find()
  101. ->select($field)
  102. ->where(['mall_id' => $mall_id, 'course_id' => $course_id, 'status' => StatusEnum::ENABLED])
  103. ->andWhere('id != 0')
  104. ->orderBy('sort asc,created_at desc')
  105. ->asArray()
  106. ->all();
  107. return $list;
  108. }
  109. /**
  110. * @name:
  111. * @msg: 分别统计某一个课程下各个目录下的章节的数量
  112. * @param {array} $list 某一个课程下的目录列表,必须包含目录id字段,并且字段名为 id
  113. * @param {int} $mall_id
  114. * @return {*}
  115. */
  116. public static function chapterSum(array $list, int $mall_id, int $course_id)
  117. {
  118. // 目录和章节数映射
  119. // dd($list);
  120. // 课程所有目录 id
  121. if (!empty($list)) {
  122. $dir_ids = array_values(array_flip(array_flip(array_column($list, 'id', 'id'))));
  123. // dd($dir_ids, false);
  124. foreach ($dir_ids as $idk => $idv) {
  125. // 目录下的章节数量,初始化为 0
  126. $dir_chapter_sum[$idv] = 0;
  127. }
  128. // dd($dir_chapter_sum, false);
  129. $dir_chapter_info = AddonsCourseChapter::find()
  130. ->select('id,dir_id')
  131. ->where(['mall_id' => $mall_id, 'dir_id' => $dir_ids, 'course_id' => $course_id, 'status' => StatusEnum::ENABLED])
  132. ->asArray()
  133. ->all();
  134. $all_count = count($dir_chapter_info);
  135. // dd(array_unique(array_column($dir_chapter_info, 'dir_id')));
  136. // dd($dir_chapter_info);
  137. if (!empty($dir_chapter_info)) {
  138. foreach ($dir_chapter_info as $dk => $dv) {
  139. // if (empty($dir_chapter_sum[$dv['dir_id']])) {
  140. // $dir_chapter_sum[$dv['dir_id']] = 0;
  141. // }
  142. $dir_chapter_sum[$dv['dir_id']] += 1;
  143. }
  144. }
  145. // dd($dir_chapter_sum);
  146. foreach ($list as $lk => $lv) {
  147. if (!empty($dir_chapter_sum[$lv['id']])) {
  148. $list[$lk]['chapter_number'] = $dir_chapter_sum[$lv['id']];
  149. // $dir_chapter_number_map[$lv['id']] = $dir_chapter_sum[$lv['id']];
  150. } else {
  151. // $dir_chapter_number_map[$lv['id']] = 0;
  152. $list[$lk]['chapter_number'] = 0;
  153. }
  154. $tmp_list[$lv['parent_id']][] = $lv;
  155. }
  156. // dd($dir_chapter_sum);
  157. // dd($tmp_list);
  158. // 组装二级目录的树形结构
  159. $tree = $tmp_list[0];
  160. foreach ($tree as $lpk => $lpv) {
  161. foreach ($list as $lk => $lv) {
  162. if ($lpv['id'] == $lv['parent_id']) {
  163. $tree[$lpk]['sub_dir'][] = $lv;
  164. }
  165. }
  166. }
  167. // dd($tree);
  168. foreach ($tree as $trk => $trv) {
  169. $tree[$trk]['chapter_number'] = $dir_chapter_sum[$trv['id']];
  170. if (!empty($trv['sub_dir'])) {
  171. $tree[$trk]['chapter_number'] += array_sum(array_column($trv['sub_dir'], 'chapter_number'));
  172. }
  173. }
  174. // dd($tree);
  175. // 未分类的章节
  176. $no_dir_chapters = AddonsCourseChapter::find()
  177. ->where(['mall_id' => $mall_id, 'dir_id' => 0, 'course_id' => $course_id, 'status' => StatusEnum::ENABLED])
  178. ->asArray()
  179. ->all();
  180. $no_dir_count = count($no_dir_chapters);
  181. $tree[] = [
  182. 'id' => 0,
  183. 'name' => '未分类',
  184. 'course_id' => $course_id,
  185. 'parent_id' => 0,
  186. 'chapter_number' => $no_dir_count,
  187. ];
  188. // dd($tree);
  189. $res = ['all_count' => $all_count + $no_dir_count, 'tree' => $tree];
  190. } else {
  191. // dd(13213231321322331);
  192. // 当前课程没有设置目录
  193. $dir_ids = 0;
  194. $dir_chapter_info = AddonsCourseChapter::find()
  195. ->select('id,dir_id')
  196. ->where(['mall_id' => $mall_id, 'dir_id' => $dir_ids, 'course_id' => $course_id, 'status' => StatusEnum::ENABLED])
  197. ->asArray()
  198. ->all();
  199. $all_count = count($dir_chapter_info);
  200. $res = [
  201. 'all_count' => $all_count,
  202. 'tree' => [
  203. [
  204. 'id' => 0,
  205. 'name' => '未分类',
  206. 'course_id' => $course_id,
  207. 'parent_id' => 0,
  208. 'chapter_number' => $all_count,
  209. ]
  210. ],
  211. ];
  212. }
  213. return $res;
  214. }
  215. public static function getDirTreeList(int $mall_id, int $course_id, string $field = '*')
  216. {
  217. // $course_id = 1212121;
  218. $list = self::getList($mall_id, $course_id, $field);
  219. $tree_info = self::chapterSum($list, $mall_id, $course_id);
  220. return $tree_info;
  221. }
  222. /**
  223. * @name:
  224. * @msg: 获取同级最后一个目录的排序
  225. * @param {int} $mall_id
  226. * @param {int} $course_id
  227. * @param {int} $parent_id
  228. * @param {int} $level
  229. * @return {int}
  230. */
  231. public static function getLastSort(int $mall_id, int $course_id, int $parent_id, int $level): int
  232. {
  233. $prev_sort = self::find()
  234. ->select('sort')
  235. ->where(['mall_id' => $mall_id, 'course_id' => $course_id, 'parent_id' => $parent_id, 'level' => $level, 'status' => StatusEnum::ENABLED])
  236. ->orderBy('sort desc')
  237. ->limit(1)
  238. ->asArray()
  239. ->one();
  240. // dd($prev_sort);
  241. if (!empty($prev_sort['sort'])) {
  242. $sort = $prev_sort['sort'] + 1;
  243. } else {
  244. $sort = 1;
  245. }
  246. return $sort;
  247. }
  248. /**
  249. * @name:
  250. * @msg: 获取某一个目录相邻的目录的排序(上一个或者下一个)
  251. * @param {int} $id 当前目录的 id
  252. * @param {int} $course_id 课程 id
  253. * @param {int} $parent_id 父级目录 id
  254. * @param {int} $level 当前目录级别
  255. * @param {int} $type 获取目录的方向,1:上一个,2:下一个
  256. * @return {array} 包含相邻目录的id和排序的一个一维数组
  257. */
  258. public static function adjoinSort(int $id, int $mall_id, int $course_id, int $parent_id, int $level, int $type): array
  259. {
  260. // var_dump($id, $mall_id, $course_id, $parent_id, $level, $type);exit;
  261. $model = self::find()
  262. ->select('id,sort')
  263. ->where(['mall_id' => $mall_id, 'course_id' => $course_id, 'parent_id' => $parent_id, 'level' => $level, 'status' => StatusEnum::ENABLED]);
  264. $current_sort = self::getCurrentSort($mall_id, $id);
  265. // dd($current_sort);
  266. if (1 == $type) {
  267. $order = 'desc';
  268. $model->andWhere(['<', 'sort', $current_sort]);
  269. } else {
  270. $order = 'asc';
  271. $model->andWhere(['>', 'sort', $current_sort]);
  272. }
  273. $adjoin_info = $model
  274. ->orderBy('sort ' . $order . ',created_at desc')
  275. ->limit(1)
  276. ->asArray()
  277. ->one();
  278. // dd($adjoin_info);
  279. return $adjoin_info;
  280. }
  281. /**
  282. * @name:
  283. * @msg: 获取当前目录的排序
  284. * @param {int} $mall_id
  285. * @param {int} $id
  286. * @return {*}
  287. */
  288. public static function getCurrentSort(int $mall_id, int $id): int
  289. {
  290. $dir_info = self::find()
  291. ->select('sort')
  292. ->where(['mall_id' => $mall_id, 'id' => $id, 'status' => StatusEnum::ENABLED])
  293. ->limit(1)
  294. ->asArray()
  295. ->one();
  296. if (empty($dir_info)) {
  297. $sort = 1;
  298. } else {
  299. $sort = $dir_info['sort'];
  300. }
  301. return $sort;
  302. }
  303. public static function switchDirSort(int $dir_id, int $mall_id, int $sort_type) : bool
  304. {
  305. $dir_info = self::find()
  306. ->select('id,mall_id,course_id,parent_id,level')
  307. ->where(['id' => $dir_id, 'mall_id' => $mall_id])
  308. ->asArray()
  309. ->one();
  310. if (empty($dir_info)) {
  311. self::$static_error = '目录不存在';
  312. return false;
  313. }
  314. $dir_info['type'] = $sort_type;
  315. // dd($dir_info);
  316. // 相邻目录
  317. $adjoin_info = self::adjoinSort(...array_values($dir_info));
  318. // dd($adjoin_info);
  319. // 当前目录
  320. $curr_info = [
  321. 'id' => $dir_id,
  322. 'sort' => self::getCurrentSort($mall_id, $dir_id),
  323. ];
  324. // dd($curr_info);
  325. // 与相邻目录互换排序
  326. $tmp_sort = $curr_info['sort'];
  327. $curr_info['sort'] = $adjoin_info['sort'];
  328. $adjoin_info['sort'] = $tmp_sort;
  329. $transaction = \Yii::$app->db->beginTransaction();
  330. $current_params = [
  331. 'id' => $curr_info['id'],
  332. 'sort' => $curr_info['sort'],
  333. ];
  334. // 更新当前目录
  335. $curr_res = self::setData($mall_id, $current_params);
  336. if (false === $curr_res) {
  337. $transaction->rollBack();
  338. return false;
  339. }
  340. // 更新相邻目录
  341. $adjoin_params = [
  342. 'id' => $adjoin_info['id'],
  343. 'sort' => $adjoin_info['sort'],
  344. ];
  345. $adjoin_res = self::setData($mall_id, $adjoin_params);
  346. if (false === $adjoin_res) {
  347. $transaction->rollBack();
  348. return false;
  349. }
  350. $transaction->commit();
  351. return true;
  352. }
  353. }