diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php
index 88f53bb17..252c70422 100755
--- a/app/Http/Controllers/Api/ProjectController.php
+++ b/app/Http/Controllers/Api/ProjectController.php
@@ -2997,6 +2997,7 @@ class ProjectController extends AbstractController
return Base::retError('参数错误');
}
$templates = ProjectTaskTemplate::where('project_id', $projectId)
+ ->orderBy('sort')
->orderByDesc('id')
->get();
return Base::retSuccess('success', $templates);
@@ -3060,11 +3061,66 @@ class ProjectController extends AbstractController
if ($templateCount >= 50) {
return Base::retError('每个项目最多添加50个模板');
}
- $template = ProjectTaskTemplate::create($data);
+ $maxSort = ProjectTaskTemplate::where('project_id', $projectId)->max('sort');
+ $template = ProjectTaskTemplate::create(array_merge($data, [
+ 'sort' => is_numeric($maxSort) ? intval($maxSort) + 1 : 0
+ ]));
}
return Base::retSuccess('保存成功', $template);
}
+ /**
+ * @api {post} api/project/task/template_sort 48.1 排序任务模板
+ *
+ * @apiDescription 需要token身份(限:项目负责人)
+ * @apiVersion 1.0.0
+ * @apiGroup project
+ * @apiName task__template_sort
+ *
+ * @apiParam {Number} project_id 项目ID
+ * @apiParam {Array} list 模板ID列表,按新顺序排列
+ *
+ * @apiSuccess {Number} ret 返回状态码(1正确、0错误)
+ * @apiSuccess {String} msg 返回信息(错误描述)
+ * @apiSuccess {Object} data 返回数据
+ */
+ public function task__template_sort()
+ {
+ User::auth();
+ $projectId = intval(Request::input('project_id'));
+ $list = Base::json2array(Request::input('list'));
+ if ($projectId <= 0 || !is_array($list)) {
+ return Base::retError('参数错误');
+ }
+ $project = Project::userProject($projectId, true, true);
+ $index = 0;
+ $handled = [];
+ foreach ($list as $templateId) {
+ $templateId = intval($templateId);
+ if ($templateId <= 0) continue;
+ $updated = ProjectTaskTemplate::where('project_id', $projectId)
+ ->where('id', $templateId)
+ ->update(['sort' => $index]);
+ if ($updated) {
+ $handled[] = $templateId;
+ $index++;
+ }
+ }
+ $others = ProjectTaskTemplate::where('project_id', $projectId)
+ ->when(!empty($handled), function ($query) use ($handled) {
+ $query->whereNotIn('id', $handled);
+ })
+ ->orderBy('sort')
+ ->orderByDesc('id')
+ ->pluck('id');
+ foreach ($others as $templateId) {
+ ProjectTaskTemplate::where('id', $templateId)->update(['sort' => $index]);
+ $index++;
+ }
+ $project->addLog('调整模板排序');
+ return Base::retSuccess('排序已保存');
+ }
+
/**
* @api {get} api/project/task/template_delete 49. 删除任务模板
*
diff --git a/database/migrations/2025_09_24_202833_backfill_sort_project_task_templates.php b/database/migrations/2025_09_24_202833_backfill_sort_project_task_templates.php
new file mode 100644
index 000000000..3f798dcca
--- /dev/null
+++ b/database/migrations/2025_09_24_202833_backfill_sort_project_task_templates.php
@@ -0,0 +1,46 @@
+select('project_id')
+ ->distinct()
+ ->orderBy('project_id')
+ ->chunk(100, function ($projects) {
+ foreach ($projects as $project) {
+ $templates = \App\Models\ProjectTaskTemplate::query()
+ ->where('project_id', $project->project_id)
+ ->orderByDesc('id')
+ ->get(['id']);
+ $index = 0;
+ foreach ($templates as $template) {
+ \App\Models\ProjectTaskTemplate::where('id', $template->id)->update(['sort' => $index++]);
+ }
+ }
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ // no-op
+ }
+}
diff --git a/resources/assets/js/pages/manage/components/ProjectTaskTemplate/index.vue b/resources/assets/js/pages/manage/components/ProjectTaskTemplate/index.vue
index bb6739761..83de170e6 100644
--- a/resources/assets/js/pages/manage/components/ProjectTaskTemplate/index.vue
+++ b/resources/assets/js/pages/manage/components/ProjectTaskTemplate/index.vue
@@ -7,6 +7,14 @@