# CRM销售自动化（渠道版）执行级详细设计说明书 V3

# 1. 文档说明

## 1.1 文档目标

本文档用于指导HZHub项目中CRM销售自动化（渠道版）系统的：

- 数据库设计（适配 MySQL 8 + MyBatis-Plus）
- 后端接口开发（适配 hzhub-system 服务）
- 前端页面开发（适配 **hzhub-portal-employee 员工门户**）
- AI能力集成（适配 LangChain4j + Weaviate）
- 企业微信集成
- 自动化流程配置（适配 warm-flow）
- 权限与组织体系建设（适配 Sa-Token）

本文档属于"开发执行版设计文档 V3"，针对**员工门户（hzhub-portal-employee）**进行定制化适配。

---

## 1.2 与 V1/V2 版本的主要差异

| 方面 | V1 版本 | V2 版本 | V3 版本（员工门户适配） |
|---|---|---|---|
| 前端项目 | Vue3 + Element Plus（通用） | Vben Admin（管理后台） | **Element Plus（员工门户）** |
| 前端路径 | `/api/**` | `/crm/**`（管理后台） | **`/crm/**`（员工门户）** |
| 现有基础 | 无 | 无 | **已有CRM和经销商页面** |
| 数据来源 | 独立CRM表 | 独立CRM表 | **ERP客户数据 + CRM表** |
| 技术栈 | Python FastAPI | LangChain4j | **LangChain4j + Vue3 Composition API** |
| UI风格 | 未指定 | Vben Admin 企业级 | **Element Plus 卡片式** |
| 用户角色 | 通用销售人员 | 管理员 + 销售 | **企业员工 + 销售人员** |

---

## 1.3 员工门户现有功能

### 已实现页面

| 页面 | 路径 | 功能 | 数据来源 |
|---|---|---|---|
| 销售CRM | `/crm` | 商机管道视图 + 客户列表 | ERP Customer（动态API） |
| 经销商管理 | `/dealer` | 经销商卡片视图 + 筛选 | ERP Customer（动态API） |

### 现有API

```typescript
// ERP 客户数据（动态API）
GET /erp/dynamic/v1/customer/list      // 客户列表
GET /erp/dynamic/v1/customer/detail    // 客户详情
GET /erp/dynamic/v1/customer/sales-areas  // 销区列表
GET /erp/dynamic/v1/customer/brands    // 品牌列表
```

### 现有数据模型（CustomerVO）

```typescript
interface CustomerVO {
  customerCode: string;      // 客户编码
  customerName: string;      // 客户名称
  companyCode: string;       // 公司编码
  companyName: string;       // 公司名称
  brand: string;             // 品牌
  brandName: string;         // 品牌名称
  contactName: string;       // 联系人
  salesAreaCode: string;     // 销区编码
  salesAreaName: string;     // 销区名称
  salesPersonCode: string;   // 销售人员编码
  salesPersonName: string;   // 销售人员姓名
  province: string;          // 省
  city: string;              // 市
  isStop: number;            // 状态（0合作中，1停用）
  // ... 其他字段
}
```

---

# 2. 系统总体架构

## 2.1 HZHub 集成架构（员工门户）

### 服务归属

CRM模块归属于 **hzhub-system** 服务（端口 8083），前端在 **hzhub-portal-employee** 实现。

```
┌─────────────────────────────────────────┐
│  hzhub-portal-employee (员工门户)        │
│  Vue3 + Element Plus + TypeScript       │
│  Port: 5137                             │
│  已有: /crm (销售CRM) + /dealer (经销商) │
└────────────┬────────────────────────────┘
             │
    ┌────────┴────────┐
    │  hzhub-gateway  │  (API Gateway, port 8080)
    │  Spring Cloud   │  JWT auth, routing
    └───┬──────┬──────┘
        │      │
    ┌───▼──────────┐
    │ hzhub-system │  CRM 模块归属服务
    │   8083       │  (Users, Roles, CRM)
    └─────────────┘
```

### Gateway 路由配置

在 `hzhub-gateway/src/main/resources/application.yml` 中添加 CRM 路由：

```yaml
spring:
  cloud:
    gateway:
      routes:
        # CRM 路由（新增）
        - id: hzhub-crm
          uri: lb://hzhub-system
          predicates:
            - Path=/crm/**
          filters:
            - StripPrefix=1  # 去除 /crm 前缀
```

---

## 2.2 技术栈适配（员工门户）

