ActivityController.php 15.4 KB
<?php

namespace App\Http\Container\AdminSection\Controllers\Audition;

use App\Enums\ActivityAuditStatusEnum;
use App\Enums\ActivitySongTypeEnum;
use App\Enums\ActivityStatusEnum;
use App\Enums\ActivityWorkStatusEnum;
use App\Enums\ActivityWorkTypeEnum;
use App\Excel\ActivityDemoExcel;
use App\Excel\ActivityExcel;
use App\Excel\ActivitySongExcel;
use App\Excel\ActivityWorkExcel;
use App\Helpers\OperationLog;
use App\Http\Container\AdminSection\Requests\Audition\ActivityChangeStatusRequest;
use App\Http\Container\AdminSection\Requests\Audition\ActivityCreateRequest;
use App\Http\Container\AdminSection\Requests\Audition\ActivityUpdateRequest;
use App\Http\Service\ActivityService;
use App\Jobs\ActivityChangeStatusJob;
use App\Jobs\ActivityMakeMediaJob;
use App\Models\Activity;
use App\Models\ActivityShareUser;
use App\Models\Pivots\UserActivityCollectionPivot;
use App\Models\Pivots\UserActivityViewPivot;
use App\Models\User;
use App\Models\Views\ActivityWork;
use App\Models\Views\UserManageActivity;
use App\Support\Controller;
use App\Support\Model;
use Arr;
use Auth;
use DB;
use Hikoon\LaravelApi\Facades\Response;
use Hikoon\LaravelApi\Support\ApiCode;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class ActivityController extends Controller
{
    /**
     * @param \Illuminate\Http\Request $request
     * @return \Hikoon\LaravelApi\Facades\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function index(Request $request): Response|BinaryFileResponse
    {
        $pageSize  = $request->get('pageSize', 20);
        $fetchType = $request->get('fetchType', 'page');
        $filter    = $request->except(['page', 'pageSize', 'fetchType']);
        $build     = Activity::filter($filter)->where('audit_status', 1);

        return match ($fetchType) {
            'excel' => match ($request->integer('songType')) {
                1 => ActivitySongExcel::withBuilder($build)->download(),
                2 => ActivityDemoExcel::withBuilder($build)->download(),
                default => ActivityExcel::withBuilder($build)->download(),
            },
            default => $this->successWithData($build->paginate($pageSize))
        };
    }

    /**
     * @param \App\Http\Container\AdminSection\Requests\Audition\ActivityCreateRequest $request
     * @param \App\Http\Service\ActivityService                                        $service
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function store(ActivityCreateRequest $request, ActivityService $service): Response
    {
        $data = array_merge($request->safe()->toArray(), [
            'song_type' => 1, 'audit_status' => 1, 'audit_at' => now()->toDateTimeString(), 'status' => 0, 'user_id' => Auth::id(), 'publish_at' => now()->toDateTimeString()
        ]);

        if (Cache::lock('user-' . Auth::id() . '-create-activity', 5)->get()) {
            $result = DB::transaction(static function () use ($data, $service) {
                $activity = Activity::query()->create(Arr::except($data, 'out_side_manages'));

                if (isset($data['out_side_manages'])) {
                    $service->syncManageLink($activity, $data['out_side_manages']);
                }

                OperationLog::admin()->subject($activity)->createAction()->content('歌曲《%s》', $activity->getAttribute('song_name'));
                ActivityMakeMediaJob::dispatch($activity, ActivityStatusEnum::UP, true);

                return $activity->loadMissing('user:id,nick_name,real_name');
            });
            return $this->successWithData($result, 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
    {
        $activity = Activity::filter($request->all())->findOrFail($id);

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

    /**
     * @param \App\Http\Container\AdminSection\Requests\Audition\ActivityUpdateRequest $request
     * @param \App\Models\Activity                                                     $activity
     * @param \App\Http\Service\ActivityService                                        $service
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function update(ActivityUpdateRequest $request, Activity $activity, ActivityService $service): Response
    {
        if ($activity->getAttribute('status') === ActivityStatusEnum::PROCESS) {
            return $this->fail(ApiCode::VALIDATION_ERROR, '音频处理中');
        }

        $data = $request->safe()->toArray();

        $activity->update(Model::dot(Arr::except($data, 'out_side_manages')));

        $change = $activity->getChangeColumn();

        if (isset($data['out_side_manages'])) {
            $syncResult = $service->syncManageLink($activity, $data['out_side_manages']);

            if (count($syncResult) !== 0) {
                $change->add('manage_link');
            }
        }

        OperationLog::admin()->subject($activity)->updateAction()
            ->content('《%s》%s', $activity->getAttribute('song_name'), $change->except(['audit_status', 'status'])->format(',修改了:'));


        if ($activity->wasChanged(['lyric', 'clip_lyric', '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 \App\Http\Container\AdminSection\Requests\Audition\ActivityChangeStatusRequest $request
     * @param \App\Models\Activity                                                           $activity
     * @param \App\Http\Service\ActivityService                                              $service
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function changeStatus(ActivityChangeStatusRequest $request, Activity $activity, ActivityService $service): Response
    {
        $attribute = $request->validated();

        //上架
        if ($attribute['status'] === 'up' && $activity->getAttribute('status') === ActivityStatusEnum::DOWN) {
            $activity->update(['status' => ActivityStatusEnum::UP, 'p_is_top' => 0, 'publish_at' => now()->toDateTimeString()]);
            OperationLog::admin()->statusAction()->subject($activity)->content('上架歌曲《%s》', $activity->getAttribute('song_name'));
            if ($activity->getAttribute('song_type') === ActivitySongTypeEnum::SONG->value) {
                ActivityChangeStatusJob::dispatch($activity, Auth::user());
            }
            return $this->success(ApiCode::UPDATE_SUCCESS);
        }

        //下架
        if ($attribute['status'] === 'down' && $activity->getAttribute('status') === ActivityStatusEnum::UP) {
            $activity->update(['status' => ActivityStatusEnum::DOWN]);
            OperationLog::admin()->statusAction()->subject($activity)->content('下架歌曲《%s》,理由:%s', $activity->getAttribute('song_name'), $attribute['msg']);
            if ($activity->getAttribute('song_type') === ActivitySongTypeEnum::SONG->value) {
                ActivityChangeStatusJob::dispatch($activity, Auth::user(), ['msg' => $attribute['msg']]);
            }
            return $this->success(ApiCode::UPDATE_SUCCESS);
        }

        //发行
        if ($attribute['status'] === 'send' && $activity->getAttribute('status') === ActivityStatusEnum::MATCH) {
            if ($activity->getAttribute('status') === ActivityStatusEnum::MATCH) {
                $activity->update(['status' => ActivityStatusEnum::SEND, 'send_at' => now()->toDateTimeString(), 'send_url' => [['type' => 'default', 'url' => $attribute['link']]]]);
                OperationLog::admin()->statusAction()->subject($activity)->content('发行歌曲《%s》', $activity->getAttribute('song_name'));
                if ($activity->getAttribute('song_type') === ActivitySongTypeEnum::SONG->value) {
                    ActivityChangeStatusJob::dispatch($activity, Auth::user());
                }
            }
            if ($activity->getAttribute('status') === ActivityStatusEnum::SEND) {
                $activity->update(['send_url->url' => $attribute['link']]);
                OperationLog::admin()->updateAction()->subject($activity)->content('歌曲《%s》,修改了:外部平台播放链接', $activity->getAttribute('song_name'));
            }

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

        //重新上架
        if ($attribute['status'] === 'reUp' && $activity->getAttribute('status') === ActivityStatusEnum::MATCH) {
            $service->reUp($activity);
            OperationLog::admin()->statusAction()->subject($activity)->content('重新上架歌曲《%s》', $activity->getAttribute('song_name'));
            return $this->success(ApiCode::UPDATE_SUCCESS);
        }


        return $this->fail(ApiCode::VALIDATION_ERROR, '此活动状态无法变更状态');
    }

    /**
     * @param \App\Models\Activity              $activity
     * @param \App\Http\Service\ActivityService $service
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function destroy(Activity $activity, ActivityService $service): Response
    {
        if ($activity->getAttribute('audit_status') !== ActivityAuditStatusEnum::SUCCESS->value && $activity->getAttribute('status') !== ActivityStatusEnum::DOWN) {
            return $this->fail(ApiCode::VALIDATION_ERROR, '只允许删除下架歌曲');
        }

        $service->delete($activity);
        OperationLog::admin()->subject($activity)->deleteAction()->content('歌曲《%s》', $activity->getAttribute('song_name'));

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

    /**
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function viewUser(Request $request, Activity $activity): Response
    {
        $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', 'real_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 \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function likeUser(Request $request, Activity $activity): Response
    {
        $pageSize = $request->get('pageSize', 20);

        $viewPivotQuery = UserActivityCollectionPivot::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', 'real_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 \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function submitUser(Request $request, Activity $activity): Response|BinaryFileResponse
    {
        $pageSize = $request->get('pageSize');
        $filter   = $request->except(['page', 'pageSize', 'fetchType']);

        $query = ActivityWork::filter($filter)->where('activity_id', $activity->getKey())->where('type', ActivityWorkTypeEnum::SUBMIT);

        if ($request->get('fetchType') === 'excel') {
            return ActivityWorkExcel::withBuilder($query)->download();
        }

        return $this->successWithData($query->paginate($pageSize));
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function changeUserShare(Request $request, Activity $activity): Response
    {
        $data = $request->validate(['user_id' => 'bail|required', 'share_id' => 'bail|required'], ['user_id.required' => '请选择提交者', 'share_id.required' => '请选择分享者']);
        ActivityShareUser::query()->updateOrCreate(['user_id' => $data['user_id'], 'activity_id' => $activity->getKey()], ['share_id' => $data['share_id']]);
        return $this->success(ApiCode::UPDATE_SUCCESS);
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function matchUser(Request $request, Activity $activity): Response
    {
        $pageSize = $request->get('pageSize');
        $filter   = $request->except(['page', 'pageSize', 'fetchType']);
        $query    = ActivityWork::filter($filter)
            ->where('activity_id', $activity->getKey())
            ->where('type', 'submit')
            ->where('status', ActivityWorkStatusEnum::SUCCESS);

        return $this->successWithData($query->paginate($pageSize));
    }


    /**
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function manageUser(Request $request, Activity $activity): Response
    {
        $pageSize = $request->get('pageSize', 20);
        $filter   = $request->except(['page', 'pageSize']);

        $data = UserManageActivity::filter($filter)
            ->with('user:id,avatar,nick_name,real_name,sex,email,area_code,phone,official_status,status,identity')
            ->where('activity_id', $activity->getKey())
            ->paginate($pageSize);

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

    /**
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\Activity     $activity
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function sendNotify(Request $request, Activity $activity): Response
    {
        $request->validate([
            'push_type'   => 'bail|required_if:is_push,1|array',
            'push_user'   => 'bail|array',
            'push_user.*' => 'bail|sometimes|numeric'
        ], [
            'push_type.required_if' => '请选择推送方式',
            'push_user.required_if' => '请选择推送歌手',
            'push_user.array'       => '请选择推送歌手',
            'push_user.*.numeric'   => '推送歌手参数错误'
        ]);


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