order-creation.component.ts 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. import { Component, Input, Output, EventEmitter, OnInit, signal } from '@angular/core';
  2. import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
  3. import { CommonModule } from '@angular/common';
  4. import { FormsModule } from '@angular/forms';
  5. import { QuotationDetailsComponent, QuotationData } from '../quotation-details/quotation-details.component';
  6. export interface OrderCreationData {
  7. orderAmount: number;
  8. deliveryTime: string;
  9. quotationData?: QuotationData;
  10. }
  11. // 报价规则接口
  12. export interface PricingRule {
  13. spaceType: string;
  14. basePrice: number; // 基础价格(元/人天)
  15. styleMultiplier: number; // 风格系数
  16. finalPrice: number; // 最终价格
  17. description: string; // 服务内容描述
  18. }
  19. // 空间类型配置
  20. export interface SpaceTypeConfig {
  21. type: string;
  22. basePrice: number; // 元/人天
  23. description: string;
  24. }
  25. // 风格等级配置
  26. export interface StyleLevelConfig {
  27. level: string;
  28. name: string;
  29. multiplier: number;
  30. description: string;
  31. }
  32. @Component({
  33. selector: 'app-order-creation',
  34. standalone: true,
  35. imports: [CommonModule, FormsModule, ReactiveFormsModule, QuotationDetailsComponent],
  36. templateUrl: './order-creation.component.html',
  37. styleUrls: ['./order-creation.component.scss']
  38. })
  39. export class OrderCreationComponent implements OnInit {
  40. @Input() initialData?: OrderCreationData;
  41. @Output() dataChange = new EventEmitter<OrderCreationData>();
  42. @Output() validityChange = new EventEmitter<boolean>();
  43. orderForm: FormGroup;
  44. quotationData?: QuotationData;
  45. // 替换为停滞项目筛选的本地状态
  46. hideStagnantProjects = false;
  47. // 报价规则配置
  48. showPricingRulesModal = signal(false);
  49. showAdjustModal = false; // 添加调整价格模态框状态
  50. // 空间类型配置
  51. spaceTypeConfig = signal<SpaceTypeConfig[]>([
  52. { type: '客餐厅', basePrice: 600, description: '客厅餐厅一体化设计' },
  53. { type: '卧室', basePrice: 400, description: '主卧/次卧设计' },
  54. { type: '厨房', basePrice: 500, description: '厨房空间设计' },
  55. { type: '卫生间', basePrice: 350, description: '卫生间设计' },
  56. { type: '书房', basePrice: 450, description: '书房/工作区设计' },
  57. { type: '阳台', basePrice: 300, description: '阳台/露台设计' }
  58. ]);
  59. // 风格等级配置
  60. styleLevelConfig = signal<StyleLevelConfig[]>([
  61. { level: 'standard', name: '标准', multiplier: 1.0, description: '基础设计方案' },
  62. { level: 'premium', name: '高端', multiplier: 1.5, description: '精装设计方案,4K单张,6K全景' },
  63. { level: 'luxury', name: '奢华', multiplier: 2.0, description: '顶级设计方案,8K渲染' }
  64. ]);
  65. // 当前选择的报价配置
  66. selectedSpaceType = signal<string>('');
  67. selectedStyleLevel = signal<string>('');
  68. // 生成的报价清单
  69. generatedQuotation = signal<PricingRule[]>([]);
  70. constructor(private fb: FormBuilder) {
  71. this.orderForm = this.fb.group({
  72. orderAmount: ['', [
  73. Validators.required,
  74. Validators.min(0.01),
  75. Validators.pattern(/^\d+(\.\d{1,2})?$/)
  76. ]],
  77. deliveryTime: ['', Validators.required]
  78. });
  79. }
  80. ngOnInit() {
  81. if (this.initialData) {
  82. this.orderForm.patchValue(this.initialData);
  83. this.quotationData = this.initialData.quotationData;
  84. }
  85. // 监听表单变化
  86. this.orderForm.valueChanges.subscribe(value => {
  87. this.emitDataChange();
  88. this.validityChange.emit(this.isFormValid());
  89. });
  90. // 初始状态发送
  91. this.validityChange.emit(this.isFormValid());
  92. }
  93. // 显示报价规则配置
  94. showPricingRules(): void {
  95. this.showPricingRulesModal.set(true);
  96. }
  97. // 隐藏报价规则配置
  98. hidePricingRules(): void {
  99. this.showPricingRulesModal.set(false);
  100. }
  101. // 添加空间类型
  102. addSpaceType(): void {
  103. const current = this.spaceTypeConfig();
  104. current.push({ type: '', basePrice: 400, description: '' });
  105. this.spaceTypeConfig.set([...current]);
  106. }
  107. // 删除空间类型
  108. removeSpaceType(index: number): void {
  109. const current = this.spaceTypeConfig();
  110. current.splice(index, 1);
  111. this.spaceTypeConfig.set([...current]);
  112. }
  113. // 添加风格等级
  114. addStyleLevel(): void {
  115. const current = this.styleLevelConfig();
  116. current.push({ level: '', name: '', multiplier: 1.0, description: '' });
  117. this.styleLevelConfig.set([...current]);
  118. }
  119. // 删除风格等级
  120. removeStyleLevel(index: number): void {
  121. const current = this.styleLevelConfig();
  122. current.splice(index, 1);
  123. this.styleLevelConfig.set([...current]);
  124. }
  125. // 保存报价规则配置
  126. savePricingRules(): void {
  127. // 这里应该调用服务保存配置到后端
  128. console.log('保存报价规则配置:', {
  129. spaceTypes: this.spaceTypeConfig(),
  130. styleLevels: this.styleLevelConfig()
  131. });
  132. this.hidePricingRules();
  133. }
  134. // 生成自动报价
  135. generateAutoQuotation(): void {
  136. if (!this.selectedSpaceType() || !this.selectedStyleLevel()) {
  137. window?.fmode?.alert('请先选择空间类型和风格等级');
  138. return;
  139. }
  140. const spaceConfig = this.spaceTypeConfig().find(s => s.type === this.selectedSpaceType());
  141. const styleConfig = this.styleLevelConfig().find(s => s.level === this.selectedStyleLevel());
  142. if (!spaceConfig || !styleConfig) {
  143. window?.fmode?.alert('配置信息不完整');
  144. return;
  145. }
  146. const finalPrice = spaceConfig.basePrice * styleConfig.multiplier;
  147. const rule: PricingRule = {
  148. spaceType: spaceConfig.type,
  149. basePrice: spaceConfig.basePrice,
  150. styleMultiplier: styleConfig.multiplier,
  151. finalPrice: finalPrice,
  152. description: `${styleConfig.name}${spaceConfig.type}项目 - ${spaceConfig.description},${styleConfig.description}`
  153. };
  154. this.generatedQuotation.set([rule]);
  155. // 更新订单金额
  156. this.orderForm.patchValue({
  157. orderAmount: finalPrice
  158. });
  159. // 生成报价数据
  160. this.quotationData = {
  161. items: [{
  162. id: '1',
  163. category: '设计服务', // 添加category属性
  164. name: `${styleConfig.name}${spaceConfig.type}设计`,
  165. quantity: 1,
  166. unit: '项',
  167. unitPrice: finalPrice,
  168. totalPrice: finalPrice,
  169. description: rule.description
  170. }],
  171. totalAmount: finalPrice,
  172. materialCost: 0,
  173. laborCost: finalPrice,
  174. designFee: finalPrice,
  175. managementFee: 0
  176. };
  177. this.emitDataChange();
  178. }
  179. // 调整报价
  180. adjustQuotation(newPrice: number, reason: string): void {
  181. if (this.generatedQuotation().length === 0) {
  182. window?.fmode?.alert('请先生成报价');
  183. return;
  184. }
  185. const currentRule = this.generatedQuotation()[0];
  186. const adjustedRule: PricingRule = {
  187. ...currentRule,
  188. finalPrice: newPrice,
  189. description: `${currentRule.description} (调整原因: ${reason})`
  190. };
  191. this.generatedQuotation.set([adjustedRule]);
  192. // 更新订单金额
  193. this.orderForm.patchValue({
  194. orderAmount: newPrice
  195. });
  196. // 更新报价数据
  197. if (this.quotationData) {
  198. this.quotationData.items[0].unitPrice = newPrice;
  199. this.quotationData.items[0].totalPrice = newPrice;
  200. this.quotationData.totalAmount = newPrice;
  201. this.quotationData.laborCost = newPrice;
  202. this.quotationData.designFee = newPrice;
  203. }
  204. this.emitDataChange();
  205. // 记录调整日志(应该发送到后端)
  206. console.log('报价调整记录:', {
  207. originalPrice: currentRule.finalPrice,
  208. adjustedPrice: newPrice,
  209. reason: reason,
  210. timestamp: new Date(),
  211. spaceType: currentRule.spaceType
  212. });
  213. }
  214. // 获取服务内容说明
  215. getServiceDescription(spaceType: string, styleLevel: string): string {
  216. const spaceConfig = this.spaceTypeConfig().find(s => s.type === spaceType);
  217. const styleConfig = this.styleLevelConfig().find(s => s.level === styleLevel);
  218. if (!spaceConfig || !styleConfig) return '';
  219. const baseServices = ['建模', '渲染', '1次小图修改'];
  220. const premiumServices = styleLevel === 'premium' ? ['4K单张交付', '6K全景交付'] : [];
  221. const luxuryServices = styleLevel === 'luxury' ? ['8K渲染', '无限次修改'] : [];
  222. return [...baseServices, ...premiumServices, ...luxuryServices].join('、');
  223. }
  224. // 处理报价明细数据变化
  225. onQuotationDataChange(data: QuotationData) {
  226. this.quotationData = data;
  227. this.emitDataChange();
  228. this.validityChange.emit(this.isFormValid());
  229. }
  230. // 发送数据变化事件
  231. private emitDataChange() {
  232. const formData = this.orderForm.value;
  233. const completeData: OrderCreationData = {
  234. ...formData,
  235. quotationData: this.quotationData
  236. };
  237. this.dataChange.emit(completeData);
  238. }
  239. // 检查表单有效性
  240. private isFormValid(): boolean {
  241. return this.orderForm.valid && !!this.quotationData && this.quotationData.items.length > 0;
  242. }
  243. // 获取表单控件
  244. get orderAmount() { return this.orderForm.get('orderAmount'); }
  245. get deliveryTime() { return this.orderForm.get('deliveryTime'); }
  246. // 获取表单数据
  247. getFormData(): OrderCreationData {
  248. return {
  249. ...this.orderForm.value,
  250. quotationData: this.quotationData
  251. };
  252. }
  253. // 重置表单
  254. resetForm() {
  255. this.orderForm.reset();
  256. this.quotationData = undefined;
  257. this.generatedQuotation.set([]);
  258. this.selectedSpaceType.set('');
  259. this.selectedStyleLevel.set('');
  260. }
  261. // 验证表单
  262. validateForm(): boolean {
  263. this.orderForm.markAllAsTouched();
  264. return this.isFormValid();
  265. }
  266. // 切换停滞项目筛选(仅本地UI状态)
  267. toggleStagnantFilter() {
  268. this.hideStagnantProjects = !this.hideStagnantProjects;
  269. }
  270. }