| 层级 | HZHub 技术栈 | 说明 |
|---|---|---|
| 前端Web | Vue3 + Element Plus + TypeScript | **hzhub-portal-employee 已部署** |
| 前端路由 | Vue Router | 静态路由配置（`staticRouter.ts`） |
| 状态管理 | Pinia + persistedstate | 已集成 |
| HTTP请求 | hook-fetch + SSE | 已集成 |
| 后端 | Spring Boot 3.5.8 + MyBatis-Plus | hzhub-system 服务 |
| 数据库 | MySQL 8.0 | 已部署 |
| ERP数据 | SQL Server 2008 R2 | **hzhub-erp 服务** |
| 缓存 | Redis 7 | 已部署 |
| 向量数据库 | Weaviate 1.25.0 | 已部署 |
| AI服务 | LangChain4j + LangGraph4j | hzhub-ai 服务集成 |
| 文件存储 | MinIO | 已部署 |
| 工作流 | warm-flow 1.8.2 | 已集成在 hzhub-system |
| 权限 | Sa-Token | 已集成，JWT-based |

---

# 3. 数据库设计规范（HZHub 适配）

## 3.1 通用字段规范

所有CRM业务表继承 `TenantEntity`，包含以下字段：

| 字段 | 类型 | 注解 | 说明 |
|---|---|---|---|
| tenant_id | varchar(20) | 无注解（继承） | 租户ID（多租户） |
| create_dept | bigint | @TableField(fill = INSERT) | 创建部门 |
| create_by | bigint | @TableField(fill = INSERT) | 创建人 |
| create_time | datetime | @TableField(fill = INSERT) | 创建时间 |
| update_by | bigint | @TableField(fill = INSERT_UPDATE) | 更新人 |
| update_time | datetime | @TableField(fill = INSERT_UPDATE) | 更新时间 |

**注意：** 不需要手动添加 `id` 字段，使用 MyBatis-Plus 的 `@TableId` 注解。

---

## 3.2 Entity 实体类规范

### 基类继承

```java
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("crm_lead")
public class CrmLead extends TenantEntity {

    @TableId(value = "lead_id", type = IdType.ASSIGN_ID)
    private Long leadId;

    // 业务字段...

    /**
     * 删除标志（0代表存在 1代表删除）
     */
    @TableLogic
    private Integer delFlag;
}
```

---

# 4. 线索中心模块设计（适配员工门户）

## 4.1 模块目标

用于管理潜在经销商，支持：

- 多渠道线索接入
- **关联ERP客户数据**（customer_code）
- AI意向识别（LangChain4j）
- AI风险分析
- 自动分配销售
- 商机转化

---

## 4.2 数据表设计

### 4.2.1 crm_lead（线索表）

| 字段 | 类型 | 注解 | 说明 |
|---|---|---|---|
| lead_id | bigint | @TableId(ASSIGN_ID) | 主键 |
| customer_code | varchar(100) | - | **ERP客户编码（关联）** |
| company_name | varchar(200) | - | 公司名称 |
| contact_name | varchar(100) | - | 联系人 |
| mobile | varchar(50) | - | 手机号 |
| wechat | varchar(100) | - | 微信号 |
| province | varchar(50) | - | 省 |
| city | varchar(50) | - | 市 |
| region_id | bigint | - | 区域ID（关联 sys_dept） |
| source_type | varchar(50) | - | 来源类型（字典：crm_lead_source） |
| activity_name | varchar(100) | - | 活动名称 |
| referrer_name | varchar(100) | - | 推荐人 |
| industry | varchar(100) | - | 行业（字典：crm_industry） |
| company_scale | varchar(100) | - | 公司规模（字典：crm_scale） |
| store_count | int | - | 门店数 |
| intent_level | varchar(20) | - | AI意向等级（字典：crm_intent_level） |
| ai_score | decimal(5,2) | - | AI评分 |
| risk_level | varchar(20) | - | 风险等级（字典：crm_risk_level） |
| owner_user_id | bigint | - | 负责人（关联 sys_user） |
| lead_status | varchar(50) | - | 状态（字典：crm_lead_status） |
| converted_dealer_id | bigint | - | 转化经销商ID |
| del_flag | int | @TableLogic | 删除标志 |

**继承字段：** tenant_id, create_dept, create_by, create_time, update_by, update_time

**关键设计：**
- `customer_code` 关联 ERP 客户数据（可选，支持同步）
- 如果 `customer_code` 存在，自动从 ERP 拉取基础信息
- 线索转化时，创建 `crm_dealer` 并关联 `customer_code`

---

### 4.2.2 crm_lead_follow（线索跟进记录）

| 字段 | 类型 | 说明 |
|---|---|---|
| follow_id | bigint | 主键 |
| lead_id | bigint | 线索ID |
| follow_type | varchar(50) | 跟进方式（字典：crm_follow_type） |
| content | text | 跟进内容 |
| ai_summary | text | AI摘要 |
| next_follow_time | datetime | 下次跟进时间 |
| follow_user_id | bigint | 跟进人（关联 sys_user） |
| del_flag | int | 删除标志 |

