项目-需求确认.md 21 KB

项目管理 - 需求确认阶段 PRD (Product表版本)

1. 功能概述

1.1 阶段定位

需求确认阶段包含"需求沟通"和"方案确认"两个子环节,是连接订单分配与交付执行的关键桥梁。该阶段通过AI辅助分析工具深入理解客户需求,并将抽象需求转化为可执行的设计方案。

1.2 核心目标

  • 多产品设计需求差异化处理:按产品设计维度独立管理需求,支持跨产品一致性检查
  • 需求沟通环节:深度挖掘客户的色彩、空间、材质、照明等多维度需求
  • 方案确认环节:基于需求分析生成初步设计方案,并获得客户确认
  • 建立需求与设计方案之间的映射关系
  • 为后续建模、软装、渲染阶段提供标准化输入

1.3 涉及角色

  • 客服人员:协助收集客户需求材料、沟通确认需求细节
  • 设计师:主导需求分析、方案设计、与客户沟通确认
  • 组长:审核方案可行性、协调资源、把控质量

1.4 多产品设计需求特性

1.4.1 产品设计需求管理模式

  • 单产品设计项目:统一需求管理,基于Product表的标准需求数据结构
  • 双产品设计项目:支持独立产品设计需求,基础的跨产品一致性检查
  • 多产品设计项目
    • 按产品设计独立管理需求(Product.requirements字段)
    • 跨产品风格一致性要求
    • 产品间功能协调性分析
    • 整体预算和时间约束管理

1.4.2 多产品设计需求管理流程

graph TD
    A[订单分配完成] --> B{是否多产品设计项目?}
    B -->|否| C[单产品设计需求管理流程]
    B -->|是| D[多产品设计需求管理流程]

    D --> E[产品设计需求识别]
    D --> F[全局需求定义]
    D --> G[跨产品关系分析]

    E --> H[各产品设计独立需求采集]
    F --> I[整体风格和预算约束]
    G --> J[产品间依赖和一致性]

    H --> K[需求一致性检查]
    I --> K
    J --> K

    K --> L{一致性检查通过?}
    L -->|是| M[生成多产品设计方案]
    L -->|否| N[需求调整和协调]
    N --> E

    M --> O[客户确认方案]
    O --> P[推进到交付执行]

    style C fill:#e8f5e9
    style D fill:#fff3e0
    style P fill:#e3f2fd

2. 基于Product表的产品设计需求管理系统

2.1 产品设计需求数据结构

2.1.1 Product表的需求字段结构

interface Product {
  // 产品基本信息
  objectId: string;
  project: Pointer<Project>;
  profile: Pointer<Profile>;
  productName: string;           // "李总主卧设计"
  productType: string;           // "bedroom"

  // 空间信息字段 (Product.space)
  space: {
    spaceName: string;            // "主卧"
    area: number;                 // 18.5
    dimensions: {
      length: number;
      width: number;
      height: number;
    };
    features: string[];           // ["朝南", "飘窗", "独立卫浴"]
    constraints: string[];        // ["承重墙不可动"]
    priority: string;             // "high"
    complexity: string;           // "medium"
  };

  // 产品需求字段 (Product.requirements)
  requirements: {
    // 色彩需求
    colorRequirement: {
      primaryHue: number;
      saturation: number;
      temperature: string;        // "暖色调"
      colorDistribution: Array<{
        hex: string;
        percentage: number;
        name: string;
      }>;
    };

    // 材质需求
    materialRequirement: {
      preferred: string[];         // ["实木", "环保材料"]
      avoid: string[];            // ["塑料", "合成材料"]
      budget: {
        min: number;
        max: number;
      };
    };

    // 照明需求
    lightingRequirement: {
      naturalLight: string;        // "充足"
      lightColor: string;          // "暖白"
      specialRequirements: string[]; // ["床头阅读灯", "氛围灯"]
    };

    // 具体需求
    specificRequirements: string[]; // ["需要大储物空间", "独立卫浴"]

    // 参考图片
    referenceImages: string[];

    // 约束条件
    constraints: {
      structural: string[];
      budget: number;
      timeline: number;
    };
  };

