CreatorController.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. <?php
  2. namespace Modules\Api\Controllers;
  3. use App\Constants\CreatorConstant;
  4. use App\Model\TypeModel;
  5. use App\Model\TypeVideoModel;
  6. use App\Model\VideoModel;
  7. use App\Repositories\ConfigRepoistory;
  8. use App\Repositories\CreatorRepository;
  9. use App\Repositories\CreatorRuleRepository;
  10. use App\Repositories\UserRepository;
  11. use App\Repositories\Utils\M3u8CacheRepository;
  12. use App\Repositories\Utils\MediaCenterRepository;
  13. use App\Repositories\VideoRepository;
  14. use \Hyperf\Validation\Contract\ValidatorFactoryInterface;
  15. class CreatorController extends BaseController
  16. {
  17. // 创作者中心
  18. public function center()
  19. {
  20. $result = [
  21. 'level' => 0,
  22. 'count_up' => 0, // 上架作品数.
  23. 'count_down' => 0, // 下架作品数
  24. 'count_reject' => 0, // 拒绝作品数
  25. 'count_checking' => 0, // 审核中作品数
  26. 'total_creator' => 0, // 多少创作者
  27. 'tutorial' => [],
  28. 'course' => [],
  29. 'top_week' => [], // 收益月榜单
  30. 'top_all' => [], // 收益总计榜单
  31. 'upload_is_maintenance' => false, // 上传是否维护中
  32. 'upload_maintenance_desc' => '', // 上传维护描述信息
  33. ];
  34. $userCode = $this->getUserId();
  35. $userRepo = make(UserRepository::class);
  36. $userInfo = $userRepo->getUserInfoFromCache($userCode);
  37. $creatorRepo = make(CreatorRepository::class);
  38. $configRepo = make(ConfigRepoistory::class);
  39. $detail = $creatorRepo->detail($userCode);
  40. $level = 0;
  41. if (!empty($detail)) {
  42. $level = intval($detail->level);
  43. }
  44. $countUp = $creatorRepo->countVideoByStatusType($userCode, 'up');
  45. $countDown = $creatorRepo->countVideoByStatusType($userCode, 'down');
  46. $countReject = $creatorRepo->countVideoByStatusType($userCode, 'reject');
  47. $countChecking = $creatorRepo->countVideoByStatusType($userCode, 'checking');
  48. $totalCreator = $creatorRepo->countCreator();
  49. // 攻略
  50. $tutorial = [
  51. [
  52. 'cover' => '',
  53. 'title' => '剪辑创作技巧',
  54. 'scheme' => 'url://',
  55. 'link' => 'http://h5.py163.xyz/'. env('STATIC_DIR_NAME') .'/creator/jiqiao.html',
  56. ],
  57. [
  58. 'cover' => '',
  59. 'title' => '剪辑工具推荐',
  60. 'scheme' => 'url://',
  61. 'link' => 'http://h5.py163xyz/'. env('STATIC_DIR_NAME') .'/creator/gongju.html',
  62. ],
  63. ];
  64. // 教程出品
  65. $course = [
  66. [
  67. 'cover' => '',
  68. 'title' => '如何利用视频盈利',
  69. 'scheme' => 'url://',
  70. 'link' => 'http://h5.py163xyz/'. env('STATIC_DIR_NAME') .'/creator/zhuanqian.html',
  71. ],
  72. [
  73. 'cover' => '',
  74. 'title' => '如何直走高质量视频',
  75. 'scheme' => 'url://',
  76. 'link' => 'http://h5.py163xyz/'. env('STATIC_DIR_NAME') .'/creator/tigao.html',
  77. ],
  78. ];
  79. $result['level'] = $level;
  80. $result['count_up'] = $countUp;
  81. $result['count_down'] = $countDown;
  82. $result['count_reject'] = $countReject;
  83. $result['count_checking'] = $countChecking;
  84. $result['total_creator'] = $totalCreator;
  85. $result['tutorial'] = $tutorial;
  86. $result['course'] = $course;
  87. $topWeekItems = $creatorRepo->getTopIncome('week', 5, false);
  88. $topAllItems = $creatorRepo->getTopIncome('all', 5, false);
  89. // TODO 过段时间,换成上面真实的数据.
  90. // $topWeekItems = $creatorRepo->fakeTopIncome('week', true);
  91. // $topAllItems = $creatorRepo->fakeTopIncome('all', true);
  92. if (!empty($topWeekItems)) {
  93. foreach ($topWeekItems as &$v) {
  94. $v['avatar'] = M3u8CacheRepository::getImageUrl($v['avatar']);
  95. }
  96. }
  97. if (!empty($topAllItems)) {
  98. foreach ($topAllItems as &$v) {
  99. $v['avatar'] = M3u8CacheRepository::getImageUrl($v['avatar']);
  100. }
  101. }
  102. $result['top_week'] = !empty($topWeekItems) ? $topWeekItems : [];
  103. $result['top_all'] = !empty($topAllItems) ? $topAllItems : [];
  104. if (isset($userInfo['is_vip']) && $userInfo['is_vip'] != 'y') {
  105. $result['upload_is_maintenance'] = true;
  106. $result['upload_maintenance_desc'] = '会员VIP才可以上传视频赚钱哦!';
  107. }
  108. $arrConfig = $configRepo->gets(['upload_maintenance_status', 'upload_maintenance_desc'], 'sys', []);
  109. if (isset($arrConfig['upload_maintenance_status']) && intval($arrConfig['upload_maintenance_status']) == 1) {
  110. $result['upload_is_maintenance'] = true;
  111. $result['upload_maintenance_desc'] = $arrConfig['upload_maintenance_desc'] ?? '上传维护中,请稍后恢复再试';
  112. }
  113. return json_success($result);
  114. }
  115. //等级中心
  116. public function levelCenter()
  117. {
  118. $validatorFactory = make(ValidatorFactoryInterface::class);
  119. $userCode = $this->getUserId();
  120. $userRepo = make(UserRepository::class);
  121. $arrUserInfo = $userRepo->getUserInfoData($userCode);
  122. $ruleRepo = make(CreatorRuleRepository::class);
  123. $creatorRepo = make(CreatorRepository::class);
  124. $detail = $creatorRepo->detail($userCode);
  125. $income = 0; // 当前收入, 提现会从累计里扣除算出来的.
  126. $totalIncome = 0; // 累计收入
  127. $level = 0;
  128. $dayAddonNum = 0;
  129. if (!empty($detail)) {
  130. $income = floatval($detail->income);
  131. $totalIncome = floatval($detail->total_income);
  132. $level = intval($detail->level);
  133. $dayAddonNum = intval($detail->day_addon_num);
  134. }
  135. $ruleTable = $ruleRepo->getRules();
  136. $level0Rule = $ruleTable[0];
  137. if (!empty($ruleTable)) {
  138. foreach ($ruleTable as &$v) {
  139. $v['day_addon_num'] = $dayAddonNum;
  140. unset($v['deduction_scale']);
  141. }
  142. }
  143. $ruleText = <<<EOT
  144. 1.申请创作者需上传并审核通过上架%s部短视频;
  145. 2.视频总收益满足条件即可升级;
  146. 3.未认证用户分成比例为%s%%;
  147. 4.一旦发现上传的视频不符合规则或滥竽充数,则取消创作者资格;
  148. 5.上传视频依据创作者等级有不同数量限制,每日上传限制于每日零点清除重计。
  149. 6.视频出售获得的金币会自动转化成现金收益(可在我的钱包-账单-现金明细里查看),10金币=1元。
  150. 7.邀请可以永久增加每日上传次数限制,邀请3人--增加1次,10人--2次,30人--3次,80人--5次,120人--6次,200人--9次
  151. EOT;
  152. $ruleText = sprintf($ruleText, CreatorConstant::LEVEL0_1_VIDEO_NUM, $level0Rule['commission_ratio']);
  153. $ruleText = trim($ruleText);
  154. $result = [
  155. 'user_code' => $userCode,
  156. 'nick' => !empty($detail->user->nick) ? $detail->user->nick : '',
  157. 'total_income' => $totalIncome,
  158. 'level' => $level,
  159. 'published_video' => $creatorRepo->countPublishedVideo($userCode),
  160. 'require_video' => CreatorConstant::APPLY_REQUIRE_VIDEO,
  161. 'total_like' => $creatorRepo->sumLikedVideo($userCode),
  162. 'require_like' => CreatorConstant::APPLY_REQUIRE_LIKE,
  163. 'rule_text' => $ruleText,
  164. 'rule_table' => $ruleTable,
  165. ];
  166. return json_success($result);
  167. }
  168. // 申请创作者
  169. public function apply()
  170. {
  171. $userCode = $this->getUserId();
  172. $userRepo = make(UserRepository::class);
  173. $arrUserInfo = $userRepo->getUserInfoData($userCode);
  174. $ruleRepo = make(CreatorRuleRepository::class);
  175. $creatorRepo = make(CreatorRepository::class);
  176. $detail = $creatorRepo->detail($userCode);
  177. $level = 0;
  178. if (!empty($detail)) {
  179. $level = intval($detail->level);
  180. }
  181. if ($level != 0) {
  182. return json_fail('您已经是创作者了,无需再申请');
  183. } else {
  184. if (!empty($detail)) {
  185. if ($detail->status == 3) {
  186. return json_fail('请耐心等待,正在审核中,如需加急请联系客服');
  187. } elseif ($detail->status == 2) {
  188. return json_fail('申请已被拒绝');
  189. }
  190. }
  191. }
  192. $publishedVideo = $creatorRepo->countPublishedVideo($userCode);
  193. if ($publishedVideo < CreatorConstant::APPLY_REQUIRE_VIDEO) {
  194. return json_fail('作品数不足', 6001);
  195. }
  196. $creatorRepo->applyToUncheck($userCode);
  197. return json_success(['result' => 'success', 'msg' => '申请成功,等待审核']);
  198. }
  199. // 我的审核视频列表
  200. public function videoPages()
  201. {
  202. $validatorFactory = make(ValidatorFactoryInterface::class);
  203. $userCode = $this->getUserId();
  204. $userRepo = make(UserRepository::class);
  205. $inputData = $this->getJsonData();
  206. $rules = [
  207. 'status_type' => 'required|in:up,down,check',
  208. 'page' => 'nullable|int',
  209. 'page_size' => 'nullable|int',
  210. ];
  211. $validator = $validatorFactory->make($inputData, $rules);
  212. if ($validator->fails()) {
  213. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  214. return json_fail($validator->errors()->first());
  215. }
  216. $statusType = data_get($inputData, 'status_type', '');
  217. $page = format_page(data_get($inputData, 'page', 1));
  218. $pageSize = intval(data_get($inputData, 'page_size', 10));
  219. if ($pageSize > 20) {
  220. $pageSize = 20;
  221. }
  222. $creatorRepo = make(CreatorRepository::class);
  223. $lists = $creatorRepo->videoPages($userCode, $statusType, $page, $pageSize);
  224. $arrLists = $lists->toArray();
  225. if (!empty($arrLists['data'])) {
  226. foreach ($arrLists['data'] as &$v) {
  227. $oldMu = $v['mu'];
  228. $v['mu'] = '';
  229. $v['cover'] = M3u8CacheRepository::getImageUrl($v['cover']);
  230. $videoStatus = intval($v['status']);
  231. $videoCheck = intval($v['check']);
  232. $income = 0.00;
  233. $totalBuy = 0;
  234. $v['status_text'] = '未知状态';
  235. if ($videoStatus == 1 && $videoCheck == 1) {
  236. $v['status_text'] = '上架';
  237. $v['mu'] = M3u8CacheRepository::getVideoInnerUrl($oldMu, $userCode, $v['id'], 'video');
  238. $incomeData = $creatorRepo->oneVideoIncome($userCode, $v['id']);
  239. $income = isset($incomeData['sum']) ? $incomeData['sum'] : 0;
  240. $totalBuy = $creatorRepo->countVideoBuyer($v['id']);
  241. } elseif ($videoStatus == 2 && $videoCheck == 1) {
  242. $v['status_text'] = '下架';
  243. $incomeData = $creatorRepo->oneVideoIncome($userCode, $v['id']);
  244. $income = isset($incomeData['sum']) ? $incomeData['sum'] : 0;
  245. $totalBuy = $creatorRepo->countVideoBuyer($v['id']);
  246. } elseif ($videoCheck == 0) {
  247. $v['status_text'] = '审核中';
  248. $v['cover'] = '';
  249. if ($videoStatus == 3) {
  250. $v['status_text'] = '转码中';
  251. } elseif ($videoStatus == 4) {
  252. $v['status_text'] = '转码失败';
  253. }
  254. } elseif ($videoCheck == 2) {
  255. $v['status_text'] = '拒绝';
  256. } else {
  257. $v['cover'] = '';
  258. }
  259. $v['income'] = $income; // 收益.
  260. $v['total_buy'] = $totalBuy; // 购买人次
  261. }
  262. }
  263. return json_success($arrLists);
  264. }
  265. public function todayVideo()
  266. {
  267. $userCode = $this->getUserId();
  268. $userRepo = make(UserRepository::class);
  269. $arrUserInfo = $userRepo->getUserInfoData($userCode);
  270. $ruleRepo = make(CreatorRuleRepository::class);
  271. $creatorRepo = make(CreatorRepository::class);
  272. $detail = $creatorRepo->detail($userCode);
  273. $income = 0;
  274. $level = 0;
  275. $dayAddonNum = 0;
  276. $dayVideo = 0;
  277. if (!empty($detail)) {
  278. $income = floatval($detail->income);
  279. $level = intval($detail->level);
  280. $dayAddonNum = intval($detail->day_addon_num);
  281. $dayVideo = intval($detail->day_video);
  282. }
  283. $ruleLevel = $ruleRepo->getRuleByLevel($level);
  284. $dayMaxVideo = intval($ruleLevel->day_max_video) + $dayAddonNum;
  285. $todayVideo = $dayVideo;
  286. $isCanUpload = true;
  287. if ($todayVideo >= $dayMaxVideo) {
  288. $isCanUpload = false;
  289. }
  290. $isCanUploadCoin = isset($detail->coin_uper) ? boolval($detail->coin_uper) : false; // 是否能传收费视频
  291. $needUploadFreeNum = 0; // 还需要上传免费视频个数.
  292. $countFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, true); // 统计免费视频个数
  293. $countNotFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, false); //统计收费视频个数
  294. if ($level <= 0) {
  295. if (CreatorConstant::LEVEL_0_FREE_VIDEO_NUM > 0) {
  296. // 金币视频 x 免费要求 = 最低历史上传免费个数
  297. $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::LEVEL_0_FREE_VIDEO_NUM : CreatorConstant::LEVEL_0_FREE_VIDEO_NUM;
  298. if ($countFreeVideos >= $leastFreeNum) {
  299. $isCanUploadCoin = true;
  300. } else {
  301. $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
  302. }
  303. } else {
  304. $isCanUploadCoin = true;
  305. }
  306. } else {
  307. if (CreatorConstant::FREE_VIDEO_NUM > 0) {
  308. // 金币视频 x 免费要求 = 最低限制上传免费个数
  309. $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::FREE_VIDEO_NUM : CreatorConstant::FREE_VIDEO_NUM;
  310. if ($countFreeVideos >= $leastFreeNum) {
  311. $isCanUploadCoin = true;
  312. } else {
  313. $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
  314. }
  315. } else {
  316. $isCanUploadCoin = true;
  317. }
  318. }
  319. // $todayideo = $creatorRepo->countTodayPublishedVideo($userCode);
  320. $result = [
  321. 'level' => $level,
  322. 'day_max_video' => $dayMaxVideo,
  323. 'commission_ratio' => $ruleLevel->commission_ratio,
  324. 'today_video' => $todayVideo, // 计划任务每日凌晨3点清零一次.
  325. 'is_can_upload' => $isCanUpload, // 今天是否能上传.
  326. 'is_can_upload_coin' => $isCanUploadCoin,
  327. 'need_upload_free_num' => $needUploadFreeNum,
  328. 'count_free_videos' => $countFreeVideos,
  329. 'count_not_free_videos' => $countNotFreeVideos,
  330. ];
  331. // TODO
  332. // $result['is_can_upload'] = false;
  333. // $result['is_can_upload_coin'] = false;
  334. return json_success($result);
  335. }
  336. public function createVideo()
  337. {
  338. // TODO
  339. // return json_fail('视频服务器正在扩容,预计2022-04-25日晚间恢复');
  340. $validatorFactory = make(ValidatorFactoryInterface::class);
  341. $userCode = $this->getUserId();
  342. $userRepo = make(UserRepository::class);
  343. $userInfo = $userRepo->getUserInfoFromCache($userCode);
  344. if (isset($userInfo['is_vip']) && $userInfo['is_vip'] != 'y') {
  345. return json_fail('会员VIP才可以上传视频赚钱哦!');
  346. }
  347. $inputData = $this->getJsonData();
  348. $rules = [
  349. 'title' => 'required',
  350. 'cover' => 'nullable|max:700',
  351. 'coins' => 'required|int',
  352. 'tags' => 'required', // 这个是ID
  353. 'file_hash' => 'required'
  354. ];
  355. $validator = $validatorFactory->make($inputData, $rules);
  356. if ($validator->fails()) {
  357. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  358. return json_fail($validator->errors()->first());
  359. }
  360. $videoRepo = make(VideoRepository::class);
  361. if ($videoRepo->checkExist($inputData['file_hash'])) {
  362. return json_fail('此视频已被其他人上传过,请重新更换');
  363. }
  364. $mediaCenterRepo = make(MediaCenterRepository::class);
  365. $hashVideoInfo = $mediaCenterRepo->getHashInfo($inputData['file_hash']);
  366. if (!empty($hashVideoInfo)) {
  367. return json_fail('此视频有人上传过了,请重新更换');
  368. }
  369. $ruleRepo = make(CreatorRuleRepository::class);
  370. $creatorRepo = make(CreatorRepository::class);
  371. $detail = $creatorRepo->detail($userCode);
  372. $level = 0;
  373. $dayAddonNum = 0;
  374. $dayVideo = 0;
  375. if (!empty($detail)) {
  376. $level = intval($detail->level);
  377. $dayAddonNum = intval($detail->day_addon_num);
  378. $dayVideo = intval($detail->day_video);
  379. } else {
  380. // 自动申请为原创者.
  381. $detail = $creatorRepo->applyToUncheck($userCode);
  382. $level = intval($detail->level);
  383. }
  384. $ruleLevel = $ruleRepo->getRuleByLevel($level);
  385. $dayMaxVideo = intval($ruleLevel->day_max_video) + $dayAddonNum;
  386. $todayVideo = !empty($detail) ? $dayVideo : 0;
  387. if ($todayVideo >= $dayMaxVideo) {
  388. return json_fail('今日已经超出上传数量限制');
  389. }
  390. $cover = data_get($inputData, 'cover', '');
  391. $coins = intval(data_get($inputData, 'coins', 0)); // 金币,单位数量个,10金币=1元人民币
  392. $uploadingUrl = ''; // TODO,这里可以做一个固定视频,等待用户上传转码中.
  393. if ($coins < 0) {
  394. $coins = 0;
  395. }
  396. if ($coins > CreatorConstant::VIDEO_SELL_MAX_COIN) {
  397. return json_fail('售卖金币价格太大,可以提前联系客服');
  398. }
  399. $arrTagIds = [];
  400. $tmpTagIds = data_get($inputData, 'tags', '');
  401. if (is_string($tmpTagIds)) {
  402. $arrTagIds = explode(',', $tmpTagIds);
  403. } else {
  404. $arrTagIds = $tmpTagIds;
  405. }
  406. if (!empty($arrTagIds)) {
  407. $arrTagIds = array_filter($arrTagIds);
  408. $arrTagIds = array_unique($arrTagIds);
  409. }
  410. if (empty($arrTagIds)) {
  411. return json_fail('请选择至少1个口味');
  412. }
  413. if (count($arrTagIds) > CreatorConstant::VIDEO_TAG_MAX_NUM) {
  414. return json_fail('最多选择'. strval(CreatorConstant::VIDEO_TAG_MAX_NUM) .'个口味');
  415. }
  416. // 处理关联标签.
  417. $tagIdsRaltion = [];
  418. $tagNames = [];
  419. if (!empty($arrTagIds)) {
  420. foreach ($arrTagIds as $v) {
  421. $tagObj = TypeModel::query()->where('id', $v)->first();
  422. if (!empty($tagObj->id)) {
  423. $tagIdsRaltion[] = $tagObj->id;
  424. $tagNames[] = $tagObj->title;
  425. }
  426. }
  427. }
  428. $isCanUploadCoin = isset($detail->coin_uper) ? boolval($detail->coin_uper) : false; // 是否能传收费视频
  429. $needUploadFreeNum = 0; // 还需要上传免费视频个数.
  430. $countFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, true); // 统计免费视频个数
  431. $countNotFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, false); //统计收费视频个数
  432. if ($level <= 0) {
  433. if (CreatorConstant::LEVEL_0_FREE_VIDEO_NUM > 0) {
  434. // 金币视频 x 免费要求 = 最低历史上传免费个数
  435. $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::LEVEL_0_FREE_VIDEO_NUM : CreatorConstant::LEVEL_0_FREE_VIDEO_NUM;
  436. if ($countFreeVideos >= $leastFreeNum) {
  437. $isCanUploadCoin = true;
  438. } else {
  439. $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
  440. }
  441. } else {
  442. $isCanUploadCoin = true;
  443. }
  444. } else {
  445. if (CreatorConstant::FREE_VIDEO_NUM > 0) {
  446. // 金币视频 x 免费要求 = 最低限制上传免费个数
  447. $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::FREE_VIDEO_NUM : CreatorConstant::FREE_VIDEO_NUM;
  448. if ($countFreeVideos >= $leastFreeNum) {
  449. $isCanUploadCoin = true;
  450. } else {
  451. $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
  452. }
  453. } else {
  454. $isCanUploadCoin = true;
  455. }
  456. }
  457. if ($coins > 0 && !$isCanUploadCoin) {
  458. return json_fail('还不能上传收费视频,请先再传'. strval($needUploadFreeNum) . '个免费视频');
  459. }
  460. $payType = 2; // 默认金币
  461. if ($coins == 0) {
  462. $payType = 1; // vip
  463. }
  464. $newStrTagNames = !empty($tagNames) ? implode(',', $tagNames) : '';
  465. $newStrTagIds = !empty($arrTagIds) ? implode(',', $arrTagIds) : '';
  466. $setarr = [
  467. 'uid' => $userCode,
  468. 'status' => 3,
  469. 'check' => 0,
  470. 'pay_type' => $payType,
  471. 'type' => 1,
  472. 'mu' => $uploadingUrl,
  473. 'title' => trim(data_get($inputData, 'title', '')),
  474. 'cover' => $cover,
  475. 'coins' => $coins,
  476. 'tags' => $newStrTagNames,
  477. 'file_hash' => data_get($inputData, 'file_hash', ''),
  478. 'custom_cover' => $cover, // 用户自定义封面.
  479. ];
  480. $videoObj = VideoModel::query()->create($setarr);
  481. if ($videoObj) {
  482. $videoId = $videoObj->id;
  483. if (!empty($tagIdsRaltion)) {
  484. foreach ($tagIdsRaltion as $tagId) {
  485. $setarr2 = [
  486. 'type_id' => $tagId,
  487. 'video_id' => $videoId,
  488. 'status' => 1,
  489. ];
  490. TypeVideoModel::query()->create($setarr2);
  491. }
  492. }
  493. // 累加今日上传视频数量.
  494. $detail->day_video++;
  495. $detail->save();
  496. } else {
  497. return json_fail('创建视频失败');
  498. }
  499. $result = [
  500. 'video' => [
  501. 'id' => $videoObj->id, // 给前端的。前端拿到这个, 拼接 app应用全称(媒资库里定义的)| 模块名 | 视频ID ,doukui|video|video_id
  502. 'title' => $setarr['title'],
  503. 'coins' => $setarr['coins'],
  504. 'cover' => '', // 这里ppvod的是暴露的jpg路径,不能用,直接访问空字符串
  505. 'tag_names' => $newStrTagNames,
  506. 'tag_ids' => $newStrTagIds,
  507. ],
  508. ];
  509. return json_success($result);
  510. }
  511. /**
  512. * 上传设置描述
  513. * @return array
  514. */
  515. public function uploadSetting()
  516. {
  517. $configRepo = make(ConfigRepoistory::class);
  518. $creatorRepo = make(CreatorRepository::class);
  519. $userCode = $this->getUserId();
  520. $detail = $creatorRepo->detail($userCode);
  521. $level = 0;
  522. if (!empty($detail)) {
  523. $level = intval($detail->level);
  524. }
  525. $fileMaxSizeMb = CreatorConstant::VIDEO_MAX_SIZE_MB; // 文件最大多少MB
  526. $maxCoin = CreatorConstant::VIDEO_SELL_MAX_COIN; // 最多设置金币个数
  527. $creatorMinVideoNum = CreatorConstant::FREE_VIDEO_NUM; // 创作者,level>0
  528. $normalMinVideoNum = CreatorConstant::LEVEL_0_FREE_VIDEO_NUM; // 普通人, level=0
  529. $maxTagNum = CreatorConstant::VIDEO_TAG_MAX_NUM; // 最多选择标签个数.
  530. $agreementLink = 'http://h5.py163xyz/'. env('STATIC_DIR_NAME') .'/creator/upload_agreement.html';
  531. $tags = $creatorRepo->canUseTags();
  532. $ppvodParams = $configRepo->gets(['ppvod_upload_category', 'ppvod_upload_tpl_id', 'ppvod_upload_tpl_name'], 'sys', []);
  533. $isCanUploadCoin = isset($detail->coin_uper) ? boolval($detail->coin_uper) : false; // 是否能传收费视频
  534. $needUploadFreeNum = 0; // 还需要上传免费视频个数.
  535. $countFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, true); // 统计免费视频个数
  536. $countNotFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, false); //统计收费视频个数
  537. if ($level <= 0) {
  538. if (CreatorConstant::LEVEL_0_FREE_VIDEO_NUM > 0) {
  539. // 金币视频 x 免费要求 = 最低历史上传免费个数
  540. $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::LEVEL_0_FREE_VIDEO_NUM : CreatorConstant::LEVEL_0_FREE_VIDEO_NUM;
  541. if ($countFreeVideos >= $leastFreeNum) {
  542. $isCanUploadCoin = true;
  543. } else {
  544. $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
  545. }
  546. } else {
  547. $isCanUploadCoin = true;
  548. }
  549. } else {
  550. if (CreatorConstant::FREE_VIDEO_NUM > 0) {
  551. // 金币视频 x 免费要求 = 最低限制上传免费个数
  552. $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::FREE_VIDEO_NUM : CreatorConstant::FREE_VIDEO_NUM;
  553. if ($countFreeVideos >= $leastFreeNum) {
  554. $isCanUploadCoin = true;
  555. } else {
  556. $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
  557. }
  558. } else {
  559. $isCanUploadCoin = true;
  560. }
  561. }
  562. $coverDesc = <<<EOT
  563. 1. 封面可以选,若不上传则以第一帧为封面。推荐你自己上传封面,更吸引用户.
  564. 2. 视频小于%sM
  565. 3. 视频暂不限制时长.
  566. 4. 视频不可带有广告性质水印!
  567. EOT;
  568. $coverDesc = sprintf($coverDesc, $fileMaxSizeMb);
  569. $coverDesc = trim($coverDesc);
  570. $priceDesc = <<<EOT
  571. 1. 为维护观看体验,视频金币价格不得超过%s个金币.
  572. 2. 创作者每上传%s个免费视频(审核通过并上架才算),即可上传一个收费视频.
  573. 3. 普通用户上传%s个免费视频,可上传一个收费视频.
  574. EOT;
  575. $priceDesc = sprintf($priceDesc, $maxCoin, $creatorMinVideoNum, $normalMinVideoNum);
  576. $priceDesc = trim($priceDesc);
  577. $result = [
  578. 'cover_desc' => $coverDesc,
  579. 'price_desc' => $priceDesc,
  580. 'file_max_size_mb' => $fileMaxSizeMb,
  581. 'max_coin' => $maxCoin,
  582. 'creator_min_video_num' => $creatorMinVideoNum,
  583. 'normal_min_video_num' => $normalMinVideoNum,
  584. 'max_tag_num' => $maxTagNum,
  585. 'tags' => $tags,
  586. 'agreement_link' => $agreementLink,
  587. 'is_can_upload_coin' => $isCanUploadCoin,
  588. 'need_upload_free_num' => $needUploadFreeNum,
  589. 'count_free_videos' => $countFreeVideos,
  590. 'count_not_free_videos' => $countNotFreeVideos,
  591. 'ppvod_upload_category' => !empty($ppvodParams['ppvod_upload_category']) ? $ppvodParams['ppvod_upload_category'] : '用户上传',
  592. 'ppvod_upload_tpl_id' => !empty($ppvodParams['ppvod_upload_tpl_id']) ? $ppvodParams['ppvod_upload_tpl_id'] : '',
  593. 'ppvod_upload_tpl_name' => !empty($ppvodParams['ppvod_upload_tpl_name']) ? $ppvodParams['ppvod_upload_tpl_name'] : '默认',
  594. ];
  595. // TODO
  596. // $result['file_max_size_mb'] = 1;
  597. return json_success($result);
  598. }
  599. /**
  600. * 删除视频.
  601. * @return mixed
  602. * @throws \Exception
  603. */
  604. public function deleteVideo()
  605. {
  606. $creatorRepo = make(CreatorRepository::class);
  607. $validatorFactory = make(ValidatorFactoryInterface::class);
  608. $userCode = $this->getUserId();
  609. $inputData = $this->getJsonData();
  610. $rules = [
  611. 'video_id' => 'required',
  612. 'force_state' => 'nullable|in:yes,no'
  613. ];
  614. $validator = $validatorFactory->make($inputData, $rules);
  615. if ($validator->fails()) {
  616. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  617. return json_fail($validator->errors()->first());
  618. }
  619. $isForce = false;
  620. $videoId = data_get($inputData, 'video_id', '');
  621. $forceState = data_get($inputData, 'force_state', 'no');
  622. if ($forceState == 'yes') {
  623. $isForce = true;
  624. }
  625. $deleteStatus = $creatorRepo->deleteVideo($userCode, $videoId, $isForce);
  626. if (!$deleteStatus) {
  627. return json_fail('删除失败,请联系管理员');
  628. }
  629. return json_success(['result' => 'success']);
  630. }
  631. }