getProject($request); return ProjectResource::collection($projectAsset); } public function publicSearch(Request $request) { $projectAsset=$this->getProject($request); return ProjectSimpleResource::collection($projectAsset); } protected function getProject(Request $request){ $pageSize=$request->get('page_size') ?? 10; $sort=$request->input('sort','desc'); $projects=Project::filter($request->all())->allowed()->orderBy('created_at',$sort)->with('assets')->paginate($pageSize); return $projects; } public function byAsset(Request $request) { $asset=$request->asset; if (! $asset) { return $this->badRequest("asset is empty"); } $asset = Asset::withTrashed()->allowed()->findOrFail($asset); $projectId=$asset->projects->pluck('id'); $projects=Project::allowed()->whereIn('id',$projectId)->get(); return ProjectSimpleResource::collection($projects); } public function projectAssetTree(string $id){ $project = Project::allowed($id)->findOrFail($id); // return AssetRequirementGroupTreeResource::collection($filteredAssets); $projectLinkAssets = $project->assets()->select('assets.id', 'assets.name', 'assets.parent_id')->get(); $projectLinkAssets->each(function ($assets){ $assets->type='asset'; $assets->uniId=$assets->type.'_'.$assets->id; }); $projectAsset=!empty(make_tree($projectLinkAssets->toArray()))?make_tree($projectLinkAssets->toArray()):$projectLinkAssets->toArray(); return $this->success([ 'data' => $projectAsset ]); } public function projectRequirementGroupsTree(string $id){ $projectRequirementsGroup=Asset::query()->findOrFail($id)->projectRequirementsGroup()->select('requirement_groups.id', 'requirement_groups.name','requirement_groups.asset_id')->get(); $projectRequirementsGroup->each(function ($requirementsgroups){ $requirementsgroups->type='requirementsgroups'; $requirementsgroups->uniId=$requirementsgroups->type.'_'.$requirementsgroups->id; }); return $this->success([ 'data' => $projectRequirementsGroup ]); } /** * Store a newly created resource in storage. */ public function store(FileAssociationService $service, CreateOrUpdateRequest $request) { $project = new Project(); $project->mergeFillable([ 'company_id', 'created_by' ]); $service->check( $request->get("file_ids", []), FileObjectType::PROJECT, $request->get("file_uuid"), ); DB::transaction(function () use ($request, $project, $service) { $project->fill([ ...$request->all(), 'company_id' => Auth::user()->company_id, 'created_by' => Auth::id(), 'description' => $request->description? (new \App\Services\File\ImageUrlService)->interceptImageUrl($request->description) : null, 'whitelist' => $request->whitelist ? sprintf(",%s,", implode(',', $request->whitelist)) : null, ]); $project->save(); ActionRepository::createByProject($project, ObjectAction::CREATED); $service->association($project->id); if ($request->has("assets")) { foreach ($request->get("assets", []) as $assetId) { ProjectAsset::create([ 'project_id' => $project->id, 'asset_id' => $assetId, ]); } } if ($request->has("plans")) { foreach ($request->get("plans", []) as $planId) { ProjectPlan::create([ 'project_id' => $project->id, 'plan_id' => $planId, ]); } } TeamMember::create([ 'project_id' => $project->id, 'user_id' => Auth::id(), 'role' => '', 'limited' => 1, 'join_at' => Carbon::now()->toDateString(), 'created_by' => Auth::id(), ]); }); return $this->created(); } /** * Display the specified resource. */ public function show(string $id) { $project = Project::allowed($id)->findOrFail($id); return new ProjectDetailResource($project); } /** * Update the specified resource in storage. */ public function update(CreateOrUpdateRequest $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->fill([ ...$request->all(), 'description' => $request->description? (new \App\Services\File\ImageUrlService)->interceptImageUrl($request->description) : null, 'whitelist' => $request->whitelist ? sprintf(",%s,", implode(',', $request->whitelist)) : null, ]); $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project); $project->save(); ActionRepository::createByProject($project, ObjectAction::EDITED, objectChanges: $changes); if ($request->has("assets")) { ProjectAsset::where('project_id', $project->id)->delete(); foreach ($request->get("assets", []) as $assetId) { ProjectAsset::create([ 'project_id' => $project->id, 'asset_id' => $assetId, ]); } } if ($request->has("plans")) { ProjectPlan::where('project_id', $project->id)->delete(); foreach ($request->get("plans", []) as $planId) { ProjectPlan::create([ 'project_id' => $project->id, 'plan_id' => $planId, ]); } } return $this->noContent(); } /** * Remove the specified resource from storage. */ public function destroy(string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->delete(); Approval::query()->where('object_type','project')->where('object_id',$id)->delete(); ActionRepository::createByProject($project, ObjectAction::DELETED); return $this->noContent(); } public function closed(Request $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->status = ProjectStatus::CLOSED->value; $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project); $project->save(); ActionRepository::createByProject( $project, ObjectAction::CLOSED, $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null, objectChanges: $changes ); return $this->noContent(); } public function start(Request $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->status = ProjectStatus::DOING->value; $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project); $project->save(); ActionRepository::createByProject( $project, ObjectAction::STARTED, $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null, objectChanges: $changes ); return $this->noContent(); } public function pause(Request $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->status = ProjectStatus::PAUSE->value; $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project); $project->save(); ActionRepository::createByProject( $project, ObjectAction::PAUSED, $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null, objectChanges: $changes ); return $this->noContent(); } /** * 延期 * * @param PostponeRequest $request * @param string $id * @return \Illuminate\Http\Response */ public function postpone(PostponeRequest $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->fill($request->only([ 'begin', 'end' ])); $project->status = ProjectStatus::DELAY->value; $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project); $project->save(); ActionRepository::createByProject( $project, ObjectAction::DELAY, $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null, objectChanges: $changes ); return $this->noContent(); } public function done(Request $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $project->status = ProjectStatus::DONE->value; $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project); $project->save(); ActionRepository::createByProject( $project, ObjectAction::DONE, $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null, objectChanges: $changes ); return $this->noContent(); } public function linkRequirement(LinkRequirementRequest $request, string $id) { $requirementIds = $request->get("requirement_id",[]); $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; if(! $requirementIds){ return $this->forbidden("Please select the correct requirement"); } // $requirement = Requirement::findOrFail($request->requirement_id); // $exists = ProjectAsset::query() // ->where('project_id', $project->id) // ->where('asset_id', $requirement->asset_id) // ->count(); // if (! $exists) { // return $this->forbidden("Please select the correct requirement"); // } DB::transaction(function () use ($requirementIds,$project) { foreach ($requirementIds as $requirementId) { $requirement=Requirement::query()->where('id',$requirementId)->first(); ProjectRequirement::query()->firstOrCreate([ 'project_id' => $project->id, 'requirement_id' => $requirement->id, 'asset_id' => $requirement->asset_id, 'requirement_group_id'=> $requirement->requirement_group_id, ]); } }); return $this->noContent(); } public function unlinkRequirement(UnlinkRequirementRequest $request, string $id) { $requirementIds = $request->get("requirement_id",[]); $isAction=true; $project = Project::with(['tasks'=>function($query) use ($requirementIds){ $query->whereIn('requirement_id', $requirementIds); }])->allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; if (! $requirementIds) { return $this->forbidden("Please select the correct requirement"); } if($project->requirements->isEmpty()){ return $this->forbidden("Project has no associated requirements"); } DB::transaction(function () use ($requirementIds,$project) { foreach ($requirementIds as $requirement) { ProjectRequirement::query()->where([ 'project_id' => $project->id, 'requirement_id' => $requirement, ])->delete(); } Task::whereIn('id', $project->tasks->pluck('id'))->update(['requirement_id' => null]); }); return $this->noContent(); } public function linkRequirementByPlan(LinkRequirementByPlanRequest $request, string $id) { $isAction=true; $project = Project::allowed($id,$isAction)->find($id); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $plan = Plan::findOrFail($request->plan_id); foreach ($plan->requirements as $requirement) { ProjectRequirement::query()->firstOrCreate([ 'project_id' => $project->id, 'requirement_id' => $requirement->id, ]); } return $this->noContent(); } public function plan(string $id) { $project = Project::allowed($id)->findOrFail($id); return SimplePlanResource::collection($project->plans); } //用于新建任务时的公共列表 public function publicSearchRequirement(Request $request,string $id) { $requirements=$this->getRequirement($request,$id); return ProjectRequirementSimpleResource::collection($requirements); } //菜单页面管理的需求列表 public function requirement(Request $request,string $id) { $requirements=$this->getRequirement($request,$id); return ProjectRequirementResource::collection($requirements); } protected function getRequirement(Request $request,string $id) { $pageSize=$request->get('page_size') ?? 10; $project = Project::allowed($id)->findOrFail($id); // 初始化 requirements 的查询构建器 $requirementsQuery = $project->requirements(); if ($request->has('asset')) { $asset_id = $request->input('asset'); $requirementsQuery->where('requirements.asset_id', $asset_id); } if ($request->has('requirementGroup')) { $requirementGroup = $request->input('requirementGroup'); $requirementsQuery->where('requirements.requirement_group_id', $requirementGroup); } if ($request->has('requirementStatus')) { $status = $request->input('requirementStatus'); $requirementsQuery->where('requirements.status', $status); } $requirements = $requirementsQuery ->with(['createdBy']) // 预加载 createdBy 关联 ->paginate($pageSize); make_display_id($requirements,$pageSize); return $requirements; } public function notLinkAssetRequirement(Request $request,string $id) { $pageSize=$request->get('page_size') ?? 10; $project = Project::allowed($id)->findOrFail($id);; $requirements = $project->assets ? Requirement::query()->whereIn('asset_id', $project->assets?->pluck('id')->toArray())->whereNotIn('id', $project->requirements?->pluck('id')->toArray())->paginate($pageSize) : []; make_display_id($requirements,$pageSize); return AssetRequirementResource::collection($requirements); } public function updateLinkAssets(UpdateLinkAssetsRequest $request,string $projectId) { $isAction=true; $project = Project::allowed($projectId,$isAction)->find($projectId); if($project===null||is_null($project)){ return $this->badRequest('Permission denied or project not found. Please contact the administrator.'); }; $oldAssetId=$project->assets()->select('assets.id')->pluck('id'); $assetsIds = $request->assets; DB::transaction(function () use ($projectId,$assetsIds) { ProjectAsset::where('project_id', $projectId)->delete(); foreach ($assetsIds as $assetId) { ProjectAsset::create([ 'project_id' => $projectId, 'asset_id' => $assetId, ]); } }); //取消关联没有关联资产的需求 if(!$oldAssetId->isEmpty()){ $removedAssetIds = $oldAssetId->diff($assetsIds); ProjectRequirement::query()->where('project_id', $projectId)->whereIn('asset_id',$removedAssetIds)->delete(); } return $this->noContent(); } public function dynamic(Request $request, string $id) { $project = Project::allowed($id)->findOrFail($id); return $this->success([ 'data' => ActionRepository::dynamic($project, $request->all()) ]); } public function kanban(Request $request, ProjectKanbanService $service, string $id) { $project = Project::allowed($id)->findOrFail($id); return $this->success([ 'data' => $service->kanban($project, $request->get("group", "requirement_asc")) ]); } public function groupView(Request $request, string $id) { $project = Project::allowed($id)->findOrFail($id); $group = in_array( $request->get("group"), ['requirement_id','status','assign','finished_by','closed_by','task_type'] ) ? $request->get("group") : "requirement_id"; return $this->success([ 'data' => (new ProjectTaskGroupViewService())->groupView($project, $group, $request->all()) ]); } public function gantt(Request $request, string $id) { $project = Project::allowed($id)->findOrFail($id); $group = in_array( $request->get("group"), ['requirement_id','assign','task_type'] ) ? $request->get("group") : "task_type"; return $this->success([ 'data' => (new ProjectGanttService())->gantt($project, $group) ]); } public function printKanban(string $id) { $project = Project::allowed($id)->findOrFail($id); return $this->success([ 'data' => [ 'requirements' => ProjectKanbanRequirementResource::collection($project->requirements), 'tasks' => ProjectKanbanTaskResource::collection($project->tasks), 'task_status' => TaskApprovalStatus::cases(), ] ]); } public function latestDynamic(string $id) { $project = Project::allowed($id)->findOrFail($id); return $this->success([ 'data' => ActionRepository::projectLatestDynamic($project) ]); } public function requirementsLinkGroup(string $id){ $requirementsLinksGroup = Project::allowed($id)->findOrFail($id)->requirementsGroup->unique('id'); return RequirementGroupParentResource::collection($requirementsLinksGroup); } public function kanbanExport(Request $request) { return $this->downloadExcelHelper( new ProjectKanbanExport(), "project_kanban", $request->get("extension"), ); } public function ganttExport(Request $request) { return $this->downloadExcelHelper( new ProjectGanttExport(), "project_gantt", $request->get("extension"), ); } public function tree() { $attachmentArray = []; $projects = Project::allowed()->get(['id', 'name'])->each(function ($project)use(&$attachmentArray){ // 设置固定的type值 $project->type = 'project'; $project->uniId=$project->type.'_'.$project->id; $attachmentArray[$project->id][]=[ 'parent_id'=>$project->id, 'type'=>'attachment', 'name'=>'attachment', 'uuId'=>'attachment_' . $project->id, 'id'=>'project_id_' . $project->id, ]; $project->children=$attachmentArray[$project->id]; }); return $this->success([ 'data' => $projects ]); } public function project4s(Request $request){ return $this->success([ ]); } }