  // 产品报价字段 (Product.quotation)
  quotation: {
    price: number;
    currency: string;             // "CNY"
    breakdown: {
      design: number;
      modeling: number;
      rendering: number;
      softDecor: number;
    };
    status: string;               // "pending" | "approved"
    validUntil: Date;
  };

  // 产品状态
  status: 'not_started' | 'in_progress' | 'awaiting_review' | 'completed';
}

2.2 需求管理系统功能

2.2.1 产品需求采集服务

class ProductRequirementService {
  // 创建产品设计需求
  async createProductRequirement(
    projectId: string,
    designerId: string,
    requirementData: ProductRequirementData
  ): Promise<Product> {

    const product = new Parse.Object("Product");
    product.set("project", { __type: "Pointer", className: "Project", objectId: projectId });
    product.set("profile", { __type: "Pointer", className: "Profile", objectId: designerId });
    product.set("productName", requirementData.productName);
    product.set("productType", requirementData.productType);

    // 设置空间信息
    product.set("space", requirementData.space);

    // 设置需求信息
    product.set("requirements", requirementData.requirements);

    // 设置初始报价
    product.set("quotation", this.generateInitialQuotation(requirementData));

    await product.save();
    return product;
  }

  // 需求一致性检查
  async checkRequirementConsistency(
    products: Product[]
  ): Promise<ConsistencyCheckResult> {
    const result: ConsistencyCheckResult = {
      isConsistent: true,
      conflicts: [],
      recommendations: []
    };

    // 检查跨产品风格一致性
    const styleConflicts = this.checkStyleConsistency(products);
    if (styleConflicts.length > 0) {
      result.isConsistent = false;
      result.conflicts.push(...styleConflicts);
    }

    // 检查预算约束
    const budgetConflicts = this.checkBudgetConstraints(products);
    if (budgetConflicts.length > 0) {
      result.isConsistent = false;
      result.conflicts.push(...budgetConflicts);
    }

    // 检查时间约束
    const timelineConflicts = this.checkTimelineConstraints(products);
    if (timelineConflicts.length > 0) {
      result.isConsistent = false;
      result.conflicts.push(...timelineConflicts);
    }

    return result;
  }

  // AI需求分析
  async analyzeRequirement(
    customerDescription: string,
    referenceImages: string[]
  ): Promise<RequirementAnalysisResult> {
    // 调用AI服务分析客户描述
    const aiAnalysis = await this.aiService.analyzeDesignRequirement({
      description: customerDescription,
      images: referenceImages,
      context: "home_design"
    });

    return {
      colorPreference: aiAnalysis.colorPreference,
      materialPreference: aiAnalysis.materialPreference,
      stylePreference: aiAnalysis.stylePreference,
      spaceRequirements: aiAnalysis.spaceRequirements,
      confidence: aiAnalysis.confidence,
      suggestedQuestions: aiAnalysis.suggestedQuestions
    };
  }
}

2.2.2 需求管理界面组件

// React 组件示例
const ProductRequirementPanel = ({ projectId, onRequirementUpdate }) => {
  const [products, setProducts] = useState<Product[]>([]);
  const [selectedProduct, setSelectedProduct] = useState<Product | null>(null);
  const [consistencyResult, setConsistencyResult] = useState<ConsistencyCheckResult | null>(null);

  // 加载项目的产品列表
  useEffect(() => {
    loadProjectProducts();
  }, [projectId]);

  const loadProjectProducts = async () => {
    const query = new Parse.Query("Product");
    query.equalTo("project", { __type: "Pointer", className: "Project", objectId: projectId });
    query.include("profile");
    const results = await query.find();
    setProducts(results);
  };

  // 需求一致性检查
  const checkConsistency = async () => {
    if (products.length > 1) {
      const result = await requirementService.checkRequirementConsistency(products);
      setConsistencyResult(result);
    }
  };

  return (
    <div className="product-requirement-panel">
      {/* 产品列表 */}
      <div className="product-list">
        <h3>空间设计产品</h3>
        {products.map(product => (
          <ProductRequirementCard
            key={product.id}
            product={product}
            onSelect={setSelectedProduct}
            onUpdate={loadProjectProducts}
          />
        ))}
      </div>

      {/* 需求编辑器 */}
      {selectedProduct && (
        <RequirementEditor
          product={selectedProduct}
          onSave={async (updatedRequirements) => {
            selectedProduct.set("requirements", updatedRequirements);
            await selectedProduct.save();
            loadProjectProducts();
            onRequirementUpdate();
          }}
        />
      )}

      {/* 一致性检查结果 */}
      {consistencyResult && (
        <ConsistencyCheckResult result={consistencyResult} />
      )}
    </div>
  );
};

