|
@@ -80,171 +80,161 @@
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 客户信息卡片 -->
|
|
|
- <section class="info-card customer-card">
|
|
|
- <div class="card-header">
|
|
|
- <div class="header-left">
|
|
|
- <div class="icon-wrapper customer-icon">
|
|
|
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
|
|
- <circle cx="12" cy="7" r="4"></circle>
|
|
|
- </svg>
|
|
|
- </div>
|
|
|
- <div class="header-text">
|
|
|
- <h2>客户信息</h2>
|
|
|
- <p>搜索或新建客户档案</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="header-actions">
|
|
|
- <div class="order-time" *ngIf="orderTime()">
|
|
|
- <span class="time-label">下单时间:</span>
|
|
|
- <span class="time-value">{{ orderTime() }}</span>
|
|
|
- </div>
|
|
|
- <button
|
|
|
- *ngIf="orderCreationMethod() === 'miniprogram'"
|
|
|
- class="btn-primary btn-sm sync-btn"
|
|
|
- (click)="syncMiniprogramCustomerInfo()"
|
|
|
- [disabled]="isSyncing()"
|
|
|
- >
|
|
|
- <mat-spinner *ngIf="isSyncing()" diameter="16" class="sync-spinner"></mat-spinner>
|
|
|
- <svg *ngIf="!isSyncing()" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <polyline points="23 4 23 10 17 10"></polyline>
|
|
|
- <polyline points="1 20 1 14 7 14"></polyline>
|
|
|
- <path d="m3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
|
|
- </svg>
|
|
|
- {{ isSyncing() ? '同步中...' : '同步客户信息' }}
|
|
|
- </button>
|
|
|
- <button *ngIf="selectedCustomer()" class="btn-ghost btn-sm" (click)="clearSelectedCustomer()">
|
|
|
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <line x1="18" y1="6" x2="6" y2="18"></line>
|
|
|
- <line x1="6" y1="6" x2="18" y2="18"></line>
|
|
|
- </svg>
|
|
|
- 清除
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="card-content">
|
|
|
- <!-- 客户搜索区域 -->
|
|
|
- <div *ngIf="!selectedCustomer() && orderCreationMethod() === 'manual'" class="customer-search-section">
|
|
|
- <div class="search-container">
|
|
|
- <div class="search-input-wrapper">
|
|
|
- <svg class="search-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <circle cx="11" cy="11" r="8"></circle>
|
|
|
- <path d="m21 21-4.35-4.35"></path>
|
|
|
- </svg>
|
|
|
+ <!-- 客户信息长条栏 -->
|
|
|
+ <section class="customer-info-bar">
|
|
|
+ <div class="customer-bar-container">
|
|
|
+ <!-- 左侧客户搜索和信息 -->
|
|
|
+ <div class="customer-search-area">
|
|
|
+ @if (!selectedCustomer()) {
|
|
|
+ <div class="search-input-container">
|
|
|
+ <div class="search-icon">
|
|
|
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
|
|
+ <circle cx="12" cy="7" r="4"></circle>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
<input
|
|
|
type="text"
|
|
|
[ngModel]="searchKeyword()"
|
|
|
(ngModelChange)="searchKeyword.set($event); searchCustomer()"
|
|
|
- placeholder="输入客户姓名或手机号快速填写..."
|
|
|
- class="search-input"
|
|
|
+ placeholder="输入客户姓名或手机号快速匹配老客户..."
|
|
|
+ class="customer-search-input"
|
|
|
autocomplete="off"
|
|
|
(keyup.enter)="quickFillCustomerInfo(searchKeyword())"
|
|
|
/>
|
|
|
<button
|
|
|
- class="quick-fill-btn"
|
|
|
+ class="search-action-btn"
|
|
|
(click)="quickFillCustomerInfo(searchKeyword())"
|
|
|
[disabled]="!searchKeyword().trim() || isSyncing()"
|
|
|
>
|
|
|
- <mat-spinner *ngIf="isSyncing()" diameter="16"></mat-spinner>
|
|
|
- <span *ngIf="!isSyncing()">快速填写</span>
|
|
|
+ @if (isSyncing()) {
|
|
|
+ <mat-spinner diameter="16"></mat-spinner>
|
|
|
+ } @else {
|
|
|
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path d="M9 11l3 3 8-8"></path>
|
|
|
+ <path d="M21 12c0 4.97-4.03 9-9 9s-9-4.03-9-9 4.03-9 9-9c1.51 0 2.93.37 4.18 1.03"></path>
|
|
|
+ </svg>
|
|
|
+ 匹配
|
|
|
+ }
|
|
|
</button>
|
|
|
</div>
|
|
|
- <div class="search-hint">
|
|
|
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <circle cx="12" cy="12" r="10"></circle>
|
|
|
- <path d="m9 12 2 2 4-4"></path>
|
|
|
- </svg>
|
|
|
- <span>直接输入姓名/手机号,按回车或点击"快速填写"自动匹配客户信息</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 搜索结果 -->
|
|
|
- <div *ngIf="searchResults().length > 0" class="search-results">
|
|
|
- <div class="results-header">
|
|
|
- <span class="results-count">找到 {{ searchResults().length }} 位客户</span>
|
|
|
- </div>
|
|
|
- <div class="customer-list">
|
|
|
- <div *ngFor="let customer of searchResults()" class="customer-item" (click)="selectCustomer(customer)">
|
|
|
- <div class="customer-avatar">
|
|
|
- <img [src]="customer.avatar" [alt]="customer.name" *ngIf="customer.avatar">
|
|
|
- <div *ngIf="!customer.avatar" class="avatar-placeholder">
|
|
|
- {{ customer.name.charAt(0) }}
|
|
|
- </div>
|
|
|
+
|
|
|
+ <!-- 搜索结果下拉 -->
|
|
|
+ @if (searchResults().length > 0) {
|
|
|
+ <div class="search-dropdown">
|
|
|
+ <div class="dropdown-header">
|
|
|
+ <span>找到 {{ searchResults().length }} 位客户</span>
|
|
|
</div>
|
|
|
- <div class="customer-info">
|
|
|
- <div class="customer-name">{{ customer.name }}</div>
|
|
|
- <div class="customer-phone">{{ customer.phone }}</div>
|
|
|
- <div class="customer-tags" *ngIf="customer.customerType || customer.source">
|
|
|
- <span *ngIf="customer.customerType" class="tag type-tag">{{ customer.customerType }}</span>
|
|
|
- <span *ngIf="customer.source" class="tag source-tag">{{ customer.source }}</span>
|
|
|
+ @for (customer of searchResults(); track customer.id) {
|
|
|
+ <div class="customer-option" (click)="selectCustomer(customer)">
|
|
|
+ <div class="customer-avatar-sm">
|
|
|
+ @if (customer.avatar) {
|
|
|
+ <img [src]="customer.avatar" [alt]="customer.name">
|
|
|
+ } @else {
|
|
|
+ <span>{{ customer.name.charAt(0) }}</span>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ <div class="customer-details">
|
|
|
+ <div class="customer-name">{{ customer.name }}</div>
|
|
|
+ <div class="customer-phone">{{ customer.phone }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="customer-tags">
|
|
|
+ @if (customer.customerType) {
|
|
|
+ <span class="tag">{{ customer.customerType }}</span>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class="select-indicator">
|
|
|
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <polyline points="9 18 15 12 9 6"></polyline>
|
|
|
- </svg>
|
|
|
- </div>
|
|
|
+ }
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <!-- 客户信息表单 -->
|
|
|
- <form [formGroup]="customerForm" class="customer-form">
|
|
|
- <!-- 基本信息组 -->
|
|
|
- <div class="form-section">
|
|
|
- <h3 class="section-title">基本信息</h3>
|
|
|
- <div class="form-grid">
|
|
|
- <div class="form-field">
|
|
|
- <label for="name" class="field-label">客户姓名 <span class="required">*</span></label>
|
|
|
- <input type="text" id="name" formControlName="name" placeholder="请输入客户姓名" class="field-input">
|
|
|
+ }
|
|
|
+ } @else {
|
|
|
+ <!-- 已选择客户信息展示 -->
|
|
|
+ <div class="selected-customer-info">
|
|
|
+ <div class="customer-avatar-lg">
|
|
|
+ @if (selectedCustomer()?.avatar) {
|
|
|
+ <img [src]="selectedCustomer()?.avatar" [alt]="selectedCustomer()?.name">
|
|
|
+ } @else {
|
|
|
+ <span>{{ selectedCustomer()?.name?.charAt(0) }}</span>
|
|
|
+ }
|
|
|
</div>
|
|
|
- <div class="form-field">
|
|
|
- <label for="phone" class="field-label">手机号码 <span class="required">*</span></label>
|
|
|
- <input type="tel" id="phone" formControlName="phone" placeholder="请输入手机号码" class="field-input">
|
|
|
+ <div class="customer-main-info">
|
|
|
+ <div class="customer-name-lg">{{ selectedCustomer()?.name }}</div>
|
|
|
+ <div class="customer-contact">
|
|
|
+ <span class="phone">{{ selectedCustomer()?.phone }}</span>
|
|
|
+ @if (selectedCustomer()?.wechat) {
|
|
|
+ <span class="wechat">微信: {{ selectedCustomer()?.wechat }}</span>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="form-field">
|
|
|
- <label for="wechat" class="field-label">微信账号 <span class="optional">(可选)</span></label>
|
|
|
- <input type="text" id="wechat" formControlName="wechat" placeholder="请输入微信账号" class="field-input">
|
|
|
+ <div class="customer-history">
|
|
|
+ <div class="history-item">
|
|
|
+ <span class="label">合作项目:</span>
|
|
|
+ <span class="value">3个项目</span>
|
|
|
+ </div>
|
|
|
+ <div class="history-item">
|
|
|
+ <span class="label">历史反馈:</span>
|
|
|
+ <span class="value">满意度95%</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 分类信息组 -->
|
|
|
- <div class="form-section">
|
|
|
- <h3 class="section-title">分类信息 <span class="section-subtitle">(可选填写,便于客户管理)</span></h3>
|
|
|
- <div class="form-grid">
|
|
|
- <div class="form-field">
|
|
|
- <label for="customerType" class="field-label">客户类型 <span class="optional">(可选)</span></label>
|
|
|
- <select id="customerType" formControlName="customerType" class="field-select">
|
|
|
- <option value="">请选择客户类型</option>
|
|
|
- <option value="新客户">新客户</option>
|
|
|
- <option value="老客户">老客户</option>
|
|
|
- <option value="VIP客户">VIP客户</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧操作按钮 -->
|
|
|
+ <div class="customer-actions">
|
|
|
+ @if (selectedCustomer()) {
|
|
|
+ <button class="action-btn secondary" (click)="clearSelectedCustomer()">
|
|
|
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path d="M3 6h18"></path>
|
|
|
+ <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
|
|
|
+ <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
|
|
|
+ </svg>
|
|
|
+ 重新选择
|
|
|
+ </button>
|
|
|
+ }
|
|
|
+ @if (orderCreationMethod() === 'miniprogram') {
|
|
|
+ <button
|
|
|
+ class="action-btn primary"
|
|
|
+ (click)="syncMiniprogramCustomerInfo()"
|
|
|
+ [disabled]="isSyncing()"
|
|
|
+ >
|
|
|
+ @if (isSyncing()) {
|
|
|
+ <mat-spinner diameter="16"></mat-spinner>
|
|
|
+ } @else {
|
|
|
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <polyline points="23 4 23 10 17 10"></polyline>
|
|
|
+ <polyline points="1 20 1 14 7 14"></polyline>
|
|
|
+ <path d="m3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
|
|
+ </svg>
|
|
|
+ }
|
|
|
+ {{ isSyncing() ? '同步中...' : '同步小程序' }}
|
|
|
+ </button>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
|
|
|
- <div class="form-field">
|
|
|
- <label for="demandType" class="field-label">需求类型 <span class="optional">(可选)</span></label>
|
|
|
- <select id="demandType" formControlName="demandType" class="field-select">
|
|
|
- <option value="">请选择需求类型</option>
|
|
|
- <option *ngFor="let type of demandTypes" [value]="type.value">{{ type.label }}</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
- <div class="form-field">
|
|
|
- <label for="followUpStatus" class="field-label">跟进状态 <span class="optional">(可选)</span></label>
|
|
|
- <select id="followUpStatus" formControlName="followUpStatus" class="field-select">
|
|
|
- <option value="">请选择跟进状态</option>
|
|
|
- <option *ngFor="let status of followUpStatus" [value]="status.value">{{ status.label }}</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
+ <!-- 新客户快速填写表单 -->
|
|
|
+ @if (!selectedCustomer() && orderCreationMethod() === 'manual') {
|
|
|
+ <section class="new-customer-form">
|
|
|
+ <div class="form-header">
|
|
|
+ <h3>新客户信息</h3>
|
|
|
+ <p>仅需填写基本信息,其他信息可通过企业微信聊天记录补充</p>
|
|
|
+ </div>
|
|
|
+ <form [formGroup]="customerForm" class="simple-customer-form">
|
|
|
+ <div class="form-row">
|
|
|
+ <div class="form-field">
|
|
|
+ <label for="name" class="field-label">客户姓名 <span class="required">*</span></label>
|
|
|
+ <input type="text" id="name" formControlName="name" placeholder="请输入客户姓名" class="field-input">
|
|
|
+ </div>
|
|
|
+ <div class="form-field">
|
|
|
+ <label for="phone" class="field-label">手机号码 <span class="required">*</span></label>
|
|
|
+ <input type="tel" id="phone" formControlName="phone" placeholder="请输入手机号码" class="field-input">
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
</form>
|
|
|
- </div>
|
|
|
- </section>
|
|
|
+ </section>
|
|
|
+ }
|
|
|
|
|
|
<!-- 项目需求卡片(可折叠) -->
|
|
|
<section class="info-card requirement-card" *ngIf="isRequirementCardExpanded()">
|
|
@@ -258,7 +248,7 @@
|
|
|
</div>
|
|
|
<div class="header-text">
|
|
|
<h2>项目需求</h2>
|
|
|
- <p>项目需求、风格、小组匹配等信息</p>
|
|
|
+ <p>项目基本信息配置</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="header-actions">
|
|
@@ -277,176 +267,39 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="card-content">
|
|
|
-
|
|
|
- <form [formGroup]="requirementForm" class="requirement-form">
|
|
|
- <!-- 基础需求组 -->
|
|
|
- <div class="form-section">
|
|
|
- <h3 class="section-title">基础需求</h3>
|
|
|
- <div class="form-grid">
|
|
|
- <div class="form-field">
|
|
|
- <label for="style" class="field-label">装修风格 <span class="required">*</span></label>
|
|
|
- <select id="style" formControlName="style" class="field-select">
|
|
|
- <option value="">请选择装修风格</option>
|
|
|
- <option *ngFor="let style of styleOptions" [value]="style">{{ style }}</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
- <div class="form-field">
|
|
|
- <label for="budget" class="field-label">预算范围 <span class="required">*</span></label>
|
|
|
- <select id="budget" formControlName="budget" class="field-select">
|
|
|
- <option value="">请选择预算范围</option>
|
|
|
- <option value="5-10万">5-10万</option>
|
|
|
- <option value="10-20万">10-20万</option>
|
|
|
- <option value="20-30万">20-30万</option>
|
|
|
- <option value="30-50万">30-50万</option>
|
|
|
- <option value="50万以上">50万以上</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
+ <form [formGroup]="requirementForm" class="requirement-form">
|
|
|
+ <div class="form-grid">
|
|
|
+ <div class="form-field">
|
|
|
+ <label for="style" class="field-label">装修风格 <span class="required">*</span></label>
|
|
|
+ <select id="style" formControlName="style" class="field-select">
|
|
|
+ <option value="">请选择装修风格</option>
|
|
|
+ <option *ngFor="let style of styleOptions" [value]="style">{{ style }}</option>
|
|
|
+ </select>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
-
|
|
|
- <!-- 项目管理组 -->
|
|
|
- <div class="form-section">
|
|
|
- <h3 class="section-title">项目管理</h3>
|
|
|
- <div class="form-grid">
|
|
|
- <div class="form-field">
|
|
|
- <label for="projectGroup" class="field-label">项目小组 <span class="required">*</span></label>
|
|
|
- <select id="projectGroup" formControlName="projectGroup" class="field-select">
|
|
|
- <option value="">请选择项目小组</option>
|
|
|
- <option *ngFor="let group of projectGroupOptions" [value]="group">{{ group }}</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
- <div class="form-field">
|
|
|
- <label for="firstDraftDate" class="field-label">首稿时间 <span class="required">*</span></label>
|
|
|
- <input type="date" id="firstDraftDate" formControlName="firstDraftDate" class="field-input">
|
|
|
- </div>
|
|
|
- <div class="form-field">
|
|
|
- <label for="downPayment" class="field-label">首付款 <span class="required">*</span></label>
|
|
|
- <div class="input-with-unit">
|
|
|
- <input type="number" id="downPayment" formControlName="downPayment" placeholder="请输入首付款金额" class="field-input">
|
|
|
- <span class="input-unit">元</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <div class="form-field">
|
|
|
+ <label for="projectGroup" class="field-label">项目小组 <span class="required">*</span></label>
|
|
|
+ <select id="projectGroup" formControlName="projectGroup" class="field-select">
|
|
|
+ <option value="">请选择项目小组</option>
|
|
|
+ <option *ngFor="let group of projectGroupOptions" [value]="group">{{ group }}</option>
|
|
|
+ </select>
|
|
|
</div>
|
|
|
- <div class="form-field full-width">
|
|
|
- <label for="priceDetails" class="field-label">价格明细</label>
|
|
|
- <textarea id="priceDetails" formControlName="priceDetails" rows="4" placeholder="可通过聊天或复制聊天记录提取价格明细信息" class="field-textarea"></textarea>
|
|
|
+ <div class="form-field">
|
|
|
+ <label for="firstDraftDate" class="field-label">首稿时间 <span class="required">*</span></label>
|
|
|
+ <input type="date" id="firstDraftDate" formControlName="firstDraftDate" class="field-input">
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 其他需求组 -->
|
|
|
- <div class="form-section">
|
|
|
- <h3 class="section-title">其他需求</h3>
|
|
|
- <div class="form-grid">
|
|
|
- <div class="form-field">
|
|
|
- <label for="preferredDesigner" class="field-label">意向设计师</label>
|
|
|
- <input type="text" id="preferredDesigner" formControlName="preferredDesigner" placeholder="请输入意向设计师姓名" class="field-input">
|
|
|
+ <div class="form-field">
|
|
|
+ <label for="downPayment" class="field-label">首付款 <span class="required">*</span></label>
|
|
|
+ <div class="input-with-unit">
|
|
|
+ <input type="number" id="downPayment" formControlName="downPayment" placeholder="请输入首付款金额" class="field-input">
|
|
|
+ <span class="input-unit">元</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="form-field full-width">
|
|
|
- <label for="specialRequirements" class="field-label">特殊需求</label>
|
|
|
- <textarea id="specialRequirements" formControlName="specialRequirements" rows="4" placeholder="请详细描述特殊需求或关注点" class="field-textarea"></textarea>
|
|
|
- </div>
|
|
|
</div>
|
|
|
</form>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
- <!-- 报价与案例匹配卡片 -->
|
|
|
- <section class="info-card price-match-card">
|
|
|
- <div class="card-header">
|
|
|
- <div class="header-left">
|
|
|
- <div class="icon-wrapper price-icon">
|
|
|
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <rect x="2" y="6" width="20" height="12" rx="2"></rect>
|
|
|
- <path d="M12 6v4"></path>
|
|
|
- <path d="M2 10h20"></path>
|
|
|
- </svg>
|
|
|
- </div>
|
|
|
- <div class="header-text">
|
|
|
- <h2>报价与案例匹配</h2>
|
|
|
- <p>智能匹配相似案例和预估报价</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="card-content">
|
|
|
- <!-- 预估报价区域 -->
|
|
|
- <div class="price-section">
|
|
|
- <div class="price-card">
|
|
|
- <div class="price-header">
|
|
|
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <circle cx="12" cy="12" r="10"></circle>
|
|
|
- <path d="M12 6v6l4 2"></path>
|
|
|
- </svg>
|
|
|
- <span>预估报价范围</span>
|
|
|
- </div>
|
|
|
- <div class="price-value">
|
|
|
- {{ estimatedPriceRange() || '请填写需求信息以获取报价' }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 匹配案例区域 -->
|
|
|
- <div class="cases-section" *ngIf="matchedCases().length > 0">
|
|
|
- <div class="section-header">
|
|
|
- <h3>推荐案例</h3>
|
|
|
- <span class="section-subtitle">点击选择参考案例</span>
|
|
|
- </div>
|
|
|
- <div class="cases-grid">
|
|
|
- <div *ngFor="let caseItem of matchedCases()" class="case-card" (click)="selectReferenceCase(caseItem)">
|
|
|
- <div class="case-image-wrapper">
|
|
|
- <img [src]="caseItem.imageUrl" [alt]="caseItem.name" class="case-image">
|
|
|
- <div class="similarity-badge">{{ caseItem.similarity }}%</div>
|
|
|
- </div>
|
|
|
- <div class="case-content">
|
|
|
- <h4 class="case-name">{{ caseItem.name }}</h4>
|
|
|
- <div class="case-meta">
|
|
|
- <span class="case-designer">
|
|
|
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
|
|
- <circle cx="12" cy="7" r="4"></circle>
|
|
|
- </svg>
|
|
|
- {{ caseItem.designer }}
|
|
|
- </span>
|
|
|
- <span class="case-area">
|
|
|
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
|
|
|
- </svg>
|
|
|
- {{ caseItem.area }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 已选案例区域 -->
|
|
|
- <div *ngIf="requirementForm.get('referenceCases')?.value.length > 0" class="selected-cases-section">
|
|
|
- <div class="section-header">
|
|
|
- <h3>已选参考案例</h3>
|
|
|
- <span class="section-subtitle">{{ requirementForm.get('referenceCases')?.value.length }} 个案例</span>
|
|
|
- </div>
|
|
|
- <div class="selected-cases-list">
|
|
|
- <div *ngFor="let caseId of requirementForm.get('referenceCases')?.value" class="selected-case-item">
|
|
|
- <div class="case-info">
|
|
|
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <path d="M9 11l3 3 8-8"></path>
|
|
|
- <path d="M21 12c0 4.97-4.03 9-9 9s-9-4.03-9-9 4.03-9 9-9c1.51 0 2.93.37 4.18 1.03"></path>
|
|
|
- </svg>
|
|
|
- <span>案例 #{{ caseId }}</span>
|
|
|
- </div>
|
|
|
- <button class="remove-case-btn" (click)="removeReferenceCase(caseId)">
|
|
|
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <line x1="18" y1="6" x2="6" y2="18"></line>
|
|
|
- <line x1="6" y1="6" x2="18" y2="18"></line>
|
|
|
- </svg>
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </section>
|
|
|
+
|
|
|
|
|
|
<section class="action-section">
|
|
|
<div class="action-buttons">
|