---

## 4.3 接口设计

### 4.3.1 创建线索

**API：** `POST /crm/lead`

**请求参数：**

```json
{
  "customerCode": "C001",           // ERP客户编码（可选）
  "companyName": "XX贸易有限公司",
  "contactName": "张三",
  "mobile": "13800000000",
  "wechat": "zhangsan",
  "province": "广东省",
  "city": "深圳市",
  "industry": "食品",
  "storeCount": 20
}
```

**业务逻辑：**

1. 如果提供 `customer_code`，调用 `hzhub-erp:8082/erp/dynamic/v1/customer/detail` 拉取客户信息
2. 自动填充客户基础信息（companyName, contactName, mobile 等）
3. 校验手机号是否重复（同租户内）
4. 调用 LangChain4j AI服务分析意向等级（`hzhub-ai:6039/ai/analyze/intent`）
5. 自动生成AI评分
6. 根据区域规则（sys_dept）分配销售（owner_user_id）
7. 创建自动跟进任务（warm-flow）

---

### 4.3.2 线索转经销商

**API：** `POST /crm/lead/convert`

**请求参数：**

```json
{
  "leadId": 12345,
  "dealerName": "XX贸易",
  "dealerCode": "DL20260001",
  "customerCode": "C001"          // ERP客户编码（可选）
}
```

**逻辑：**

1. 创建 `crm_dealer` 数据
2. 如果 `customer_code` 存在，同步 ERP 客户数据
3. 迁移历史跟进记录到 `crm_dealer_follow`
4. 创建初始商机（`crm_opportunity`）
5. 更新线索状态为"已转化"
6. 触发 warm-flow 工作流（经销商审批）

---

## 4.4 前端页面设计（Element Plus - 员工门户）

### 4.4.1 扩展现有CRM页面

**路径：** `hzhub-portal-employee/src/pages/crm/index.vue`（**已存在，需扩展**）

**现有功能：**
- 商机管道视图（Pipeline）
- 客户列表表格（使用 ERP CustomerVO）
- 新建客户对话框（基础功能）

**新增功能：**

#### 1. 线索列表Tab页

在现有CRM页面添加Tab切换：

```vue
<el-tabs v-model="activeTab">
  <el-tab-pane label="商机管道" name="pipeline">
    <!-- 现有管道视图 -->
  </el-tab-pane>
  <el-tab-pane label="线索管理" name="leads">
    <!-- 新增线索管理 -->
  </el-tab-pane>
  <el-tab-pane label="经销商" name="dealers">
    <!-- 新增经销商管理 -->
  </el-tab-pane>
</el-tabs>
```

#### 2. 线索管理模块

**筛选栏：**

```vue
<div class="filter-bar">
  <el-input v-model="filters.keyword" placeholder="搜索公司、联系人..." />
  <el-select v-model="filters.intentLevel" placeholder="AI意向等级">
    <el-option label="高意向" value="high" />
    <el-option label="中意向" value="medium" />
    <el-option label="低意向" value="low" />
  </el-select>
  <el-select v-model="filters.ownerUserId" placeholder="负责人">
    <!-- 用户选择器 -->
  </el-select>
  <el-date-picker v-model="filters.createTimeRange" type="daterange" />
  <el-button type="primary" @click="loadLeads">搜索</el-button>
</div>
```

**线索列表（Element Plus Table）：**

```vue
<el-table :data="leadList" v-loading="loading">
  <el-table-column prop="companyName" label="公司名称">
    <template #default="{ row }">
      <el-tag v-if="row.intentLevel === 'high'" type="danger" effect="plain">
        {{ row.companyName }}
      </el-tag>
      <span v-else>{{ row.companyName }}</span>
    </template>
  </el-table-column>
  <el-table-column prop="contactName" label="联系人" />
  <el-table-column prop="mobile" label="手机">
    <template #default="{ row }">
      {{ maskPhone(row.mobile) }}
    </template>
  </el-table-column>
  <el-table-column prop="intentLevel" label="AI意向">
    <template #default="{ row }">
      <el-badge :value="row.aiScore" :type="getIntentBadgeType(row.intentLevel)">
        {{ getIntentLabel(row.intentLevel) }}
      </el-badge>
    </template>
  </el-table-column>
  <el-table-column prop="ownerUserName" label="负责人">
    <template #default="{ row }">
      <el-avatar :size="32">{{ row.ownerUserName?.charAt(0) }}</el-avatar>
    </template>
  </el-table-column>
  <el-table-column label="操作" width="180">
    <template #default="{ row }">
      <el-button type="primary" link @click="showLeadDetail(row)">详情</el-button>
      <el-button type="primary" link @click="showFollowDrawer(row)">跟进</el-button>
      <el-button type="success" link @click="convertToDealer(row)">转经销商</el-button>
    </template>
  </el-table-column>
</el-table>
```

