From e10aa073679d4eddfc8e590760cffbfde2b80886 Mon Sep 17 00:00:00 2001 From: JiaoTianBo Date: Tue, 31 Mar 2026 17:03:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(project):=20=E5=AE=9E=E7=8E=B0=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=92=8C=E9=87=8C=E7=A8=8B=E7=A2=91=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增项目里程碑相关API接口,包括增删改查和状态进度更新 - 新增项目任务相关API接口,支持任务列表查询及增删改查 - 在项目详情页增加任务与里程碑权限控制及操作按钮展示 - 实现任务和里程碑的新增、编辑和删除模态框及表单校验 - 支持任务优先级、状态、进度、负责人等字段的管理和展示 - 里程碑支持关键标记、计划与实际日期、交付物等信息编辑 - 任务列表以表格形式展示,支持按状态展示颜色和标签 - 里程碑时间线增加操作按钮,支持权限校验后编辑和删除 - 任务状态显示对应颜色和文本,提升用户体验 - 优化项目详情页布局,新增任务列表分区和样式调整 --- src/api/project.ts | 164 +++ src/api/默认模块.openapi.json | 1860 ++++++++++++++++++++++++++------- src/views/project/detail.vue | 1571 ++++++++++++++++++++-------- 3 files changed, 2745 insertions(+), 850 deletions(-) diff --git a/src/api/project.ts b/src/api/project.ts index b3ab19a..a7636ee 100644 --- a/src/api/project.ts +++ b/src/api/project.ts @@ -441,3 +441,167 @@ export const getTaskStatus = (taskId: string) => { `/api/v1/project-init/task/${taskId}` ); }; + +// ==================== 里程碑管理 API ==================== + +/** 里程碑查询参数 */ +export type MilestoneQueryParams = { + pageNum?: number; + pageSize?: number; + projectId?: string; + status?: string; +}; + +/** 分页查询里程碑列表 */ +export const getMilestoneList = (params?: MilestoneQueryParams) => { + return http.request>>( + "get", + "/api/v1/milestone/list", + { params } + ); +}; + +/** 根据ID查询里程碑详情 */ +export const getMilestoneById = (id: string) => { + return http.request>( + "get", + `/api/v1/milestone/${id}` + ); +}; + +/** 新增里程碑 */ +export const createMilestone = (data: ProjectMilestone) => { + return http.request>("post", "/api/v1/milestone", { data }); +}; + +/** 修改里程碑 */ +export const updateMilestone = (data: ProjectMilestone) => { + return http.request>("put", "/api/v1/milestone", { data }); +}; + +/** 删除里程碑 */ +export const deleteMilestone = (id: string) => { + return http.request>("delete", `/api/v1/milestone/${id}`); +}; + +/** 更新里程碑进度 */ +export const updateMilestoneProgress = (id: string, progress: number) => { + return http.request>("put", `/api/v1/milestone/${id}/progress`, { + params: { progress } + }); +}; + +/** 更新里程碑状态 */ +export const updateMilestoneStatus = (id: string, status: string) => { + return http.request>("put", `/api/v1/milestone/${id}/status`, { + params: { status } + }); +}; + +/** 查询已延期的关键里程碑 */ +export const getDelayedKeyMilestones = (projectId: string) => { + return http.request>( + "get", + "/api/v1/milestone/delayed-key", + { params: { projectId } } + ); +}; + +/** 查询即将到期的里程碑 */ +export const getUpcomingMilestones = (projectId: string, days: number = 7) => { + return http.request>( + "get", + "/api/v1/milestone/upcoming", + { params: { projectId, days } } + ); +}; + +/** 查询里程碑完成进度统计 */ +export const getMilestoneProgressStats = (projectId: string) => { + return http.request>>( + "get", + "/api/v1/milestone/stats/progress", + { params: { projectId } } + ); +}; + +// ==================== 任务管理 API ==================== + +/** 任务查询参数 */ +export type TaskQueryParams = { + pageNum?: number; + pageSize?: number; + projectId?: string; + milestoneId?: string; + assigneeId?: string; + status?: string; + priority?: string; + keyword?: string; +}; + +/** 分页查询任务列表 */ +export const getTaskList = (params?: TaskQueryParams) => { + return http.request>>( + "get", + "/api/v1/task/list", + { params } + ); +}; + +/** 根据ID查询任务详情 */ +export const getTaskById = (id: string) => { + return http.request>("get", `/api/v1/task/${id}`); +}; + +/** 新增任务 */ +export const createTask = (data: ProjectTask) => { + return http.request>("post", "/api/v1/task", { data }); +}; + +/** 修改任务 */ +export const updateTask = (data: ProjectTask) => { + return http.request>("put", "/api/v1/task", { data }); +}; + +/** 删除任务 */ +export const deleteTask = (id: string) => { + return http.request>("delete", `/api/v1/task/${id}`); +}; + +/** 查询我的待办任务 */ +export const getMyTodoTasks = (userId: string, projectId?: string) => { + return http.request>("get", "/api/v1/task/my-tasks", { + params: { userId, projectId } + }); +}; + +/** 更新任务进度 */ +export const updateTaskProgress = (id: string, progress: number) => { + return http.request>("put", `/api/v1/task/${id}/progress`, { + params: { progress } + }); +}; + +/** 更新任务状态 */ +export const updateTaskStatus = (id: string, status: string) => { + return http.request>("put", `/api/v1/task/${id}/status`, { + params: { status } + }); +}; + +/** 查询任务依赖关系 */ +export const getTaskDependencies = (id: string) => { + return http.request[]>>( + "get", + `/api/v1/task/${id}/dependencies` + ); +}; + +/** 统计项目任务状态分布 */ +export const getTaskStatusStats = (projectId: string) => { + return http.request[]>>( + "get", + "/api/v1/task/stats/status", + { params: { projectId } } + ); +}; diff --git a/src/api/默认模块.openapi.json b/src/api/默认模块.openapi.json index dee0a4f..20171b0 100644 --- a/src/api/默认模块.openapi.json +++ b/src/api/默认模块.openapi.json @@ -1,413 +1,1467 @@ { - "project": { - "project_name": "AIHR 智能简历筛选系统", - "project_type": "研发项目", - "description": "利用大语言模型(LLM)和自然语言处理(NLP)技术,实现简历的自动化解析、人岗匹配度评分及候选人排序,提升招聘效率。", - "objectives": "1. 效率提升:单份简历平均处理时间降低至10秒以内。2. 精准匹配:人岗匹配度评分准确率达到90%以上。3. 系统集成:无缝对接主流招聘网站及企业内部ATS。4. 合规安全:确保候选人数据脱敏处理,符合《个人信息保护法》要求。", - "plan_start_date": "2026-04-01", - "plan_end_date": "2026-09-30", - "budget": 2850000, - "currency": "CNY", - "priority": "high", - "tags": ["AI", "NLP", "LLM", "人力资源", "招聘系统"] + "openapi": "3.0.1", + "info": { + "title": "默认模块", + "description": "", + "version": "1.0.0" }, - "milestones": [ - { - "milestone_name": "M1 需求分析与架构设计", - "description": "需求评审通过,技术架构可行性验证完成。", - "plan_date": "2026-04-30", - "deliverables": "《需求规格说明书》、《系统架构设计文档》、《数据库设计文档》", - "owner_role": "产品负责人" + "tags": [], + "paths": { + "/api/v1/milestone/list": { + "get": { + "summary": "分页查询里程碑列表", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "pageNum", + "in": "query", + "description": "", + "required": true, + "example": 1, + "schema": { + "type": "integer" + } + }, + { + "name": "pageSize", + "in": "query", + "description": "", + "required": true, + "example": 10, + "schema": { + "type": "integer" + } + }, + { + "name": "projectId", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "status", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponsePageMapObject" + } + } + } + } + }, + "security": [] + } }, - { - "milestone_name": "M2 核心算法模型训练与验证", - "description": "模型在测试集上的准确率>85%,解析字段覆盖率>95%。", - "plan_date": "2026-06-15", - "deliverables": "简历解析引擎 V1.0、人岗匹配算法模型、测试报告", - "owner_role": "AI算法工程师" + "/api/v1/milestone/{id}": { + "get": { + "summary": "根据ID查询里程碑详情", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseProjectMilestone" + } + } + } + } + }, + "security": [] + }, + "delete": { + "summary": "删除里程碑", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } }, - { - "milestone_name": "M3 系统功能开发完成 (Alpha 版)", - "description": "核心功能(上传、解析、评分、搜索)闭环跑通。", - "plan_date": "2026-07-31", - "deliverables": "可运行的后端服务、前端管理界面、API 接口文档", - "owner_role": "项目经理" + "/api/v1/milestone": { + "post": { + "summary": "新增里程碑", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectMilestone", + "description": "" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseLong" + } + } + } + } + }, + "security": [] + }, + "put": { + "summary": "修改里程碑", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProjectMilestone", + "description": "" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } }, - { - "milestone_name": "M4 系统集成与内部测试 (Beta 版)", - "description": "支持并发用户数>50,响应时间<2秒,无严重 Bug。", - "plan_date": "2026-08-31", - "deliverables": "集成测试报告、性能测试报告、用户操作手册", - "owner_role": "测试工程师" + "/api/v1/milestone/{id}/progress": { + "put": { + "summary": "更新里程碑进度", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "progress", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } }, - { - "milestone_name": "M5 用户验收测试 (UAT) 与试点", - "description": "试点部门(人力资源部)确认功能满足业务需求。", - "plan_date": "2026-09-15", - "deliverables": "UAT 验收报告、试点运行反馈报告", - "owner_role": "产品负责人" + "/api/v1/milestone/{id}/status": { + "put": { + "summary": "更新里程碑状态", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "status", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } }, - { - "milestone_name": "M6 正式上线与交付", - "description": "系统正式部署至生产环境,完成全员培训。", - "plan_date": "2026-09-30", - "deliverables": "最终源代码、部署文档、运维手册、项目总结报告", - "owner_role": "项目经理" + "/api/v1/milestone/delayed-key": { + "get": { + "summary": "查询已延期的关键里程碑", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "projectId", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseListProjectMilestone" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/milestone/upcoming": { + "get": { + "summary": "查询即将到期的里程碑", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "projectId", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "days", + "in": "query", + "description": "", + "required": true, + "example": 7, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseListProjectMilestone" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/milestone/stats/progress": { + "get": { + "summary": "查询里程碑完成进度统计", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "projectId", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseMapObject" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/list": { + "get": { + "summary": "分页查询任务列表", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "pageNum", + "in": "query", + "description": "", + "required": true, + "example": 1, + "schema": { + "type": "integer" + } + }, + { + "name": "pageSize", + "in": "query", + "description": "", + "required": true, + "example": 10, + "schema": { + "type": "integer" + } + }, + { + "name": "projectId", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "milestoneId", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "assigneeId", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "status", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "priority", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "keyword", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponsePageMapObject" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/{id}": { + "get": { + "summary": "根据ID查询任务详情", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseTask" + } + } + } + } + }, + "security": [] + }, + "delete": { + "summary": "删除任务", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task": { + "post": { + "summary": "新增任务", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Task", + "description": "" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseLong" + } + } + } + } + }, + "security": [] + }, + "put": { + "summary": "修改任务", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Task", + "description": "" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/my-tasks": { + "get": { + "summary": "查询我的待办任务", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "userId", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "projectId", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseListTask" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/{id}/progress": { + "put": { + "summary": "更新任务进度", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "progress", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/{id}/status": { + "put": { + "summary": "更新任务状态", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "status", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseVoid" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/{id}/dependencies": { + "get": { + "summary": "查询任务依赖关系", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseListMapObject" + } + } + } + } + }, + "security": [] + } + }, + "/api/v1/task/stats/status": { + "get": { + "summary": "统计项目任务状态分布", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "projectId", + "in": "query", + "description": "", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95", + "schema": { + "type": "string", + "default": "Bearer b35c6f5b-bc0b-4652-bef2-eca04a5cdd95" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BaseResponseListMapObject" + } + } + } + } + }, + "security": [] + } } - ], - "tasks": [ - { - "task_id": "T001", - "task_name": "需求分析与产品设计", - "parent_task_id": null, - "description": "完成需求梳理、原型设计及用户故事编写", - "plan_start_date": "2026-04-01", - "plan_end_date": "2026-04-15", - "estimated_hours": 80, - "priority": "high", - "assignee_role": "产品负责人", - "dependencies": [], - "deliverables": "《需求规格说明书》、原型图" + }, + "components": { + "schemas": { + "OrderItem": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "需要进行排序的字段" + }, + "asc": { + "type": "boolean", + "description": "是否正序排列,默认 true", + "default": true + } + } + }, + "MapObject": { + "type": "object", + "properties": { + "key": { + "$ref": "#/components/schemas/key" + } + } + }, + "BaseResponseMapObject": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "$ref": "#/components/schemas/MapObject", + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "PageMapObject": { + "type": "object", + "properties": { + "records": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MapObject" + }, + "description": "查询数据列表", + "default": "Collections.emptyList()" + }, + "total": { + "type": "integer", + "description": "总数", + "format": "int64", + "default": 0 + }, + "size": { + "type": "integer", + "description": "每页显示条数,默认 10", + "format": "int64", + "default": 10 + }, + "current": { + "type": "integer", + "description": "当前页", + "format": "int64", + "default": 1 + }, + "orders": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrderItem", + "description": "com.baomidou.mybatisplus.core.metadata.OrderItem" + }, + "description": "排序字段信息", + "default": "new ArrayList<>()" + }, + "optimizeCountSql": { + "type": "boolean", + "description": "自动优化 COUNT SQL", + "default": true + }, + "searchCount": { + "type": "boolean", + "description": "是否进行 count 查询", + "default": true + }, + "optimizeJoinOfCountSql": { + "type": "boolean", + "description": "{@link #optimizeJoinOfCountSql()}", + "default": true + }, + "maxLimit": { + "type": "integer", + "description": "单页分页条数限制", + "format": "int64" + }, + "countId": { + "type": "string", + "description": "countId" + }, + "pages": { + "type": "integer", + "format": "int64" + } + } + }, + "BaseResponsePageMapObject": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "$ref": "#/components/schemas/PageMapObject", + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "ProjectMilestone": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "", + "format": "int64" + }, + "projectId": { + "type": "integer", + "description": "项目ID", + "format": "int64" + }, + "milestoneName": { + "type": "string", + "description": "里程碑名称" + }, + "description": { + "type": "string", + "description": "描述" + }, + "planDate": { + "type": "string", + "description": "计划日期" + }, + "actualDate": { + "type": "string", + "description": "实际日期" + }, + "status": { + "type": "string", + "description": "状态: pending-待开始, in_progress-进行中, completed-已完成, delayed-延期" + }, + "progress": { + "type": "integer", + "description": "完成进度" + }, + "sortOrder": { + "type": "integer", + "description": "排序" + }, + "isKey": { + "type": "integer", + "description": "是否关键里程碑: 1-是, 0-否" + }, + "deliverables": { + "type": "array", + "items": { + "type": "string" + }, + "description": "交付物列表" + }, + "extraData": { + "type": "object", + "properties": {}, + "description": "扩展数据" + }, + "createBy": { + "type": "integer", + "description": "创建人", + "format": "int64" + }, + "createTime": { + "type": "string", + "description": "创建时间" + }, + "updateBy": { + "type": "integer", + "description": "更新人", + "format": "int64" + }, + "updateTime": { + "type": "string", + "description": "更新时间" + }, + "deleted": { + "type": "integer", + "description": "删除标记" + } + } + }, + "Task": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "", + "format": "int64" + }, + "taskCode": { + "type": "string", + "description": "任务编号" + }, + "projectId": { + "type": "integer", + "description": "项目ID", + "format": "int64" + }, + "milestoneId": { + "type": "integer", + "description": "所属里程碑ID", + "format": "int64" + }, + "taskName": { + "type": "string", + "description": "任务名称" + }, + "description": { + "type": "string", + "description": "任务描述" + }, + "taskType": { + "type": "string", + "description": "任务类型" + }, + "assigneeId": { + "type": "integer", + "description": "执行人ID", + "format": "int64" + }, + "planStartDate": { + "type": "string", + "description": "计划开始日期" + }, + "planEndDate": { + "type": "string", + "description": "计划结束日期" + }, + "actualStartDate": { + "type": "string", + "description": "实际开始日期" + }, + "actualEndDate": { + "type": "string", + "description": "实际结束日期" + }, + "planHours": { + "type": "number", + "description": "计划工时(小时)" + }, + "actualHours": { + "type": "number", + "description": "实际工时(小时)" + }, + "progress": { + "type": "integer", + "description": "进度百分比" + }, + "priority": { + "type": "string", + "description": "优先级: critical-关键, high-高, medium-中, low-低" + }, + "status": { + "type": "string", + "description": "状态: pending-待开始, in_progress-进行中, completed-已完成, cancelled-已取消" + }, + "sortOrder": { + "type": "integer", + "description": "排序" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "标签" + }, + "attachments": { + "type": "array", + "items": { + "type": "object", + "properties": {} + }, + "description": "附件列表" + }, + "extraData": { + "type": "object", + "properties": {}, + "description": "扩展数据" + }, + "createBy": { + "type": "integer", + "description": "创建人", + "format": "int64" + }, + "createTime": { + "type": "string", + "description": "创建时间" + }, + "updateBy": { + "type": "integer", + "description": "更新人", + "format": "int64" + }, + "updateTime": { + "type": "string", + "description": "更新时间" + }, + "deleted": { + "type": "integer", + "description": "删除标记" + } + } + }, + "key": { + "type": "object", + "properties": {} + }, + "BaseResponseLong": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "type": "integer", + "description": "", + "format": "int64" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "BaseResponseProjectMilestone": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "$ref": "#/components/schemas/ProjectMilestone", + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "BaseResponseTask": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "$ref": "#/components/schemas/Task", + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "BaseResponseVoid": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "description": "", + "type": "null" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "BaseResponseListProjectMilestone": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectMilestone", + "description": "项目里程碑实体类\n对应数据库表: project_milestone" + }, + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "BaseResponseListTask": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Task", + "description": "任务实体类\n对应数据库表: task" + }, + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + }, + "BaseResponseListMapObject": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "description": "" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MapObject" + }, + "description": "" + }, + "message": { + "type": "string", + "description": "" + } + } + } }, - { - "task_id": "T002", - "task_name": "技术架构与数据库设计", - "parent_task_id": null, - "description": "系统整体技术选型、架构设计及数据库设计", - "plan_start_date": "2026-04-16", - "plan_end_date": "2026-04-30", - "estimated_hours": 80, - "priority": "high", - "assignee_role": "技术架构师", - "dependencies": ["T001"], - "deliverables": "《系统架构设计文档》、《数据库设计文档》" - }, - { - "task_id": "T003", - "task_name": "数据清洗与标注", - "parent_task_id": null, - "description": "历史简历数据的清洗、标注及训练数据集构建", - "plan_start_date": "2026-04-10", - "plan_end_date": "2026-05-15", - "estimated_hours": 100, - "priority": "high", - "assignee_role": "数据标注专员", - "dependencies": ["T001"], - "deliverables": "训练数据集" - }, - { - "task_id": "T004", - "task_name": "算法模型训练与调优", - "parent_task_id": null, - "description": "NLP模型选型、简历解析算法开发及匹配模型训练", - "plan_start_date": "2026-05-01", - "plan_end_date": "2026-06-15", - "estimated_hours": 260, - "priority": "high", - "assignee_role": "AI算法工程师", - "dependencies": ["T003"], - "deliverables": "简历解析引擎、算法模型" - }, - { - "task_id": "T005", - "task_name": "后端功能开发", - "parent_task_id": null, - "description": "后端API开发、数据库对接及高并发处理优化", - "plan_start_date": "2026-05-01", - "plan_end_date": "2026-07-15", - "estimated_hours": 320, - "priority": "high", - "assignee_role": "后端开发工程师", - "dependencies": ["T002"], - "deliverables": "后端服务、API接口文档" - }, - { - "task_id": "T006", - "task_name": "前端页面开发", - "parent_task_id": null, - "description": "管理后台前端页面开发、数据可视化展示及交互实现", - "plan_start_date": "2026-05-15", - "plan_end_date": "2026-07-15", - "estimated_hours": 320, - "priority": "high", - "assignee_role": "前端开发工程师", - "dependencies": ["T002"], - "deliverables": "前端管理界面" - }, - { - "task_id": "T007", - "task_name": "系统联调与Alpha版发布", - "parent_task_id": null, - "description": "前后端联调、算法模型集成及核心功能闭环测试", - "plan_start_date": "2026-07-16", - "plan_end_date": "2026-07-31", - "estimated_hours": 120, - "priority": "high", - "assignee_role": "后端开发工程师", - "dependencies": ["T004", "T005", "T006"], - "deliverables": "Alpha版系统" - }, - { - "task_id": "T008", - "task_name": "系统集成与性能测试", - "parent_task_id": null, - "description": "功能测试、性能测试及自动化测试脚本编写", - "plan_start_date": "2026-08-01", - "plan_end_date": "2026-08-31", - "estimated_hours": 160, - "priority": "high", - "assignee_role": "测试工程师", - "dependencies": ["T007"], - "deliverables": "集成测试报告、性能测试报告" - }, - { - "task_id": "T009", - "task_name": "UAT验收与试点运行", - "parent_task_id": null, - "description": "组织人力资源部进行用户验收测试并收集反馈", - "plan_start_date": "2026-09-01", - "plan_end_date": "2026-09-15", - "estimated_hours": 80, - "priority": "medium", - "assignee_role": "产品负责人", - "dependencies": ["T008"], - "deliverables": "UAT验收报告" - }, - { - "task_id": "T010", - "task_name": "正式上线与培训部署", - "parent_task_id": null, - "description": "系统生产环境部署、全员培训及总结报告编写", - "plan_start_date": "2026-09-16", - "plan_end_date": "2026-09-30", - "estimated_hours": 80, - "priority": "high", - "assignee_role": "项目经理", - "dependencies": ["T009"], - "deliverables": "部署文档、运维手册、最终源代码" - } - ], - "members": [ - { - "name": "张伟", - "role_code": "manager", - "responsibility": "负责整体项目规划、进度控制、风险管理及跨部门协调。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "李娜", - "role_code": "leader", - "responsibility": "负责需求梳理、原型设计、用户故事编写及验收测试。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "王强", - "role_code": "leader", - "responsibility": "负责系统整体技术选型、架构设计、核心技术难点攻关。", - "department": "未来科技研发部", - "weekly_hours": 20 - }, - { - "name": "陈思", - "role_code": "member", - "responsibility": "负责 NLP 模型选型、简历解析算法开发、匹配模型训练与调优。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "赵杰", - "role_code": "member", - "responsibility": "负责后端 API 开发、数据库设计、第三方系统接口对接。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "刘洋", - "role_code": "member", - "responsibility": "协助后端开发,负责高并发处理及缓存策略优化。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "孙丽", - "role_code": "member", - "responsibility": "负责管理后台前端页面开发、数据可视化展示及交互实现。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "周敏", - "role_code": "member", - "responsibility": "负责测试用例编写、功能测试、性能测试及自动化测试脚本。", - "department": "未来科技研发部", - "weekly_hours": 40 - }, - { - "name": "吴凯", - "role_code": "member", - "responsibility": "负责系统界面设计、用户体验优化及交互规范制定。", - "department": "未来科技研发部", - "weekly_hours": 20 - }, - { - "name": "郑浩", - "role_code": "member", - "responsibility": "负责历史简历数据的清洗、标注及训练数据集构建。", - "department": "未来科技研发部", - "weekly_hours": 20 - } - ], - "resources": [ - { - "resource_name": "高性能云服务器", - "resource_type": "equipment", - "quantity": 5, - "unit": "台", - "unit_price": 0, - "supplier": "云服务商" - }, - { - "resource_name": "云端GPU算力(A100/A800)", - "resource_type": "equipment", - "quantity": 2000, - "unit": "小时", - "unit_price": 0, - "supplier": "GPU云服务提供商" - }, - { - "resource_name": "对象存储", - "resource_type": "equipment", - "quantity": 5, - "unit": "TB", - "unit_price": 0, - "supplier": "云服务商" - }, - { - "resource_name": "历史简历数据", - "resource_type": "material", - "quantity": 100000, - "unit": "份", - "unit_price": 0, - "supplier": "企业内部" - }, - { - "resource_name": "简历-JD匹配对标注数据集", - "resource_type": "material", - "quantity": 5000, - "unit": "对", - "unit_price": 0, - "supplier": "内部构建" - }, - { - "resource_name": "OCR识别 API", - "resource_type": "software", - "quantity": 1, - "unit": "套", - "unit_price": 0, - "supplier": "第三方服务商" - }, - { - "resource_name": "大模型调用 API", - "resource_type": "software", - "quantity": 1, - "unit": "套", - "unit_price": 0, - "supplier": "第三方大模型服务商" - }, - { - "resource_name": "法律合规咨询服务", - "resource_type": "human", - "quantity": 1, - "unit": "项", - "unit_price": 0, - "supplier": "外部法律顾问" - } - ], - "risks": [ - { - "risk_name": "数据合规与隐私泄露风险", - "category": "other", - "description": "处理大量包含个人隐私的简历数据,可能违反《个人信息保护法》或引发数据泄露。", - "probability": 5, - "impact": 5, - "mitigation_plan": "聘请专业法律顾问审核数据采集、存储及使用流程;对所有简历数据进行严格的脱敏处理和加密存储。" - }, - { - "risk_name": "模型匹配准确率不达标", - "category": "technical", - "description": "人岗匹配度评分准确率难以达到预期的90%以上目标。", - "probability": 40, - "impact": 4, - "mitigation_plan": "构建高质量的专家标注数据集,引入人力资源专家进行人工抽检复核,持续微调和优化算法模型。" - }, - { - "risk_name": "系统并发性能瓶颈", - "category": "technical", - "description": "在处理大量并发解析请求时,系统响应时间可能超过2秒或出现崩溃。", - "probability": 35, - "impact": 4, - "mitigation_plan": "优化系统架构,引入Redis缓存和负载均衡机制,并在Beta阶段进行充分的压力测试和性能调优。" - }, - { - "risk_name": "第三方API依赖及限流风险", - "category": "schedule", - "description": "过度依赖外部大模型API和OCR服务,可能因网络延迟或服务商限流影响项目进度和系统稳定性。", - "probability": 25, - "impact": 3, - "mitigation_plan": "设计灵活的接口适配层以支持多家API服务商切换,并在必要时考虑本地部署轻量级备用模型。" - } - ], - "timeline_nodes": [ - { - "node_name": "项目正式启动", - "node_type": "event", - "plan_date": "2026-04-01", - "description": "项目团队组建完毕,进入需求分析阶段", - "kb_scope": ["file"] - }, - { - "node_name": "需求与架构设计完成", - "node_type": "milestone", - "plan_date": "2026-04-30", - "description": "完成M1里程碑,架构设计通过评审", - "kb_scope": ["report", "file"] - }, - { - "node_name": "核心算法就绪", - "node_type": "milestone", - "plan_date": "2026-06-15", - "description": "完成M2里程碑,模型准确率达标", - "kb_scope": ["report", "file", "risk"] - }, - { - "node_name": "Alpha版发布", - "node_type": "milestone", - "plan_date": "2026-07-31", - "description": "完成M3里程碑,系统核心功能闭环跑通", - "kb_scope": ["report", "ticket"] - }, - { - "node_name": "Beta版发布", - "node_type": "milestone", - "plan_date": "2026-08-31", - "description": "完成M4里程碑,内部集成测试与性能测试完成", - "kb_scope": ["report", "ticket", "risk"] - }, - { - "node_name": "UAT验收通过", - "node_type": "milestone", - "plan_date": "2026-09-15", - "description": "完成M5里程碑,试点部门确认功能满足需求", - "kb_scope": ["report", "ticket"] - }, - { - "node_name": "项目正式上线交付", - "node_type": "milestone", - "plan_date": "2026-09-30", - "description": "完成M6里程碑,生产环境部署及全员培训完成", - "kb_scope": ["report", "file"] - } - ] + "responses": {}, + "securitySchemes": {} + }, + "servers": [], + "security": [] } diff --git a/src/views/project/detail.vue b/src/views/project/detail.vue index 1cbc82d..c38025b 100644 --- a/src/views/project/detail.vue +++ b/src/views/project/detail.vue @@ -4,6 +4,12 @@ import { useRoute, useRouter } from "vue-router"; import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { getProjectDetail, + createTask, + updateTask, + deleteTask, + createMilestone, + updateMilestone, + deleteMilestone, type ProjectDetail, type ProjectMember, type ProjectMilestone, @@ -11,6 +17,7 @@ import { type ProjectResource, type ProjectRisk } from "@/api/project"; +import { hasPerms } from "@/utils/auth"; import { GGanttChart, GGanttRow } from "@infectoone/vue-ganttastic"; import { message } from "@/utils/message"; import dayjs from "dayjs"; @@ -39,6 +46,16 @@ const route = useRoute(); const router = useRouter(); const projectId = ref(route.params.id as string); +// 权限控制 - 任务(基础权限) +const canCreateTask = computed(() => hasPerms("project:task:create")); +const canUpdateTask = computed(() => hasPerms("project:task:update")); +const canDeleteTask = computed(() => hasPerms("project:task:delete")); + +// 权限控制 - 里程碑(基础权限) +const canCreateMilestone = computed(() => hasPerms("project:milestone:create")); +const canUpdateMilestone = computed(() => hasPerms("project:milestone:update")); +const canDeleteMilestone = computed(() => hasPerms("project:milestone:delete")); + // 加载状态 const loading = ref(false); const ganttLoading = ref(false); @@ -63,6 +80,65 @@ const projectDetail = ref(null); const memberDetailModal = ref(false); const selectedMember = ref(null); +// 任务编辑模态框 +const taskEditModal = ref(false); +const taskEditForm = ref({ + id: "", + taskName: "", + description: "", + taskType: "", + milestoneId: "", + assigneeId: "", + assigneeName: "", + planStartDate: "", + planEndDate: "", + actualStartDate: "", + actualEndDate: "", + planHours: 0, + actualHours: 0, + progress: 0, + priority: "medium", + status: "pending", + sortOrder: 0 +}); +const taskEditLoading = ref(false); +const isTaskEdit = ref(false); // true=编辑, false=新增 + +// 里程碑编辑模态框 +const milestoneEditModal = ref(false); +const milestoneEditForm = ref({ + id: "", + milestoneName: "", + description: "", + planDate: "", + actualDate: "", + status: "pending", + progress: 0, + isKey: 0, + deliverables: "", + sortOrder: 0 +}); +const milestoneEditLoading = ref(false); +const isMilestoneEdit = ref(false); // true=编辑, false=新增 + +// 权限控制 - 派生权限(需要放在 isTaskEdit/isMilestoneEdit 定义之后) +// 任务编辑权限:新增或编辑任一即可显示按钮 +const canEditTask = computed(() => canCreateTask.value || canUpdateTask.value); +// 任务保存权限:新增时需要create权限,编辑时需要update权限 +const canSaveTask = computed(() => { + return isTaskEdit.value ? canUpdateTask.value : canCreateTask.value; +}); +// 里程碑编辑权限:新增或编辑任一即可显示按钮 +const canEditMilestone = computed( + () => canCreateMilestone.value || canUpdateMilestone.value +); +// 里程碑保存权限:新增时需要create权限,编辑时需要update权限 +const canSaveMilestone = computed(() => { + return isMilestoneEdit.value + ? canUpdateMilestone.value + : canCreateMilestone.value; +}); + // 项目基本信息(计算属性) const projectInfo = computed(() => { const data = projectDetail.value; @@ -257,6 +333,42 @@ function getTaskColor(status?: string, progress?: number): string { return "#409eff"; // 默认 - 蓝色 } +// 获取任务状态标签类型 +function getTaskStatusType( + status?: string +): "success" | "warning" | "info" | "primary" | "danger" { + switch (status) { + case "completed": + return "success"; + case "in_progress": + case "ongoing": + return "primary"; + case "pending": + return "warning"; + case "delayed": + return "danger"; + case "paused": + case "cancelled": + return "info"; + default: + return "info"; + } +} + +// 获取任务状态文本 +function getTaskStatusText(status?: string): string { + const statusMap: Record = { + completed: "已完成", + in_progress: "进行中", + ongoing: "进行中", + pending: "待开始", + delayed: "延期", + paused: "暂停", + cancelled: "已取消" + }; + return statusMap[status || ""] || "待开始"; +} + // 将里程碑数据转换为 vue-ganttastic 格式 const ganttMilestones = computed(() => { return milestoneList.value.map(milestone => ({ @@ -440,6 +552,153 @@ function getRiskLevelType( } } +// ==================== 任务编辑功能 ==================== + +/** 打开新增任务对话框 */ +function openAddTaskModal() { + isTaskEdit.value = false; + taskEditForm.value = { + id: "", + taskName: "", + description: "", + taskType: "", + milestoneId: "", + assigneeId: "", + assigneeName: "", + planStartDate: "", + planEndDate: "", + actualStartDate: "", + actualEndDate: "", + planHours: 0, + actualHours: 0, + progress: 0, + priority: "medium", + status: "pending", + sortOrder: taskList.value.length + }; + taskEditModal.value = true; +} + +/** 打开编辑任务对话框 */ +function openEditTaskModal(task: ProjectTask) { + isTaskEdit.value = true; + taskEditForm.value = { ...task }; + taskEditModal.value = true; +} + +/** 保存任务 */ +async function saveTask() { + if (!taskEditForm.value.taskName) { + message("请输入任务名称", { type: "warning" }); + return; + } + taskEditLoading.value = true; + try { + const data = { + ...taskEditForm.value, + projectId: projectId.value + }; + if (isTaskEdit.value) { + await updateTask(data); + message("任务更新成功", { type: "success" }); + } else { + await createTask(data); + message("任务创建成功", { type: "success" }); + } + taskEditModal.value = false; + await fetchProjectDetail(); + } catch (error) { + console.error("保存任务失败:", error); + message("保存任务失败", { type: "error" }); + } finally { + taskEditLoading.value = false; + } +} + +/** 删除任务 */ +async function handleDeleteTask(taskId: string) { + try { + await deleteTask(taskId); + message("任务删除成功", { type: "success" }); + await fetchProjectDetail(); + } catch (error) { + console.error("删除任务失败:", error); + message("删除任务失败", { type: "error" }); + } +} + +// ==================== 里程碑编辑功能 ==================== + +/** 打开新增里程碑对话框 */ +function openAddMilestoneModal() { + isMilestoneEdit.value = false; + milestoneEditForm.value = { + id: "", + milestoneName: "", + description: "", + planDate: "", + actualDate: "", + status: "pending", + progress: 0, + isKey: 0, + deliverables: "", + sortOrder: milestoneList.value.length + }; + milestoneEditModal.value = true; +} + +/** 打开编辑里程碑对话框 */ +function openEditMilestoneModal(milestone: ProjectMilestone) { + isMilestoneEdit.value = true; + milestoneEditForm.value = { ...milestone }; + milestoneEditModal.value = true; +} + +/** 保存里程碑 */ +async function saveMilestone() { + if (!milestoneEditForm.value.milestoneName) { + message("请输入里程碑名称", { type: "warning" }); + return; + } + if (!milestoneEditForm.value.planDate) { + message("请选择计划日期", { type: "warning" }); + return; + } + milestoneEditLoading.value = true; + try { + const data = { + ...milestoneEditForm.value, + projectId: projectId.value + }; + if (isMilestoneEdit.value) { + await updateMilestone(data); + message("里程碑更新成功", { type: "success" }); + } else { + await createMilestone(data); + message("里程碑创建成功", { type: "success" }); + } + milestoneEditModal.value = false; + await fetchProjectDetail(); + } catch (error) { + console.error("保存里程碑失败:", error); + message("保存里程碑失败", { type: "error" }); + } finally { + milestoneEditLoading.value = false; + } +} + +/** 删除里程碑 */ +async function handleDeleteMilestone(milestoneId: string) { + try { + await deleteMilestone(milestoneId); + message("里程碑删除成功", { type: "success" }); + await fetchProjectDetail(); + } catch (error) { + console.error("删除里程碑失败:", error); + message("删除里程碑失败", { type: "error" }); + } +} + onMounted(() => { fetchProjectDetail(); fetchGanttData(); @@ -447,469 +706,874 @@ onMounted(() => {