IndexController.php 13.6 KB
<?php

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

use App\Enums\ActivityWorkTypeEnum;
use App\Enums\UserScopeEnum;
use App\Enums\UserStatusEnum;
use App\Exceptions\SingerLimitException;
use App\Helpers\OperationLog;
use App\Helpers\PasswordHelper;
use App\Http\Container\AdminSection\Requests\User\UserUpdateRequest;
use App\Http\Request\BooleanStatusRequest;
use App\Http\Request\UserChangePwdRequest;
use App\Http\Service\UserService;
use App\Jobs\UserSyncIMJob;
use App\Models\Activity;
use App\Models\GroupHasMember;
use App\Models\Groups;
use App\Models\Pivots\UserActivityCollectionPivot;
use App\Models\Pivots\UserActivityViewPivot;
use App\Models\Pivots\UserProjectPivot;
use App\Models\Pivots\UserRolePivot;
use App\Models\Project;
use App\Models\User;
use App\Models\UserCertify;
use App\Models\UserDynamic;
use App\Models\UserMessage;
use App\Models\UserTagRelation;
use App\Models\Views\ActivitySubmitWork;
use App\Models\Views\ActivityWork;
use App\Models\Views\UserManageActivity;
use App\Support\Controller;
use Arr;
use DB;
use Hikoon\LaravelApi\Facades\Response;
use Hikoon\LaravelApi\Support\ApiCode;
use Illuminate\Http\Request;
use RuntimeException;

class IndexController extends Controller
{