#### 3. 线索详情 Drawer

```vue
<el-drawer v-model="showDetailDrawer" title="线索详情" size="50%">
  <el-descriptions :column="2" border>
    <el-descriptions-item label="公司名称">{{ currentLead.companyName }}</el-descriptions-item>
    <el-descriptions-item label="联系人">{{ currentLead.contactName }}</el-descriptions-item>
    <el-descriptions-item label="手机">{{ currentLead.mobile }}</el-descriptions-item>
    <el-descriptions-item label="ERP客户编码">
      <el-link v-if="currentLead.customerCode" @click="viewErpCustomer">
        {{ currentLead.customerCode }}
      </el-link>
    </el-descriptions-item>
    <!-- AI分析信息 -->
    <el-descriptions-item label="AI意向等级">
      <el-progress :percentage="currentLead.aiScore" :color="getIntentColor(currentLead.intentLevel)" />
    </el-descriptions-item>
    <el-descriptions-item label="风险等级">
      <el-tag :type="getRiskTagType(currentLead.riskLevel)">
        {{ getRiskLabel(currentLead.riskLevel) }}
      </el-tag>
    </el-descriptions-item>
  </el-descriptions>

  <!-- 跟进记录Timeline -->
  <el-divider content-position="left">跟进记录</el-divider>
  <el-timeline>
    <el-timeline-item v-for="follow in followRecords" :key="follow.followId"
                      :timestamp="follow.createTime" placement="top">
      <el-card>
        <div class="follow-header">
          <span class="follow-type">{{ getFollowTypeLabel(follow.followType) }}</span>
          <span class="follow-user">{{ follow.followUserName }}</span>
        </div>
        <div class="follow-content">{{ follow.content }}</div>
        <div v-if="follow.aiSummary" class="follow-ai-summary">
          <el-icon><MagicStick /></el-icon> AI摘要：{{ follow.aiSummary }}
        </div>
      </el-card>
    </el-timeline-item>
  </el-timeline>
</el-drawer>
```

#### 4. 新建线索 Dialog

```vue
<el-dialog v-model="showAddLeadDialog" title="新建线索" width="600px">
  <el-form :model="leadForm" label-width="100px">
    <el-form-item label="ERP客户">
      <el-select v-model="leadForm.customerCode" filterable placeholder="选择ERP客户（可选）">
        <!-- 从ERP拉取客户列表 -->
      </el-select>
    </el-form-item>
    <el-form-item label="公司名称" required>
      <el-input v-model="leadForm.companyName" />
    </el-form-item>
    <el-form-item label="联系人" required>
      <el-input v-model="leadForm.contactName" />
    </el-form-item>
    <el-form-item label="手机号" required>
      <el-input v-model="leadForm.mobile" />
    </el-form-item>
    <!-- 其他字段 -->
  </el-form>
  <template #footer>
    <el-button @click="showAddLeadDialog = false">取消</el-button>
    <el-button type="primary" @click="handleAddLead">创建线索</el-button>
  </template>
</el-dialog>
```

---

### 4.4.2 AI分析侧边栏（Element Plus Drawer）

右侧固定展示：

```vue
<el-drawer v-model="showAiDrawer" title="AI分析" size="40%" direction="rtl">
  <div class="ai-analysis">
    <el-card class="ai-card">
      <div class="ai-score">
        <el-progress type="dashboard" :percentage="aiScore" :color="getAiColor" />
        <span class="ai-label">AI意向评分</span>
      </div>
    </el-card>
    <el-alert v-if="riskLevel === 'high'" title="高风险提示" type="error" :closable="false">
      {{ riskReason }}
    </el-alert>
    <el-collapse>
      <el-collapse-item title="推荐动作" name="actions">
        <el-steps :active="recommendedStep" direction="vertical">
          <el-step title="首次拜访" description="建议本周完成首次拜访" />
          <el-step title="发送招商政策" description="发送返点政策文档" />
          <el-step title="样品测试" description="寄送样品进行测试" />
        </el-steps>
      </el-collapse-item>
      <el-collapse-item title="推荐销售话术" name="scripts">
        <div v-html="recommendedScript"></div>
      </el-collapse-item>
    </el-collapse>
  </div>
</el-drawer>
```

