|
|
@@ -0,0 +1,544 @@
|
|
|
+# 订单分配阶段组件拆分方案
|
|
|
+
|
|
|
+## 📦 概述
|
|
|
+
|
|
|
+将订单分配阶段(`StageOrderComponent`)拆分为多个可复用的子组件,提高代码的可维护性、可测试性和可复用性。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🎯 拆分目标
|
|
|
+
|
|
|
+1. **模块化**:每个组件负责单一职责
|
|
|
+2. **可复用**:组件可在其他地方复用
|
|
|
+3. **易维护**:代码结构清晰,易于理解和修改
|
|
|
+4. **易测试**:每个组件可独立测试
|
|
|
+5. **性能优化**:支持OnPush变更检测策略
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📂 组件结构
|
|
|
+
|
|
|
+```
|
|
|
+stage-order/
|
|
|
+├── components/ # 子组件目录
|
|
|
+│ ├── approval-status-banner/ # 审批状态横幅
|
|
|
+│ │ ├── approval-status-banner.component.ts
|
|
|
+│ │ ├── approval-status-banner.component.html
|
|
|
+│ │ └── approval-status-banner.component.scss
|
|
|
+│ ├── leader-approval-bar/ # 组长审批操作条
|
|
|
+│ │ ├── leader-approval-bar.component.ts
|
|
|
+│ │ ├── leader-approval-bar.component.html
|
|
|
+│ │ └── leader-approval-bar.component.scss
|
|
|
+│ ├── project-basic-info/ # 项目基本信息
|
|
|
+│ │ ├── project-basic-info.component.ts
|
|
|
+│ │ ├── project-basic-info.component.html
|
|
|
+│ │ └── project-basic-info.component.scss
|
|
|
+│ └── order-action-buttons/ # 操作按钮
|
|
|
+│ ├── order-action-buttons.component.ts
|
|
|
+│ ├── order-action-buttons.component.html
|
|
|
+│ └── order-action-buttons.component.scss
|
|
|
+├── stage-order.component.ts # 主组件
|
|
|
+├── stage-order.component.html # 主组件模板
|
|
|
+└── stage-order.component.scss # 主组件样式
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🧩 子组件详解
|
|
|
+
|
|
|
+### 1. ApprovalStatusBannerComponent(审批状态横幅)
|
|
|
+
|
|
|
+**职责**:显示订单审批状态(待审批、已通过、已驳回)
|
|
|
+
|
|
|
+**输入属性**:
|
|
|
+- `status`: ApprovalStatus | null - 审批状态
|
|
|
+- `rejectionReason`: string - 驳回原因
|
|
|
+
|
|
|
+**输出事件**:
|
|
|
+- `resubmit`: void - 重新提交事件
|
|
|
+
|
|
|
+**使用示例**:
|
|
|
+```html
|
|
|
+<app-approval-status-banner
|
|
|
+ [status]="getApprovalStatus()"
|
|
|
+ [rejectionReason]="getRejectionReason()"
|
|
|
+ (resubmit)="prepareResubmit()">
|
|
|
+</app-approval-status-banner>
|
|
|
+```
|
|
|
+
|
|
|
+**特性**:
|
|
|
+- 3种状态样式(pending/approved/rejected)
|
|
|
+- 支持重新提交操作
|
|
|
+- 响应式设计,移动端优化
|
|
|
+- 下滑动画效果
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2. LeaderApprovalBarComponent(组长审批操作条)
|
|
|
+
|
|
|
+**职责**:提供组长审批订单的操作按钮
|
|
|
+
|
|
|
+**输入属性**:
|
|
|
+- `saving`: boolean - 是否正在保存
|
|
|
+
|
|
|
+**输出事件**:
|
|
|
+- `approve`: void - 通过审批事件
|
|
|
+- `reject`: void - 驳回订单事件
|
|
|
+
|
|
|
+**使用示例**:
|
|
|
+```html
|
|
|
+<app-leader-approval-bar
|
|
|
+ [saving]="saving"
|
|
|
+ (approve)="approveOrder()"
|
|
|
+ (reject)="rejectOrder()">
|
|
|
+</app-leader-approval-bar>
|
|
|
+```
|
|
|
+
|
|
|
+**特性**:
|
|
|
+- 渐变背景按钮
|
|
|
+- 波纹点击效果
|
|
|
+- 禁用状态处理
|
|
|
+- 移动端纵向排列
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 3. ProjectBasicInfoComponent(项目基本信息)
|
|
|
+
|
|
|
+**职责**:可折叠的项目基本信息表单
|
|
|
+
|
|
|
+**输入属性**:
|
|
|
+- `projectInfo`: ProjectInfo - 项目信息对象
|
|
|
+- `expanded`: boolean - 是否展开
|
|
|
+- `canEdit`: boolean - 是否可编辑
|
|
|
+
|
|
|
+**输出事件**:
|
|
|
+- `expandedChange`: boolean - 展开状态变化
|
|
|
+- `projectInfoChange`: ProjectInfo - 项目信息变化
|
|
|
+- `projectTypeChange`: string - 项目类型变化
|
|
|
+
|
|
|
+**接口定义**:
|
|
|
+```typescript
|
|
|
+export interface ProjectInfo {
|
|
|
+ title: string;
|
|
|
+ projectType: string;
|
|
|
+ renderType: string;
|
|
|
+ demoday: Date | null;
|
|
|
+ deadline: Date | null;
|
|
|
+ description: string;
|
|
|
+ priceLevel: string;
|
|
|
+ spaceType: string;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**使用示例**:
|
|
|
+```html
|
|
|
+<app-project-basic-info
|
|
|
+ [projectInfo]="projectInfo"
|
|
|
+ [expanded]="projectInfoExpanded"
|
|
|
+ [canEdit]="canEdit"
|
|
|
+ (expandedChange)="projectInfoExpanded = $event"
|
|
|
+ (projectInfoChange)="onProjectInfoChange($event)"
|
|
|
+ (projectTypeChange)="onProjectTypeChange($event)">
|
|
|
+</app-project-basic-info>
|
|
|
+```
|
|
|
+
|
|
|
+**特性**:
|
|
|
+- 可折叠交互
|
|
|
+- 双向数据绑定
|
|
|
+- 日期选择器集成
|
|
|
+- 条件渲染(渲染类型仅家装显示)
|
|
|
+- 完整的表单验证支持
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 4. OrderActionButtonsComponent(操作按钮)
|
|
|
+
|
|
|
+**职责**:提供保存草稿和确认订单操作
|
|
|
+
|
|
|
+**输入属性**:
|
|
|
+- `canEdit`: boolean - 是否可编辑
|
|
|
+- `saving`: boolean - 是否正在保存
|
|
|
+- `submittedPending`: boolean - 是否已提交待审批
|
|
|
+- `approvalStatus`: string | null - 审批状态
|
|
|
+
|
|
|
+**输出事件**:
|
|
|
+- `saveDraft`: void - 保存草稿事件
|
|
|
+- `submit`: void - 提交订单事件
|
|
|
+
|
|
|
+**使用示例**:
|
|
|
+```html
|
|
|
+<app-order-action-buttons
|
|
|
+ [canEdit]="canEdit"
|
|
|
+ [saving]="saving"
|
|
|
+ [submittedPending]="submittedPending"
|
|
|
+ [approvalStatus]="getApprovalStatus()"
|
|
|
+ (saveDraft)="saveDraft()"
|
|
|
+ (submit)="submitForOrder()">
|
|
|
+</app-order-action-buttons>
|
|
|
+```
|
|
|
+
|
|
|
+**特性**:
|
|
|
+- 自动禁用逻辑
|
|
|
+- 渐变样式按钮
|
|
|
+- 移动端优化布局
|
|
|
+- 图标+文字组合
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🔄 主组件更新
|
|
|
+
|
|
|
+### 修改后的HTML结构
|
|
|
+
|
|
|
+```html
|
|
|
+<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)="onProjectInfoChange($event)"
|
|
|
+ (projectTypeChange)="onProjectTypeChange($event)">
|
|
|
+ </app-project-basic-info>
|
|
|
+
|
|
|
+ <!-- 4. 产品报价管理(已有组件) -->
|
|
|
+ <div class="card quotation-card">
|
|
|
+ <app-quotation-editor ...>
|
|
|
+ </app-quotation-editor>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 5. 设计师分配(已有组件) -->
|
|
|
+ <app-team-assign ...>
|
|
|
+ </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>
|
|
|
+```
|
|
|
+
|
|
|
+### TypeScript导入更新
|
|
|
+
|
|
|
+```typescript
|
|
|
+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({
|
|
|
+ selector: 'app-stage-order',
|
|
|
+ standalone: true,
|
|
|
+ imports: [
|
|
|
+ CommonModule,
|
|
|
+ FormsModule,
|
|
|
+ QuotationEditorComponent,
|
|
|
+ TeamAssignComponent,
|
|
|
+ CustomDatePickerComponent,
|
|
|
+ ApprovalStatusBannerComponent, // 新增
|
|
|
+ LeaderApprovalBarComponent, // 新增
|
|
|
+ ProjectBasicInfoComponent, // 新增
|
|
|
+ OrderActionButtonsComponent // 新增
|
|
|
+ ],
|
|
|
+ ...
|
|
|
+})
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📈 优势对比
|
|
|
+
|
|
|
+### Before(拆分前)
|
|
|
+
|
|
|
+**单一大组件**:
|
|
|
+- ❌ HTML文件230行,难以阅读
|
|
|
+- ❌ 所有逻辑集中在一个组件
|
|
|
+- ❌ 难以复用
|
|
|
+- ❌ 难以测试
|
|
|
+- ❌ 修改影响面广
|
|
|
+
|
|
|
+### After(拆分后)
|
|
|
+
|
|
|
+**模块化小组件**:
|
|
|
+- ✅ 每个组件职责单一明确
|
|
|
+- ✅ HTML结构清晰,易于理解
|
|
|
+- ✅ 组件可独立复用
|
|
|
+- ✅ 易于单元测试
|
|
|
+- ✅ 修改影响范围小
|
|
|
+- ✅ 支持OnPush策略,性能更好
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🎨 样式管理
|
|
|
+
|
|
|
+### 样式隔离策略
|
|
|
+
|
|
|
+每个子组件都有独立的样式文件,避免样式冲突:
|
|
|
+
|
|
|
+```
|
|
|
+approval-status-banner.component.scss # 横幅样式
|
|
|
+leader-approval-bar.component.scss # 审批栏样式
|
|
|
+project-basic-info.component.scss # 表单样式
|
|
|
+order-action-buttons.component.scss # 按钮样式
|
|
|
+stage-order.component.scss # 主组件布局样式
|
|
|
+```
|
|
|
+
|
|
|
+### 共享样式
|
|
|
+
|
|
|
+公共样式可以提取到:
|
|
|
+- 全局样式文件(styles.scss)
|
|
|
+- 共享SCSS变量文件
|
|
|
+- 主题配置文件
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🧪 测试建议
|
|
|
+
|
|
|
+### 单元测试
|
|
|
+
|
|
|
+每个子组件都可以独立测试:
|
|
|
+
|
|
|
+```typescript
|
|
|
+// approval-status-banner.component.spec.ts
|
|
|
+describe('ApprovalStatusBannerComponent', () => {
|
|
|
+ it('should display pending status', () => {
|
|
|
+ component.status = 'pending';
|
|
|
+ fixture.detectChanges();
|
|
|
+ expect(compiled.querySelector('.status-icon').textContent).toBe('⏳');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should emit resubmit event', () => {
|
|
|
+ spyOn(component.resubmit, 'emit');
|
|
|
+ component.onResubmit();
|
|
|
+ expect(component.resubmit.emit).toHaveBeenCalled();
|
|
|
+ });
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 集成测试
|
|
|
+
|
|
|
+测试主组件与子组件的交互:
|
|
|
+
|
|
|
+```typescript
|
|
|
+// stage-order.component.spec.ts
|
|
|
+describe('StageOrderComponent', () => {
|
|
|
+ it('should pass approval status to banner component', () => {
|
|
|
+ const banner = fixture.debugElement.query(By.directive(ApprovalStatusBannerComponent));
|
|
|
+ expect(banner.componentInstance.status).toBe('pending');
|
|
|
+ });
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📱 响应式设计
|
|
|
+
|
|
|
+所有子组件都实现了移动端优化:
|
|
|
+
|
|
|
+### 断点策略
|
|
|
+
|
|
|
+```scss
|
|
|
+// 移动端优化 (≤480px)
|
|
|
+@media (max-width: 480px) {
|
|
|
+ // 横幅纵向布局,居中显示
|
|
|
+ .approval-status-banner {
|
|
|
+ flex-direction: column;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 审批按钮纵向排列,占满宽度
|
|
|
+ .leader-approval-bar {
|
|
|
+ .approval-buttons-container {
|
|
|
+ flex-direction: column;
|
|
|
+ button { width: 100%; }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 表单输入框增大触摸区域
|
|
|
+ .form-input {
|
|
|
+ min-height: 44px;
|
|
|
+ padding: 12px;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🚀 迁移步骤
|
|
|
+
|
|
|
+### 1. 创建子组件
|
|
|
+
|
|
|
+✅ 已创建所有子组件文件
|
|
|
+
|
|
|
+### 2. 更新主组件
|
|
|
+
|
|
|
+```typescript
|
|
|
+// stage-order.component.ts
|
|
|
+
|
|
|
+// 1. 导入子组件
|
|
|
+import { ApprovalStatusBannerComponent } from './components/approval-status-banner/approval-status-banner.component';
|
|
|
+// ... 其他导入
|
|
|
+
|
|
|
+// 2. 添加到imports数组
|
|
|
+@Component({
|
|
|
+ imports: [
|
|
|
+ // ... 现有导入
|
|
|
+ ApprovalStatusBannerComponent,
|
|
|
+ LeaderApprovalBarComponent,
|
|
|
+ ProjectBasicInfoComponent,
|
|
|
+ OrderActionButtonsComponent
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+// 3. 添加事件处理方法(如果需要)
|
|
|
+onProjectInfoChange(info: ProjectInfo): void {
|
|
|
+ this.projectInfo = info;
|
|
|
+ // 触发变更检测或其他操作
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 更新主组件HTML
|
|
|
+
|
|
|
+将原有的HTML块替换为子组件标签
|
|
|
+
|
|
|
+### 4. 清理主组件样式
|
|
|
+
|
|
|
+将已移到子组件的样式从主组件SCSS中删除
|
|
|
+
|
|
|
+### 5. 测试验证
|
|
|
+
|
|
|
+- [ ] 审批状态显示正常
|
|
|
+- [ ] 审批按钮点击正常
|
|
|
+- [ ] 项目信息表单交互正常
|
|
|
+- [ ] 操作按钮功能正常
|
|
|
+- [ ] 移动端布局正常
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🔧 维护建议
|
|
|
+
|
|
|
+### 1. 组件职责
|
|
|
+
|
|
|
+- 每个组件只负责自己的UI和交互
|
|
|
+- 业务逻辑保留在主组件
|
|
|
+- 子组件通过事件与主组件通信
|
|
|
+
|
|
|
+### 2. 数据流
|
|
|
+
|
|
|
+```
|
|
|
+主组件 (StageOrderComponent)
|
|
|
+ ↓ @Input
|
|
|
+子组件 (ApprovalStatusBannerComponent)
|
|
|
+ ↓ @Output
|
|
|
+主组件 (StageOrderComponent)
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 性能优化
|
|
|
+
|
|
|
+- 所有子组件使用OnPush策略
|
|
|
+- 使用Immutable数据更新
|
|
|
+- 避免在模板中使用复杂计算
|
|
|
+
|
|
|
+### 4. 代码复用
|
|
|
+
|
|
|
+这些组件可以在其他地方复用:
|
|
|
+- 审批状态横幅 → 其他需要审批的页面
|
|
|
+- 操作按钮 → 其他表单页面
|
|
|
+- 项目信息表单 → 项目编辑页面
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📊 代码量对比
|
|
|
+
|
|
|
+### Before(拆分前)
|
|
|
+
|
|
|
+| 文件 | 行数 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| stage-order.component.html | 230行 | 所有HTML在一个文件 |
|
|
|
+| stage-order.component.scss | 3024行 | 所有样式在一个文件 |
|
|
|
+| stage-order.component.ts | 2170行 | 所有逻辑在一个文件 |
|
|
|
+| **总计** | **5424行** | |
|
|
|
+
|
|
|
+### After(拆分后)
|
|
|
+
|
|
|
+| 文件 | 行数 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| **主组件** |
|
|
|
+| stage-order.component.html | ~80行 | 组件编排 |
|
|
|
+| stage-order.component.scss | ~500行 | 布局样式 |
|
|
|
+| stage-order.component.ts | ~1500行 | 主要逻辑 |
|
|
|
+| **子组件** |
|
|
|
+| approval-status-banner | ~200行 | 3个文件 |
|
|
|
+| leader-approval-bar | ~150行 | 3个文件 |
|
|
|
+| project-basic-info | ~400行 | 3个文件 |
|
|
|
+| order-action-buttons | ~150行 | 3个文件 |
|
|
|
+| **总计** | **~3000行** | 13个文件 |
|
|
|
+
|
|
|
+**优势**:
|
|
|
+- ✅ 代码行数减少44%
|
|
|
+- ✅ 文件组织更清晰
|
|
|
+- ✅ 易于定位和修改
|
|
|
+- ✅ 支持并行开发
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## ✅ 完成清单
|
|
|
+
|
|
|
+- [x] 创建ApprovalStatusBannerComponent
|
|
|
+- [x] 创建LeaderApprovalBarComponent
|
|
|
+- [x] 创建ProjectBasicInfoComponent
|
|
|
+- [x] 创建OrderActionButtonsComponent
|
|
|
+- [ ] 更新主组件导入
|
|
|
+- [ ] 更新主组件HTML
|
|
|
+- [ ] 更新主组件样式
|
|
|
+- [ ] 添加单元测试
|
|
|
+- [ ] 测试移动端布局
|
|
|
+- [ ] 文档更新
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 🎯 下一步
|
|
|
+
|
|
|
+1. **更新主组件**:导入并使用新创建的子组件
|
|
|
+2. **清理代码**:删除已移到子组件的代码
|
|
|
+3. **测试验证**:确保功能正常
|
|
|
+4. **性能测试**:验证OnPush策略效果
|
|
|
+5. **代码审查**:团队review代码质量
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 📚 参考资料
|
|
|
+
|
|
|
+- [Angular组件交互](https://angular.io/guide/component-interaction)
|
|
|
+- [变更检测策略](https://angular.io/api/core/ChangeDetectionStrategy)
|
|
|
+- [响应式设计最佳实践](https://web.dev/responsive-web-design-basics/)
|
|
|
+- [组件样式隔离](https://angular.io/guide/component-styles)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**创建时间**:2024-12-09
|
|
|
+
|
|
|
+**状态**:✅ 子组件创建完成,待集成到主组件
|