|
|
@@ -10,15 +10,21 @@ import {
|
|
|
CustomerFeedback,
|
|
|
DesignerChange,
|
|
|
Settlement,
|
|
|
- ProjectStage
|
|
|
+ ProjectStage,
|
|
|
+ PanoramicSynthesis
|
|
|
} from '../../../models/project.model';
|
|
|
import { ConsultationOrderPanelComponent } from '../../../shared/components/consultation-order-panel/consultation-order-panel.component';
|
|
|
import { RequirementsConfirmCardComponent } from '../../../shared/components/requirements-confirm-card/requirements-confirm-card';
|
|
|
import { SettlementCardComponent } from '../../../shared/components/settlement-card/settlement-card';
|
|
|
import { CustomerReviewCardComponent } from '../../../shared/components/customer-review-card/customer-review-card';
|
|
|
+import { CustomerReviewFormComponent } from '../../../shared/components/customer-review-form/customer-review-form';
|
|
|
import { ComplaintCardComponent } from '../../../shared/components/complaint-card/complaint-card';
|
|
|
+import { PanoramicSynthesisCardComponent } from '../../../shared/components/panoramic-synthesis-card/panoramic-synthesis-card';
|
|
|
+import { QuotationDetailsComponent, QuotationData } from './components/quotation-details/quotation-details.component';
|
|
|
+import { DesignerAssignmentComponent, DesignerAssignmentData, Designer as AssignmentDesigner } from './components/designer-assignment/designer-assignment.component';
|
|
|
+// 引入客户服务模块的设计师日历组件
|
|
|
+import { DesignerCalendarComponent, Designer as CalendarDesigner, ProjectGroup as CalendarProjectGroup } from '../../customer-service/consultation-order/components/designer-calendar/designer-calendar.component';
|
|
|
|
|
|
-import { VerticalNavComponent } from './components/vertical-nav/vertical-nav.component';
|
|
|
import { ColorAnalysisResult } from '../../../shared/services/color-analysis.service';
|
|
|
|
|
|
interface ExceptionHistory {
|
|
|
@@ -188,7 +194,7 @@ interface ProposalAnalysis {
|
|
|
@Component({
|
|
|
selector: 'app-project-detail',
|
|
|
standalone: true,
|
|
|
- imports: [CommonModule, FormsModule, ReactiveFormsModule, ConsultationOrderPanelComponent, RequirementsConfirmCardComponent, SettlementCardComponent, CustomerReviewCardComponent, ComplaintCardComponent, VerticalNavComponent],
|
|
|
+ imports: [CommonModule, FormsModule, ReactiveFormsModule, ConsultationOrderPanelComponent, RequirementsConfirmCardComponent, SettlementCardComponent, CustomerReviewCardComponent, CustomerReviewFormComponent, ComplaintCardComponent, PanoramicSynthesisCardComponent, QuotationDetailsComponent, DesignerAssignmentComponent, DesignerCalendarComponent],
|
|
|
templateUrl: './project-detail.html',
|
|
|
styleUrls: ['./project-detail.scss', './debug-styles.scss']
|
|
|
})
|
|
|
@@ -214,6 +220,8 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
// 新增:尾款结算完成状态
|
|
|
isSettlementCompleted: boolean = false;
|
|
|
isConfirmingSettlement: boolean = false;
|
|
|
+ isSettlementInitiated: boolean = false;
|
|
|
+ isPaymentVerified: boolean = false;
|
|
|
|
|
|
// 客户信息卡片展开/收起状态
|
|
|
isCustomerInfoExpanded: boolean = false;
|
|
|
@@ -250,7 +258,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
{ key: 'order', label: '订单创建', stages: ['订单创建'] },
|
|
|
{ key: 'requirements', label: '确认需求', stages: ['需求沟通', '方案确认'] },
|
|
|
{ key: 'delivery', label: '交付执行', stages: ['建模', '软装', '渲染', '后期'] },
|
|
|
- { key: 'aftercare', label: '售后', stages: ['尾款结算', '客户评价', '投诉处理'] }
|
|
|
+ { key: 'aftercare', label: '售后', stages: [] }
|
|
|
];
|
|
|
expandedSection: SectionKey | null = null;
|
|
|
// 渲染异常反馈相关属性
|
|
|
@@ -265,7 +273,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
|
|
|
// 标签页相关
|
|
|
activeTab: 'progress' | 'members' | 'files' = 'progress';
|
|
|
- tabs = [
|
|
|
+ tabs: Array<{ id: 'progress' | 'members' | 'files'; name: string }> = [
|
|
|
{ id: 'progress', name: '项目进度' },
|
|
|
{ id: 'members', name: '项目成员' },
|
|
|
{ id: 'files', name: '项目文件' }
|
|
|
@@ -294,7 +302,7 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
// 增加审核状态reviewStatus与是否已同步synced标记(仅由组长操作)
|
|
|
whiteModelImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
|
|
|
softDecorImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
|
|
|
- renderLargeImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
|
|
|
+ renderLargeImages: Array<{ id: string; name: string; url: string; size?: string; locked?: boolean; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
|
|
|
postProcessImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
|
|
|
showRenderUploadModal: boolean = false;
|
|
|
pendingRenderLargeItems: Array<{ id: string; name: string; url: string; file: File }> = [];
|
|
|
@@ -1532,8 +1540,13 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
showImagePreview: boolean = false;
|
|
|
previewImageData: any = null;
|
|
|
|
|
|
- // 图片预览方法
|
|
|
+ // 图片预览方法(含渲染大图加锁校验)
|
|
|
previewImage(img: any): void {
|
|
|
+ const isRenderLarge = !!this.renderLargeImages.find(i => i.id === img?.id);
|
|
|
+ if (isRenderLarge && img?.locked) {
|
|
|
+ alert('该渲染大图已加锁,需完成尾款结算并上传/识别支付凭证后方可预览。');
|
|
|
+ return;
|
|
|
+ }
|
|
|
this.previewImageData = img;
|
|
|
this.showImagePreview = true;
|
|
|
}
|
|
|
@@ -1544,6 +1557,11 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
}
|
|
|
|
|
|
downloadImage(img: any): void {
|
|
|
+ const isRenderLarge = !!this.renderLargeImages.find(i => i.id === img?.id);
|
|
|
+ if (isRenderLarge && img?.locked) {
|
|
|
+ alert('该渲染大图已加锁,需完成尾款结算并上传/识别支付凭证后方可下载。');
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (img) {
|
|
|
const link = document.createElement('a');
|
|
|
link.href = img.url;
|
|
|
@@ -1751,7 +1769,8 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
id: item.id,
|
|
|
name: item.name,
|
|
|
url: item.url,
|
|
|
- size: this.formatFileSize(f.size)
|
|
|
+ size: this.formatFileSize(f.size),
|
|
|
+ locked: true
|
|
|
});
|
|
|
}
|
|
|
input.value = '';
|
|
|
@@ -2381,22 +2400,128 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
return Math.round((completedCount / totalCount) * 100);
|
|
|
}
|
|
|
|
|
|
- // 获取预估小图时间
|
|
|
- getEstimatedSmallImageTime(): string {
|
|
|
- // 根据需求复杂度计算预估时间
|
|
|
- const baseTime = 2; // 基础时间2小时
|
|
|
- let additionalTime = 0;
|
|
|
+ // 订单金额
|
|
|
+ orderAmount: number = 0;
|
|
|
+
|
|
|
+ // 报价明细
|
|
|
+ quotationDetails: Array<{
|
|
|
+ id: string;
|
|
|
+ room: string;
|
|
|
+ amount: number;
|
|
|
+ description?: string;
|
|
|
+ }> = [];
|
|
|
+
|
|
|
+ // AI生成报价明细
|
|
|
+ generateQuotationDetails(): void {
|
|
|
+ // 基于项目信息生成报价明细
|
|
|
+ const rooms = ['客餐厅', '主卧', '次卧', '厨房', '卫生间'];
|
|
|
+ this.quotationDetails = rooms.map((room, index) => ({
|
|
|
+ id: `quote_${index + 1}`,
|
|
|
+ room: room,
|
|
|
+ amount: Math.floor(Math.random() * 1000) + 300, // 示例金额
|
|
|
+ description: `${room}装修设计费用`
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 更新总订单金额
|
|
|
+ this.orderAmount = this.quotationDetails.reduce((total, item) => total + item.amount, 0);
|
|
|
+ }
|
|
|
|
|
|
- // 根据材质复杂度增加时间
|
|
|
- if (this.requirementKeyInfo.materialWeights.woodRatio > 0) additionalTime += 0.5;
|
|
|
- if (this.requirementKeyInfo.materialWeights.fabricRatio > 0) additionalTime += 0.5;
|
|
|
- if (this.requirementKeyInfo.materialWeights.metalRatio > 0) additionalTime += 0.5;
|
|
|
+ // 添加报价明细项
|
|
|
+ addQuotationItem(): void {
|
|
|
+ this.quotationDetails.push({
|
|
|
+ id: `quote_${Date.now()}`,
|
|
|
+ room: '',
|
|
|
+ amount: 0,
|
|
|
+ description: ''
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- // 根据空间复杂度增加时间
|
|
|
- if (this.requirementKeyInfo.spaceStructure.aspectRatio > 2) additionalTime += 1;
|
|
|
+ // 删除报价明细项
|
|
|
+ removeQuotationItem(id: string): void {
|
|
|
+ this.quotationDetails = this.quotationDetails.filter(item => item.id !== id);
|
|
|
+ this.updateOrderAmount();
|
|
|
+ }
|
|
|
|
|
|
- const totalTime = baseTime + additionalTime;
|
|
|
- return `${totalTime}小时`;
|
|
|
+ // 更新订单总金额
|
|
|
+ updateOrderAmount(): void {
|
|
|
+ this.orderAmount = this.quotationDetails.reduce((total, item) => total + item.amount, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 报价组件数据
|
|
|
+ quotationData: QuotationData = {
|
|
|
+ items: [],
|
|
|
+ totalAmount: 0,
|
|
|
+ materialCost: 0,
|
|
|
+ laborCost: 0,
|
|
|
+ designFee: 0,
|
|
|
+ managementFee: 0
|
|
|
+ };
|
|
|
+
|
|
|
+ // 设计师指派数据
|
|
|
+ designerAssignmentData?: DesignerAssignmentData;
|
|
|
+
|
|
|
+ // 设计师日历弹窗状态与数据
|
|
|
+ showDesignerCalendar: boolean = false;
|
|
|
+ selectedCalendarDate: Date = new Date();
|
|
|
+ calendarDesigners: CalendarDesigner[] = [];
|
|
|
+ calendarGroups: CalendarProjectGroup[] = [];
|
|
|
+
|
|
|
+ onQuotationDataChange(data: QuotationData): void {
|
|
|
+ this.quotationData = { ...data };
|
|
|
+ this.orderAmount = data.totalAmount || 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ onDesignerAssignmentChange(data: DesignerAssignmentData): void {
|
|
|
+ this.designerAssignmentData = { ...data };
|
|
|
+ }
|
|
|
+
|
|
|
+ onDesignerClick(designer: AssignmentDesigner): void {
|
|
|
+ const mapped = this.mapAssignmentDesignerToCalendar(designer);
|
|
|
+ this.calendarDesigners = [mapped];
|
|
|
+ this.calendarGroups = [{ id: designer.teamId, name: designer.teamName, leaderId: designer.id, memberIds: [designer.id] }];
|
|
|
+ this.selectedCalendarDate = new Date();
|
|
|
+ this.showDesignerCalendar = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ closeDesignerCalendar(): void {
|
|
|
+ this.showDesignerCalendar = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ onCalendarDesignerSelected(designer: CalendarDesigner): void {
|
|
|
+ this.selectedDesigner = designer;
|
|
|
+ this.closeDesignerCalendar();
|
|
|
+ }
|
|
|
+
|
|
|
+ onCalendarAssignmentRequested(designer: CalendarDesigner): void {
|
|
|
+ this.selectedDesigner = designer;
|
|
|
+ this.closeDesignerCalendar();
|
|
|
+ }
|
|
|
+
|
|
|
+ private mapAssignmentDesignerToCalendar(d: AssignmentDesigner): CalendarDesigner {
|
|
|
+ return {
|
|
|
+ id: d.id,
|
|
|
+ name: d.name,
|
|
|
+ avatar: d.avatar,
|
|
|
+ groupId: d.teamId,
|
|
|
+ groupName: d.teamName,
|
|
|
+ isLeader: !!d.isTeamLeader,
|
|
|
+ status: d.status === 'idle' ? 'available' : 'busy',
|
|
|
+ currentProjects: Math.max(0, d.recentOrders || 0),
|
|
|
+ lastOrderDate: d.lastOrderDate,
|
|
|
+ idleDays: Math.max(0, d.idleDays || 0),
|
|
|
+ completedThisMonth: Math.max(0, d.recentOrders || 0),
|
|
|
+ averageCycle: 15,
|
|
|
+ upcomingEvents: (d.reviewDates || []).map((dateStr, idx) => ({
|
|
|
+ id: `${d.id}-review-${idx}`,
|
|
|
+ date: new Date(dateStr),
|
|
|
+ title: '对图评审',
|
|
|
+ type: 'review',
|
|
|
+ projectId: undefined,
|
|
|
+ duration: 2
|
|
|
+ })),
|
|
|
+ workload: Math.max(0, d.workload || 0),
|
|
|
+ nextAvailableDate: new Date()
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
// 处理咨询订单表单提交
|
|
|
@@ -2409,11 +2534,14 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
// 保存订单创建数据
|
|
|
this.orderCreationData = formData;
|
|
|
|
|
|
- // 更新projectData以便传递给子组件
|
|
|
+ // 更新projectData以便传递给子组件(集成报价与指派信息)
|
|
|
this.projectData = {
|
|
|
customerInfo: formData.customerInfo,
|
|
|
requirementInfo: formData.requirementInfo,
|
|
|
- preferenceTags: formData.preferenceTags
|
|
|
+ preferenceTags: formData.preferenceTags,
|
|
|
+ quotation: this.quotationData ? { ...this.quotationData } : undefined,
|
|
|
+ assignment: this.designerAssignmentData ? { ...this.designerAssignmentData } : undefined,
|
|
|
+ orderAmount: this.quotationData?.totalAmount ?? this.orderAmount ?? 0
|
|
|
};
|
|
|
|
|
|
// 实时更新左侧客户信息显示
|
|
|
@@ -2424,6 +2552,10 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
// 客服端创建的订单需要同步到设计师端
|
|
|
this.syncOrderToDesignerView(formData);
|
|
|
}
|
|
|
+
|
|
|
+ // 根据报价数据更新订单金额
|
|
|
+ this.orderAmount = this.quotationData?.totalAmount ?? this.orderAmount ?? 0;
|
|
|
+ this.updateOrderAmount();
|
|
|
|
|
|
// 触发变更检测以更新UI
|
|
|
this.cdr.detectChanges();
|
|
|
@@ -2467,7 +2599,6 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
area: formData.requirementInfo.area,
|
|
|
houseType: formData.requirementInfo.houseType,
|
|
|
smallImageTime: formData.requirementInfo.smallImageTime,
|
|
|
- largeImageTime: formData.requirementInfo.largeImageTime,
|
|
|
spaceRequirements: formData.requirementInfo.spaceRequirements,
|
|
|
designAngles: formData.requirementInfo.designAngles,
|
|
|
specialAreaHandling: formData.requirementInfo.specialAreaHandling,
|
|
|
@@ -2492,7 +2623,11 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
demandType: formData.customerInfo.demandType,
|
|
|
preferenceTags: formData.preferenceTags,
|
|
|
followUpStatus: formData.customerInfo.followUpStatus
|
|
|
- }
|
|
|
+ },
|
|
|
+ // 新增:报价与指派信息(可选)
|
|
|
+ quotation: this.quotationData ? { ...this.quotationData } : undefined,
|
|
|
+ assignment: this.designerAssignmentData ? { ...this.designerAssignmentData } : undefined,
|
|
|
+ orderAmount: this.quotationData?.totalAmount ?? this.orderAmount ?? 0
|
|
|
};
|
|
|
|
|
|
// 调用项目服务创建项目
|
|
|
@@ -3051,6 +3186,254 @@ export class ProjectDetail implements OnInit, OnDestroy {
|
|
|
fileType: file.type,
|
|
|
uploadTime: new Date().toISOString()
|
|
|
});
|
|
|
+ // 自动标记验证通过并解锁渲染大图
|
|
|
+ this.isPaymentVerified = true;
|
|
|
+ this.renderLargeImages = this.renderLargeImages.map(img => ({ ...img, locked: false }));
|
|
|
+ }, 2000);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前设计师名称
|
|
|
+ getCurrentDesignerName(): string {
|
|
|
+ // 这里应该从用户服务或认证信息中获取当前用户名称
|
|
|
+ // 暂时返回一个默认值
|
|
|
+ return '张设计师';
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 售后相关变量 ====================
|
|
|
+
|
|
|
+ // 售后标签页控制
|
|
|
+ activeAftercareTab: string = 'services'; // 当前激活的售后标签页
|
|
|
+
|
|
|
+ // 售后状态管理
|
|
|
+ afterSalesStage: string = '未开始'; // 售后阶段:未开始、进行中、已完成
|
|
|
+ afterSalesStatus: 'pending' | 'in_progress' | 'completed' | 'cancelled' = 'pending'; // 售后状态
|
|
|
+ afterSalesProgress: number = 0; // 售后进度百分比
|
|
|
+
|
|
|
+ // 售后服务数据
|
|
|
+ afterSalesServices: Array<{
|
|
|
+ id: string;
|
|
|
+ type: string; // 服务类型:维修、保养、咨询、投诉处理
|
|
|
+ description: string;
|
|
|
+ assignedTo: string; // 指派给的人员
|
|
|
+ scheduledDate?: Date; // 计划服务日期
|
|
|
+ completedDate?: Date; // 完成日期
|
|
|
+ status: 'pending' | 'scheduled' | 'in_progress' | 'completed' | 'cancelled';
|
|
|
+ priority: 'low' | 'medium' | 'high';
|
|
|
+ }> = [];
|
|
|
+
|
|
|
+ // 售后评价和反馈
|
|
|
+ afterSalesRating: number = 0; // 售后评分(0-5)
|
|
|
+ afterSalesFeedback: string = ''; // 售后反馈内容
|
|
|
+ afterSalesFeedbackDate?: Date; // 反馈日期
|
|
|
+
|
|
|
+ // 售后时间跟踪
|
|
|
+ afterSalesResponseTime?: Date; // 首次响应时间
|
|
|
+ afterSalesStartTime?: Date; // 售后开始时间
|
|
|
+ afterSalesCompletionTime?: Date; // 售后完成时间
|
|
|
+ afterSalesTotalDuration: number = 0; // 总耗时(小时)
|
|
|
+
|
|
|
+ // 售后联系人信息
|
|
|
+ afterSalesContact: {
|
|
|
+ name: string;
|
|
|
+ phone: string;
|
|
|
+ wechat?: string;
|
|
|
+ email?: string;
|
|
|
+ } = {
|
|
|
+ name: '',
|
|
|
+ phone: ''
|
|
|
+ };
|
|
|
+
|
|
|
+ // 售后问题记录
|
|
|
+ afterSalesIssues: Array<{
|
|
|
+ id: string;
|
|
|
+ title: string;
|
|
|
+ description: string;
|
|
|
+ severity: 'low' | 'medium' | 'high' | 'critical';
|
|
|
+ reportedDate: Date;
|
|
|
+ resolvedDate?: Date;
|
|
|
+ status: 'reported' | 'investigating' | 'resolved' | 'closed';
|
|
|
+ }> = [];
|
|
|
+
|
|
|
+ // 售后文件记录
|
|
|
+ afterSalesDocuments: Array<{
|
|
|
+ id: string;
|
|
|
+ name: string;
|
|
|
+ type: string; // 文件类型:合同、报告、照片、视频
|
|
|
+ uploadDate: Date;
|
|
|
+ url: string;
|
|
|
+ }> = [];
|
|
|
+
|
|
|
+ // 售后费用记录
|
|
|
+ afterSalesCosts: Array<{
|
|
|
+ id: string;
|
|
|
+ description: string;
|
|
|
+ amount: number;
|
|
|
+ category: 'material' | 'labor' | 'transportation' | 'other';
|
|
|
+ date: Date;
|
|
|
+ status: 'pending' | 'approved' | 'paid' | 'rejected';
|
|
|
+ }> = [];
|
|
|
+
|
|
|
+ // 售后沟通记录
|
|
|
+ afterSalesCommunications: Array<{
|
|
|
+ id: string;
|
|
|
+ type: 'phone' | 'wechat' | 'email' | 'visit';
|
|
|
+ date: Date;
|
|
|
+ summary: string;
|
|
|
+ participants: string[];
|
|
|
+ }> = [];
|
|
|
+
|
|
|
+ // 切换售后标签页
|
|
|
+ switchAftercareTab(tab: string): void {
|
|
|
+ this.activeAftercareTab = tab;
|
|
|
+ console.log('切换到售后标签页:', tab);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 自动结算相关 ====================
|
|
|
+
|
|
|
+ // 自动结算状态
|
|
|
+ isAutoSettling: boolean = false;
|
|
|
+
|
|
|
+ // 启动自动结算
|
|
|
+ initiateAutoSettlement(): void {
|
|
|
+ this.isAutoSettling = true;
|
|
|
+ console.log('启动自动结算流程...');
|
|
|
+
|
|
|
+ // 模拟自动结算过程
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isAutoSettling = false;
|
|
|
+ console.log('自动结算完成');
|
|
|
+ alert('自动结算已完成!');
|
|
|
+ }, 3000);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 全景图合成相关 ====================
|
|
|
+
|
|
|
+ // 全景图合成数据
|
|
|
+ panoramicSyntheses: PanoramicSynthesis[] = [];
|
|
|
+
|
|
|
+ // 启动全景图合成
|
|
|
+ startPanoramicSynthesis(): void {
|
|
|
+ const synthesis: PanoramicSynthesis = {
|
|
|
+ id: 'panoramic-' + Date.now(),
|
|
|
+ projectId: this.projectId,
|
|
|
+ projectName: this.project?.name || '未知项目',
|
|
|
+ spaces: [],
|
|
|
+ status: 'processing',
|
|
|
+ quality: 'high',
|
|
|
+ createdAt: new Date(),
|
|
|
+ updatedAt: new Date()
|
|
|
+ };
|
|
|
+
|
|
|
+ this.panoramicSyntheses.push(synthesis);
|
|
|
+ console.log('启动全景图合成:', synthesis);
|
|
|
+
|
|
|
+ // 模拟合成进度
|
|
|
+ const progressInterval = setInterval(() => {
|
|
|
+ const currentSynthesis = this.panoramicSyntheses.find(s => s.id === synthesis.id);
|
|
|
+ if (currentSynthesis) {
|
|
|
+ // 模拟进度更新
|
|
|
+ if (currentSynthesis.status === 'processing') {
|
|
|
+ currentSynthesis.status = 'completed';
|
|
|
+ currentSynthesis.completedAt = new Date();
|
|
|
+ currentSynthesis.updatedAt = new Date();
|
|
|
+ currentSynthesis.previewUrl = 'https://via.placeholder.com/1920x1080';
|
|
|
+ currentSynthesis.downloadUrl = 'https://via.placeholder.com/1920x1080';
|
|
|
+ currentSynthesis.renderTime = 120;
|
|
|
+ currentSynthesis.fileSize = 1024 * 1024 * 50; // 50MB
|
|
|
+ clearInterval(progressInterval);
|
|
|
+ console.log('全景图合成完成:', currentSynthesis);
|
|
|
+ }
|
|
|
+ }
|
|
|
}, 2000);
|
|
|
}
|
|
|
+
|
|
|
+ // 查看全景图画廊
|
|
|
+ viewPanoramicGallery(): void {
|
|
|
+ console.log('打开全景图画廊');
|
|
|
+ // 这里可以打开一个模态框或导航到画廊页面
|
|
|
+ alert('全景图画廊功能开发中...');
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 评价统计相关 ====================
|
|
|
+
|
|
|
+ // 评价统计数据
|
|
|
+ reviewStats: {
|
|
|
+ overallScore: number;
|
|
|
+ timelinessScore: number;
|
|
|
+ qualityScore: number;
|
|
|
+ communicationScore: number;
|
|
|
+ } = {
|
|
|
+ overallScore: 4.8,
|
|
|
+ timelinessScore: 4.7,
|
|
|
+ qualityScore: 4.9,
|
|
|
+ communicationScore: 4.6
|
|
|
+ };
|
|
|
+
|
|
|
+ // ==================== 客户评价相关 ====================
|
|
|
+
|
|
|
+ // 生成评价链接
|
|
|
+ generateReviewLink(): void {
|
|
|
+ console.log('生成客户评价链接');
|
|
|
+ const reviewLink = `https://review.example.com/project/${this.projectId}`;
|
|
|
+ navigator.clipboard.writeText(reviewLink).then(() => {
|
|
|
+ alert('评价链接已复制到剪贴板!');
|
|
|
+ }).catch(() => {
|
|
|
+ alert(`评价链接:${reviewLink}`);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 投诉管理相关 ====================
|
|
|
+
|
|
|
+ // 手动创建投诉
|
|
|
+ createComplaintManually(): void {
|
|
|
+ console.log('手动创建投诉');
|
|
|
+ // 这里可以打开一个模态框来创建投诉
|
|
|
+ alert('手动创建投诉功能开发中...');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置关键词监控
|
|
|
+ setupKeywordMonitoring(): void {
|
|
|
+ console.log('设置关键词监控');
|
|
|
+ // 这里可以打开关键词监控设置界面
|
|
|
+ alert('关键词监控设置功能开发中...');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理评价表单提交
|
|
|
+ onReviewSubmitted(reviewData: any): void {
|
|
|
+ console.log('客户评价已提交:', reviewData);
|
|
|
+
|
|
|
+ // 这里应该调用API将评价数据保存到服务器
|
|
|
+ // 模拟API调用
|
|
|
+ setTimeout(() => {
|
|
|
+ alert('客户评价提交成功!评价数据已保存。');
|
|
|
+
|
|
|
+ // 更新本地反馈数据
|
|
|
+ const newFeedback: CustomerFeedback = {
|
|
|
+ id: Date.now().toString(),
|
|
|
+ customerName: '客户', // 应该从项目信息中获取
|
|
|
+ rating: reviewData.overallRating,
|
|
|
+ content: reviewData.improvementSuggestions || '无具体建议',
|
|
|
+ createdAt: new Date(),
|
|
|
+ status: '已解决',
|
|
|
+ isSatisfied: reviewData.overallRating >= 4,
|
|
|
+ projectId: this.projectId
|
|
|
+ };
|
|
|
+
|
|
|
+ this.feedbacks = [...this.feedbacks, newFeedback];
|
|
|
+
|
|
|
+ // 自动标记客户评价完成
|
|
|
+ this.confirmCustomerReview();
|
|
|
+ }, 1000);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理评价表单保存草稿
|
|
|
+ onReviewSaved(reviewData: any): void {
|
|
|
+ console.log('客户评价草稿已保存:', reviewData);
|
|
|
+
|
|
|
+ // 这里应该调用API将草稿数据保存到服务器
|
|
|
+ // 模拟API调用
|
|
|
+ setTimeout(() => {
|
|
|
+ alert('评价草稿保存成功!您可以稍后继续完善。');
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
}
|