**AI服务调用：** 通过 Gateway 调用 `hzhub-ai:6039/ai/chat/analyze`

---

# 5. 经销商中心模块设计

## 5.1 现有页面扩展

**路径：** `hzhub-portal-employee/src/pages/dealer/index.vue`（**已存在，需扩展**）

**现有功能：**
- 经销商卡片视图（使用 ERP CustomerVO）
- 筛选（销区、品牌、状态、搜索）
- 统计数据展示

**新增功能：**

### 5.1.1 关联CRM经销商数据

```typescript
interface DealerVO extends CustomerVO {
  // CRM扩展字段
  dealerId?: number;           // CRM经销商ID
  level?: string;              // 经销商等级
  lifecycle?: string;          // 生命周期
  totalOrderAmount?: number;   // 累计订单金额
  totalPaymentAmount?: number; // 累计回款金额
  activityScore?: number;      // 活跃评分
  riskScore?: number;          // 风险评分
  tags?: DealerTagVO[];        // AI标签
}
```

### 5.1.2 经销商详情 Dialog

```vue
<el-dialog v-model="showDealerDetail" title="经销商详情" width="800px">
  <el-tabs>
    <el-tab-pane label="基础档案">
      <el-descriptions :column="2" border>
        <el-descriptions-item label="ERP客户编码">{{ dealer.customerCode }}</el-descriptions-item>
        <el-descriptions-item label="经销商等级">
          <el-tag>{{ dealer.level }}</el-tag>
        </el-descriptions-item>
        <!-- ... -->
      </el-descriptions>
    </el-tab-pane>
    <el-tab-pane label="商机管理">
      <!-- 商机列表 -->
    </el-tab-pane>
    <el-tab-pane label="拜访记录">
      <el-timeline>
        <!-- 拜访Timeline -->
      </el-timeline>
    </el-tab-pane>
    <el-tab-pane label="AI画像">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card>
            <div class="ai-metric">
              <span class="metric-label">活跃度评分</span>
              <el-progress :percentage="dealer.activityScore" />
            </div>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card>
            <div class="ai-metric">
              <span class="metric-label">风险评分</span>
              <el-progress :percentage="dealer.riskScore" :color="getRiskColor" />
            </div>
          </el-card>
        </el-col>
      </el-row>
    </el-tab-pane>
  </el-tabs>
</el-dialog>
```

---

## 5.2 数据表设计

### 5.2.1 crm_dealer（经销商表）

| 字段 | 类型 | 说明 |
|---|---|---|
| dealer_id | bigint | 主键 |
| customer_code | varchar(100) | **ERP客户编码（关联）** |
| dealer_name | varchar(200) | 经销商名称 |
| dealer_code | varchar(100) | 编码 |
| contact_name | varchar(100) | 联系人 |
| mobile | varchar(50) | 手机 |
| province | varchar(50) | 省 |
| city | varchar(50) | 市 |
| level | varchar(50) | 等级（字典：crm_dealer_level） |
| lifecycle | varchar(50) | 生命周期（字典：crm_lifecycle） |
| signed_at | datetime | 签约时间 |
| store_count | int | 门店数 |
| team_size | int | 团队规模 |
| total_order_amount | decimal(18,2) | 累计订单金额 |
| total_payment_amount | decimal(18,2) | 累计回款金额 |
| activity_score | decimal(5,2) | 活跃评分 |
| risk_score | decimal(5,2) | 飆险评分 |
| owner_user_id | bigint | 负责人（关联 sys_user） |
| del_flag | int | 删除标志 |

---

# 6. API 接口设计（员工门户适配）

## 6.1 前端 API 定义

**路径：** `hzhub-portal-employee/src/api/crm/`（**新建目录**）

创建：
- `index.ts`（API调用）
- `types.ts`（类型定义）

### API示例

```typescript
import request from '@/utils/request';

// 线索列表
export function getLeadList(params: LeadQueryParams) {
  return request.get<TableDataInfo<LeadVO>>('/crm/lead/list', params).json();
}

// 创建线索
export function createLead(data: LeadForm) {
  return request.post<R<void>>('/crm/lead', data).json();
}

// 线索详情
export function getLeadDetail(leadId: number) {
  return request.get<R<LeadVO>>(`/crm/lead/${leadId}`).json();
}

// 线索跟进记录
export function getLeadFollowRecords(leadId: number) {
  return request.get<R<LeadFollowVO[]>>(`/crm/lead/follow/${leadId}`).json();
}

// 添加跟进记录
export function addLeadFollow(data: LeadFollowForm) {
  return request.post<R<void>>('/crm/lead/follow', data).json();
}

// 线索转经销商
export function convertLeadToDealer(data: ConvertForm) {
  return request.post<R<void>>('/crm/lead/convert', data).json();
}
```

