order-creation.component.html 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <div class="order-creation-container">
  2. <div class="section-header">
  3. <h3>订单分配信息</h3>
  4. <span class="required-note">* 为必填项</span>
  5. <div class="header-actions">
  6. <button type="button" class="btn-primary" (click)="showPricingRules()">
  7. 报价规则配置
  8. </button>
  9. <button type="button" class="btn-secondary" (click)="toggleStagnantFilter()">
  10. @if (hideStagnantProjects) { 隐藏停滞项目:已开启 } @else { 隐藏停滞项目:未开启 }
  11. </button>
  12. </div>
  13. </div>
  14. <form [formGroup]="orderForm" class="order-form">
  15. <!-- 自动报价生成 -->
  16. <div class="form-group">
  17. <label class="form-label">自动报价生成</label>
  18. <div class="auto-quotation-section">
  19. <div class="quotation-selectors">
  20. <div class="selector-group">
  21. <label for="spaceType">空间类型</label>
  22. <select id="spaceType" class="form-select" [(ngModel)]="selectedSpaceType">
  23. <option value="">请选择空间类型</option>
  24. @for (space of spaceTypeConfig(); track space.type) {
  25. <option [value]="space.type">{{ space.type }} ({{ space.basePrice }}元/人天)</option>
  26. }
  27. </select>
  28. </div>
  29. <div class="selector-group">
  30. <label for="styleLevel">风格等级</label>
  31. <select id="styleLevel" class="form-select" [(ngModel)]="selectedStyleLevel">
  32. <option value="">请选择风格等级</option>
  33. @for (style of styleLevelConfig(); track style.level) {
  34. <option [value]="style.level">{{ style.name }} ({{ style.multiplier }}x)</option>
  35. }
  36. </select>
  37. </div>
  38. </div>
  39. <div class="quotation-actions">
  40. <button type="button" class="btn-primary" (click)="generateAutoQuotation()">
  41. 生成报价
  42. </button>
  43. </div>
  44. </div>
  45. </div>
  46. <!-- 生成的报价清单 -->
  47. @if (generatedQuotation().length > 0) {
  48. <div class="form-group">
  49. <label class="form-label">生成的报价清单</label>
  50. <div class="quotation-result">
  51. @for (rule of generatedQuotation(); track rule.spaceType) {
  52. <div class="quotation-item">
  53. <div class="item-header">
  54. <h4>{{ rule.spaceType }} - {{ rule.finalPrice }}元</h4>
  55. <div class="item-actions">
  56. <button type="button" class="btn-text" (click)="showAdjustModal = true">调整价格</button>
  57. </div>
  58. </div>
  59. <div class="item-details">
  60. <p><strong>基础价格:</strong>{{ rule.basePrice }}元/人天</p>
  61. <p><strong>风格系数:</strong>{{ rule.styleMultiplier }}x</p>
  62. <p><strong>服务内容:</strong>{{ rule.description }}</p>
  63. <p><strong>包含服务:</strong>{{ getServiceDescription(rule.spaceType, selectedStyleLevel()) }}</p>
  64. </div>
  65. </div>
  66. }
  67. </div>
  68. </div>
  69. }
  70. <!-- 订单金额 -->
  71. <div class="form-group">
  72. <label for="orderAmount" class="form-label required">订单金额</label>
  73. <div class="input-wrapper">
  74. <input
  75. id="orderAmount"
  76. type="number"
  77. formControlName="orderAmount"
  78. class="form-input"
  79. placeholder="请输入订单金额"
  80. min="0.01"
  81. step="0.01"
  82. />
  83. <span class="currency-unit">元</span>
  84. </div>
  85. @if (orderAmount?.invalid && orderAmount?.touched) {
  86. <div class="error-message">
  87. @if (orderAmount?.errors?.['required']) {
  88. <span>订单金额为必填项</span>
  89. }
  90. @if (orderAmount?.errors?.['min']) {
  91. <span>订单金额必须大于0</span>
  92. }
  93. @if (orderAmount?.errors?.['pattern']) {
  94. <span>请输入有效的金额格式</span>
  95. }
  96. </div>
  97. }
  98. </div>
  99. <!-- 交付时间 -->
  100. <div class="form-group">
  101. <label for="deliveryTime" class="form-label required">交付时间</label>
  102. <input
  103. id="deliveryTime"
  104. type="date"
  105. formControlName="deliveryTime"
  106. class="form-input"
  107. />
  108. @if (deliveryTime?.invalid && deliveryTime?.touched) {
  109. <div class="error-message">
  110. <span>交付时间为必填项</span>
  111. </div>
  112. }
  113. </div>
  114. <!-- 报价明细组件 -->
  115. <app-quotation-details
  116. [projectData]="{ customerInfo: {}, requirementInfo: {} }"
  117. (dataChange)="onQuotationDataChange($event)">
  118. </app-quotation-details>
  119. </form>
  120. </div>
  121. <!-- 报价规则配置弹窗 -->
  122. @if (showPricingRulesModal()) {
  123. <div class="modal-overlay" (click)="hidePricingRules()">
  124. <div class="modal-content pricing-rules-modal" (click)="$event.stopPropagation()">
  125. <div class="modal-header">
  126. <h3>报价规则配置</h3>
  127. <button type="button" class="close-btn" (click)="hidePricingRules()">×</button>
  128. </div>
  129. <div class="modal-body">
  130. <!-- 空间类型配置 -->
  131. <div class="config-section">
  132. <div class="section-header">
  133. <h4>空间类型价格配置</h4>
  134. <button type="button" class="btn-secondary" (click)="addSpaceType()">添加空间类型</button>
  135. </div>
  136. <div class="config-list">
  137. @for (space of spaceTypeConfig(); track $index; let i = $index) {
  138. <div class="config-item">
  139. <div class="config-fields">
  140. <input type="text" [(ngModel)]="space.type" placeholder="空间类型" class="field-input">
  141. <input type="number" [(ngModel)]="space.basePrice" placeholder="基础价格" class="field-input">
  142. <input type="text" [(ngModel)]="space.description" placeholder="描述" class="field-input">
  143. <button type="button" class="btn-danger" (click)="removeSpaceType(i)">删除</button>
  144. </div>
  145. </div>
  146. }
  147. </div>
  148. </div>
  149. <!-- 风格等级配置 -->
  150. <div class="config-section">
  151. <div class="section-header">
  152. <h4>风格等级系数配置</h4>
  153. <button type="button" class="btn-secondary" (click)="addStyleLevel()">添加风格等级</button>
  154. </div>
  155. <div class="config-list">
  156. @for (style of styleLevelConfig(); track $index; let i = $index) {
  157. <div class="config-item">
  158. <div class="config-fields">
  159. <input type="text" [(ngModel)]="style.level" placeholder="等级代码" class="field-input">
  160. <input type="text" [(ngModel)]="style.name" placeholder="等级名称" class="field-input">
  161. <input type="number" [(ngModel)]="style.multiplier" step="0.1" placeholder="系数" class="field-input">
  162. <input type="text" [(ngModel)]="style.description" placeholder="描述" class="field-input">
  163. <button type="button" class="btn-danger" (click)="removeStyleLevel(i)">删除</button>
  164. </div>
  165. </div>
  166. }
  167. </div>
  168. </div>
  169. </div>
  170. <div class="modal-footer">
  171. <button type="button" class="btn-secondary" (click)="hidePricingRules()">取消</button>
  172. <button type="button" class="btn-primary" (click)="savePricingRules()">保存配置</button>
  173. </div>
  174. </div>
  175. </div>
  176. }