使用说明:复制下面的脚本,粘贴到浏览器控制台执行
http://localhost:4200/admin/project-managementF12 打开开发者工具Console 标签// ================================
// 项目负责人批量更新脚本
// ================================
(async function() {
console.log('🚀 开始批量更新项目负责人...');
try {
// 获取Parse实例
const FmodeParse = (window as any).FmodeParse || await import('fmode-ng/parse').then(m => m.FmodeParse);
const Parse = FmodeParse.with('nova');
// 获取公司ID
const company = localStorage.getItem('company');
if (!company) {
console.error('❌ 未找到公司ID,请先登录');
return;
}
console.log('✅ 公司ID:', company);
// 查询所有项目
const projectQuery = new Parse.Query('Project');
projectQuery.equalTo('company', company);
projectQuery.notEqualTo('isDeleted', true);
projectQuery.include(['assignee', 'department', 'department.leader']);
projectQuery.limit(1000);
const projects = await projectQuery.find();
console.log(`📊 找到 ${projects.length} 个项目`);
// 统计
let updated = 0;
let skipped = 0;
let failed = 0;
// 遍历每个项目
for (let i = 0; i < projects.length; i++) {
const project = projects[i];
const title = project.get('title') || '未命名项目';
const existingAssignee = project.get('assignee');
try {
// 如果已有负责人,跳过
if (existingAssignee) {
console.log(`⏭️ [${i+1}/${projects.length}] "${title}" 已有负责人: ${existingAssignee.get('name')}`);
skipped++;
continue;
}
// 检查是否有项目组
let department = project.get('department');
// 如果没有项目组,查找默认项目组
if (!department) {
console.log(`🔍 [${i+1}/${projects.length}] "${title}" 没有项目组,查找默认项目组...`);
const deptQuery = new Parse.Query('Department');
deptQuery.equalTo('company', company);
deptQuery.equalTo('type', 'project');
deptQuery.notEqualTo('isDeleted', true);
deptQuery.include('leader');
deptQuery.ascending('createdAt');
deptQuery.limit(1);
department = await deptQuery.first();
} else {
// 如果有项目组,确保加载了leader
await department.fetch({ include: ['leader'] });
}
if (!department) {
console.warn(`⚠️ [${i+1}/${projects.length}] "${title}" 没有可用的项目组`);
failed++;
continue;
}
// 获取组长
const leader = department.get('leader');
if (!leader) {
console.warn(`⚠️ [${i+1}/${projects.length}] "${title}" 的项目组没有组长`);
failed++;
continue;
}
// 更新项目
project.set('assignee', leader);
project.set('department', department);
await project.save();
updated++;
console.log(`✅ [${i+1}/${projects.length}] "${title}" 已设置负责人: ${leader.get('name')}`);
} catch (error) {
console.error(`❌ [${i+1}/${projects.length}] 更新 "${title}" 失败:`, error);
failed++;
}
}
// 输出结果
console.log('');
console.log('='.repeat(60));
console.log('🎉 批量更新完成!');
console.log('='.repeat(60));
console.log(`📊 总计: ${projects.length} 个项目`);
console.log(`✅ 成功更新: ${updated} 个`);
console.log(`⏭️ 跳过(已有负责人): ${skipped} 个`);
console.log(`❌ 失败: ${failed} 个`);
console.log('='.repeat(60));
console.log('');
console.log('💡 请刷新页面查看结果(Ctrl+Shift+R)');
} catch (error) {
console.error('❌ 执行失败:', error);
}
})();
控制台会输出类似信息:
🚀 开始批量更新项目负责人...
✅ 公司ID: cDL6R1hgSi
📊 找到 11 个项目
⏭️ [1/11] "未命名案例组三期项目" 已有负责人: 汪奥
✅ [2/11] "张家界凤凰城三期项目" 已设置负责人: 汪奥
✅ [3/11] "日式10.6" 已设置负责人: 汪奥
...
============================================================
🎉 批量更新完成!
============================================================
📊 总计: 11 个项目
✅ 成功更新: 10 个
⏭️ 跳过(已有负责人): 1 个
❌ 失败: 0 个
============================================================
💡 请刷新页面查看结果(Ctrl+Shift+R)
按 Ctrl+Shift+R 强制刷新页面,查看项目列表中的"负责人"列。
预期结果:所有项目的"负责人"列应显示组长名字(如"汪奥"),而不是"未分配"。
如果上面的脚本报错,试试这个简化版:
(async function() {
const Parse = window.FmodeParse.with('nova');
const company = localStorage.getItem('company');
const query = new Parse.Query('Project');
query.equalTo('company', company);
query.notEqualTo('isDeleted', true);
query.doesNotExist('assignee');
query.limit(100);
const projects = await query.find();
console.log('需要更新的项目数:', projects.length);
// 获取第一个项目组
const deptQuery = new Parse.Query('Department');
deptQuery.equalTo('company', company);
deptQuery.include('leader');
const dept = await deptQuery.first();
if (!dept) {
console.error('没有找到项目组');
return;
}
const leader = dept.get('leader');
console.log('使用组长:', leader.get('name'));
// 批量更新
for (const p of projects) {
p.set('assignee', leader);
p.set('department', dept);
await p.save();
console.log('✅', p.get('title'));
}
console.log('完成!请刷新页面');
})();
执行更新后,运行这个脚本验证结果:
(async function() {
const Parse = window.FmodeParse.with('nova');
const company = localStorage.getItem('company');
const query = new Parse.Query('Project');
query.equalTo('company', company);
query.notEqualTo('isDeleted', true);
query.include(['assignee', 'department']);
query.limit(20);
const projects = await query.find();
console.table(projects.map(p => ({
'项目名称': p.get('title'),
'负责人': p.get('assignee')?.get('name') || '未分配',
'项目组': p.get('department')?.get('name') || '无'
})));
})();
预期输出表格:
┌─────────┬────────────────────────┬──────────┬──────────┐
│ (index) │ 项目名称 │ 负责人 │ 项目组 │
├─────────┼────────────────────────┼──────────┼──────────┤
│ 0 │ '未命名案例组三期' │ '汪奥' │ '汪奥组'│
│ 1 │ '张家界凤凰城三期' │ '汪奥' │ '汪奥组'│
│ 2 │ '日式10.6' │ '汪奥' │ '汪奥组'│
│ ... │ ... │ ... │ ... │
└─────────┴────────────────────────┴──────────┴──────────┘
FmodeParse is not defined解决方法:
// 先初始化FmodeParse
const { FmodeParse } = await import('fmode-ng/parse');
// 然后继续执行脚本
company is null解决方法:
// 手动设置公司ID
localStorage.setItem('company', 'cDL6R1hgSi'); // 替换为你的公司ID
解决方法:
现在就执行脚本,一键修复所有项目的负责人! 🚀