stage-order-integration-guide.md 9.7 KB

订单分配组件集成快速指南

🚀 5分钟快速集成

步骤1:更新主组件导入(stage-order.component.ts)

在文件顶部添加导入:

// 在现有导入后添加
import { ApprovalStatusBannerComponent } from './components/approval-status-banner/approval-status-banner.component';
import { LeaderApprovalBarComponent } from './components/leader-approval-bar/leader-approval-bar.component';
import { ProjectBasicInfoComponent } from './components/project-basic-info/project-basic-info.component';
import { OrderActionButtonsComponent } from './components/order-action-buttons/order-action-buttons.component';

@Component 装饰器的 imports 数组中添加:

@Component({
  selector: 'app-stage-order',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    QuotationEditorComponent,
    TeamAssignComponent,
    CustomDatePickerComponent,
    // ⭐ 新增子组件
    ApprovalStatusBannerComponent,
    LeaderApprovalBarComponent,
    ProjectBasicInfoComponent,
    OrderActionButtonsComponent
  ],
  ...
})

步骤2:更新主组件HTML(stage-order.component.html)

替换审批状态部分(第14-44行)

从:

@if (project) {
  @if (getApprovalStatus() === 'pending') {
    <div class="approval-status-banner pending">...</div>
  }
  @if (getApprovalStatus() === 'approved') {
    <div class="approval-status-banner approved">...</div>
  }
  @if (getApprovalStatus() === 'rejected') {
    <div class="approval-status-banner rejected">...</div>
  }
}

改为:

@if (project) {
  <app-approval-status-banner
    [status]="getApprovalStatus()"
    [rejectionReason]="getRejectionReason()"
    (resubmit)="prepareResubmit()">
  </app-approval-status-banner>
}

替换组长审批操作条(第46-60行)

从:

@if (getApprovalStatus() === 'pending' && isTeamLeader && !isFromCustomerService) {
  <div class="leader-approval-bar">
    <div class="approval-buttons-container">
      <button class="btn-approve" (click)="approveOrder()" [disabled]="saving">...</button>
      <button class="btn-reject" (click)="rejectOrder()" [disabled]="saving">...</button>
    </div>
  </div>
}

改为:

@if (getApprovalStatus() === 'pending' && isTeamLeader && !isFromCustomerService) {
  <app-leader-approval-bar
    [saving]="saving"
    (approve)="approveOrder()"
    (reject)="rejectOrder()">
  </app-leader-approval-bar>
}

替换项目基本信息(第62-167行)

从:

<div class="card project-info-card">
  <div class="card-header collapsible" (click)="toggleProjectInfo()">
    <h3 class="card-title">...</h3>
    ...
  </div>
  @if (projectInfoExpanded) {
    <div class="card-content">
      <div class="form-list">
        <!-- 所有表单字段 -->
      </div>
    </div>
  }
</div>

改为:

<app-project-basic-info
  [projectInfo]="projectInfo"
  [expanded]="projectInfoExpanded"
  [canEdit]="canEdit"
  (expandedChange)="projectInfoExpanded = $event"
  (projectInfoChange)="projectInfo = $event"
  (projectTypeChange)="onProjectTypeChange()">
</app-project-basic-info>

替换操作按钮(第203-226行)

从:

@if (canEdit) {
  <div class="action-buttons">
    <button class="btn btn-outline" (click)="saveDraft()" [disabled]="...">...</button>
    <button class="btn btn-primary" (click)="submitForOrder()" [disabled]="...">...</button>
  </div>
}

改为:

<app-order-action-buttons
  [canEdit]="canEdit"
  [saving]="saving"
  [submittedPending]="submittedPending"
  [approvalStatus]="getApprovalStatus()"
  (saveDraft)="saveDraft()"
  (submit)="submitForOrder()">
</app-order-action-buttons>

步骤3:清理主组件样式(stage-order.component.scss)

可以删除以下样式块(它们已移到子组件中):

// 删除这些样式块(2762行之前)
.approval-status-banner { ... }
.leader-approval-bar { ... }
.project-info-card { ... }
.action-buttons { ... }

// 以及移动端优化中对应的样式
@media (max-width: 480px) {
  .approval-status-banner { ... }
  .leader-approval-bar { ... }
  .action-buttons { ... }
}

保留的样式:

  • .stage-order-container - 容器布局
  • .card - 通用卡片样式
  • .quotation-card - 报价卡片样式(如果有)
  • 其他布局相关样式

📝 完整的更新后HTML结构

<!-- 加载中 -->
@if (loading) {
  <div class="loading-container">
    <div class="spinner"><div class="spinner-circle"></div></div>
    <p>加载订单信息...</p>
  </div>
}