    /**
     * @param \Illuminate\Http\Request $request
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function index(Request $request): Response
    {
        $pageSize  = $request->get('pageSize', 20);
        $fetchType = $request->get('fetchType', 'page');
        $filter    = $request->except(['page', 'pageSize', 'fetchType']);
        $build     = User::withTrashed()->filter($filter);

        return match ($fetchType) {
            'all' => $this->successWithData($build->get()),
            default => $this->successWithData($build->paginate($pageSize))
        };
    }

    /**
     * @param \App\Models\User $user
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function show(User $user): Response
    {
        $user->loadMissing(['business:id,nick_name,real_name,identity', 'inviter:id,nick_name,real_name,identity', 'styleTags:id,name', 'authTags:id,name', 'roles:id,name', 'projects:id,name']);
        $user->setAttribute('image_dynamic_count', $user->dynamics()->where('type', 'image')->count());
        $user->setAttribute('audio_dynamic_count', $user->dynamics()->where('type', 'audio')->count());
        $user->setAttribute('video_dynamic_count', $user->dynamics()->where('type', 'video')->count());
        $user->setAttribute('group_id', Groups::query()->where('user_id', $user->getKey())->value('id') ?? 0);

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

    /**
     * @param \App\Http\Container\AdminSection\Requests\User\UserUpdateRequest $request
     * @param \App\Models\User                                                 $user
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function update(UserUpdateRequest $request, User $user): Response
    {
        try {
            $data      = $request->safe()->toArray();
            $attribute = Arr::only($data, ['nick_name', 'real_name', 'email', 'lang', 'area_code', 'phone', 'scope', 'demo_type', 'user_tag_id', 'business_singer_limit']);

            DB::beginTransaction();

            $user->fill($attribute);
            if (isset($data['authIds'])) {
                $oldAuthIds = $user->authTags()->pluck('system_tags.id')->toArray();
                if (array_diff($oldAuthIds, $data['authIds']) || array_diff($data['authIds'], $oldAuthIds)) {
                    UserService::updateAuthTags($user, $data['authIds'], ['audit_at' => now()->toDateTimeString()]);
                }
            }
            if ($attribute['scope'] === UserScopeEnum::UNSET->value) {
                $user->roles()->detach();
                UserProjectPivot::query()->where('user_id', $user->getKey())->delete();
                Project::query()->where('master_id', $user->getKey())->update(['master_id' => 0]);
            }
            if ($attribute['scope'] === UserScopeEnum::SYSTEM->value) {
                if ($user->getOriginal('scope')->value !== (int)$attribute['scope']) {
                    $user->fill(['password' => PasswordHelper::make($user->getAttribute('phone'))]);
                }
                $user->roles()->sync($data['roleIds']);
                UserProjectPivot::query()->where('user_id', $user->getKey())->delete();
                Project::query()->where('master_id', $user->getKey())->update(['master_id' => 0]);
            }
            if ($attribute['scope'] === UserScopeEnum::PROJECT->value) {
                if ($user->getOriginal('scope')->value !== (int)$attribute['scope']) {
                    $user->fill(['password' => PasswordHelper::make($user->getAttribute('phone'))]);
                }
                $user->roles()->sync([]);

                UserProjectPivot::query()->where('user_id', $user->getKey())->whereNotIn('project_id', $data['projectIds'])
                    ->eachById(fn($item) => $item->delete());
                $user->projects()->sync($data['projectIds']);
            }

            $user->save();

            UserSyncIMJob::dispatch($user);

            OperationLog::admin()->action('内容调整')->subject($user)
                ->content('用户《%s》%s', $user->getFullName(), $user->getChangeColumn()->format(',修改了:'));
            DB::commit();
            return $this->successWithData($user->load(['authTags:id,name', 'roles:id,name', 'projects:id,name']), ApiCode::UPDATE_SUCCESS);
        } catch (SingerLimitException $exception) {
            DB::rollBack();
            return $this->fail(ApiCode::VALIDATION_ERROR, '团队内歌手名额已满');
        } catch (RuntimeException $exception) {
            DB::rollBack();
            throw $exception;
        }
    }

    /**
     * @param \App\Http\Request\BooleanStatusRequest $request
     * @param \App\Models\User                       $user
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function changeStatus(BooleanStatusRequest $request, User $user): Response
    {
        $data = $request->safe()->toArray();

        if ($user->getAttribute('status') === UserStatusEnum::UNSET) {
            return $this->fail(ApiCode::VALIDATION_ERROR, '用户已注销');
        }

        $user->update($data);
        OperationLog::admin()->subject($user)->statusAction()->content('用户《%s》', $user->getFullName());

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

    /**
     * @param \App\Http\Request\UserChangePwdRequest $request
     * @param \App\Models\User                       $user
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function changePwd(UserChangePwdRequest $request, User $user): Response
    {
        $data = $request->safe()->toArray();

        $user->update($data);
        OperationLog::admin()->subject($user)->updateAction()->content('用户《%s》重置密码', $user->getFullName());

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

    /**
     * 试听歌曲
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function listenSong(Request $request, int $id): Response
    {
        $pageSize = $request->get('pageSize', 20);
        $filter   = $request->except(['page', 'pageSize']);


        $innerQuery = UserActivityViewPivot::query()
            ->selectRaw('activity_id,max(updated_at) as listen_at')->where('user_id', $id)
            ->groupBy('activity_id');

        $data = Activity::filter($filter)
            ->joinSub($innerQuery, 'listen', 'activitys.id', 'listen.activity_id')
            ->with(['project:id,name', 'user:id,real_name,nick_name,role', 'tags:id,name'])
            ->select(['id', 'cover', 'song_name', 'sub_title', 'user_id', 'project_id', 'listen_at', 'status'])
            ->addSelect([
                'view_count'        => UserActivityViewPivot::selectRaw('count(*)')->whereColumn('activitys.id', 'user_view_activitys.activity_id'),
                'like_count'        => UserActivityCollectionPivot::selectRaw('count(*)')->whereColumn('activitys.id', 'user_activity_collections.activity_id'),
                'submit_work_count' => ActivitySubmitWork::selectRaw('count(*)')->whereColumn('activitys.id', 'activity_user_submits.activity_id')
            ])
            ->paginate($pageSize);

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

    /**
     * 收藏歌曲
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function likeSong(Request $request, int $id): Response
    {
        $pageSize = $request->get('pageSize', 20);
        $filter   = $request->except(['page', 'pageSize']);


        $innerQuery = UserActivityCollectionPivot::query()
            ->selectRaw('activity_id,max(updated_at) as like_at')->where('user_id', $id)
            ->groupBy('activity_id');

        $data = Activity::filter($filter)
            ->joinSub($innerQuery, 'like', 'activitys.id', 'like.activity_id')
            ->with(['project:id,name', 'user:id,real_name,nick_name,role', 'tags:id,name'])
            ->select(['id', 'cover', 'song_name', 'sub_title', 'user_id', 'project_id', 'like_at', 'status'])
            ->addSelect([
                'view_count'        => UserActivityViewPivot::selectRaw('count(*)')->whereColumn('activitys.id', 'user_view_activitys.activity_id'),
                'like_count'        => UserActivityCollectionPivot::selectRaw('count(*)')->whereColumn('activitys.id', 'user_activity_collections.activity_id'),
                'submit_work_count' => ActivitySubmitWork::selectRaw('count(*)')->whereColumn('activitys.id', 'activity_user_submits.activity_id')
            ])
            ->paginate($pageSize);

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

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

        $data = UserManageActivity::filter($filter)
            ->with('project:id,name')
            ->addSelect([
                'view_count'        => UserActivityViewPivot::selectRaw('count(*)')->whereColumn('user_manage_activities.activity_id', 'user_view_activitys.activity_id'),
                'like_count'        => UserActivityCollectionPivot::selectRaw('count(*)')->whereColumn('user_manage_activities.activity_id', 'user_activity_collections.activity_id'),
                'submit_work_count' => ActivitySubmitWork::selectRaw('count(*)')->whereColumn('user_manage_activities.activity_id', 'activity_user_submits.activity_id')
            ])
            ->where('user_id', $id)->paginate($pageSize);

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

    /**
     * 参与歌曲
     * @param \Illuminate\Http\Request $request
     * @param int                      $id
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function submitSong(Request $request, int $id): Response
    {
        $pageSize = $request->get('pageSize', 20);
        $filter   = $request->except(['page', 'pageSize']);

        $data = ActivityWork::filter($filter)->with(['project:id,name', 'tags:id,name'])
            ->select(['id', 'activity_id', 'activity_name', 'activity_title', 'activity_cover', 'project_id', 'mode', 'sing_type', 'demo_url', 'submit_at', 'status', 'activity_status'])
            ->where('type', ActivityWorkTypeEnum::SUBMIT)->where('user_id', $id)
            ->paginate($pageSize);

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

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

        $data = UserDynamic::filter($filter)->where('user_id', $id)->orderByDesc('created_at')->paginate($pageSize);

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

    /**
     * @param \App\Models\User $user
     * @return \Hikoon\LaravelApi\Facades\Response
     */
    public function destroy(User $user): Response
    {
        DB::transaction(static function () use ($user) {
            User::query()->where('business_id', $user->getKey())->update(['business_id' => 0, 'chat_mode' => 0]);
            UserMessage::query()->where('sender_id', $user->getKey())->orWhere('receiver_id', $user->getKey())->delete();
            UserTagRelation::query()->where('user_id', $user->getKey())->delete();
            UserDynamic::query()->where('user_id', $user->getKey())->delete();
            UserRolePivot::query()->where('user_id', $user->getKey())->delete();
            UserCertify::query()->where('user_id', $user->getKey())->delete();
            GroupHasMember::query()->where('member_id', $user->getKey())->delete();
            UserProjectPivot::query()->where('user_id', $user->getKey())->delete();
            Project::query()->where('master_id', $user->getKey())->update(['master_id' => 0]);
            User::query()->whereKey($user->getKey())->update(['status' => 2, 'deleted_at' => now()->toDateTimeString()]);
            UserService::syncBusinessIdentity($user->getAttribute('business'));
            OperationLog::admin()->subject($user)->deleteAction()->content('用户《%s》注销', $user->getFullName());
        });

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

}