# 项目数据库结构说明 - 停滞期和改图期字段 ## 📊 数据存储位置 ### ✅ 正确的存储位置 停滞期和改图期的数据保存在 **Parse 数据库的 `Project` 表的 `data` 字段**中: ``` Project 表 ├── id (字符串) ├── title (字符串) - 项目标题 ├── currentStage (字符串) - 当前阶段(如"订单分配"、"确认需求"、"交付执行"等) ├── stage (字符串) - 兼容旧字段,与 currentStage 类似 └── data (JSON 对象) ⬅️ 停滞期和改图期数据在这里 ├── isStalled (布尔值) - 是否处于停滞期 ├── isModification (布尔值) - 是否处于改图期 ├── stagnationReasonType (字符串) - 停滞原因类型 ├── stagnationCustomReason (字符串) - 自定义停滞原因 ├── modificationReasonType (字符串) - 改图原因类型 ├── modificationCustomReason (字符串) - 自定义改图原因 ├── estimatedResumeDate (日期) - 预计恢复时间 ├── reasonNotes (字符串) - 备注说明 ├── markedAt (日期) - 标记时间 ├── markedBy (字符串) - 标记人 └── ... (其他项目数据) ``` ### ❌ 不在这些位置 - **不在** `Project.stage` 字段中 - **不在** `Project.currentStage` 字段中 - **不在** `ProjectFile` 表中 ## 🔍 字段用途说明 ### 1. `currentStage` 字段 **用途**:存储项目当前所处的**工作流阶段** **可能的值**: - `"订单分配"` - 订单分配阶段 - `"确认需求"` - 确认需求阶段 - `"方案深化"` - 方案深化阶段 - `"交付执行"` / `"白模"` / `"软装"` / `"渲染"` / `"后期"` - 交付执行阶段 - `"尾款结算"` - 售后归档阶段 - 等等... **示例**: ```json { "currentStage": "交付执行" } ``` ### 2. `stage` 字段 **用途**:兼容旧版本的阶段字段,功能与 `currentStage` 类似 **说明**:在新代码中主要使用 `currentStage`,但保留 `stage` 以兼容旧数据 ### 3. `data` 字段 **用途**:存储项目的**扩展数据**,包括停滞期、改图期等状态信息 **完整结构示例**: ```json { "data": { // 停滞期相关 "isStalled": true, "stagnationReasonType": "customer", "stagnationCustomReason": "", "estimatedResumeDate": "2024-12-15T00:00:00.000Z", "reasonNotes": "客户出差暂时无法沟通", "markedAt": "2024-12-07T13:42:00.000Z", "markedBy": "张组长", // 改图期相关(互斥,同时只能有一个为 true) "isModification": false, "modificationReasonType": "", "modificationCustomReason": "", // 其他扩展数据 "phaseDeadlines": { ... }, "approvalStatus": "approved", "requirementsAnalysis": { ... }, // ... } } ``` ## 💾 实际保存代码 ### 组长端标记(dashboard.ts) ```typescript private async updateProjectMarkStatus( projectId: string, type: 'stagnation' | 'modification', reason: any ): Promise { const Parse = (window as any).Parse; const query = new Parse.Query('Project'); const project = await query.get(projectId); // ✅ 获取 data 字段 const projectData = project.get('data') || {}; // ✅ 设置停滞期/改图期字段 if (type === 'stagnation') { projectData.isStalled = true; projectData.isModification = false; projectData.stagnationReasonType = reason.reasonType; projectData.stagnationCustomReason = reason.customReason; projectData.estimatedResumeDate = reason.estimatedResumeDate; projectData.reasonNotes = reason.notes; projectData.markedAt = new Date(); projectData.markedBy = this.currentUser.name; } else { projectData.isModification = true; projectData.isStalled = false; projectData.modificationReasonType = reason.reasonType; projectData.modificationCustomReason = reason.customReason; projectData.reasonNotes = reason.notes; projectData.markedAt = new Date(); projectData.markedBy = this.currentUser.name; } // ✅ 保存回 data 字段 project.set('data', projectData); await project.save(); } ``` ### 组员端读取(project-detail.component.ts) ```typescript // ✅ 从 data 字段读取停滞期状态 get isStalled(): boolean { const data = this.project?.get('data') || {}; return data.isStalled === true; } // ✅ 从 data 字段读取改图期状态 get isModification(): boolean { const data = this.project?.get('data') || {}; return data.isModification === true; } // ✅ 从 data 字段读取停滞期详情 get stagnationInfo() { const data = this.project?.get('data') || {}; return { reasonType: data.stagnationReasonType, customReason: data.stagnationCustomReason, estimatedResumeDate: data.estimatedResumeDate, notes: data.reasonNotes, markedAt: data.markedAt, markedBy: data.markedBy }; } ``` ## 🔧 数据库查询示例 ### 查询所有停滞期项目 ```javascript const Parse = require('parse/node'); const query = new Parse.Query('Project'); // 注意:Parse 不支持直接查询嵌套 JSON 字段 // 需要使用特殊语法或在代码中过滤 // 获取所有项目后过滤 const projects = await query.find(); const stalledProjects = projects.filter(p => { const data = p.get('data') || {}; return data.isStalled === true; }); console.log('停滞期项目数量:', stalledProjects.length); ``` ### 查询所有改图期项目 ```javascript const query = new Parse.Query('Project'); const projects = await query.find(); const modificationProjects = projects.filter(p => { const data = p.get('data') || {}; return data.isModification === true; }); console.log('改图期项目数量:', modificationProjects.length); ``` ### 更新项目数据 ```javascript const query = new Parse.Query('Project'); const project = await query.get('项目ID'); const data = project.get('data') || {}; data.isStalled = true; data.stagnationReasonType = 'customer'; data.markedAt = new Date(); project.set('data', data); await project.save(); ``` ## 📋 数据验证清单 要验证停滞期/改图期数据是否正确保存,可以检查: ### 1. Parse Dashboard 检查 1. 登录 Parse Dashboard 2. 选择 `Project` 类 3. 找到标记的项目 4. 查看 `data` 列(JSON 格式) 5. ✅ 确认有 `isStalled` 或 `isModification` 字段 ### 2. 浏览器控制台检查 ```javascript // 在浏览器控制台运行 const Parse = window.Parse; const query = new Parse.Query('Project'); query.get('你的项目ID').then(project => { const data = project.get('data'); console.log('停滞期:', data.isStalled); console.log('改图期:', data.isModification); console.log('完整data:', data); }); ``` ### 3. 代码日志检查 标记项目后,控制台应该显示: ``` ✅ [数据库] 停滞期标记已保存到数据库 项目ID ``` ## ⚠️ 常见问题 ### Q1: 为什么不保存在 `currentStage` 字段中? **A**: `currentStage` 表示项目的工作流阶段(如"订单分配"、"交付执行"),与停滞期/改图期的**状态标记**是不同的概念。一个项目可以同时处于"交付执行"阶段和"停滞期"状态。 ### Q2: 为什么不保存在 `ProjectFile` 表中? **A**: `ProjectFile` 表用于存储项目文件(图片、文档等),而停滞期/改图期是**项目级别**的状态,应该保存在 `Project` 表中。 ### Q3: 如何批量查询停滞期项目? **A**: 由于 Parse 限制,无法直接查询嵌套 JSON 字段。建议: 1. 查询所有项目 2. 在代码中过滤 `data.isStalled === true` 的项目 3. 或者在 `Project` 表添加顶层字段 `isStalled`(需要同步更新) ### Q4: 数据会丢失吗? **A**: 不会。所有标记操作都会调用 `project.save()` 保存到 Parse 数据库。只要保存成功(有日志确认),数据就会持久化。 ## 🎯 总结 ✅ **停滞期和改图期数据保存在**:`Project.data.isStalled` / `Project.data.isModification` ❌ **不在**:`Project.currentStage` 或 `Project.stage` ❌ **不在**:`ProjectFile` 表 如需查看实际数据库内容,请访问 Parse Dashboard 查看 `Project` 表的 `data` 字段。