|
@@ -7,12 +7,12 @@ import { PaymentVoucherRecognitionService } from '../../../services/payment-vouc
|
|
import {
|
|
import {
|
|
Project,
|
|
Project,
|
|
RenderProgress,
|
|
RenderProgress,
|
|
- ModelCheckItem,
|
|
|
|
CustomerFeedback,
|
|
CustomerFeedback,
|
|
DesignerChange,
|
|
DesignerChange,
|
|
Settlement,
|
|
Settlement,
|
|
ProjectStage,
|
|
ProjectStage,
|
|
- PanoramicSynthesis
|
|
|
|
|
|
+ PanoramicSynthesis,
|
|
|
|
+ ModelCheckItem
|
|
} from '../../../models/project.model';
|
|
} from '../../../models/project.model';
|
|
import { ConsultationOrderPanelComponent } from '../../../shared/components/consultation-order-panel/consultation-order-panel.component';
|
|
import { ConsultationOrderPanelComponent } from '../../../shared/components/consultation-order-panel/consultation-order-panel.component';
|
|
import { RequirementsConfirmCardComponent } from '../../../shared/components/requirements-confirm-card/requirements-confirm-card';
|
|
import { RequirementsConfirmCardComponent } from '../../../shared/components/requirements-confirm-card/requirements-confirm-card';
|
|
@@ -192,6 +192,32 @@ interface ProposalAnalysis {
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 交付执行板块数据结构
|
|
|
|
+interface DeliverySpace {
|
|
|
|
+ id: string;
|
|
|
|
+ name: string; // 空间名称:卧室、餐厅、厨房等
|
|
|
|
+ isExpanded: boolean; // 是否展开
|
|
|
|
+ order: number; // 排序
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface DeliveryProcess {
|
|
|
|
+ id: string;
|
|
|
|
+ name: string; // 流程名称:建模、软装、渲染、后期
|
|
|
|
+ type: 'modeling' | 'softDecor' | 'rendering' | 'postProcess';
|
|
|
|
+ spaces: DeliverySpace[]; // 该流程下的空间列表
|
|
|
|
+ isExpanded: boolean; // 是否展开
|
|
|
|
+ content: {
|
|
|
|
+ [spaceId: string]: {
|
|
|
|
+ // 每个空间的具体内容
|
|
|
|
+ images: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected' }>;
|
|
|
|
+ progress: number; // 进度百分比
|
|
|
|
+ status: 'pending' | 'in_progress' | 'completed' | 'approved';
|
|
|
|
+ notes: string; // 备注
|
|
|
|
+ lastUpdated: Date;
|
|
|
|
+ };
|
|
|
|
+ };
|
|
|
|
+}
|
|
|
|
+
|
|
@Component({
|
|
@Component({
|
|
selector: 'app-project-detail',
|
|
selector: 'app-project-detail',
|
|
standalone: true,
|
|
standalone: true,
|
|
@@ -204,7 +230,6 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
projectId: string = '';
|
|
projectId: string = '';
|
|
project: Project | undefined;
|
|
project: Project | undefined;
|
|
renderProgress: RenderProgress | undefined;
|
|
renderProgress: RenderProgress | undefined;
|
|
- modelCheckItems: ModelCheckItem[] = [];
|
|
|
|
feedbacks: CustomerFeedback[] = [];
|
|
feedbacks: CustomerFeedback[] = [];
|
|
designerChanges: DesignerChange[] = [];
|
|
designerChanges: DesignerChange[] = [];
|
|
settlements: Settlement[] = [];
|
|
settlements: Settlement[] = [];
|
|
@@ -244,8 +269,8 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
referenceImages: any[] = [];
|
|
referenceImages: any[] = [];
|
|
cadFiles: any[] = [];
|
|
cadFiles: any[] = [];
|
|
|
|
|
|
- // 新增:9阶段顺序(串式流程)- 删除后期阶段
|
|
|
|
- stageOrder: ProjectStage[] = ['订单创建', '需求沟通', '方案确认', '建模', '软装', '渲染', '尾款结算', '客户评价', '投诉处理'];
|
|
|
|
|
|
+ // 新增:9阶段顺序(串式流程)- 包含后期阶段
|
|
|
|
+ stageOrder: ProjectStage[] = ['订单创建', '需求沟通', '方案确认', '建模', '软装', '渲染', '后期', '尾款结算', '客户评价', '投诉处理'];
|
|
// 新增:阶段展开状态(默认全部收起,当前阶段在数据加载后自动展开)
|
|
// 新增:阶段展开状态(默认全部收起,当前阶段在数据加载后自动展开)
|
|
expandedStages: Partial<Record<ProjectStage, boolean>> = {
|
|
expandedStages: Partial<Record<ProjectStage, boolean>> = {
|
|
'订单创建': false,
|
|
'订单创建': false,
|
|
@@ -254,6 +279,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
'建模': false,
|
|
'建模': false,
|
|
'软装': false,
|
|
'软装': false,
|
|
'渲染': false,
|
|
'渲染': false,
|
|
|
|
+ '后期': false,
|
|
'尾款结算': false,
|
|
'尾款结算': false,
|
|
'客户评价': false,
|
|
'客户评价': false,
|
|
'投诉处理': false,
|
|
'投诉处理': false,
|
|
@@ -316,6 +342,87 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
// 视图上下文:根据路由前缀识别角色视角(客服/设计师/组长)
|
|
// 视图上下文:根据路由前缀识别角色视角(客服/设计师/组长)
|
|
roleContext: 'customer-service' | 'designer' | 'team-leader' = 'designer';
|
|
roleContext: 'customer-service' | 'designer' | 'team-leader' = 'designer';
|
|
|
|
|
|
|
|
+ // ============ 模型检查项数据 ============
|
|
|
|
+ modelCheckItems: ModelCheckItem[] = [
|
|
|
|
+ { id: 'check-1', name: '户型匹配度检查', isPassed: false, notes: '' },
|
|
|
|
+ { id: 'check-2', name: '尺寸精度验证', isPassed: false, notes: '' },
|
|
|
|
+ { id: 'check-3', name: '材质贴图检查', isPassed: false, notes: '' },
|
|
|
|
+ { id: 'check-4', name: '光影效果验证', isPassed: false, notes: '' },
|
|
|
|
+ { id: 'check-5', name: '细节完整性检查', isPassed: false, notes: '' }
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ // ============ 交付执行板块数据 ============
|
|
|
|
+ deliveryProcesses: DeliveryProcess[] = [
|
|
|
|
+ {
|
|
|
|
+ id: 'modeling',
|
|
|
|
+ name: '建模',
|
|
|
|
+ type: 'modeling',
|
|
|
|
+ isExpanded: false,
|
|
|
|
+ spaces: [
|
|
|
|
+ { id: 'bedroom', name: '卧室', isExpanded: false, order: 1 },
|
|
|
|
+ { id: 'living', name: '客厅', isExpanded: false, order: 2 },
|
|
|
|
+ { id: 'kitchen', name: '厨房', isExpanded: false, order: 3 }
|
|
|
|
+ ],
|
|
|
|
+ content: {
|
|
|
|
+ 'bedroom': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'living': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'kitchen': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'softDecor',
|
|
|
|
+ name: '软装',
|
|
|
|
+ type: 'softDecor',
|
|
|
|
+ isExpanded: false,
|
|
|
|
+ spaces: [
|
|
|
|
+ { id: 'bedroom', name: '卧室', isExpanded: false, order: 1 },
|
|
|
|
+ { id: 'living', name: '客厅', isExpanded: false, order: 2 },
|
|
|
|
+ { id: 'kitchen', name: '厨房', isExpanded: false, order: 3 }
|
|
|
|
+ ],
|
|
|
|
+ content: {
|
|
|
|
+ 'bedroom': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'living': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'kitchen': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'rendering',
|
|
|
|
+ name: '渲染',
|
|
|
|
+ type: 'rendering',
|
|
|
|
+ isExpanded: false,
|
|
|
|
+ spaces: [
|
|
|
|
+ { id: 'bedroom', name: '卧室', isExpanded: false, order: 1 },
|
|
|
|
+ { id: 'living', name: '客厅', isExpanded: false, order: 2 },
|
|
|
|
+ { id: 'kitchen', name: '厨房', isExpanded: false, order: 3 }
|
|
|
|
+ ],
|
|
|
|
+ content: {
|
|
|
|
+ 'bedroom': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'living': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'kitchen': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ id: 'postProcess',
|
|
|
|
+ name: '后期',
|
|
|
|
+ type: 'postProcess',
|
|
|
|
+ isExpanded: false,
|
|
|
|
+ spaces: [
|
|
|
|
+ { id: 'bedroom', name: '卧室', isExpanded: false, order: 1 },
|
|
|
|
+ { id: 'living', name: '客厅', isExpanded: false, order: 2 },
|
|
|
|
+ { id: 'kitchen', name: '厨房', isExpanded: false, order: 3 }
|
|
|
|
+ ],
|
|
|
|
+ content: {
|
|
|
|
+ 'bedroom': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'living': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() },
|
|
|
|
+ 'kitchen': { images: [], progress: 0, status: 'pending', notes: '', lastUpdated: new Date() }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ // 新增空间输入框状态
|
|
|
|
+ newSpaceName: { [processId: string]: string } = {};
|
|
|
|
+ showAddSpaceInput: { [processId: string]: boolean } = {};
|
|
|
|
+
|
|
constructor(
|
|
constructor(
|
|
private route: ActivatedRoute,
|
|
private route: ActivatedRoute,
|
|
private projectService: ProjectService,
|
|
private projectService: ProjectService,
|
|
@@ -753,7 +860,6 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
if (this.projectId) {
|
|
if (this.projectId) {
|
|
this.loadProjectDetails();
|
|
this.loadProjectDetails();
|
|
this.loadRenderProgress();
|
|
this.loadRenderProgress();
|
|
- this.loadModelCheckItems();
|
|
|
|
this.loadCustomerFeedbacks();
|
|
this.loadCustomerFeedbacks();
|
|
this.loadDesignerChanges();
|
|
this.loadDesignerChanges();
|
|
this.loadSettlements();
|
|
this.loadSettlements();
|
|
@@ -967,6 +1073,28 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
const currentSec = this.getSectionKeyForStage(currentStage);
|
|
const currentSec = this.getSectionKeyForStage(currentStage);
|
|
this.expandedSection = currentSec;
|
|
this.expandedSection = currentSec;
|
|
console.log('展开板块:', currentSec);
|
|
console.log('展开板块:', currentSec);
|
|
|
|
+
|
|
|
|
+ // 新增:如果当前阶段是建模、软装或渲染,自动展开对应的折叠面板
|
|
|
|
+ if (currentStage === '建模' || currentStage === '软装' || currentStage === '渲染') {
|
|
|
|
+ const processTypeMap = {
|
|
|
|
+ '建模': 'modeling',
|
|
|
|
+ '软装': 'softDecor',
|
|
|
|
+ '渲染': 'rendering'
|
|
|
|
+ };
|
|
|
|
+ const processType = processTypeMap[currentStage] as 'modeling' | 'softDecor' | 'rendering';
|
|
|
|
+ const targetProcess = this.deliveryProcesses.find(p => p.type === processType);
|
|
|
|
+ if (targetProcess) {
|
|
|
|
+ // 展开对应的流程面板
|
|
|
|
+ targetProcess.isExpanded = true;
|
|
|
|
+ // 展开第一个空间以便用户操作
|
|
|
|
+ if (targetProcess.spaces.length > 0) {
|
|
|
|
+ targetProcess.spaces[0].isExpanded = true;
|
|
|
|
+ // 关闭其他空间
|
|
|
|
+ targetProcess.spaces.slice(1).forEach(space => space.isExpanded = false);
|
|
|
|
+ }
|
|
|
|
+ console.log('自动展开折叠面板:', currentStage, processType);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// 整理项目详情
|
|
// 整理项目详情
|
|
@@ -1004,12 +1132,6 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
}, 1000);
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
|
|
- loadModelCheckItems(): void {
|
|
|
|
- this.projectService.getModelCheckItems().subscribe(items => {
|
|
|
|
- this.modelCheckItems = items;
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
loadCustomerFeedbacks(): void {
|
|
loadCustomerFeedbacks(): void {
|
|
this.projectService.getCustomerFeedbacks().subscribe(feedbacks => {
|
|
this.projectService.getCustomerFeedbacks().subscribe(feedbacks => {
|
|
this.feedbacks = feedbacks.filter(f => f.projectId === this.projectId);
|
|
this.feedbacks = feedbacks.filter(f => f.projectId === this.projectId);
|
|
@@ -1051,12 +1173,6 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
- updateModelCheckItem(itemId: string, isPassed: boolean): void {
|
|
|
|
- this.projectService.updateModelCheckItem(itemId, isPassed).subscribe(() => {
|
|
|
|
- this.loadModelCheckItems(); // 重新加载检查项
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
updateFeedbackStatus(feedbackId: string, status: '处理中' | '已解决'): void {
|
|
updateFeedbackStatus(feedbackId: string, status: '处理中' | '已解决'): void {
|
|
this.projectService.updateFeedbackStatus(feedbackId, status).subscribe(() => {
|
|
this.projectService.updateFeedbackStatus(feedbackId, status).subscribe(() => {
|
|
this.loadCustomerFeedbacks(); // 重新加载反馈
|
|
this.loadCustomerFeedbacks(); // 重新加载反馈
|
|
@@ -1091,6 +1207,23 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
// 更新板块展开状态
|
|
// 更新板块展开状态
|
|
const nextSection = this.getSectionKeyForStage(next);
|
|
const nextSection = this.getSectionKeyForStage(next);
|
|
this.expandedSection = nextSection;
|
|
this.expandedSection = nextSection;
|
|
|
|
+
|
|
|
|
+ // 新增:自动展开对应阶段的折叠面板
|
|
|
|
+ if (next === '软装' || next === '渲染') {
|
|
|
|
+ const processType = next === '软装' ? 'softDecor' : 'rendering';
|
|
|
|
+ const targetProcess = this.deliveryProcesses.find(p => p.type === processType);
|
|
|
|
+ if (targetProcess) {
|
|
|
|
+ // 展开对应的流程面板
|
|
|
|
+ targetProcess.isExpanded = true;
|
|
|
|
+ // 展开第一个空间以便用户操作
|
|
|
|
+ if (targetProcess.spaces.length > 0) {
|
|
|
|
+ targetProcess.spaces[0].isExpanded = true;
|
|
|
|
+ // 关闭其他空间
|
|
|
|
+ targetProcess.spaces.slice(1).forEach(space => space.isExpanded = false);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
// 触发变更检测以更新导航栏颜色
|
|
// 触发变更检测以更新导航栏颜色
|
|
this.cdr.detectChanges();
|
|
this.cdr.detectChanges();
|
|
}
|
|
}
|
|
@@ -1140,6 +1273,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
'建模': '项目执行',
|
|
'建模': '项目执行',
|
|
'软装': '项目执行',
|
|
'软装': '项目执行',
|
|
'渲染': '项目执行',
|
|
'渲染': '项目执行',
|
|
|
|
+ '后期': '项目执行',
|
|
'尾款结算': '收尾验收',
|
|
'尾款结算': '收尾验收',
|
|
'客户评价': '收尾验收',
|
|
'客户评价': '收尾验收',
|
|
'投诉处理': '收尾验收'
|
|
'投诉处理': '收尾验收'
|
|
@@ -1253,9 +1387,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
}
|
|
}
|
|
|
|
|
|
// 检查是否所有模型检查项都已通过
|
|
// 检查是否所有模型检查项都已通过
|
|
- areAllModelChecksPassed(): boolean {
|
|
|
|
- return this.modelCheckItems.every(item => item.isPassed);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
|
|
// 获取技能匹配度警告
|
|
// 获取技能匹配度警告
|
|
getSkillMismatchWarning(): string | null {
|
|
getSkillMismatchWarning(): string | null {
|
|
@@ -1578,16 +1710,36 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
|
|
|
removeImageFromPreview(): void {
|
|
removeImageFromPreview(): void {
|
|
if (this.previewImageData) {
|
|
if (this.previewImageData) {
|
|
- // 根据图片类型调用相应的删除方法
|
|
|
|
- if (this.whiteModelImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
- this.removeWhiteModelImage(this.previewImageData.id);
|
|
|
|
- } else if (this.softDecorImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
- this.removeSoftDecorImage(this.previewImageData.id);
|
|
|
|
- } else if (this.renderLargeImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
- this.removeRenderLargeImage(this.previewImageData.id);
|
|
|
|
- } else if (this.postProcessImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
- this.removePostProcessImage(this.previewImageData.id);
|
|
|
|
|
|
+ // 首先检查新的 deliveryProcesses 结构
|
|
|
|
+ let imageFound = false;
|
|
|
|
+
|
|
|
|
+ for (const process of this.deliveryProcesses) {
|
|
|
|
+ for (const space of process.spaces) {
|
|
|
|
+ if (process.content[space.id]?.images) {
|
|
|
|
+ const imageIndex = process.content[space.id].images.findIndex(img => img.id === this.previewImageData.id);
|
|
|
|
+ if (imageIndex > -1) {
|
|
|
|
+ this.removeSpaceImage(process.id, space.id, this.previewImageData.id);
|
|
|
|
+ imageFound = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (imageFound) break;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // 如果在新结构中没找到,检查旧的图片数组
|
|
|
|
+ if (!imageFound) {
|
|
|
|
+ if (this.whiteModelImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
+ this.removeWhiteModelImage(this.previewImageData.id);
|
|
|
|
+ } else if (this.softDecorImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
+ this.removeSoftDecorImage(this.previewImageData.id);
|
|
|
|
+ } else if (this.renderLargeImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
+ this.removeRenderLargeImage(this.previewImageData.id);
|
|
|
|
+ } else if (this.postProcessImages.find(i => i.id === this.previewImageData.id)) {
|
|
|
|
+ this.removePostProcessImage(this.previewImageData.id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
this.closeImagePreview();
|
|
this.closeImagePreview();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1690,10 +1842,10 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
this.postProcessImages = this.postProcessImages.filter(i => i.id !== id);
|
|
this.postProcessImages = this.postProcessImages.filter(i => i.id !== id);
|
|
}
|
|
}
|
|
|
|
|
|
- // 新增:后期阶段确认上传并自动进入下一阶段(已删除后期阶段,此方法保留但不会被调用)
|
|
|
|
|
|
+ // 新增:后期阶段 确认上传并自动进入下一阶段(尾款结算)
|
|
confirmPostProcessUpload(): void {
|
|
confirmPostProcessUpload(): void {
|
|
- // 由于删除了后期阶段,此方法不再使用
|
|
|
|
- console.log('后期阶段已删除,此方法不再使用');
|
|
|
|
|
|
+ if (this.postProcessImages.length === 0) return;
|
|
|
|
+ this.advanceToNextStage('后期');
|
|
}
|
|
}
|
|
|
|
|
|
// 新增:尾款结算阶段确认并自动进入下一阶段(客户评价)
|
|
// 新增:尾款结算阶段确认并自动进入下一阶段(客户评价)
|
|
@@ -1799,6 +1951,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
case '建模':
|
|
case '建模':
|
|
case '软装':
|
|
case '软装':
|
|
case '渲染':
|
|
case '渲染':
|
|
|
|
+ case '后期':
|
|
return 'delivery';
|
|
return 'delivery';
|
|
case '尾款结算':
|
|
case '尾款结算':
|
|
case '客户评价':
|
|
case '客户评价':
|
|
@@ -1860,6 +2013,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
'建模': 'modeling',
|
|
'建模': 'modeling',
|
|
'软装': 'softdecor',
|
|
'软装': 'softdecor',
|
|
'渲染': 'render',
|
|
'渲染': 'render',
|
|
|
|
+ '后期': 'postprocess',
|
|
'尾款结算': 'settlement',
|
|
'尾款结算': 'settlement',
|
|
'客户评价': 'customer-review',
|
|
'客户评价': 'customer-review',
|
|
'投诉处理': 'complaint'
|
|
'投诉处理': 'complaint'
|
|
@@ -2379,6 +2533,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
'建模': 40,
|
|
'建模': 40,
|
|
'软装': 55,
|
|
'软装': 55,
|
|
'渲染': 70,
|
|
'渲染': 70,
|
|
|
|
+ '后期': 80,
|
|
'尾款结算': 90,
|
|
'尾款结算': 90,
|
|
'客户评价': 95,
|
|
'客户评价': 95,
|
|
'投诉处理': 100
|
|
'投诉处理': 100
|
|
@@ -3545,4 +3700,59 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
alert('评价草稿保存成功!您可以稍后继续完善。');
|
|
alert('评价草稿保存成功!您可以稍后继续完善。');
|
|
}, 500);
|
|
}, 500);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // ============ 缺少的方法实现 ============
|
|
|
|
+
|
|
|
|
+ // 处理空间文件选择
|
|
|
|
+ onSpaceFileSelected(event: Event, processId: string, spaceId: string): void {
|
|
|
|
+ const input = event.target as HTMLInputElement;
|
|
|
|
+ if (!input.files || input.files.length === 0) return;
|
|
|
|
+
|
|
|
|
+ const files = Array.from(input.files);
|
|
|
|
+ const process = this.deliveryProcesses.find(p => p.id === processId);
|
|
|
|
+ if (!process || !process.content[spaceId]) return;
|
|
|
|
+
|
|
|
|
+ files.forEach(file => {
|
|
|
|
+ if (/\.(jpg|jpeg|png)$/i.test(file.name)) {
|
|
|
|
+ const imageItem = this.makeImageItem(file);
|
|
|
|
+ process.content[spaceId].images.push({
|
|
|
|
+ id: imageItem.id,
|
|
|
|
+ name: imageItem.name,
|
|
|
|
+ url: imageItem.url,
|
|
|
|
+ size: this.formatFileSize(file.size)
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 清空输入
|
|
|
|
+ input.value = '';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 更新模型检查项状态
|
|
|
|
+ updateModelCheckItem(itemId: string, isPassed: boolean): void {
|
|
|
|
+ const item = this.modelCheckItems.find(i => i.id === itemId);
|
|
|
|
+ if (item) {
|
|
|
|
+ item.isPassed = isPassed;
|
|
|
|
+ console.log(`模型检查项 ${item.name} 状态更新为: ${isPassed ? '已通过' : '待处理'}`);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 删除空间图片
|
|
|
|
+ removeSpaceImage(processId: string, spaceId: string, imageId: string): void {
|
|
|
|
+ const process = this.deliveryProcesses.find(p => p.id === processId);
|
|
|
|
+ if (process && process.content[spaceId]) {
|
|
|
|
+ const images = process.content[spaceId].images;
|
|
|
|
+ const imageIndex = images.findIndex(img => img.id === imageId);
|
|
|
|
+ if (imageIndex > -1) {
|
|
|
|
+ // 释放URL资源
|
|
|
|
+ const image = images[imageIndex];
|
|
|
|
+ if (image.url && image.url.startsWith('blob:')) {
|
|
|
|
+ URL.revokeObjectURL(image.url);
|
|
|
|
+ }
|
|
|
|
+ // 从数组中移除
|
|
|
|
+ images.splice(imageIndex, 1);
|
|
|
|
+ console.log(`已删除空间图片: ${processId}/${spaceId}/${imageId}`);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|