---

## 6.2 后端接口设计（hzhub-system）

### Controller规范

```java
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/crm/lead")
public class CrmLeadController extends BaseController {

    private final ICrmLeadService leadService;

    /**
     * 获取线索列表
     */
    @GetMapping("/list")
    public TableDataInfo<CrmLeadVo> list(CrmLeadBo lead, PageQuery pageQuery) {
        return leadService.selectPageLeadList(lead, pageQuery);
    }

    /**
     * 新增线索
     */
    @Log(title = "线索管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated @RequestBody CrmLeadBo lead) {
        return R.ok(leadService.insertLead(lead));
    }

    /**
     * 线索详情
     */
    @GetMapping("/{leadId}")
    public R<CrmLeadVo> detail(@PathVariable Long leadId) {
        return R.ok(leadService.selectLeadById(leadId));
    }

    /**
     * 线索跟进记录
     */
    @GetMapping("/follow/{leadId}")
    public R<List<CrmLeadFollowVo>> followRecords(@PathVariable Long leadId) {
        return R.ok(leadService.selectFollowRecordsByLeadId(leadId));
    }

    /**
     * 添加跟进记录
     */
    @Log(title = "线索跟进", businessType = BusinessType.INSERT)
    @PostMapping("/follow")
    public R<Void> addFollow(@Validated @RequestBody CrmLeadFollowBo follow) {
        return R.ok(leadService.insertFollowRecord(follow));
    }

    /**
     * 线索转经销商
     */
    @Log(title = "线索转化", businessType = BusinessType.INSERT)
    @PostMapping("/convert")
    public R<Void> convert(@Validated @RequestBody CrmLeadConvertBo convert) {
        return R.ok(leadService.convertToDealer(convert));
    }
}
```

---

# 7. ERP数据集成设计

## 7.1 数据同步策略

### 同步方式

**方式1：关联查询（实时）**

线索/经销商表存储 `customer_code`，实时调用 ERP 动态API 拉取客户信息。

```java
public CrmLeadVo selectLeadById(Long leadId) {
    CrmLead lead = leadMapper.selectById(leadId);
    CrmLeadVo vo = BeanUtil.toBean(lead, CrmLeadVo.class);

    // 如果有ERP客户编码，拉取ERP数据补充
    if (StringUtils.isNotBlank(lead.getCustomerCode())) {
        CustomerVO erpCustomer = erpService.getCustomerDetail(lead.getCustomerCode());
        vo.setErpCustomerName(erpCustomer.getCustomerName());
        vo.setErpSalesAreaName(erpCustomer.getSalesAreaName());
        // ...
    }
    return vo;
}
```

**方式2：定时同步（批量）**

使用 XXL-Job 定时任务同步 ERP 客户数据到 CRM 表。

```java
@Scheduled(cron = "0 0 2 * * ?")  // 每天凌晨2点
public void syncErpCustomers() {
    // 调用 hzhub-erp:8082/erp/dynamic/v1/customer/list
    // 批量更新 crm_dealer 表
}
```

---

## 7.2 ERP动态API调用

**hzhub-system 服务调用 ERP：**

```java
@Service
public class ErpIntegrationService {

    @Value("${erp.base-url}")
    private String erpBaseUrl;  // http://localhost:8082

    /**
     * 获取ERP客户详情
     */
    public CustomerVO getCustomerDetail(String customerCode) {
        String url = erpBaseUrl + "/erp/dynamic/v1/customer/detail?customerCode=" + customerCode;
        ResponseEntity<R<CustomerVO>> response = restTemplate.getForEntity(url, R.class);
        return response.getBody().getData();
    }

    /**
     * 获取ERP客户列表
     */
    public List<CustomerVO> getCustomerList(CustomerQueryParam param) {
        String url = erpBaseUrl + "/erp/dynamic/v1/customer/list";
        // ...
    }
}
```

---

# 8. 企业微信集成（员工门户）

## 8.1 企业微信侧边栏

**展示内容：**

- 经销商画像（从 CRM + ERP 拉取）
- 最近订单
- 最近拜访
- 商机阶段
- AI风险

**实现：**

1. 企业微信应用配置（应用ID、Secret）
2. 后端接口：`GET /crm/wecom/sidebar/{externalUserId}`
3. 前端嵌入企业微信侧边栏（H5页面）

---

## 8.2 移动端H5页面

**员工门户支持企业微信H5：**

```typescript
// 企业微信环境判断
if (window.location.href.includes('wework')) {
  // 使用企业微信JS-SDK
  wx.config({
    beta: true,
    appId: 'YOUR_APPID',
    // ...
  });
}
```

