VoiceService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <?php
  2. namespace App\Services\Goodnight;
  3. use App\Exceptions\AlertException;
  4. use App\Exceptions\DBException;
  5. use App\Models\Goodnight\SubscribeModel;
  6. use App\models\Goodnight\SystemTagModel;
  7. use App\Models\Goodnight\TagModel;
  8. use App\Models\Goodnight\ThumbModel;
  9. use App\Models\Goodnight\VoiceModel;
  10. use App\Models\User\UserModel;
  11. use App\Services\Service;
  12. use Illuminate\Support\Facades\DB;
  13. use Illuminate\Support\Facades\Redis;
  14. class VoiceService extends Service
  15. {
  16. public function create(array $data): int
  17. {
  18. $user = UserModel::find($data['uid']);
  19. $data['sex'] = $user->sex;
  20. $vModel = new VoiceModel();
  21. $voice = $vModel->fill($data);
  22. if ($voice->save()) {
  23. return $voice->id;
  24. } else {
  25. throw new DBException("数据库异常", 501);
  26. }
  27. }
  28. /**
  29. * 删除声音
  30. * @param int $uid
  31. * @param int $voice_id
  32. * @return bool
  33. * @throws DBException
  34. * @throws AlertException
  35. */
  36. public function delete(int $uid, int $voice_id): bool
  37. {
  38. $vModel = new VoiceModel();
  39. $voice = $vModel->findOrFail($voice_id);
  40. if ($uid != $voice->uid) {
  41. throw new AlertException("权限不足", 403);
  42. }
  43. if ($voice->delete()) {
  44. return true;
  45. } else {
  46. throw new DBException("数据库异常", 501);
  47. }
  48. }
  49. /**
  50. * 点赞声音
  51. * @param int $uid
  52. * @param int $voice_id
  53. * @return bool
  54. * @throws AlertException
  55. * @throws DBException
  56. */
  57. public function thumb(int $uid, int $voice_id)
  58. {
  59. $voice = VoiceModel::findOrFail($voice_id);
  60. if ($voice->uid == $uid) {
  61. throw new AlertException("不能点赞自己", 403);
  62. }
  63. if (
  64. ThumbModel::where([
  65. ['voice_id', $voice->id],
  66. ['uid', $uid],
  67. ])->exists()
  68. ) {
  69. throw new AlertException("你已经点过赞", 410);
  70. }
  71. $vuser = \App\Models\Goodnight\UserModel::find($voice->uid);
  72. $headimgurls = json_decode($vuser->get_like_headimgurl, true) ?? [];
  73. $user = UserModel::find($uid);
  74. array_unshift($headimgurls, $user->headimgurl);
  75. $headimgurls = array_slice($headimgurls, 0, 3);
  76. \DB::beginTransaction();
  77. try {
  78. DB::table('kdgx_goodnight_voice_thumb')->insert([
  79. 'created_at' => time(),
  80. 'updated_at' => time(),
  81. 'voice_id' => $voice->id,
  82. 'uid' => $uid,
  83. ]);
  84. VoiceModel::where('id', $voice->id)->increment('like', 1);
  85. \DB::table('kdgx_goodnight_user')->where('uid', $voice->uid)->increment('get_like', 1);
  86. \DB::table('kdgx_goodnight_user')->where('uid', $voice->uid)->increment('gnight_coin', 1);
  87. \DB::table('kdgx_goodnight_user')->where('uid', $voice->uid)->update([
  88. 'get_like_headimgurl' => json_encode($headimgurls),
  89. ]);
  90. \DB::commit();
  91. return true;
  92. } catch (\Exception $e) {
  93. \DB::rollBack();
  94. throw new DBException("数据库异常", 500);
  95. }
  96. }
  97. /**
  98. * 标记声音
  99. * @param int $uid
  100. * @param array $data
  101. * @return bool
  102. * @throws AlertException
  103. * @throws DBException
  104. */
  105. public function tag(int $uid, array $data)
  106. {
  107. $add_gnight_coin = 0;
  108. $voice = VoiceModel::findOrFail($data['voice_id']);
  109. if ($voice->uid == $uid) {
  110. throw new AlertException("不能标记自己", 201);
  111. }
  112. if (
  113. $uid != 0 && TagModel::where([
  114. ['voice_id', $voice->id],
  115. ['uid', $uid],
  116. ])->exists()
  117. ) {
  118. throw new AlertException("你已经标记过", 203);
  119. }
  120. $tags = json_decode(empty($voice->tags) ? json_encode([]) : $voice->tags, true);
  121. if (isset($tags[$data['tag']])) {
  122. $tags[$data['tag']] += 1;
  123. } else {
  124. $tags[$data['tag']] = 1;
  125. }
  126. \DB::beginTransaction();
  127. try {
  128. if (!TagModel::where('uid', $uid)->where('created_at', '>', mktime(0, 0, 0))->exists()) {
  129. \DB::table('kdgx_goodnight_user')->where('uid', $uid)->increment('gnight_coin', 2);
  130. $add_gnight_coin = 2;
  131. }
  132. TagModel::create([
  133. 'voice_id' => $voice->id,
  134. 'uid' => $uid,
  135. 'tag' => $data['tag'],
  136. ]);
  137. VoiceModel::where('id', $voice->id)->update(['tags' => json_encode($tags, JSON_UNESCAPED_UNICODE)]);
  138. \DB::commit();
  139. return $add_gnight_coin;
  140. } catch (\Exception $e) {
  141. \DB::rollBack();
  142. throw new DBException("数据库异常", 500);
  143. }
  144. }
  145. /**
  146. * 用户端获取声音信息
  147. * @param int $uid
  148. * @param int $voice_id
  149. * @return VoiceModel
  150. */
  151. public function getVoice(int $uid, int $voice_id): VoiceModel
  152. {
  153. $vmodel = new VoiceModel();
  154. $voice = $vmodel->findOrFail($voice_id, [
  155. 'id',
  156. 'created_at',
  157. 'uid',
  158. 'sex',
  159. 'cover',
  160. 'voice',
  161. 'check',
  162. 'like',
  163. ]);
  164. // 自己对这张卡片的操作
  165. $self = array(
  166. 'like' => 0,
  167. 'tag' => '',
  168. 'is_self' => false,
  169. );
  170. if ($voice->uid == $uid) {
  171. $self['is_self'] = true;
  172. }
  173. if (
  174. ThumbModel::where([
  175. ['voice_id', $voice_id],
  176. ['uid', $uid],
  177. ])->exists()
  178. ) {
  179. $self['like'] = 1;
  180. }
  181. $selfTag = TagModel::where([
  182. ['voice_id', $voice_id],
  183. ['uid', $uid],
  184. ])->first();
  185. if (!collect($selfTag)->isEmpty()) {
  186. $self['tag'] = $selfTag->tag;
  187. }
  188. $voice->self = $self;
  189. // 点赞集合
  190. $thumbs = ThumbModel::where('voice_id', $voice_id)->get();
  191. $users = UserModel::whereIn('uid', $thumbs->pluck('uid'))->get(['uid', 'headimgurl']);
  192. $voice->like_headimgurl = $users ?? [];
  193. // 标签集合
  194. $res = TagModel::where('voice_id', $voice_id)->groupBy('tag')->select(
  195. 'tag',
  196. \DB::raw('count(*) as count')
  197. )->get();
  198. $idxres = array();
  199. foreach ($res as $v) {
  200. $idxres[$v->tag] = $v->count;
  201. }
  202. $strTag = array();
  203. $public_id = config('miniprogram.public_id');
  204. $strs = Redis::hget("app:config:{$public_id}", "night_voice_tags_{$voice->sex}") ?? json_encode([]);
  205. $tags = json_decode($strs, true);
  206. foreach ($tags as $tag) {
  207. if (isset($idxres[$tag])) {
  208. $count = $idxres[$tag];
  209. } else {
  210. $count = 0;
  211. }
  212. array_push($strTag, array(
  213. 'tag' => $tag,
  214. 'count' => $count,
  215. ));
  216. }
  217. $voice->tags = $strTag;
  218. // 发布者信息
  219. $voice->user = UserModel::find($voice->uid, ['uid', 'nickname', 'headimgurl']);
  220. // 订阅信息
  221. $sub = SubscribeModel::where([
  222. ['voice_id', $voice_id],
  223. ['uid', $uid],
  224. ])->first();
  225. if (!collect($sub)->isEmpty()) {
  226. $voice->geted_at = $sub->created_at;
  227. }
  228. return $voice;
  229. }
  230. /**
  231. * 我录制的晚安列表
  232. * @param int $page
  233. * @param int $limit
  234. * @param int $uid
  235. * @return array
  236. */
  237. public function myVoice(int $page, int $limit, int $uid): array
  238. {
  239. $total = VoiceModel::where('uid', $uid)->count();
  240. $data = VoiceModel::where('uid', $uid)->OrderBy(
  241. "id",
  242. "desc"
  243. )->offset(($page - 1) * $limit)->limit($limit)->get();
  244. return array(
  245. 'total' => $total,
  246. 'list' => $data,
  247. );
  248. }
  249. /**
  250. * 某人录制的晚安列表
  251. * @param int $page
  252. * @param int $limit
  253. * @param int $uid
  254. * @return array
  255. */
  256. public function userVoice(int $page, int $limit, int $uid): array
  257. {
  258. $total = VoiceModel::where([
  259. ['uid', $uid],
  260. ['check', 1],
  261. ])->count();
  262. $data = VoiceModel::where([
  263. ['uid', $uid],
  264. ['check', 1],
  265. ])->orderBy('id', 'desc')->offset(($page - 1) * $limit)->limit($limit)->get();
  266. return array(
  267. 'total' => $total,
  268. 'list' => $data,
  269. );
  270. }
  271. /**
  272. * 声音库
  273. * @param array $pages
  274. * @param array $search
  275. * @return array
  276. */
  277. public function checkList(array $pages, array $search): array
  278. {
  279. $where = array();
  280. if (isset($search['check'])) {
  281. $where[] = ['check', $search['check']];
  282. }
  283. if (!empty($search['tag'])) {
  284. $where[] = ['tags', 'like', "%{$search['tag']}%"];
  285. }
  286. if (!empty($search['expedit'])) {
  287. $where[] = ['expedit', $search['expedit']];
  288. }
  289. if (isset($search['commit'])) {
  290. $where[] = ['commit', $search['commit']];
  291. }
  292. $uids = [];
  293. if (isset($search['search'])) {
  294. $user = UserModel::where('phone', $search['search'])->get();
  295. $uids = $user->pluck('uid')->toArray();
  296. array_push($uids, $search['search']);
  297. }
  298. $total = VoiceModel::where($where)->when($uids, function ($query, $uids) {
  299. return $query->whereIn('uid', $uids);
  300. })->count();
  301. $voices = VoiceModel::where($where)->when($uids, function ($query, $uids) {
  302. return $query->whereIn('uid', $uids);
  303. })->orderBy('id', 'asc')->skip(($pages['page'] - 1) * $pages['limit'])->take($pages['limit'])->get();
  304. $public_id = config('miniprogram.public_id');
  305. $strs_1 = Redis::hget("app:config:{$public_id}", "night_voice_tags_1") ?? json_encode([]);
  306. $tags_1 = json_decode($strs_1, true);
  307. $strs_2 = Redis::hget("app:config:{$public_id}", "night_voice_tags_2") ?? json_encode([]);
  308. $tags_2 = json_decode($strs_2, true);
  309. foreach ($voices as $voice) {
  310. $strTag = array();
  311. $idxres = json_decode(empty($voice->tags) ? json_encode([]) : $voice->tags, true);
  312. if (1 == $voice->sex) {
  313. $tags = $tags_1;
  314. } else {
  315. $tags = $tags_2;
  316. }
  317. foreach ($tags as $tag) {
  318. if (isset($idxres[$tag])) {
  319. $count = $idxres[$tag];
  320. } else {
  321. $count = 0;
  322. }
  323. $pushtag = array(
  324. 'tag' => $tag,
  325. 'count' => $count,
  326. 'system' => false,
  327. );
  328. if (
  329. SystemTagModel::where([
  330. ['voice_id', $voice->id],
  331. ['tag', $tag],
  332. ])->exists()
  333. ) {
  334. $pushtag['system'] = true;
  335. }
  336. array_push($strTag, $pushtag);
  337. }
  338. $voice->tags = $strTag;
  339. }
  340. return array(
  341. 'total' => $total,
  342. 'list' => $voices,
  343. );
  344. }
  345. /**
  346. * 推荐声音
  347. * @param int $voice_id
  348. * @return bool
  349. * @throws DBException
  350. */
  351. public function commit(int $voice_id): bool
  352. {
  353. $voice = VoiceModel::findOrFail($voice_id);
  354. $voice->commit = abs($voice->commit - 1);
  355. if ($voice->save()) {
  356. return true;
  357. } else {
  358. throw new DBException("服务器异常", 500);
  359. }
  360. }
  361. /**
  362. * 审核声音
  363. * @param int $voice_id
  364. * @param int $check
  365. * @return bool
  366. * @throws \Exception
  367. */
  368. public function check(int $voice_id, int $check): bool
  369. {
  370. $voice = VoiceModel::findOrFail($voice_id);
  371. $voice->check = $check;
  372. $voice->save();
  373. try {
  374. $ns = new NoticeService();
  375. if ($check == 1) {
  376. $ns->checkSuccess($voice->uid, $voice->id);
  377. } else {
  378. $ns->checkFail($voice->uid, $voice->id);
  379. }
  380. } catch (\Exception $e) {
  381. }
  382. return true;
  383. }
  384. /**
  385. * 标记声音
  386. * @param int $voice_id
  387. * @param string $tag
  388. * @return bool
  389. * @throws \Exception
  390. */
  391. public function admintag(int $voice_id, string $tag): bool
  392. {
  393. $voice = VoiceModel::findOrFail($voice_id);
  394. $idxres = json_decode(empty($voice->tags) ? json_encode([]) : $voice->tags, true);
  395. if (
  396. SystemTagModel::where([
  397. ['voice_id', $voice_id],
  398. ['tag', $tag],
  399. ])->exists()
  400. ) {
  401. // 取消标记
  402. SystemTagModel::where([
  403. ['voice_id', $voice_id],
  404. ['tag', $tag],
  405. ])->delete();
  406. $idxres[$tag] -= 1;
  407. } else {
  408. $model = new SystemTagModel();
  409. $tag = $model->fill([
  410. 'voice_id' => $voice_id,
  411. 'tag' => $tag,
  412. ]);
  413. $tag->save();
  414. if (isset($idxres[$tag])) {
  415. $idxres[$tag] += 1;
  416. } else {
  417. $idxres[$tag] = 1;
  418. }
  419. }
  420. $voice->tags = json_encode($idxres);
  421. return true;
  422. }
  423. /**
  424. * 加急晚安
  425. * @param int $voice_id
  426. * @param int $uid
  427. * @return bool
  428. * @throws AlertException
  429. */
  430. public function expeditVoice(int $voice_id, int $uid): bool
  431. {
  432. $vm = new VoiceModel();
  433. $voice = $vm->findOrFail($voice_id);
  434. if ($voice->uid != $uid) {
  435. throw new AlertException("无权限", 101);
  436. }
  437. if ($voice->check != 0) {
  438. throw new AlertException("语音已审核", 101);
  439. }
  440. $voice->expedit = 1;
  441. $voice->save();
  442. return true;
  443. }
  444. }