ActivityController.php 8.36 KB
<?php

namespace App\Http\Container\UserSection\Controllers;

use App\Enums\ActivitySongTypeEnum;
use App\Enums\ActivityStatusEnum;
use App\Http\Container\UserSection\Requests\ActivityCreateRequest;
use App\Http\Container\UserSection\Requests\ActivityUpdateRequest;
use App\Http\Service\ActivityService;
use App\Http\Service\UserService;
use App\Jobs\ActivityChangeStatusJob;
use App\Jobs\ActivityMakeMediaJob;
use App\Models\Activity;
use App\Models\Pivots\UserActivityCollectionPivot;
use App\Models\Pivots\UserActivityViewPivot;
use App\Models\User;
use App\Support\Model;
use Auth;
use Hikoon\LaravelApi\Facades\Response;
use Hikoon\LaravelApi\Support\ApiCode;
use Hikoon\LaravelApi\Support\ApiController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class ActivityController extends ApiController
{
    /**
     * @param \Illuminate\Http\Request $request
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function index(Request $request): Response
    {
        $pageSize = $request->get('pageSize', 20);
        $filter   = $request
            ->mergeIfMissing(['setColumn' => ['id', 'song_name', 'song_type']])
            ->merge(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])
            ->except(['page', 'pageSize', 'fetchType']);

        return $this->successWithData(Activity::filter($filter)->paginate($pageSize));
    }

    /**
     * @throws \Hikoon\LaravelApi\Exceptions\ValidationException
     */
    public function store(ActivityCreateRequest $request, ActivityService $service): Response
    {
        $attribute = array_merge($request->safe()->toArray(), ['user_id' => (int)Auth::id(), 'project_id' => 0, 'created_form' => 2]);

        if (!UserService::hasDemoPermission(Auth::user())) {
            return $this->fail(ApiCode::VALIDATION_ERROR, '无Demo上传权限');
        }

        if (Cache::lock('user-' . Auth::id() . '-apply', 5)->get()) {

            $activity = match ($request->integer('song_type')) {
                ActivitySongTypeEnum::DEMO->value => $service->createDemoApply($attribute + ['is_push' => 1])
            };

            return $this->successWithData($activity, ApiCode::CREATE_SUCCESS);
        }

        return $this->fail(ApiCode::REQUEST_LIMIT_ERROR);
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function show(Request $request, int $id): Response
    {
        $filter = $request->merge(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])->toArray();

        $activity = Activity::filter($filter)->findOrFail($id);

        return $this->successWithData($activity);
    }

    /**
     * @param \App\Http\Container\UserSection\Requests\ActivityUpdateRequest $request
     * @param int                                                            $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function update(ActivityUpdateRequest $request, int $id): Response
    {
        $activity = Activity::filter(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])->findOrFail($id);

        if ($activity->getAttribute('status') === ActivityStatusEnum::PROCESS) {
            return $this->fail(ApiCode::VALIDATION_ERROR, '音频处理中');
        }
        $activity->update(Model::dot($request->safe()->toArray()));

        if ($activity->wasChanged(['expand->guide_source->url', 'expand->karaoke_source->url'])) {
            ActivityMakeMediaJob::dispatch($activity, $activity->getAttribute('status'), $activity->wasChanged(['expand->guide_source->url', 'expand->karaoke_source->url']));
            $activity->update(['status' => 0]);
        }

        return $this->successWithData($activity, ApiCode::UPDATE_SUCCESS);
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function changeStatus(Request $request, int $id): Response
    {
        $attribute = $request->validate([
            'status' => 'required|in:up,down,send,reUp',
            'msg'    => 'required_if:status,down|string|max:100',
            'link'   => 'required_if:status,send|url|max:400'
        ], [
            'status.required'  => '请选择状态值',
            'status.in'        => '状态值不在指定范围内',
            'msg.required_if'  => '请输入下架理由',
            'msg.max'          => '下架理由长度超出限制',
            'link.required_if' => '请输入发行链接',
            'link.url'         => '链接格式不正确',
            'link.max'         => '发行链接长度超出限制'
        ]);

        $activity = Activity::filter(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])->findOrFail($id);

        if ($request->offsetGet('status') === 'up') {
            $activity->update(['status' => ActivityStatusEnum::UP, 'p_is_top' => 0, 'u_top' => 0, 'publish_at' => now()->toDateTimeString()]);

            if ($activity->getAttribute('song_type') === ActivitySongTypeEnum::SONG->value) {
                ActivityChangeStatusJob::dispatch($activity, Auth::user());
            }
        }

        if ($request->offsetGet('status') === 'down') {
            $activity->update(['status' => ActivityStatusEnum::DOWN]);

            if ($activity->getAttribute('song_type') === ActivitySongTypeEnum::SONG->value) {
                ActivityChangeStatusJob::dispatch($activity, Auth::user(), ['msg' => $attribute['msg']]);
            }
        }

        return $this->success(ApiCode::UPDATE_SUCCESS);
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function viewUser(Request $request, int $id): Response
    {
        if (!$activity = Activity::filter(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])->find($id)) {
            return $this->success();
        }

        $pageSize = $request->get('pageSize', 20);

        $viewPivotQuery = UserActivityViewPivot::query()->selectRaw('user_id,activity_id,updated_at as last_listen_at')->where('activity_id', $activity->getKey());

        $data = User::withTrashed()
            ->filter($request->except(['page', 'pageSize']))
            ->select(['id', 'nick_name', 'avatar', 'sex', 'scope', 'identity', 'last_listen_at'])
            ->joinSub($viewPivotQuery, 'views', 'user_id', 'users.id')
            ->withCount(['listenActivities as listen_count', 'likeActivities as collection_count', 'submitActivities as submit_work'])
            ->paginate($pageSize);

        return $this->successWithData($data);
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function collectUser(Request $request, int $id): Response
    {
        $activity = Activity::filter(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])->findOrFail($id);
        $pageSize = $request->get('pageSize', 20);

        $collectPivotQuery = UserActivityCollectionPivot::query()->selectRaw('user_id,activity_id,updated_at as collect_at')->where('activity_id', $activity->getKey());

        $data = User::withTrashed()
            ->filter($request->except(['page', 'pageSize']))
            ->select(['id', 'nick_name', 'avatar', 'sex', 'scope', 'identity', 'collect_at'])
            ->joinSub($collectPivotQuery, 'views', 'user_id', 'users.id')
            ->withCount(['listenActivities as listen_count', 'likeActivities as collection_count', 'submitActivities as submit_work'])
            ->paginate($pageSize);

        return $this->successWithData($data);
    }

    /**
     * @param int                               $id
     * @param \App\Http\Service\ActivityService $service
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function destroy(int $id, ActivityService $service): Response
    {
        $activity = Activity::filter(['user' => Auth::id(), 'auditStatus' => 1, 'createdForm' => 2])->findOrFail($id);


        if ($activity->getAttribute('audit_status') !== 1 && $activity->getAttribute('status') !== ActivityStatusEnum::DOWN) {
            return $this->fail(ApiCode::VALIDATION_ERROR, '只允许删除下架歌曲');
        }

        $service->delete($activity);

        return $this->success(ApiCode::DELETE_SUCCESS);
    }
}