**移动端页面：**

- `/crm/mobile/visit` - 拜访记录（语音录入）
- `/crm/mobile/follow` - 快速跟进

---

# 9. AI能力集成设计

## 9.1 AI服务调用（LangChain4j）

**调用 hzhub-ai 服务：**

```java
@Service
public class CrmAiService {

    @Autowired
    private ChatClient chatClient;  // LangChain4j

    /**
     * AI意向分析
     */
    public LeadIntentAnalysis analyzeIntent(CrmLead lead) {
        String prompt = String.format(
            "分析以下线索的意向等级和风险：%s，联系人：%s，行业：%s",
            lead.getCompanyName(), lead.getContactName(), lead.getIndustry()
        );

        AiMessage response = chatClient.generate(prompt);
        // 解析AI响应，提取意向等级、评分、风险等级
        return parseIntentAnalysis(response.text());
    }

    /**
     * AI跟进摘要生成
     */
    public String generateFollowSummary(String followContent) {
        String prompt = "请为以下跟进记录生成摘要：" + followContent;
        AiMessage response = chatClient.generate(prompt);
        return response.text();
    }
}
```

---

## 9.2 向量检索（Weaviate）

**使用 Weaviate 存储历史线索案例：**

```java
@Service
public class LeadSimilarityService {

    /**
     * 查找相似线索案例
     */
    public List<LeadCase> findSimilarLeads(CrmLead newLead) {
        // 将新线索信息转为向量
        // 在 Weaviate 中检索相似案例
        // 返回历史成功案例供参考
    }
}
```

---

# 10. 自动化工作流设计（warm-flow）

## 10.1 线索分配流程

```text
线索创建
-> AI意向分析
-> 自动分配规则（根据区域）
-> warm-flow审批流程
-> 销售确认接手
```

**实现：**

```java
// 触发warm-flow流程
workflowService.startProcessInstanceByKey("crm_lead_assign_flow", leadId);
```

---

## 10.2 线索转化流程

```text
线索转化申请
-> warm-flow审批流程（区域经理审批）
-> 创建经销商数据
-> 创建商机
-> 更新线索状态
```

---

# 11. 权限与组织设计（Sa-Token）

## 11.1 数据权限层级

```text
总部（sys_dept: root）
-> 大区（sys_dept: level 1）
-> 区域（sys_dept: level 2）
-> 城市（sys_dept: level 3）
-> 销售（sys_user）
```

**实现：** 使用 `sys_dept` 表的树形结构，通过 `DataPermissionHelper` 实现数据隔离。

---

## 11.2 权限控制点

| 模块 | 权限标识 | Sa-Token 注解 |
|---|---|---|
| 线索 | crm:lead:list, crm:lead:add, crm:lead:edit, crm:lead:remove | @SaCheckPermission |
| 经销商 | crm:dealer:list, crm:dealer:edit | - |
| 合同 | crm:contract:approve, crm:contract:amount-edit | - |
| 回款 | crm:payment:list, crm:payment:verify | - |
| BI | crm:bi:view（区域数据隔离） | - |

**注意：** 员工门户不需要 Sa-Token注解，权限由 Gateway 统一控制。

---

# 12. 前端开发规范（Element Plus）

## 12.1 页面结构规范

```vue
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { getLeadList, type LeadVO } from '@/api/crm';
import { ElMessage } from 'element-plus';

// 数据
const leadList = ref<LeadVO[]>([]);
const loading = ref(false);

// 方法
async function loadLeads() {
  loading.value = true;
  try {
    const res = await getLeadList({ pageNum: 1, pageSize: 10 });
    leadList.value = res.rows || [];
  } catch (error: any) {
    ElMessage.error(error?.message || '加载失败');
  } finally {
    loading.value = false;
  }
}

onMounted(() => {
  loadLeads();
});
</script>

<template>
  <div class="crm-page">
    <!-- Element Plus组件 -->
  </div>
</template>

<style scoped lang="scss">
.crm-page {
  padding: 20px;
}
</style>
```

---

## 12.2 目录结构

```
hzhub-portal-employee/src/
├── api/
│   └── crm/
│   │   ├── index.ts        # CRM API调用
│   │   └── types.ts        # 类型定义
├── pages/
│   └── crm/
│   │   ├── index.vue       # CRM主页（扩展）
│   │   ├── LeadDetailDrawer.vue    # 线索详情组件
│   │   ├── FollowDrawer.vue        # 跟进记录组件
│   │   └── ConvertDialog.vue       # 转化对话框
│   └── dealer/
│   │   ├── index.vue       # 经销商主页（扩展）
│   │   ├── DealerDetailDialog.vue  # 经销商详情
```