<!-- 订单分配内容 -->
@if (!loading) {
  <div class="stage-order-container">
    <!-- 1. 审批状态提示 -->
    @if (project) {
      <app-approval-status-banner
        [status]="getApprovalStatus()"
        [rejectionReason]="getRejectionReason()"
        (resubmit)="prepareResubmit()">
      </app-approval-status-banner>
    }
    
    <!-- 2. 组长审批操作条 -->
    @if (getApprovalStatus() === 'pending' && isTeamLeader && !isFromCustomerService) {
      <app-leader-approval-bar
        [saving]="saving"
        (approve)="approveOrder()"
        (reject)="rejectOrder()">
      </app-leader-approval-bar>
    }
    
    <!-- 3. 项目基本信息 -->
    <app-project-basic-info
      [projectInfo]="projectInfo"
      [expanded]="projectInfoExpanded"
      [canEdit]="canEdit"
      (expandedChange)="projectInfoExpanded = $event"
      (projectInfoChange)="projectInfo = $event"
      (projectTypeChange)="onProjectTypeChange()">
    </app-project-basic-info>

    <!-- 4. 产品报价管理 -->
    <div class="card quotation-card">
      <div class="card-header">
        <h3 class="card-title">
          <svg class="icon" ...></svg>
          产品报价管理
        </h3>
        <p class="card-subtitle">基于Product表的智能报价生成和管理系统</p>
      </div>
      <div class="card-content">
        <app-quotation-editor
          [projectId]="projectId"
          [project]="project"
          [canEdit]="canEdit"
          [currentUser]="currentUser"
          (quotationChange)="onQuotationChange($event)"
          (totalChange)="onTotalChange($event)"
          (loadingChange)="onQuotationLoadingChange($event)"
          (productsChange)="onProductsChange($event)"
          (productsUpdated)="onProductsUpdated($event)">
        </app-quotation-editor>
      </div>
    </div>

    <!-- 5. 设计师分配 -->
    <app-team-assign
      [project]="project"
      [canEdit]="canEdit"
      [currentUser]="currentUser">
    </app-team-assign>

    <!-- 6. 操作按钮 -->
    <app-order-action-buttons
      [canEdit]="canEdit"
      [saving]="saving"
      [submittedPending]="submittedPending"
      [approvalStatus]="getApprovalStatus()"
      (saveDraft)="saveDraft()"
      (submit)="submitForOrder()">
    </app-order-action-buttons>
  </div>
}

✅ 测试清单

集成完成后,请测试以下功能:

桌面端测试

  • 审批状态横幅显示正常(待审批/已通过/已驳回)
  • 组长审批按钮显示和点击正常
  • 项目信息表单展开/折叠正常
  • 项目信息输入和保存正常
  • 日期选择器工作正常
  • 保存草稿按钮功能正常
  • 确认订单按钮功能正常

移动端测试(≤480px)

  • 审批状态横幅纵向布局居中
  • 组长审批按钮纵向排列占满宽度
  • 项目信息表单输入框高度≥44px
  • 操作按钮触摸区域足够大
  • 所有交互流畅无卡顿

功能测试

  • 提交订单后状态变为待审批
  • 组长通过审批后状态变为已通过
  • 组长驳回订单后可重新提交
  • 数据持久化正常

🐛 常见问题

Q1: 组件未显示

原因:未在 imports 数组中添加组件 解决:检查 @Component 装饰器的 imports 数组

Q2: 样式不生效

原因:子组件样式文件未创建或路径错误 解决:确保所有 .scss 文件已创建且路径正确

Q3: 事件不触发

原因:事件名称不匹配或未绑定处理方法 解决:检查 (eventName) 和对应的处理方法

Q4: 数据不更新

原因:未正确使用双向绑定或事件处理 解决:使用 (eventChange)="property = $event" 模式


🎨 样式定制

如需自定义子组件样式,可以:

方法1:使用CSS变量

在主组件样式中定义:

.stage-order-container {
  --primary-color: #667eea;
  --success-color: #4caf50;
  --danger-color: #f44336;
}

在子组件中使用:

.btn-approve {
  background: var(--primary-color);
}

方法2:通过@Input传递样式类

为子组件添加 @Input() customClass: string,允许父组件传递样式类名。

方法3:使用::ng-deep(不推荐)

:host ::ng-deep app-approval-status-banner {
  .status-icon { font-size: 36px; }
}

📊 性能优化提示

所有子组件已使用 ChangeDetectionStrategy.OnPush,为了最佳性能:

  1. 使用Immutable更新

    // ✅ 好的做法
    this.projectInfo = { ...this.projectInfo, title: 'new title' };
    
    // ❌ 避免
    this.projectInfo.title = 'new title';
    
  2. 避免频繁变更检测

    // 只在必要时调用
    this.cdr.markForCheck();
    
  3. 使用trackBy

    @for (item of items; track item.id) { ... }
    

🔄 回滚方案

如果集成出现问题,可以快速回滚:

  1. 从版本控制恢复原文件
  2. 或注释掉子组件,恢复原HTML结构
  3. 保留子组件文件,待修复后再集成

📞 需要帮助?

如遇到问题,请提供:

  1. 错误信息或截图
  2. 浏览器控制台日志
  3. 具体的操作步骤
  4. 预期行为 vs 实际行为

最后更新:2024-12-09

状态:✅ 集成指南完成,可开始集成