/** * 项目阶段数据修复脚本(浏览器版本) * * 使用方法: * 1. 打开项目管理页面 * 2. 打开浏览器控制台(F12) * 3. 复制粘贴此整个脚本 * 4. 输入:repairProjectStages() - 预览需要修复的项目 * 5. 输入:repairProjectStages(false) - 执行实际修复 */ (function() { 'use strict'; /** * 修复项目阶段数据 * @param {boolean} dryRun - 是否为预览模式(默认true) */ window.repairProjectStages = async function(dryRun = true) { console.log('\n' + '='.repeat(80)); console.log(dryRun ? '🔍 预览模式:查看需要修复的项目' : '🔧 执行模式:开始修复项目阶段数据'); console.log('='.repeat(80) + '\n'); try { // 获取Parse实例 const Parse = window.Parse; if (!Parse) { console.error('❌ 无法找到Parse对象,请确保在正确的页面运行此脚本'); return; } // 查询所有项目 const query = new Parse.Query('Project'); query.notEqualTo('isDeleted', true); query.limit(1000); const projects = await query.find(); console.log(`📊 共找到 ${projects.length} 个项目\n`); let needFixCount = 0; const fixedProjects = []; for (const project of projects) { const currentStage = project.get('currentStage') || '订单分配'; const data = project.get('data') || {}; let correctStage = null; let reasons = []; // ========== 检查订单分配阶段 ========== const hasTitle = !!project.get('title')?.trim(); const hasType = !!project.get('projectType'); const hasDemoday = !!project.get('demoday'); const hasQuotation = data.quotation && data.quotation.total > 0; // 检查设计师分配 const teamQuery = new Parse.Query('ProjectTeam'); teamQuery.equalTo('project', project.toPointer()); teamQuery.notEqualTo('isDeleted', true); const teams = await teamQuery.find(); const hasDesigner = teams.length > 0; const isApproved = data.approvalStatus === 'approved'; const orderCompleted = hasTitle && hasType && hasDemoday && hasQuotation && (hasDesigner || isApproved); if (!orderCompleted) { correctStage = '订单分配'; if (!hasTitle) reasons.push('缺少项目名称'); if (!hasType) reasons.push('缺少项目类型'); if (!hasDemoday) reasons.push('缺少小图日期'); if (!hasQuotation) reasons.push('缺少报价数据'); if (!hasDesigner && !isApproved) reasons.push('未分配设计师且未审批'); } // ========== 检查确认需求阶段 ========== else if (currentStage === '交付执行' || currentStage === '售后归档') { const hasRequirements = (data.requirementsAnalysis && Object.keys(data.requirementsAnalysis).length > 0) || (data.spaceRequirements && Object.keys(data.spaceRequirements).length > 0); if (!hasRequirements) { correctStage = '确认需求'; reasons.push('缺少需求分析数据'); } // ========== 检查交付执行阶段 ========== else if (currentStage === '售后归档') { const deliveryStages = data.deliveryStages || {}; const requiredStages = ['modeling', 'softDecor', 'rendering', 'postProcess']; let allCompleted = true; const uncompleted = []; for (const stageId of requiredStages) { const stageData = deliveryStages[stageId]; if (!stageData || stageData.approvalStatus !== 'approved') { allCompleted = false; uncompleted.push(stageId); } } if (!allCompleted) { correctStage = '交付执行'; reasons.push(`交付阶段未完成: ${uncompleted.join(', ')}`); } } } // 如果需要修复 if (correctStage && currentStage !== correctStage) { const title = project.get('title') || '未命名项目'; const reason = reasons.join(', '); console.log(`\n${'─'.repeat(60)}`); console.log(`📋 项目: ${title}`); console.log(` ID: ${project.id}`); console.log(` 当前阶段: ${currentStage}`); console.log(` 应该阶段: ${correctStage}`); console.log(` 回退原因: ${reason}`); if (!dryRun) { // 执行修复 project.set('currentStage', correctStage); // 清除不合理的审批状态 if (correctStage === '订单分配' && data.approvalStatus === 'approved') { data.approvalStatus = null; project.set('data', data); console.log(` 🧹 已清除错误的审批状态`); } await project.save(); console.log(` ✅ 已回退到"${correctStage}"阶段`); } else { console.log(` 🔍 [预览] 需要回退到"${correctStage}"阶段`); } fixedProjects.push({ id: project.id, title, oldStage: currentStage, newStage: correctStage, reason }); needFixCount++; } } console.log(`\n${'='.repeat(80)}`); if (needFixCount === 0) { console.log('✅ 所有项目的阶段状态都是正确的,无需修复!'); } else { if (dryRun) { console.log(`🔍 预览完成!发现 ${needFixCount} 个项目需要修复`); console.log(`\n💡 提示:输入 repairProjectStages(false) 执行实际修复`); } else { console.log(`✅ 修复完成!共回退 ${needFixCount} 个项目到正确阶段`); } console.log('\n📋 修复详情:'); console.table(fixedProjects); } console.log('='.repeat(80) + '\n'); return fixedProjects; } catch (error) { console.error('❌ 操作失败:', error); throw error; } }; /** * 导出项目数据备份 */ window.exportProjectsBackup = async function() { console.log('📦 开始导出项目数据...'); try { const Parse = window.Parse; if (!Parse) { console.error('❌ 无法找到Parse对象'); return; } const query = new Parse.Query('Project'); query.notEqualTo('isDeleted', true); query.limit(1000); const projects = await query.find(); const backup = projects.map(p => ({ id: p.id, title: p.get('title'), currentStage: p.get('currentStage'), projectType: p.get('projectType'), demoday: p.get('demoday'), createdAt: p.get('createdAt'), data: { quotation: p.get('data')?.quotation, approvalStatus: p.get('data')?.approvalStatus, requirementsAnalysis: p.get('data')?.requirementsAnalysis, deliveryStages: p.get('data')?.deliveryStages } })); console.log('✅ 导出完成,共', projects.length, '个项目'); // 下载为JSON文件 const dataStr = JSON.stringify(backup, null, 2); const dataBlob = new Blob([dataStr], { type: 'application/json' }); const url = URL.createObjectURL(dataBlob); const link = document.createElement('a'); link.href = url; link.download = `projects-backup-${new Date().toISOString().slice(0, 10)}.json`; link.click(); URL.revokeObjectURL(url); console.log('💾 备份文件已下载'); return backup; } catch (error) { console.error('❌ 导出失败:', error); throw error; } }; // 显示使用说明 console.log('✅ 项目阶段修复工具已加载'); console.log('\n💡 使用方法:'); console.log(' 1. repairProjectStages() - 预览需要修复的项目'); console.log(' 2. repairProjectStages(false) - 执行实际修复'); console.log(' 3. exportProjectsBackup() - 导出备份数据'); console.log('\n⚠️ 建议:先运行 exportProjectsBackup() 备份数据,再执行修复\n'); })();