---

# 13. 实施计划（员工门户）

## 第一阶段（1-2个月）

**建设内容：**

- 扩展员工门户现有CRM页面（线索管理Tab）
- 后端CRM基础接口（hzhub-system）
- ERP数据关联（customer_code）
- 线索跟进记录（Timeline展示）
- warm-flow审批流程（线索分配）

**技术栈：**

- 后端：Spring Boot + MyBatis-Plus + Sa-Token + warm-flow
- 前端：Vue3 + Element Plus + TypeScript
- ERP集成：hzhub-erp 动态API

---

## 第二阶段（2-3个月）

**建设内容：**

- AI意向分析（LangChain4j）
- AI跟进摘要生成
- AI风险分析
- 企业微信侧边栏集成
- 移动端H5拜访页面

**技术栈：**

- AI：LangChain4j + hzhub-ai 服务
- 向量：Weaviate（案例检索）
- 移动端：企业微信JS-SDK

---

## 第三阶段（3-4个月）

**建设内容：**

- AI预测模型（成交预测、流失预测）
- AI Copilot（LangGraph4j）
- BI仪表盘（扩展现有 `/bi` 页面）
- 自动化工作流（XXL-Job）

**技术栈：**

- AI：LangGraph4j + hzhub-ai 服务
- 定时任务：XXL-Job

---

# 14. 与 HZHub 项目的集成要点

## 14.1 Gateway 路由配置

**位置：** `hzhub-gateway/src/main/resources/application.yml`

```yaml
spring:
  cloud:
    gateway:
      routes:
        # CRM 路由（添加到现有路由列表）
        - id: hzhub-crm
          uri: lb://hzhub-system
          predicates:
            - Path=/crm/**
          filters:
            - StripPrefix=1
```

---

## 14.2 前端路由扩展

**位置：** `hzhub-portal-employee/src/routers/modules/staticRouter.ts`

**现有路由（已存在）：**

```typescript
{
  path: '/crm',
  name: 'crm',
  component: () => import('@/pages/crm/index.vue'),
  meta: {
    title: '销售CRM',
    subtitle: '客户关系管理',
    icon: 'TrendCharts',
  },
},
{
  path: '/dealer',
  name: 'dealer',
  component: () => import('@/pages/dealer/index.vue'),
  meta: {
    title: '经销商管理',
    subtitle: '经销商信息管理',
    icon: 'Shop',
  },
},
```

**无需修改，直接扩展现有页面即可。**

---

## 14.3 数据库初始化

**SQL 文件：** `hzhub-system/src/main/resources/db/crm_init.sql`

包含：

- CRM 表结构（crm_lead, crm_dealer, crm_opportunity 等）
- 数据字典（crm_lead_source, crm_opportunity_stage 等）
- 菜单配置（sys_menu - 告知管理员在后台配置）

---

# 15. 核心差异总结（员工门户 vs 管理后台）

| 方面 | 管理后台（V2） | 员工门户（V3） |
|---|---|---|
| 前端项目 | hzhub-admin | **hzhub-portal-employee** |
| UI框架 | Vben Admin + Ant Design Vue | **Element Plus** |
| 现有基础 | 无，需要新建 | **已有CRM和经销商页面** |
| 开发方式 | 新建独立页面 | **扩展现有页面** |
| 数据来源 | 独立CRM表 | **ERP客户数据 + CRM表** |
| 用户角色 | 管理员 + 销售 | **企业员工 + 销售人员** |
| 权限控制 | Sa-Token注解 | **Gateway统一控制** |
| 移动端 | 企业微信H5（新建） | **企业微信H5（员工门户支持）** |

---

# 总结

本文档将 CRM 销售自动化系统完全适配到 **员工门户（hzhub-portal-employee）**，充分利用：

1. **现有页面**：`/crm`（销售CRM）和 `/dealer`（经销商）已存在，直接扩展
2. **ERP数据集成**：关联 `customer_code`，实时拉取 ERP 客户信息
3. **Element Plus UI**：使用卡片式、Timeline、Drawer等组件
4. **Vue3 Composition API**：`<script setup>` + TypeScript
5. **hook-fetch请求**：统一API调用方式

核心改动：
1. 前端项目：**hzhub-portal-employee**（不是 hzhub-admin）
2. UI组件：**Element Plus**（不是 Ant Design Vue）
3. 开发方式：**扩展现有页面**（不是新建）
4. 数据关联：**ERP Customer + CRM Lead**（双数据源）
5. 路由配置：**无需修改**（直接使用现有路由）

后续实施时，严格按照本文档执行，确保与员工门户现有功能的一致性。