123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { FormsModule } from '@angular/forms';
- import { WorkHourService } from '../../../../../services/work-hour.service';
- import { QuotationApprovalService } from '../../../../../services/quotation-approval.service';
- import { SpaceType, ProjectStyle, AutoQuotationResult, PricingScript } from '../../../../../models/work-hour.model';
- export interface QuotationItem {
- id: string;
- category: string;
- name: string;
- quantity: number;
- unit: string;
- unitPrice: number;
- totalPrice?: number; // 添加总价属性
- description: string;
- }
- export interface QuotationData {
- items: QuotationItem[];
- totalAmount: number;
- materialCost: number;
- laborCost: number;
- designFee: number;
- managementFee: number;
- }
- @Component({
- selector: 'app-quotation-details',
- standalone: true,
- imports: [CommonModule, FormsModule],
- templateUrl: './quotation-details.component.html',
- styleUrls: ['./quotation-details.component.scss']
- })
- export class QuotationDetailsComponent implements OnInit {
- @Input() initialData?: QuotationData;
- @Input() projectData?: any; // 添加项目数据输入属性
- @Output() dataChange = new EventEmitter<QuotationData>();
- quotationData: QuotationData = {
- items: [],
- totalAmount: 0,
- materialCost: 0,
- laborCost: 0,
- designFee: 0,
- managementFee: 0
- };
- // 新增:自动报价相关
- showAutoQuotationModal = false;
- autoQuotationParams = {
- spaceType: '客餐厅' as SpaceType,
- projectStyle: '现代简约' as ProjectStyle,
- estimatedWorkDays: 3,
- projectArea: 100
- };
-
- // 报价话术库
- showScriptModal = false;
- pricingScripts: PricingScript[] = [];
- selectedScript: PricingScript | null = null;
- constructor(
- private workHourService: WorkHourService,
- private quotationApprovalService: QuotationApprovalService
- ) {}
- ngOnInit() {
- if (this.initialData) {
- this.quotationData = { ...this.initialData };
- }
-
- // 加载报价话术库
- this.loadPricingScripts();
- }
- // 添加报价项目
- addQuotationItem() {
- const newItem: QuotationItem = {
- id: Date.now().toString(),
- category: '客餐厅',
- name: '',
- quantity: 1,
- unit: '㎡',
- unitPrice: 0,
- description: ''
- };
-
- this.quotationData.items.push(newItem);
- this.calculateTotal();
- this.emitDataChange();
- }
- // 删除报价项目
- removeQuotationItem(index: number) {
- this.quotationData.items.splice(index, 1);
- this.calculateTotal();
- this.emitDataChange();
- }
- // 复制报价项目
- duplicateQuotationItem(index: number) {
- const originalItem = this.quotationData.items[index];
- const duplicatedItem: QuotationItem = {
- ...originalItem,
- id: Date.now().toString(),
- name: originalItem.name + ' (副本)'
- };
-
- this.quotationData.items.splice(index + 1, 0, duplicatedItem);
- this.calculateTotal();
- this.emitDataChange();
- }
- // 计算总金额
- calculateTotal() {
- const materialCost = this.quotationData.items.reduce((sum, item) => sum + (item.quantity * item.unitPrice), 0);
- this.quotationData.materialCost = materialCost;
- this.quotationData.laborCost = materialCost * 0.3; // 人工费按材料费30%计算
- this.quotationData.designFee = materialCost * 0.05; // 设计费按材料费5%计算
- this.quotationData.managementFee = materialCost * 0.08; // 管理费按材料费8%计算
- this.quotationData.totalAmount = this.quotationData.materialCost + this.quotationData.laborCost + this.quotationData.designFee + this.quotationData.managementFee;
- }
- // 获取总金额
- getTotalAmount(): number {
- return this.quotationData.totalAmount;
- }
- // 获取材料费用
- getMaterialCost(): number {
- return this.quotationData.materialCost;
- }
- // 获取人工费用
- getLaborCost(): number {
- return this.quotationData.laborCost;
- }
- // 格式化金额显示
- formatAmount(amount: number): string {
- return amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
- }
- // 项目数据变化处理
- onItemChange() {
- this.calculateTotal();
- this.emitDataChange();
- }
- // 发送数据变化事件
- private emitDataChange() {
- this.dataChange.emit({ ...this.quotationData });
- }
- // 加载报价话术库
- loadPricingScripts() {
- this.workHourService.getPricingScripts().subscribe(scripts => {
- this.pricingScripts = scripts;
- });
- }
- // 显示自动报价模态框
- showAutoQuotation() {
- this.showAutoQuotationModal = true;
- }
- // 关闭自动报价模态框
- hideAutoQuotation() {
- this.showAutoQuotationModal = false;
- }
- // 生成自动报价
- generateAutoQuotation() {
- this.workHourService.generateAutoQuotation(
- this.autoQuotationParams.spaceType,
- this.autoQuotationParams.projectStyle,
- this.autoQuotationParams.estimatedWorkDays
- ).subscribe({
- next: (result: AutoQuotationResult) => {
- // 将自动报价结果转换为报价项目
- const autoItem: QuotationItem = {
- id: Date.now().toString(),
- category: result.spaceType,
- name: `${result.projectStyle}${result.spaceType}设计`,
- quantity: result.estimatedWorkDays,
- unit: '人天',
- unitPrice: result.finalPrice / result.estimatedWorkDays,
- description: `包含服务:${result.serviceIncludes.join('、')}`
- };
- // 添加到报价项目列表
- this.quotationData.items.push(autoItem);
- this.calculateTotal();
- this.emitDataChange();
-
- this.hideAutoQuotation();
- },
- error: (error) => {
- console.error('自动报价生成失败:', error);
- }
- });
- }
- // 显示话术库模态框
- showScriptLibrary() {
- this.showScriptModal = true;
- }
- // 关闭话术库模态框
- hideScriptLibrary() {
- this.showScriptModal = false;
- this.selectedScript = null;
- }
- // 选择话术
- selectScript(script: PricingScript) {
- this.selectedScript = script;
-
- // 记录话术使用
- if (this.projectData?.customerInfo?.name) {
- this.quotationApprovalService.recordScriptUsage(
- 'current_quotation', // 这里应该是实际的报价ID
- script.id,
- 'current_user', // 这里应该是当前用户ID
- '当前用户' // 这里应该是当前用户名
- ).subscribe();
- }
- }
- // 复制话术内容
- copyScript(script: PricingScript) {
- navigator.clipboard.writeText(script.content).then(() => {
- console.log('话术内容已复制到剪贴板');
-
- // 记录话术使用
- if (this.projectData?.customerInfo?.name) {
- this.quotationApprovalService.recordScriptUsage(
- 'current_quotation',
- script.id,
- 'current_user',
- '当前用户'
- ).subscribe();
- }
- });
- }
-
- copyScriptContent() {
- if (this.selectedScript) {
- navigator.clipboard.writeText(this.selectedScript.content).then(() => {
- console.log('话术内容已复制到剪贴板');
-
- // 记录话术使用
- if (this.projectData?.customerInfo?.name) {
- this.quotationApprovalService.recordScriptUsage(
- 'current_quotation',
- this.selectedScript!.id,
- 'current_user',
- '当前用户'
- ).subscribe();
- }
- });
- }
- }
- // 提交报价审核
- submitForApproval() {
- if (!this.projectData?.customerInfo?.name || this.quotationData.totalAmount === 0) {
- console.warn('报价信息不完整,无法提交审核');
- return;
- }
- const submissionData = {
- quotationId: `q${Date.now()}`,
- projectId: this.projectData.projectId || `p${Date.now()}`,
- projectName: this.projectData.requirementInfo?.projectName || '未命名项目',
- customerName: this.projectData.customerInfo.name,
- submittedBy: '当前用户', // 这里应该是当前用户名
- totalAmount: this.quotationData.totalAmount,
- scriptUsed: this.selectedScript?.id
- };
- this.quotationApprovalService.submitQuotationForApproval(submissionData).subscribe({
- next: (approval) => {
- console.log('报价已提交审核:', approval);
- // 可以显示成功提示
- },
- error: (error) => {
- console.error('提交审核失败:', error);
- // 可以显示错误提示
- }
- });
- }
- // 获取空间类型选项
- getSpaceTypeOptions(): { value: SpaceType; label: string }[] {
- return [
- { value: '客餐厅', label: '客餐厅' },
- { value: '卧室', label: '卧室' },
- { value: '厨房', label: '厨房' },
- { value: '卫生间', label: '卫生间' },
- { value: '书房', label: '书房' },
- { value: '阳台', label: '阳台' },
- { value: '玄关', label: '玄关' },
- { value: '别墅', label: '别墅' }
- ];
- }
- // 获取项目风格选项
- getProjectStyleOptions(): { value: ProjectStyle; label: string }[] {
- return [
- { value: '现代简约', label: '现代简约' },
- { value: '北欧', label: '北欧' },
- { value: '新中式', label: '新中式' },
- { value: '美式', label: '美式' },
- { value: '欧式', label: '欧式' },
- { value: '日式', label: '日式' },
- { value: '工业风', label: '工业风' },
- { value: '轻奢', label: '轻奢' }
- ];
- }
- }
|