Modules_Api_Controllers_CreatorController.proxy.php 28 KB

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