From 87bdef6416d42c552b75fad5492c172a37bb19fa Mon Sep 17 00:00:00 2001 From: JiaoTianBo Date: Sat, 28 Mar 2026 15:25:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(project):=20=E6=96=B0=E5=A2=9E=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增项目菜单项及路由配置,支持项目管理入口 - 实现项目相关API接口,包括项目列表、统计、甘特图及项目初始化接口 - 添加项目新建向导组件,支持上传文件预览及确认保存 - 实现项目管理页面,包含项目列表展示、筛选、统计卡片及新建项目操作 - 支持项目基本信息、里程碑、任务、成员及风险等多维度管理数据录入 - 优化页面交互体验,支持上传文件格式校验及数据编辑预览 - 提供状态及风险等级标签显示,辅助项目状态快速识别 --- locales/en.yaml | 1 + locales/zh-CN.yaml | 1 + src/api/project.ts | 241 ++++++ src/api/默认模块.openapi.json | 486 ++++++++++-- src/router/enums.ts | 54 +- src/router/modules/project.ts | 22 + src/utils/http/index.ts | 2 +- .../components/CreateProjectWizard.vue | 722 ++++++++++++++++++ src/views/project/index.vue | 467 +++++++++++ src/views/project/utils/hook.tsx | 154 ++++ src/views/project/utils/types.ts | 79 ++ 11 files changed, 2125 insertions(+), 104 deletions(-) create mode 100644 src/api/project.ts create mode 100644 src/router/modules/project.ts create mode 100644 src/views/project/components/CreateProjectWizard.vue create mode 100644 src/views/project/index.vue create mode 100644 src/views/project/utils/hook.tsx create mode 100644 src/views/project/utils/types.ts diff --git a/locales/en.yaml b/locales/en.yaml index 7ff11b5..73b7422 100644 --- a/locales/en.yaml +++ b/locales/en.yaml @@ -69,6 +69,7 @@ panel: pureMultiTagsCache: MultiTags Cache menus: pureHome: Home + pureProject: Project Management pureLogin: Login pureEmpty: Empty Page pureTable: Table diff --git a/locales/zh-CN.yaml b/locales/zh-CN.yaml index c6b318b..53a0d28 100644 --- a/locales/zh-CN.yaml +++ b/locales/zh-CN.yaml @@ -69,6 +69,7 @@ panel: pureMultiTagsCache: 页签持久化 menus: pureHome: 首页 + pureProject: 项目管理 pureLogin: 登录 pureEmpty: 无Layout页 pureTable: 表格 diff --git a/src/api/project.ts b/src/api/project.ts new file mode 100644 index 0000000..391ebcb --- /dev/null +++ b/src/api/project.ts @@ -0,0 +1,241 @@ +import { http } from "@/utils/http"; + +/** 通用响应结果 */ +type Result = { + code: number; + message: string; + data?: T; +}; + +// ==================== 项目列表 ==================== + +/** 项目列表项 - 根据 OpenAPI 定义 */ +export type ProjectItem = { + id?: number; + projectCode?: string; + projectName?: string; + projectType?: string; + managerId?: number; + managerName?: string; + planStartDate?: string; + planEndDate?: string; + progress?: number; + status?: string; + priority?: string; + riskLevel?: string; + tags?: string[]; + budget?: number; + cost?: number; + createTime?: string; + myRole?: string; +}; + +/** 分页数据结构 */ +export type TableDataInfo = { + total: number; + rows: T[]; + code: number; + msg: string; +}; + +/** 项目查询参数 */ +export type ProjectQueryParams = { + pageNum?: number; + pageSize?: number; + keyword?: string; + status?: string; +}; + +/** 分页查询项目列表 */ +export const getProjectList = (params?: ProjectQueryParams) => { + return http.request>>( + "get", + "/api/v1/project/list", + { params } + ); +}; + +/** 删除项目 */ +export const deleteProject = (id: number) => { + return http.request>("delete", `/api/v1/project/${id}`); +}; + +// ==================== 项目统计 ==================== + +/** 项目统计数据 - 根据 OpenAPI 定义 */ +export type ProjectStatistics = { + totalCount: number; + ongoingCount: number; + completedCount: number; + pausedCount: number; + planningCount: number; + cancelledCount: number; + draftCount: number; + statusCountMap: Record; + newThisMonth: number; + aboutToExpireCount: number; + averageProgress: number; + highRiskCount: number; +}; + +/** 获取项目统计数据 */ +export const getProjectStatistics = () => { + return http.request>( + "get", + "/api/v1/project/statistics" + ); +}; + +// ==================== 项目甘特图 ==================== + +/** 甘特图任务 */ +export type GanttTask = { + id?: number; + taskName?: string; + type?: string; // task-任务, milestone-里程碑 + startDate?: string; + endDate?: string; + actualStartDate?: string; + actualEndDate?: string; + progress?: number; + status?: string; + priority?: string; + parentId?: number; + sortOrder?: number; + assigneeName?: string; + dependencies?: number[]; +}; + +/** 项目甘特图数据 */ +export type ProjectGantt = { + projectId?: number; + projectName?: string; + projectStatus?: string; + projectStartDate?: string; + projectEndDate?: string; + projectProgress?: number; + tasks?: GanttTask[]; + milestones?: GanttTask[]; +}; + +/** 获取项目甘特图数据 */ +export const getProjectGantt = (projectId: number) => { + return http.request>( + "get", + `/api/v1/project/${projectId}/gantt` + ); +}; + +// ==================== 项目初始化(复用 system.ts 中的定义) ==================== + +/** 项目信息 */ +export type ProjectInfo = { + project_name?: string; + project_type?: string; + description?: string; + objectives?: string; + plan_start_date?: string; + plan_end_date?: string; + budget?: number; + currency?: string; + priority?: string; + tags?: string[]; +}; + +/** 里程碑信息 */ +export type MilestoneInfo = { + milestone_name?: string; + description?: string; + plan_date?: string; + deliverables?: string; + owner_role?: string; +}; + +/** 任务信息 */ +export type TaskInfo = { + task_id?: string; + task_name?: string; + parent_task_id?: string; + description?: string; + plan_start_date?: string; + plan_end_date?: string; + estimated_hours?: number; + priority?: string; + assignee_role?: string; + dependencies?: string[]; + deliverables?: string; +}; + +/** 成员信息 */ +export type MemberInfo = { + name?: string; + role_code?: string; + responsibility?: string; + department?: string; + weekly_hours?: number; +}; + +/** 资源信息 */ +export type ResourceInfo = { + resource_name?: string; + resource_type?: string; + quantity?: number; + unit?: string; + unit_price?: number; + supplier?: string; +}; + +/** 风险信息 */ +export type RiskInfo = { + risk_name?: string; + category?: string; + description?: string; + probability?: number; + impact?: number; + mitigation_plan?: string; +}; + +/** 时间节点信息 */ +export type TimelineNodeInfo = { + node_name?: string; + node_type?: string; + plan_date?: string; + description?: string; + kb_scope?: string[]; +}; + +/** 项目初始化结果 */ +export type ProjectInitResult = { + project: ProjectInfo; + milestones: MilestoneInfo[]; + tasks: TaskInfo[]; + members: MemberInfo[]; + resources: ResourceInfo[]; + risks: RiskInfo[]; + timeline_nodes: TimelineNodeInfo[]; +}; + +/** 上传文件并生成项目初始化预览数据 */ +export const previewProjectInit = (file: File) => { + const formData = new FormData(); + formData.append("file", file); + return http.request>( + "post", + "/api/v1/project-init/preview", + { data: formData }, + { + headers: { + "Content-Type": undefined + } + } + ); +}; + +/** 确认并保存项目初始化数据 */ +export const confirmProjectInit = (data: ProjectInitResult) => { + return http.request>( + "post", + "/api/v1/project-init/confirm", + { data } + ); +}; diff --git a/src/api/默认模块.openapi.json b/src/api/默认模块.openapi.json index b3956c3..dee0a4f 100644 --- a/src/api/默认模块.openapi.json +++ b/src/api/默认模块.openapi.json @@ -1,81 +1,413 @@ { - "openapi": "3.0.1", - "info": { - "title": "默认模块", - "description": "", - "version": "1.0.0" + "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", "人力资源", "招聘系统"] }, - "tags": [], - "paths": { - "/api/v1/system/role/{id}/menu-ids": { - "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 000b7e25-53b2-42a3-a39b-9f4cb03644ba", - "schema": { - "type": "string", - "default": "Bearer 000b7e25-53b2-42a3-a39b-9f4cb03644ba" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BaseResponseListLong" - } - } - } - } - }, - "security": [] - } - } - }, - "components": { - "schemas": { - "BaseResponseListLong": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "description": "" - }, - "data": { - "type": "array", - "items": { - "type": "integer" - }, - "description": "" - }, - "message": { - "type": "string", - "description": "" - } - } - } + "milestones": [ + { + "milestone_name": "M1 需求分析与架构设计", + "description": "需求评审通过,技术架构可行性验证完成。", + "plan_date": "2026-04-30", + "deliverables": "《需求规格说明书》、《系统架构设计文档》、《数据库设计文档》", + "owner_role": "产品负责人" }, - "responses": {}, - "securitySchemes": {} - }, - "servers": [], - "security": [] + { + "milestone_name": "M2 核心算法模型训练与验证", + "description": "模型在测试集上的准确率>85%,解析字段覆盖率>95%。", + "plan_date": "2026-06-15", + "deliverables": "简历解析引擎 V1.0、人岗匹配算法模型、测试报告", + "owner_role": "AI算法工程师" + }, + { + "milestone_name": "M3 系统功能开发完成 (Alpha 版)", + "description": "核心功能(上传、解析、评分、搜索)闭环跑通。", + "plan_date": "2026-07-31", + "deliverables": "可运行的后端服务、前端管理界面、API 接口文档", + "owner_role": "项目经理" + }, + { + "milestone_name": "M4 系统集成与内部测试 (Beta 版)", + "description": "支持并发用户数>50,响应时间<2秒,无严重 Bug。", + "plan_date": "2026-08-31", + "deliverables": "集成测试报告、性能测试报告、用户操作手册", + "owner_role": "测试工程师" + }, + { + "milestone_name": "M5 用户验收测试 (UAT) 与试点", + "description": "试点部门(人力资源部)确认功能满足业务需求。", + "plan_date": "2026-09-15", + "deliverables": "UAT 验收报告、试点运行反馈报告", + "owner_role": "产品负责人" + }, + { + "milestone_name": "M6 正式上线与交付", + "description": "系统正式部署至生产环境,完成全员培训。", + "plan_date": "2026-09-30", + "deliverables": "最终源代码、部署文档、运维手册、项目总结报告", + "owner_role": "项目经理" + } + ], + "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": "《需求规格说明书》、原型图" + }, + { + "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"] + } + ] } diff --git a/src/router/enums.ts b/src/router/enums.ts index d9c1d66..6f2e04b 100644 --- a/src/router/enums.ts +++ b/src/router/enums.ts @@ -2,36 +2,38 @@ const home = 0, // 平台规定只有 home 路由的 rank 才能为 0 ,所以后端在返回 rank 的时候需要从非 0 开始 chatai = 1, - vueflow = 2, - ganttastic = 3, - components = 4, - able = 5, - table = 6, - form = 7, - list = 8, - result = 9, - error = 10, - frame = 11, - nested = 12, - permission = 13, - system = 14, - monitor = 15, - tabs = 16, - about = 17, - codemirror = 18, - markdown = 19, - editor = 20, - flowchart = 21, - formdesign = 22, - board = 23, - ppt = 24, - mind = 25, - guide = 26, - menuoverflow = 27; + project = 2, + vueflow = 3, + ganttastic = 4, + components = 5, + able = 6, + table = 7, + form = 8, + list = 9, + result = 10, + error = 11, + frame = 12, + nested = 13, + permission = 14, + system = 15, + monitor = 16, + tabs = 17, + about = 18, + codemirror = 19, + markdown = 20, + editor = 21, + flowchart = 22, + formdesign = 23, + board = 24, + ppt = 25, + mind = 26, + guide = 27, + menuoverflow = 28; export { home, chatai, + project, vueflow, ganttastic, components, diff --git a/src/router/modules/project.ts b/src/router/modules/project.ts new file mode 100644 index 0000000..0086416 --- /dev/null +++ b/src/router/modules/project.ts @@ -0,0 +1,22 @@ +import { $t } from "@/plugins/i18n"; +import { project } from "@/router/enums"; + +export default { + path: "/project", + redirect: "/project/index", + meta: { + icon: "ri:folder-chart-line", + title: $t("menus.pureProject"), + rank: project + }, + children: [ + { + path: "/project/index", + name: "Project", + component: () => import("@/views/project/index.vue"), + meta: { + title: $t("menus.pureProject") + } + } + ] +} satisfies RouteConfigsTable; diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts index 053c6ff..fdd622d 100644 --- a/src/utils/http/index.ts +++ b/src/utils/http/index.ts @@ -18,7 +18,7 @@ import { useUserStoreHook } from "@/store/modules/user"; // 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1 const defaultConfig: AxiosRequestConfig = { // 请求超时时间 - timeout: 10000, + timeout: 600000, headers: { Accept: "application/json, text/plain, */*", "Content-Type": "application/json", diff --git a/src/views/project/components/CreateProjectWizard.vue b/src/views/project/components/CreateProjectWizard.vue new file mode 100644 index 0000000..2defa88 --- /dev/null +++ b/src/views/project/components/CreateProjectWizard.vue @@ -0,0 +1,722 @@ + + + + + diff --git a/src/views/project/index.vue b/src/views/project/index.vue new file mode 100644 index 0000000..6805237 --- /dev/null +++ b/src/views/project/index.vue @@ -0,0 +1,467 @@ + + + + + diff --git a/src/views/project/utils/hook.tsx b/src/views/project/utils/hook.tsx new file mode 100644 index 0000000..75b4769 --- /dev/null +++ b/src/views/project/utils/hook.tsx @@ -0,0 +1,154 @@ +import { message } from "@/utils/message"; +import type { PaginationProps } from "@pureadmin/table"; +import type { ProjectItem, ProjectStatistics } from "@/api/project"; +import { + getProjectList, + getProjectStatistics, + deleteProject +} from "@/api/project"; +import { ref, reactive, onMounted } from "vue"; + +export function useProject() { + const form = reactive({ + keyword: "", + status: "" + }); + + const formRef = ref(); + const dataList = ref([]); + const loading = ref(true); + const statistics = ref({ + totalCount: 0, + ongoingCount: 0, + completedCount: 0, + pausedCount: 0, + planningCount: 0, + cancelledCount: 0, + draftCount: 0, + statusCountMap: {}, + newThisMonth: 0, + aboutToExpireCount: 0, + averageProgress: 0, + highRiskCount: 0 + }); + + const pagination = reactive({ + total: 0, + pageSize: 12, + currentPage: 1, + background: true + }); + + // 搜索 + async function onSearch() { + loading.value = true; + try { + const { code, data } = await getProjectList({ + pageNum: pagination.currentPage, + pageSize: pagination.pageSize, + keyword: form.keyword || undefined, + status: form.status || undefined + }); + + if (code === 200 && data) { + dataList.value = data.rows; + pagination.total = Number(data.total); + } + } catch { + message("获取项目列表失败", { type: "error" }); + } finally { + loading.value = false; + } + } + + // 获取统计数据 + async function fetchStatistics() { + try { + const { code, data } = await getProjectStatistics(); + if (code === 200 && data) { + statistics.value = data; + } + } catch { + console.error("获取统计数据失败"); + } + } + + // 重置表单 + const resetForm = formEl => { + if (!formEl) return; + formEl.resetFields(); + pagination.currentPage = 1; + onSearch(); + }; + + // 分页大小变化 + function handleSizeChange(val: number) { + pagination.pageSize = val; + onSearch(); + } + + // 页码变化 + function handleCurrentChange(val: number) { + pagination.currentPage = val; + onSearch(); + } + + // 删除项目 + async function handleDelete(row: ProjectItem) { + try { + const { code } = await deleteProject(row.id!); + if (code === 200) { + message(`已删除项目 "${row.projectName}"`, { type: "success" }); + onSearch(); + fetchStatistics(); + } + } catch { + message("删除项目失败", { type: "error" }); + } + } + + // 状态筛选按钮 + const statusFilterButtons = [ + { label: "全部项目", value: "" }, + { label: "进行中", value: "ongoing" }, + { label: "已完成", value: "completed" }, + { label: "高风险", value: "high_risk" } + ]; + + // 当前激活的筛选 + const activeFilter = ref(""); + + // 设置筛选 + function setFilter(filterValue: string) { + activeFilter.value = filterValue; + if (filterValue === "high_risk") { + form.status = ""; + } else { + form.status = filterValue; + } + pagination.currentPage = 1; + onSearch(); + } + + onMounted(() => { + onSearch(); + fetchStatistics(); + }); + + return { + form, + formRef, + loading, + dataList, + pagination, + statistics, + activeFilter, + statusFilterButtons, + onSearch, + resetForm, + handleDelete, + handleSizeChange, + handleCurrentChange, + setFilter + }; +} diff --git a/src/views/project/utils/types.ts b/src/views/project/utils/types.ts new file mode 100644 index 0000000..794bc76 --- /dev/null +++ b/src/views/project/utils/types.ts @@ -0,0 +1,79 @@ +import type { + ProjectInfo, + MilestoneInfo, + TaskInfo, + MemberInfo, + ResourceInfo, + RiskInfo, + TimelineNodeInfo, + ProjectItem, + ProjectStatistics +} from "@/api/project"; + +/** 项目查询参数 */ +export interface ProjectQueryParams { + pageNum?: number; + pageSize?: number; + keyword?: string; + status?: string; +} + +/** 优先级选项 */ +export const PriorityOptions = [ + { label: "最高", value: "highest" }, + { label: "高", value: "high" }, + { label: "中", value: "medium" }, + { label: "低", value: "low" }, + { label: "最低", value: "lowest" } +]; + +/** 项目类型选项 */ +export const ProjectTypeOptions = [ + { label: "建筑工程", value: "construction" }, + { label: "软件开发", value: "software" }, + { label: "产品研发", value: "product" }, + { label: "市场推广", value: "marketing" }, + { label: "其他", value: "other" } +]; + +/** 甘特图数据项 */ +export interface GanttItem { + id: string; + name: string; + startDate: string; + endDate: string; + progress: number; + status: number; + riskLevel?: number; + ownerName?: string; +} + +/** 新建项目表单数据 */ +export interface CreateProjectForm { + project: ProjectInfo; + milestones: MilestoneInfo[]; + tasks: TaskInfo[]; + members: MemberInfo[]; + resources: ResourceInfo[]; + risks: RiskInfo[]; + timeline_nodes: TimelineNodeInfo[]; +} + +/** 步骤枚举 */ +export enum WizardStep { + Upload = 0, + Preview = 1, + Confirm = 2 +} + +export type { + ProjectInfo, + MilestoneInfo, + TaskInfo, + MemberInfo, + ResourceInfo, + RiskInfo, + TimelineNodeInfo, + ProjectItem, + ProjectStatistics +};