| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- import { Injectable } from '@angular/core';
- import { FmodeParse } from 'fmode-ng/parse';
- export interface DesignerTask {
- id: string;
- projectId: string;
- projectName: string;
- stage: string;
- deadline: Date;
- isOverdue: boolean;
- priority: 'high' | 'medium' | 'low';
- customerName: string;
- space?: string; // 空间名称(如"主卧")
- productId?: string; // 关联的Product ID
- }
- @Injectable({
- providedIn: 'root'
- })
- export class DesignerTaskService {
- private Parse: any = null;
- private cid: string = '';
- constructor() {
- this.initParse();
- }
- private async initParse(): Promise<void> {
- try {
- const { FmodeParse } = await import('fmode-ng/parse');
- this.Parse = FmodeParse.with('nova');
- this.cid = localStorage.getItem('company') || '';
- } catch (error) {
- console.error('DesignerTaskService: Parse初始化失败:', error);
- }
- }
- /**
- * 获取当前设计师的任务列表
- * @param designerId Profile的objectId
- */
- async getMyTasks(designerId: string): Promise<DesignerTask[]> {
- if (!this.Parse) await this.initParse();
- if (!this.Parse || !this.cid) {
- console.error('❌ Parse 未初始化或缺少 CID');
- return [];
- }
- try {
- console.log('🔍 开始查询设计师任务,Profile ID:', designerId);
- console.log('📋 当前公司 ID:', this.cid);
-
- // 方案1:从ProjectTeam表查询(设计师实际负责的项目)
- const ProfileClass = this.Parse.Object.extend('Profile');
- const profilePointer = new ProfileClass();
- profilePointer.id = designerId;
-
- const teamQuery = new this.Parse.Query('ProjectTeam');
- teamQuery.equalTo('profile', profilePointer);
- teamQuery.notEqualTo('isDeleted', true);
- teamQuery.include('project');
- teamQuery.include('project.contact');
- teamQuery.limit(1000);
- console.log('🔍 查询 ProjectTeam 表...');
- const teamRecords = await teamQuery.find();
- console.log(`✅ ProjectTeam 查询结果: ${teamRecords.length} 条记录`);
- if (teamRecords.length === 0) {
- console.warn('⚠️ ProjectTeam 表中未找到该设计师的项目');
- console.log('🔄 尝试降级方案:从 Project.assignee 查询');
- return await this.getMyTasksFromAssignee(designerId);
- }
-
- console.log('📋 ProjectTeam 记录详情:');
- teamRecords.forEach((record: any, index: number) => {
- const project = record.get('project');
- console.log(` ${index + 1}. 项目:`, {
- projectId: project?.id,
- projectName: project?.get('title'),
- currentStage: project?.get('currentStage'),
- status: project?.get('status')
- });
- });
- const tasks: DesignerTask[] = [];
- for (const teamRecord of teamRecords) {
- try {
- const project = teamRecord.get('project');
- if (!project) {
- console.warn('⚠️ ProjectTeam 记录缺少 project 对象,跳过');
- continue;
- }
- const projectId = project.id;
- const projectName = project.get('title') || '未命名项目';
- const currentStage = project.get('currentStage') || '未知';
-
- // 安全获取 deadline
- let deadline = project.get('deadline') || project.get('deliveryDate') || project.get('expectedDeliveryDate');
- if (!deadline) {
- deadline = new Date();
- console.warn(`⚠️ 项目 ${projectName} 缺少 deadline,使用当前时间`);
- }
-
- const contact = project.get('contact');
- const customerName = contact?.get('name') || '未知客户';
-
- console.log(`✅ 处理项目: ${projectName} (${projectId})`);
- // 查询该项目下该设计师负责的Product(空间设计产品)
- let products: any[] = [];
- try {
- const ProfileClass = this.Parse.Object.extend('Profile');
- const profilePointer = new ProfileClass();
- profilePointer.id = designerId;
-
- const productQuery = new this.Parse.Query('Product');
- productQuery.equalTo('project', project);
- productQuery.equalTo('profile', profilePointer);
- productQuery.notEqualTo('isDeleted', true);
- productQuery.containedIn('status', ['in_progress', 'awaiting_review']);
-
- console.log(`🔍 查询项目 ${projectName} 的 Product...`);
- products = await productQuery.find();
- console.log(`✅ 找到 ${products.length} 个 Product`);
- } catch (productError: any) {
- console.warn(`⚠️ Product 查询失败,将创建项目级任务`);
- console.warn(`⚠️ Product 错误:`, productError.message || productError.toString());
- products = []; // 查询失败时视为没有 Product
- }
- if (products.length === 0) {
- // 如果没有具体的Product,创建项目级任务
- console.log(`📝 创建项目级任务: ${projectName}`);
- tasks.push({
- id: projectId,
- projectId,
- projectName,
- stage: currentStage,
- deadline: new Date(deadline),
- isOverdue: new Date(deadline) < new Date(),
- priority: this.calculatePriority(deadline, currentStage),
- customerName
- });
- } else {
- // 如果有Product,为每个Product创建任务
- console.log(`📝 为 ${products.length} 个 Product 创建任务`);
- products.forEach((product: any) => {
- const productName = product.get('productName') || '未命名空间';
- const productStage = product.get('stage') || currentStage;
-
- tasks.push({
- id: `${projectId}-${product.id}`,
- projectId,
- projectName: `${projectName} - ${productName}`,
- stage: productStage,
- deadline: new Date(deadline),
- isOverdue: new Date(deadline) < new Date(),
- priority: this.calculatePriority(deadline, productStage),
- customerName,
- space: productName,
- productId: product.id
- });
- });
- }
- } catch (recordError: any) {
- console.error('❌ 处理 ProjectTeam 记录时出错');
- console.error('❌ 错误类型:', typeof recordError);
-
- // Parse 错误对象特殊处理
- const errorDetails: any = {};
- for (const key in recordError) {
- if (recordError.hasOwnProperty(key)) {
- errorDetails[key] = recordError[key];
- }
- }
- console.error('❌ 错误对象属性:', errorDetails);
- console.error('❌ 完整错误:', recordError);
-
- if (recordError.message) console.error('❌ 错误消息:', recordError.message);
- if (recordError.code) console.error('❌ Parse错误代码:', recordError.code);
- if (recordError.stack) console.error('❌ 错误堆栈:', recordError.stack);
- continue;
- }
- }
- // 按截止日期排序
- tasks.sort((a, b) => a.deadline.getTime() - b.deadline.getTime());
- console.log(`✅ 成功加载 ${tasks.length} 个任务`);
- return tasks;
- } catch (error: any) {
- console.error('❌ 获取设计师任务失败');
- console.error('❌ 错误类型:', typeof error);
-
- // Parse 错误对象特殊处理
- const errorDetails: any = {};
- for (const key in error) {
- if (error.hasOwnProperty(key)) {
- errorDetails[key] = error[key];
- }
- }
- console.error('❌ 错误对象属性:', errorDetails);
- console.error('❌ 完整错误:', error);
-
- if (error.message) console.error('❌ 错误消息:', error.message);
- if (error.code) console.error('❌ Parse错误代码:', error.code);
- if (error.stack) console.error('❌ 错误堆栈:', error.stack);
- return [];
- }
- }
- /**
- * 计算任务优先级
- */
- private calculatePriority(deadline: Date, stage: string): 'high' | 'medium' | 'low' {
- const now = new Date();
- const daysLeft = Math.ceil((new Date(deadline).getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
-
- // 超期或临期(3天内)
- if (daysLeft < 0 || daysLeft <= 3) {
- return 'high';
- }
-
- // 渲染阶段优先级高
- if (stage === 'rendering' || stage === '渲染') {
- return 'high';
- }
-
- // 7天内
- if (daysLeft <= 7) {
- return 'medium';
- }
-
- return 'low';
- }
-
- /**
- * 方案2:从Project.assignee查询(降级方案)
- */
- async getMyTasksFromAssignee(designerId: string): Promise<DesignerTask[]> {
- if (!this.Parse) await this.initParse();
- if (!this.Parse || !this.cid) {
- console.error('❌ [降级方案] Parse 未初始化或缺少 CID');
- return [];
- }
- try {
- console.log('🔍 [降级方案] 从 Project.assignee 查询,Profile ID:', designerId);
-
- const ProfileClass = this.Parse.Object.extend('Profile');
- const profilePointer = new ProfileClass();
- profilePointer.id = designerId;
-
- const query = new this.Parse.Query('Project');
- query.equalTo('assignee', profilePointer);
- query.equalTo('company', this.cid);
- query.containedIn('status', ['进行中', '待审核']);
- query.notEqualTo('isDeleted', true);
- query.include('contact');
- query.ascending('deadline');
- query.limit(1000);
- console.log('🔍 [降级方案] 查询 Project 表...');
- const projects = await query.find();
- console.log(`✅ [降级方案] 从Project.assignee加载 ${projects.length} 个项目`);
-
- if (projects.length > 0) {
- console.log('📋 [降级方案] 项目详情:');
- projects.forEach((project: any, index: number) => {
- console.log(` ${index + 1}. 项目:`, {
- projectId: project.id,
- projectName: project.get('title'),
- currentStage: project.get('currentStage'),
- status: project.get('status'),
- deadline: project.get('deadline')
- });
- });
- } else {
- console.warn('⚠️ [降级方案] 也未找到项目');
- console.log('💡 提示:请检查 ProjectTeam 或 Project.assignee 字段是否正确设置');
- }
- return projects.map((project: any) => {
- const deadline = project.get('deadline') || project.get('deliveryDate') || project.get('expectedDeliveryDate') || new Date();
- const currentStage = project.get('currentStage') || '未知';
- const contact = project.get('contact');
- return {
- id: project.id,
- projectId: project.id,
- projectName: project.get('title') || '未命名项目',
- stage: currentStage,
- deadline: new Date(deadline),
- isOverdue: new Date(deadline) < new Date(),
- priority: this.calculatePriority(deadline, currentStage),
- customerName: contact?.get('name') || '未知客户'
- };
- });
- } catch (error: any) {
- console.error('❌ [降级方案] 从Project.assignee获取任务失败');
- console.error('❌ 错误类型:', typeof error);
-
- // Parse 错误对象特殊处理
- const errorDetails: any = {};
- for (const key in error) {
- if (error.hasOwnProperty(key)) {
- errorDetails[key] = error[key];
- }
- }
- console.error('❌ 错误对象属性:', errorDetails);
- console.error('❌ 完整错误:', error);
-
- if (error.message) console.error('❌ 错误消息:', error.message);
- if (error.code) console.error('❌ Parse错误代码:', error.code);
- if (error.stack) console.error('❌ 错误堆栈:', error.stack);
- return [];
- }
- }
- }
|