2.3 跨产品一致性管理

2.3.1 一致性检查规则

class ConsistencyRules {
  // 风格一致性检查
  checkStyleConsistency(products: Product[]): Conflict[] {
    const conflicts: Conflict[] = [];
    const styleMap = new Map<string, Product[]>();

    // 收集所有产品的风格信息
    products.forEach(product => {
      const style = this.extractStyleFromRequirements(product.requirements);
      if (!styleMap.has(style)) {
        styleMap.set(style, []);
      }
      styleMap.get(style)!.push(product);
    });

    // 检查风格冲突
    if (styleMap.size > 1) {
      conflicts.push({
        type: "style_conflict",
        description: "发现风格不一致的产品设计",
        affectedProducts: products,
        recommendation: "建议统一整体风格或明确各产品的风格定位"
      });
    }

    return conflicts;
  }

  // 预算约束检查
  checkBudgetConstraints(products: Product[]): Conflict[] {
    const conflicts: Conflict[] = [];
    const totalBudget = products.reduce((sum, product) => {
      return sum + (product.quotation?.price || 0);
    }, 0);

    // 获取项目总预算约束
    const projectBudget = this.getProjectBudget(products[0].project);

    if (totalBudget > projectBudget) {
      conflicts.push({
        type: "budget_exceeded",
        description: `总预算${totalBudget}超过项目预算${projectBudget}`,
        affectedProducts: products,
        recommendation: "建议调整产品报价或增加项目预算"
      });
    }

    return conflicts;
  }

  // 时间约束检查
  checkTimelineConstraints(products: Product[]): Conflict[] {
    const conflicts: Conflict[] = [];
    const totalTimeline = products.reduce((sum, product) => {
      return sum + (product.requirements?.constraints?.timeline || 0);
    }, 0);

    // 检查产品间的时间依赖
    const dependencies = this.analyzeProductDependencies(products);
    dependencies.forEach(dep => {
      if (dep.conflict) {
        conflicts.push({
          type: "timeline_conflict",
          description: `产品${dep.fromProduct.productName}与${dep.toProduct.productName}存在时间冲突`,
          affectedProducts: [dep.fromProduct, dep.toProduct],
          recommendation: "建议调整产品执行顺序或时间安排"
        });
      }
    });

    return conflicts;
  }
}

2.4 需求确认流程

2.4.1 方案生成与确认

class DesignProposalService {
  // 基于需求生成设计方案
  async generateDesignProposal(
    products: Product[],
    customerRequirements: CustomerRequirement
  ): Promise<DesignProposal> {
    const proposal: DesignProposal = {
      id: generateId(),
      projectId: products[0].project.id,
      products: [],
      overallDesign: {},
      timeline: {},
      budget: {},
      status: "draft"
    };

    // 为每个产品生成设计方案
    for (const product of products) {
      const productDesign = await this.generateProductDesign(product, customerRequirements);
      proposal.products.push(productDesign);
    }

    // 生成整体设计方案
    proposal.overallDesign = await this.generateOverallDesign(products, customerRequirements);

    // 生成时间计划
    proposal.timeline = this.generateTimeline(proposal.products);

    // 生成预算方案
    proposal.budget = this.generateBudget(proposal.products);

    return proposal;
  }

  // 客户确认方案
  async confirmProposal(
    proposalId: string,
    customerFeedback: CustomerFeedback
  ): Promise<ProposalConfirmationResult> {
    const proposal = await this.getProposal(proposalId);

    if (customerFeedback.approved) {
      // 方案确认通过,更新产品状态
      await this.updateProductStatus(proposal.products, "in_progress");

      return {
        success: true,
        message: "方案已确认,项目进入执行阶段"
      };
    } else {
      // 方案需要修改
      await this.handleProposalRevision(proposal, customerFeedback);

      return {
        success: false,
        message: "方案需要修改,请根据客户反馈调整设计"
      };
    }
  }
}

3. 需求确认界面设计

3.1 产品需求管理界面

<!-- 产品需求管理主界面 -->
<div class="requirement-confirmation-container">
  <!-- 头部导航 -->
  <div class="requirement-header">
    <h2>需求确认 - {{ project.title }}</h2>
    <div class="progress-indicator">
      <div class="step active">需求沟通</div>
      <div class="step">方案确认</div>
      <div class="step">客户确认</div>
    </div>
  </div>

  <!-- 产品列表 -->
  <div class="product-section">
    <h3>空间设计产品列表</h3>
    <div class="product-grid">
      <div v-for="product in products" :key="product.id"
           class="product-card"
           :class="{ active: selectedProduct?.id === product.id }"
           @click="selectProduct(product)">

        <div class="product-header">
          <h4>{{ product.productName }}</h4>
          <span class="product-type">{{ getProductTypeLabel(product.productType) }}</span>
        </div>

        <div class="product-info">
          <div class="space-info">
            <span class="area">{{ product.space.area }}㎡</span>
            <span class="complexity">{{ product.space.complexity }}</span>
          </div>

          <div class="designer-info">
            <img :src="product.profile.avatar" class="designer-avatar" />
            <span>{{ product.profile.name }}</span>
          </div>
        </div>

        <div class="requirement-summary">
          <div class="requirement-item">
            <label>风格:</label>
            <span>{{ getStyleLabel(product.requirements.colorRequirement.temperature) }}</span>
          </div>
          <div class="requirement-item">
            <label>材质:</label>
            <span>{{ product.requirements.materialRequirement.preferred.join(', ') }}</span>
          </div>
        </div>

        <div class="product-status">
          <span class="status-badge" :class="product.status">
            {{ getStatusLabel(product.status) }}
          </span>
        </div>
      </div>
    </div>
  </div>

  <!-- 需求编辑器 -->
  <div class="requirement-editor" v-if="selectedProduct">
    <h3>产品需求编辑 - {{ selectedProduct.productName }}</h3>

    <div class="requirement-tabs">
      <div class="tab"
           v-for="tab in requirementTabs"
           :key="tab.key"
           :class="{ active: activeTab === tab.key }"
           @click="activeTab = tab.key">
        {{ tab.label }}
      </div>
    </div>

    <!-- 色彩需求 -->
    <div class="tab-content" v-show="activeTab === 'color'">
      <ColorRequirementEditor
        :requirement="selectedProduct.requirements.colorRequirement"
        @update="updateColorRequirement" />
    </div>

    <!-- 材质需求 -->
    <div class="tab-content" v-show="activeTab === 'material'">
      <MaterialRequirementEditor
        :requirement="selectedProduct.requirements.materialRequirement"
        @update="updateMaterialRequirement" />
    </div>

    <!-- 照明需求 -->
    <div class="tab-content" v-show="activeTab === 'lighting'">
      <LightingRequirementEditor
        :requirement="selectedProduct.requirements.lightingRequirement"
        @update="updateLightingRequirement" />
    </div>

    <!-- 具体需求 -->
    <div class="tab-content" v-show="activeTab === 'specific'">
      <SpecificRequirementEditor
        :requirement="selectedProduct.requirements.specificRequirements"
        @update="updateSpecificRequirement" />
    </div>
  </div>

  <!-- 一致性检查 -->
  <div class="consistency-check" v-if="products.length > 1">
    <h3>跨产品一致性检查</h3>
    <button class="check-button" @click="checkConsistency">
      执行一致性检查
    </button>

    <div class="check-results" v-if="consistencyResult">
      <div class="result-item"
           v-for="result in consistencyResult.conflicts"
           :key="result.type"
           :class="result.type">
        <div class="conflict-header">
          <span class="conflict-type">{{ getConflictTypeLabel(result.type) }}</span>
          <span class="conflict-severity">{{ result.severity }}</span>
        </div>
        <div class="conflict-description">{{ result.description }}</div>
        <div class="conflict-recommendation">{{ result.recommendation }}</div>
      </div>
    </div>
  </div>

  <!-- 方案预览 -->
  <div class="proposal-preview">
    <h3>设计方案预览</h3>
    <button class="generate-button" @click="generateProposal">
      生成设计方案
    </button>

    <div class="proposal-content" v-if="designProposal">
      <div class="proposal-overview">
        <h4>整体设计概览</h4>
        <p>{{ designProposal.overallDesign.description }}</p>
      </div>

      <div class="proposal-budget">
        <h4>预算方案</h4>
        <div class="budget-breakdown">
          <div v-for="item in designProposal.budget.breakdown" :key="item.type">
            <span class="budget-type">{{ item.type }}:</span>
            <span class="budget-amount">¥{{ item.amount.toLocaleString() }}</span>
          </div>
          <div class="budget-total">
            <span>总计: ¥{{ designProposal.budget.total.toLocaleString() }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

3.2 需求确认流程界面

<!-- 需求确认流程界面 -->
<div class="requirement-confirmation-flow">
  <!-- 步骤指示器 -->
  <div class="flow-steps">
    <div class="step"
         v-for="(step, index) in confirmationSteps"
         :key="index"
         :class="{
           active: currentStep === index,
           completed: currentStep > index
         }">
      <div class="step-number">{{ index + 1 }}</div>
      <div class="step-label">{{ step.label }}</div>
      <div class="step-description">{{ step.description }}</div>
    </div>
  </div>

  <!-- 步骤内容 -->
  <div class="step-content">
    <!-- 需求沟通步骤 -->
    <div v-if="currentStep === 0" class="communication-step">
      <CommunicationInterface
        :products="products"
        @requirement-collected="handleRequirementCollected"
        @communication-completed="handleCommunicationCompleted" />
    </div>

    <!-- 方案确认步骤 -->
    <div v-if="currentStep === 1" class="proposal-step">
      <ProposalInterface
        :products="products"
        :requirements="collectedRequirements"
        @proposal-generated="handleProposalGenerated"
        @proposal-confirmed="handleProposalConfirmed" />
    </div>

    <!-- 客户确认步骤 -->
    <div v-if="currentStep === 2" class="confirmation-step">
      <CustomerConfirmationInterface
        :proposal="generatedProposal"
        @customer-approved="handleCustomerApproved"
        @customer-rejected="handleCustomerRejected" />
    </div>
  </div>

  <!-- 操作按钮 -->
  <div class="flow-actions">
    <button v-if="currentStep > 0"
            class="prev-button"
            @click="previousStep">
      上一步
    </button>

    <button v-if="currentStep < confirmationSteps.length - 1"
            class="next-button"
            :disabled="!canProceedToNext"
            @click="nextStep">
      下一步
    </button>

    <button v-if="currentStep === confirmationSteps.length - 1"
            class="complete-button"
            :disabled="!canCompleteFlow"
            @click="completeConfirmation">
      完成需求确认
    </button>
  </div>
</div>

4. 技术实现要点

4.1 数据操作优化

  • 批量操作:支持批量更新多个Product的需求字段
  • 事务处理:确保跨产品需求更新的事务一致性
  • 缓存机制:缓存需求分析结果,提高响应速度

4.2 性能优化

  • 懒加载:按需加载产品需求数据
  • 增量更新:只同步变更的需求字段
  • 索引优化:为Product表的requirements字段建立适当的索引

4.3 用户体验优化

  • 实时同步:需求变更实时同步到相关界面
  • 智能提示:基于历史数据提供需求填写建议
  • 可视化展示:直观展示需求一致性检查结果

文档版本: v3.0 (Product表统一空间管理) 最后更新: 2025-10-20 维护者: YSS Development Team