|
|
@@ -0,0 +1,2446 @@
|
|
|
+# 客服与管理员功能操作指南
|
|
|
+
|
|
|
+## 文档概述
|
|
|
+
|
|
|
+本文档详细梳理了**客服板块**和**管理员板块**的功能模块、操作流程、角色权限和数据字段,为产品复盘和功能优化提供完整的参考依据。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、客服板块功能体系
|
|
|
+
|
|
|
+### 1.1 客服工作台首页 (`/customer-service/dashboard`)
|
|
|
+
|
|
|
+#### 1.1.1 核心数据看板
|
|
|
+
|
|
|
+**数据统计卡片**(5个核心指标):
|
|
|
+
|
|
|
+| 指标名称 | 数据来源 | 计算逻辑 | 点击操作 |
|
|
|
+|---------|---------|---------|---------|
|
|
|
+| **项目总数** | `Project` 表 | `count()` 查询所有项目 | 跳转到项目列表(显示全部) |
|
|
|
+| **新咨询数** | `Project` 表 | 今日新增项目数(`createdAt >= 今日0点`) | - |
|
|
|
+| **待分配项目** | `Project` 表 | `currentStage` 为订单分配阶段的项目数 | 跳转到项目列表(筛选待分配) |
|
|
|
+| **异常项目** | `Project` 表 | 超期项目数(`deadline < 当前时间` 且状态为进行中) | - |
|
|
|
+| **售后服务** | `ProjectFeedback` 表 | 类型为投诉且状态为待处理的反馈数 | - |
|
|
|
+
|
|
|
+**数据表结构**:
|
|
|
+```typescript
|
|
|
+// Project 表字段
|
|
|
+{
|
|
|
+ title: string; // 项目名称
|
|
|
+ currentStage: string; // 当前阶段(订单分配/确认需求/交付执行/售后归档)
|
|
|
+ status: string; // 状态(待分配/进行中/已完成)
|
|
|
+ deadline: Date; // 截止时间
|
|
|
+ createdAt: Date; // 创建时间
|
|
|
+ company: Pointer; // 所属公司
|
|
|
+ contact: Pointer; // 客户信息
|
|
|
+ assignee: Pointer; // 负责人
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.1.2 待跟进尾款项目
|
|
|
+
|
|
|
+**功能描述**:显示处于售后归档阶段且有未付尾款的项目列表
|
|
|
+
|
|
|
+**数据来源**:
|
|
|
+- 查询 `Project` 表,筛选 `currentStage` 为售后归档相关阶段
|
|
|
+- 从 `Project.data` 字段读取支付信息(不使用 `ProjectPayment` 表)
|
|
|
+
|
|
|
+**显示字段**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ projectName: string; // 项目名称
|
|
|
+ customerName: string; // 客户姓名
|
|
|
+ customerPhone: string; // 客户电话
|
|
|
+ finalPaymentAmount: number; // 剩余未付金额
|
|
|
+ totalAmount: number; // 订单总金额
|
|
|
+ paidAmount: number; // 已付金额
|
|
|
+ dueDate: Date; // 到期日期
|
|
|
+ status: string; // 状态(已逾期/待创建/待付款)
|
|
|
+ overdueDay: number; // 逾期天数
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"开始跟进"按钮
|
|
|
+2. 跳转到项目详情页的售后归档阶段 (`/wxwork/:cid/project/:projectId/aftercare`)
|
|
|
+3. 查看尾款详情和支付凭证
|
|
|
+
|
|
|
+#### 1.1.3 紧急事件栏
|
|
|
+
|
|
|
+**功能描述**:自动计算并显示截止时间已到或即将到达但未完成的关键节点
|
|
|
+
|
|
|
+**计算逻辑**(复用组长端逻辑):
|
|
|
+```typescript
|
|
|
+// 紧急事件类型
|
|
|
+{
|
|
|
+ type: 'review' | 'delivery' | 'deadline'; // 小图对图/交付审批/项目截止
|
|
|
+ projectId: string;
|
|
|
+ projectName: string;
|
|
|
+ deadline: Date;
|
|
|
+ urgencyLevel: 'critical' | 'high' | 'medium';
|
|
|
+ description: string;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**紧急程度判断**:
|
|
|
+- **Critical(严重)**:已逾期
|
|
|
+- **High(高)**:1天内到期
|
|
|
+- **Medium(中等)**:3天内到期
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击紧急事件卡片
|
|
|
+2. 跳转到对应项目的相应阶段
|
|
|
+
|
|
|
+#### 1.1.4 待办任务栏
|
|
|
+
|
|
|
+**功能描述**:显示从问题板块加载的待办任务(待处理+处理中状态)
|
|
|
+
|
|
|
+**数据来源**:`ProjectIssue` 表
|
|
|
+
|
|
|
+**数据结构**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ title: string; // 问题标题
|
|
|
+ description: string; // 问题描述
|
|
|
+ status: '待处理' | '处理中' | '已解决' | '已关闭';
|
|
|
+ priority: '紧急' | '高' | '中' | '低';
|
|
|
+ projectId: string;
|
|
|
+ projectName: string;
|
|
|
+ creator: Pointer; // 创建人
|
|
|
+ assignee: Pointer; // 负责人
|
|
|
+ createdAt: Date;
|
|
|
+ updatedAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**操作功能**:
|
|
|
+1. **查看详情**:展开问题详细信息
|
|
|
+2. **添加评论**:在问题下添加跟进评论
|
|
|
+3. **催办**:发送催办通知给负责人
|
|
|
+4. **新建问题**:创建新的项目问题
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.2 案例库 (`/customer-service/case-library`)
|
|
|
+
|
|
|
+#### 1.2.1 案例展示
|
|
|
+
|
|
|
+**数据来源**:`Case` 表(从已完成项目自动生成)
|
|
|
+
|
|
|
+**案例数据结构**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ name: string; // 案例名称
|
|
|
+ projectId: string; // 关联项目ID
|
|
|
+ projectName: string; // 项目名称
|
|
|
+ designer: string; // 设计师姓名
|
|
|
+ designerId: string;
|
|
|
+ team: string; // 团队名称
|
|
|
+ teamId: string;
|
|
|
+ coverImage: string; // 封面图
|
|
|
+ images: string[]; // 案例图片
|
|
|
+ area: number; // 面积
|
|
|
+ projectType: '工装' | '家装';
|
|
|
+ spaceType: '平层' | '复式' | '别墅' | '自建房';
|
|
|
+ renderingLevel: '高端' | '中端' | '低端';
|
|
|
+ tag: string[]; // 风格标签
|
|
|
+ totalPrice: number; // 项目总额
|
|
|
+ completionDate: Date; // 完成时间
|
|
|
+ viewCount: number; // 浏览次数
|
|
|
+ shareCount: number; // 分享次数
|
|
|
+ favoriteCount: number; // 收藏次数
|
|
|
+ isExcellent: boolean; // 是否优秀案例
|
|
|
+ isPublished: boolean; // 是否发布
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.2.2 数据统计功能
|
|
|
+
|
|
|
+**统计按钮位置**:页面头部右侧(案例总数和本月新增统计卡片旁边)
|
|
|
+
|
|
|
+**三大统计维度**:
|
|
|
+
|
|
|
+1. **Top 5 分享案例**
|
|
|
+ - 计算逻辑:按 `shareCount` 降序排序,取前5名
|
|
|
+ - 显示:案例名称 + 分享次数
|
|
|
+ - 前3名特殊徽章:🥇金、🥈银、🥉铜
|
|
|
+
|
|
|
+2. **客户最喜欢风格**
|
|
|
+ - 计算逻辑:统计所有案例的 `tag` 标签,按 `favoriteCount` 累加
|
|
|
+ - 显示:风格名称 + 收藏次数
|
|
|
+ - 取前5个最受欢迎风格
|
|
|
+
|
|
|
+3. **设计师推荐率**
|
|
|
+ - 计算逻辑:`推荐率 = (优秀案例数 / 总案例数) × 100%`
|
|
|
+ - 优秀案例:`isExcellent = true`
|
|
|
+ - 显示:设计师姓名 + 推荐率百分比
|
|
|
+ - 取前5名设计师
|
|
|
+
|
|
|
+#### 1.2.3 筛选搜索功能
|
|
|
+
|
|
|
+**筛选条件**:
|
|
|
+- 项目案例名称(模糊搜索)
|
|
|
+- 设计师姓名
|
|
|
+- 项目类型(工装/家装)
|
|
|
+- 空间类型(平层/复式/别墅/自建房)
|
|
|
+- 渲染级别(高端/中端/低端)
|
|
|
+- 风格标签
|
|
|
+- 面积范围
|
|
|
+
|
|
|
+**分页**:每页显示12个案例(3列×4行)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.3 项目列表 (`/customer-service/project-list`)
|
|
|
+
|
|
|
+#### 1.3.1 三种视图模式
|
|
|
+
|
|
|
+**1. 卡片视图(看板)**
|
|
|
+
|
|
|
+- 按四大阶段分列:订单分配、确认需求、交付执行、售后
|
|
|
+- 每列显示该阶段的项目卡片
|
|
|
+- 卡片信息:项目名称、客户、设计师、截止时间、进度、标签
|
|
|
+
|
|
|
+**2. 列表视图**
|
|
|
+
|
|
|
+- 表格形式展示所有项目
|
|
|
+- 支持分页(每页8条)
|
|
|
+- 显示字段:项目名称、客户、设计师、当前阶段、状态、截止时间、操作
|
|
|
+
|
|
|
+**3. 监控大盘**
|
|
|
+
|
|
|
+- 嵌入组长端监控大盘(iframe)
|
|
|
+- 隐藏待办任务栏
|
|
|
+- 显示项目甘特图、负载日历等
|
|
|
+
|
|
|
+**视图切换**:
|
|
|
+- 记忆上次选择的视图模式(localStorage)
|
|
|
+- 按钮切换:卡片 | 列表 | 监控大盘
|
|
|
+
|
|
|
+#### 1.3.2 项目数据结构
|
|
|
+
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ name: string; // 项目名称
|
|
|
+ customerName: string; // 客户姓名
|
|
|
+ customerId: string;
|
|
|
+ assigneeName: string; // 负责人姓名
|
|
|
+ assigneeId: string;
|
|
|
+ currentStage: string; // 当前阶段
|
|
|
+ status: string; // 状态
|
|
|
+ deadline: Date; // 截止时间
|
|
|
+ progress: number; // 进度(0-100)
|
|
|
+ daysUntilDeadline: number; // 距离截止天数
|
|
|
+ isUrgent: boolean; // 是否紧急
|
|
|
+ tagDisplayText: string; // 标签显示文本
|
|
|
+ createdAt: Date;
|
|
|
+ updatedAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.3.3 操作路径
|
|
|
+
|
|
|
+**点击项目卡片**:
|
|
|
+1. 设置 localStorage 标记:`enterFromCustomerService = '1'`
|
|
|
+2. 跳转到项目详情页:`/wxwork/:cid/project/:projectId/:stage`
|
|
|
+3. 根据阶段显示对应内容
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.4 需求确认阶段操作流程
|
|
|
+
|
|
|
+#### 1.4.1 参考图片拖拽上传
|
|
|
+
|
|
|
+**操作步骤**:
|
|
|
+1. 展开对应空间(客厅、卧室等)
|
|
|
+2. 将多张参考图片拖拽到"参考图片"区域
|
|
|
+3. 触发AI自动分析归类
|
|
|
+
|
|
|
+**AI分析功能**:
|
|
|
+- 识别图片类型:软装/硬装/CAD/其他
|
|
|
+- 自动分类到对应标签
|
|
|
+- 提取设计元素和风格特征
|
|
|
+
|
|
|
+**数据存储**:
|
|
|
+```typescript
|
|
|
+// ProjectFile 表
|
|
|
+{
|
|
|
+ fileName: string;
|
|
|
+ fileUrl: string;
|
|
|
+ fileSize: number;
|
|
|
+ fileType: string; // 'image' | 'cad' | 'document'
|
|
|
+ category: string; // 'soft_decor' | 'hard_decor' | 'cad' | 'other'
|
|
|
+ projectId: string;
|
|
|
+ productId: string; // 空间ID
|
|
|
+ stage: 'requirements';
|
|
|
+ uploadedBy: Pointer;
|
|
|
+ uploadedAt: Date;
|
|
|
+ analysisResult: object; // AI分析结果
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.4.2 需求填写
|
|
|
+
|
|
|
+**全局需求**:
|
|
|
+- 风格偏好(现代简约、北欧、中式等)
|
|
|
+- 色彩方案(主色调、副色调、点缀色、氛围)
|
|
|
+- 预算范围(最低-最高)
|
|
|
+- 工期要求
|
|
|
+- 质量等级(标准/高端/奢华)
|
|
|
+- 特殊需求(文本描述)
|
|
|
+- 环境要求(采光、通风、隔音、温控)
|
|
|
+
|
|
|
+**空间需求**(按空间分别填写):
|
|
|
+- 功能需求
|
|
|
+- 风格偏好
|
|
|
+- 色彩方案
|
|
|
+- 材质偏好
|
|
|
+- 家具需求
|
|
|
+- 特殊要求
|
|
|
+
|
|
|
+#### 1.4.3 AI生成方案
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 填写完需求后,点击"AI生成方案"按钮
|
|
|
+2. 调用 `AIService.generateDesignSolution()`
|
|
|
+3. 使用豆包1.6模型生成设计方案
|
|
|
+
|
|
|
+**生成内容**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ overallStyle: string; // 整体风格定位
|
|
|
+ colorScheme: {
|
|
|
+ primary: string; // 主色调
|
|
|
+ secondary: string; // 副色调
|
|
|
+ accent: string; // 点缀色
|
|
|
+ };
|
|
|
+ materialRecommendations: string[]; // 材质推荐
|
|
|
+ layoutOptimization: string[]; // 布局优化建议
|
|
|
+ budgetAssessment: {
|
|
|
+ estimatedMin: number;
|
|
|
+ estimatedMax: number;
|
|
|
+ riskLevel: string;
|
|
|
+ };
|
|
|
+ timeline: string; // 预计工期
|
|
|
+ riskFactors: string[]; // 风险因素
|
|
|
+ spaceSolutions: Array<{ // 各空间方案
|
|
|
+ name: string;
|
|
|
+ styleDescription: string;
|
|
|
+ colorPalette: string[];
|
|
|
+ materials: string[];
|
|
|
+ furnitureRecommendations: string[];
|
|
|
+ }>;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.4.4 设计助手
|
|
|
+
|
|
|
+**功能描述**:AI聊天助手,回答家装设计相关问题
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"展开设计助手"
|
|
|
+2. 输入问题(如"客厅应该选择什么颜色?")
|
|
|
+3. AI基于项目需求和分析结果给出专业建议
|
|
|
+
|
|
|
+**实现**:
|
|
|
+- 使用豆包1.6模型
|
|
|
+- 上下文包含:项目需求、AI分析结果、空间信息
|
|
|
+- 回答限制在200字以内
|
|
|
+
|
|
|
+#### 1.4.5 确认需求
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 确认所有需求无误
|
|
|
+2. 点击"确认需求"按钮
|
|
|
+3. 项目进入下一阶段(交付执行)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.5 交付执行阶段操作流程
|
|
|
+
|
|
|
+#### 1.5.1 拖拽上传交付文件
|
|
|
+
|
|
|
+**操作步骤**:
|
|
|
+1. 展开对应空间
|
|
|
+2. 将交付图片拖拽到空间区域(不指定具体阶段)
|
|
|
+3. 弹出 `drag-upload-modal` 组件
|
|
|
+4. AI自动分析图片,识别阶段(白模/软装/渲染/后期)
|
|
|
+
|
|
|
+**AI分析服务**:
|
|
|
+- 服务:`ImageAnalysisService`
|
|
|
+- 模型:豆包1.6 (`fmode-1.6-cn`)
|
|
|
+- 分析内容:
|
|
|
+ - 图片质量(清晰度、亮度、对比度)
|
|
|
+ - 内容识别(类别、置信度、描述、标签)
|
|
|
+ - 技术参数(格式、色彩空间、DPI、分辨率)
|
|
|
+ - 阶段分类建议
|
|
|
+
|
|
|
+**弹窗显示**:
|
|
|
+```
|
|
|
+┌─────────────────────────────────────┐
|
|
|
+│ AI智能识别上传弹窗 │
|
|
|
+├─────────────────────────────────────┤
|
|
|
+│ 文件 │ 名称 │ 上传 │ 空间 │ 阶段 │
|
|
|
+├─────────────────────────────────────┤
|
|
|
+│ [图] │ xxx.jpg │ 完成 │ 客厅 │ 软装 │
|
|
|
+│ [图] │ yyy.png │ 完成 │ 卧室 │ 渲染 │
|
|
|
+├─────────────────────────────────────┤
|
|
|
+│ [撤回] [确认交付清单] │
|
|
|
+└─────────────────────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.5.2 确认交付清单
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. AI分析完成后,点击"确认交付清单"
|
|
|
+2. 文件自动归类到各阶段
|
|
|
+3. 系统记录上传人员身份和时间
|
|
|
+
|
|
|
+**记录信息**:
|
|
|
+```typescript
|
|
|
+// Project.data.spaceConfirmations
|
|
|
+{
|
|
|
+ [spaceId]: {
|
|
|
+ confirmedBy: string; // 确认人ID
|
|
|
+ confirmedByName: string; // 确认人姓名
|
|
|
+ confirmedByRole: string; // 确认人角色
|
|
|
+ confirmedAt: Date; // 确认时间
|
|
|
+ filesSnapshot: string[]; // 文件ID快照
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.5.3 上传交付清单(提交审批)
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 所有空间完成确认后
|
|
|
+2. 点击"上传交付清单"按钮
|
|
|
+3. 项目进入待审批状态
|
|
|
+4. 组长端看板显示待审批项目
|
|
|
+
|
|
|
+**审批状态记录**:
|
|
|
+```typescript
|
|
|
+// Project.data.deliveryApproval
|
|
|
+{
|
|
|
+ status: 'pending'; // 待审批
|
|
|
+ stage: 'delivery';
|
|
|
+ totalFiles: number;
|
|
|
+ types: { // 各类型文件数量
|
|
|
+ white_model: number;
|
|
|
+ soft_decor: number;
|
|
|
+ rendering: number;
|
|
|
+ post_process: number;
|
|
|
+ };
|
|
|
+ submittedAt: Date;
|
|
|
+ submittedByName: string;
|
|
|
+ submittedById: string;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1.6 售后归档阶段操作流程
|
|
|
+
|
|
|
+#### 1.6.1 上传支付凭证
|
|
|
+
|
|
|
+**操作步骤**:
|
|
|
+1. 点击"上传支付凭证"按钮
|
|
|
+2. 选择支付凭证图片
|
|
|
+3. AI自动提取支付金额
|
|
|
+
|
|
|
+**AI提取逻辑**:
|
|
|
+- 识别支付凭证中的金额数字
|
|
|
+- 自动填充到支付金额字段
|
|
|
+- 支持手动修改
|
|
|
+
|
|
|
+**数据存储**:
|
|
|
+```typescript
|
|
|
+// Project.data.payments
|
|
|
+{
|
|
|
+ voucherUrl: string; // 凭证图片URL
|
|
|
+ amount: number; // 支付金额
|
|
|
+ extractedAmount: number; // AI提取的金额
|
|
|
+ uploadedBy: string;
|
|
|
+ uploadedAt: Date;
|
|
|
+ type: 'deposit' | 'progress' | 'final'; // 定金/进度款/尾款
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 1.6.2 预览支付凭证
|
|
|
+
|
|
|
+**功能描述**:点击凭证图片可放大预览
|
|
|
+
|
|
|
+**显示信息**:
|
|
|
+- 凭证图片
|
|
|
+- 支付金额
|
|
|
+- 上传时间
|
|
|
+- 上传人
|
|
|
+
|
|
|
+#### 1.6.3 总金额计算
|
|
|
+
|
|
|
+**默认值**:报价总金额(从订单分配阶段获取)
|
|
|
+
|
|
|
+**计算逻辑**:
|
|
|
+```typescript
|
|
|
+totalAmount = 报价总金额;
|
|
|
+paidAmount = sum(所有支付凭证金额);
|
|
|
+remainingAmount = totalAmount - paidAmount;
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、管理员板块功能体系
|
|
|
+
|
|
|
+### 2.1 管理员后台总览看板 (`/admin/dashboard`)
|
|
|
+
|
|
|
+#### 2.1.1 核心统计数据
|
|
|
+
|
|
|
+**6大核心指标**:
|
|
|
+
|
|
|
+| 指标名称 | 数据来源 | 计算逻辑 | 点击操作 |
|
|
|
+|---------|---------|---------|---------|
|
|
|
+| **总项目数** | `Project` 表 | `count()` 所有项目 | 展开项目明细面板 |
|
|
|
+| **进行中项目** | `Project` 表 | 根据 `currentStage` 自动判断状态为"进行中" | 展开进行中项目明细 |
|
|
|
+| **已完成项目** | `Project` 表 | `currentStage` 为售后归档阶段自动标记为已完成 | 展开已完成项目明细 |
|
|
|
+| **设计师总数** | `Profile` 表 | `roleName = '组员'` 的员工数 | 展开设计师明细 |
|
|
|
+| **客户总数** | `ContactInfo` 表 | `count()` 所有客户 | 展开客户明细 |
|
|
|
+| **总收入** | `Project.data` | 从售后归档项目中累加已支付尾款 | 展开收入明细 |
|
|
|
+
|
|
|
+**状态自动判断逻辑**:
|
|
|
+```typescript
|
|
|
+function getProjectStatusByStage(stageId: string, currentStatus?: string): string {
|
|
|
+ // 如果已经是完成或取消状态,保持不变
|
|
|
+ if (currentStatus === '已完成' || currentStatus === '已取消') {
|
|
|
+ return currentStatus;
|
|
|
+ }
|
|
|
+
|
|
|
+ const corePhase = mapStageToCorePhase(stageId);
|
|
|
+
|
|
|
+ switch (corePhase) {
|
|
|
+ case 'order':
|
|
|
+ return '待分配';
|
|
|
+ case 'requirements':
|
|
|
+ case 'delivery':
|
|
|
+ return '进行中';
|
|
|
+ case 'aftercare':
|
|
|
+ return '已完成'; // 售后归档自动标记为已完成
|
|
|
+ default:
|
|
|
+ return '待分配';
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.1.2 数据可视化图表
|
|
|
+
|
|
|
+**1. 项目趋势图**(ECharts折线图)
|
|
|
+- X轴:月份
|
|
|
+- Y轴:项目数量
|
|
|
+- 数据:每月新增项目数
|
|
|
+
|
|
|
+**2. 收入趋势图**(ECharts柱状图)
|
|
|
+- X轴:月份
|
|
|
+- Y轴:收入金额
|
|
|
+- 数据:每月收入统计
|
|
|
+
|
|
|
+#### 2.1.3 明细面板
|
|
|
+
|
|
|
+**点击统计卡片后展开侧边抽屉**,显示详细数据:
|
|
|
+
|
|
|
+**项目明细**:
|
|
|
+- 项目列表(表格)
|
|
|
+- 筛选:关键词、状态、日期范围
|
|
|
+- 排序:创建时间、更新时间
|
|
|
+- 分页:每页10条
|
|
|
+
|
|
|
+**设计师明细**:
|
|
|
+- 设计师列表
|
|
|
+- 显示:姓名、职级、完成项目数、进行中项目数、平均周期
|
|
|
+- 筛选:关键词、职级
|
|
|
+
|
|
|
+**客户明细**:
|
|
|
+- 客户列表
|
|
|
+- 显示:姓名、手机号、来源、创建时间
|
|
|
+- 筛选:关键词、来源
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.2 项目管理 (`/admin/project-management`)
|
|
|
+
|
|
|
+#### 2.2.1 项目列表展示
|
|
|
+
|
|
|
+**数据查询**:
|
|
|
+```typescript
|
|
|
+// 查询逻辑
|
|
|
+const projects = await ProjectService.findProjects({
|
|
|
+ status: statusFilter, // 状态筛选
|
|
|
+ keyword: searchTerm, // 关键词搜索
|
|
|
+ skip: currentPage * pageSize,
|
|
|
+ limit: pageSize
|
|
|
+});
|
|
|
+
|
|
|
+// Include关联数据
|
|
|
+include: ['contact', 'customer', 'assignee', 'department', 'department.leader']
|
|
|
+```
|
|
|
+
|
|
|
+**显示字段**:
|
|
|
+- 项目名称
|
|
|
+- 客户姓名
|
|
|
+- 负责人(优先从 `assignee`,其次从 `ProjectTeam` 表获取)
|
|
|
+- 当前阶段(规范化为四大核心阶段)
|
|
|
+- 状态(自动判断)
|
|
|
+- 创建时间
|
|
|
+- 更新时间
|
|
|
+
|
|
|
+#### 2.2.2 项目详情预览
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 右键点击项目行
|
|
|
+2. 选择"预览详情"
|
|
|
+3. 弹出详情面板
|
|
|
+
|
|
|
+**显示内容**:
|
|
|
+- 基本信息:项目名称、客户、负责人、状态、阶段
|
|
|
+- 时间信息:创建时间、更新时间、截止时间
|
|
|
+- 团队信息:项目组、团队成员
|
|
|
+- 进度信息:当前进度、完成情况
|
|
|
+
|
|
|
+#### 2.2.3 分配设计师
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击项目行的"分配设计师"按钮
|
|
|
+2. 弹出设计师分配弹窗
|
|
|
+3. 选择主要负责人和协作成员
|
|
|
+4. 保存分配
|
|
|
+
|
|
|
+**分配逻辑**:
|
|
|
+```typescript
|
|
|
+// 更新 Project.assignee(主要负责人)
|
|
|
+project.set('assignee', {
|
|
|
+ __type: 'Pointer',
|
|
|
+ className: 'Profile',
|
|
|
+ objectId: mainDesignerId
|
|
|
+});
|
|
|
+
|
|
|
+// 保存所有分配的设计师到 Project.data
|
|
|
+project.set('data', {
|
|
|
+ ...data,
|
|
|
+ assignedDesigners: [designerId1, designerId2, ...],
|
|
|
+ crossTeamCollaborators: [...],
|
|
|
+ primaryTeamId: teamId
|
|
|
+});
|
|
|
+
|
|
|
+// 创建 ProjectTeam 记录
|
|
|
+const projectTeam = new ProjectTeam();
|
|
|
+projectTeam.set('project', project.toPointer());
|
|
|
+projectTeam.set('profile', designer.toPointer());
|
|
|
+projectTeam.set('role', 'primary' | 'collaborator');
|
|
|
+await projectTeam.save();
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.2.4 筛选和排序
|
|
|
+
|
|
|
+**筛选条件**:
|
|
|
+- 状态:全部/待分配/进行中/已完成
|
|
|
+- 关键词:项目名称模糊搜索
|
|
|
+
|
|
|
+**排序字段**:
|
|
|
+- 创建时间
|
|
|
+- 更新时间
|
|
|
+- 项目名称
|
|
|
+
|
|
|
+**分页**:每页10条
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.3 项目组管理 (`/admin/departments`)
|
|
|
+
|
|
|
+#### 2.3.1 项目组列表
|
|
|
+
|
|
|
+**数据来源**:`Department` 表
|
|
|
+
|
|
|
+**数据结构**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ name: string; // 项目组名称
|
|
|
+ leader: Pointer; // 组长(Profile)
|
|
|
+ leaderName: string; // 组长姓名
|
|
|
+ type: 'project'; // 类型
|
|
|
+ memberCount: number; // 成员数量
|
|
|
+ createdAt: Date;
|
|
|
+ isDeleted: boolean;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**显示字段**:
|
|
|
+- 项目组名称
|
|
|
+- 组长姓名
|
|
|
+- 成员数量
|
|
|
+- 创建时间
|
|
|
+- 操作按钮
|
|
|
+
|
|
|
+#### 2.3.2 新建项目组
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"新建项目组"按钮
|
|
|
+2. 填写项目组名称
|
|
|
+3. 选择组长(从员工列表选择,`roleName = '组长'`)
|
|
|
+4. 保存
|
|
|
+
|
|
|
+**创建逻辑**:
|
|
|
+```typescript
|
|
|
+const dept = await DepartmentService.createDepartment({
|
|
|
+ name: '设计一组',
|
|
|
+ leaderId: 'profileId',
|
|
|
+ type: 'project'
|
|
|
+});
|
|
|
+
|
|
|
+// 同时更新组长的 department 字段
|
|
|
+const profile = await Parse.Query('Profile').get(leaderId);
|
|
|
+profile.set('department', dept.toPointer());
|
|
|
+await profile.save();
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.3.3 编辑项目组
|
|
|
+
|
|
|
+**可编辑字段**:
|
|
|
+- 项目组名称
|
|
|
+- 组长
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"编辑"按钮
|
|
|
+2. 修改信息
|
|
|
+3. 保存
|
|
|
+
|
|
|
+#### 2.3.4 删除项目组
|
|
|
+
|
|
|
+**删除方式**:软删除(设置 `isDeleted = true`)
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"删除"按钮
|
|
|
+2. 确认删除
|
|
|
+3. 执行软删除
|
|
|
+
|
|
|
+**注意事项**:
|
|
|
+- 删除前检查是否有关联项目
|
|
|
+- 如有关联项目,提示先解除关联
|
|
|
+
|
|
|
+#### 2.3.5 查看成员
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击项目组行
|
|
|
+2. 展开成员列表
|
|
|
+
|
|
|
+**显示内容**:
|
|
|
+- 成员姓名
|
|
|
+- 角色(组长/组员)
|
|
|
+- 手机号
|
|
|
+- 状态
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.4 员工管理 (`/admin/employees`)
|
|
|
+
|
|
|
+#### 2.4.1 员工列表
|
|
|
+
|
|
|
+**数据来源**:`Profile` 表(从企微同步)
|
|
|
+
|
|
|
+**数据结构**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ name: string; // 昵称(内部沟通用)
|
|
|
+ realname: string; // 真实姓名
|
|
|
+ mobile: string; // 手机号
|
|
|
+ userid: string; // 企微ID
|
|
|
+ roleName: string; // 身份(组长/组员/客服/管理员)
|
|
|
+ department: Pointer; // 所属部门
|
|
|
+ departmentName: string; // 部门名称
|
|
|
+ isDisabled: boolean; // 是否禁用
|
|
|
+ avatar: string; // 头像
|
|
|
+ email: string; // 邮箱
|
|
|
+ position: string; // 职位
|
|
|
+ gender: string; // 性别
|
|
|
+ level: string; // 职级
|
|
|
+ skills: string[]; // 技能标签
|
|
|
+ joinDate: Date; // 入职日期
|
|
|
+ createdAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**显示字段**:
|
|
|
+- 姓名(真实姓名 + 昵称)
|
|
|
+- 手机号
|
|
|
+- 企微ID
|
|
|
+- 身份
|
|
|
+- 部门
|
|
|
+- 状态(正常/已禁用)
|
|
|
+
|
|
|
+#### 2.4.2 查看详情
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"查看"按钮
|
|
|
+2. 打开员工信息侧边栏
|
|
|
+
|
|
|
+**侧边栏包含两个标签页**:
|
|
|
+
|
|
|
+**1. 基本信息标签页**:
|
|
|
+- 员工头像、姓名、职位
|
|
|
+- 联系方式(手机、邮箱、企微ID)
|
|
|
+- 组织信息(身份、部门、职级)
|
|
|
+- 技能标签
|
|
|
+- 工作量统计(当前项目数、已完成项目数、平均质量)
|
|
|
+
|
|
|
+**2. 项目负载标签页**:
|
|
|
+- 负载概况(当前项目数、核心项目列表)
|
|
|
+- 负载详细日历(月视图、项目数量可视化)
|
|
|
+- 请假明细(未来7天)
|
|
|
+- 红色标记说明
|
|
|
+- 能力问卷展示
|
|
|
+- 详细工作日历
|
|
|
+
|
|
|
+#### 2.4.3 任务安排
|
|
|
+
|
|
|
+**查看员工任务**:
|
|
|
+- 当前负责的项目列表
|
|
|
+- 项目名称、阶段、截止时间、优先级
|
|
|
+- 任务状态(进行中/已完成/逾期)
|
|
|
+
|
|
|
+**数据来源**:
|
|
|
+```typescript
|
|
|
+// 查询员工负责的项目
|
|
|
+const projects = await Parse.Query('Project')
|
|
|
+ .equalTo('assignee', employeeId)
|
|
|
+ .equalTo('status', '进行中')
|
|
|
+ .find();
|
|
|
+
|
|
|
+// 或从 ProjectTeam 表查询
|
|
|
+const teams = await Parse.Query('ProjectTeam')
|
|
|
+ .equalTo('profile', employeeId)
|
|
|
+ .include('project')
|
|
|
+ .find();
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.4.4 编辑信息
|
|
|
+
|
|
|
+**可编辑字段**:
|
|
|
+- 昵称(name)
|
|
|
+- 真实姓名(realname)
|
|
|
+- 手机号(mobile)
|
|
|
+- 身份(roleName)
|
|
|
+- 部门(department)
|
|
|
+- 状态(isDisabled)
|
|
|
+
|
|
|
+**不可编辑字段**:
|
|
|
+- 企微ID(userid)- 只读显示
|
|
|
+- 创建时间
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"编辑"按钮
|
|
|
+2. 修改可编辑字段
|
|
|
+3. 保存
|
|
|
+
|
|
|
+**保存逻辑**:
|
|
|
+```typescript
|
|
|
+await EmployeeService.updateEmployee(employeeId, {
|
|
|
+ name: formData.name,
|
|
|
+ mobile: formData.mobile,
|
|
|
+ roleName: formData.roleName,
|
|
|
+ departmentId: formData.departmentId,
|
|
|
+ isDisabled: formData.isDisabled,
|
|
|
+ data: {
|
|
|
+ realname: formData.realname
|
|
|
+ }
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.4.5 禁用/启用员工
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"禁用"或"启用"按钮
|
|
|
+2. 确认操作
|
|
|
+3. 更新 `isDisabled` 字段
|
|
|
+
|
|
|
+**影响**:
|
|
|
+- 禁用后员工无法登录系统
|
|
|
+- 已分配的项目不受影响
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.5 客户管理 (`/admin/customers`)
|
|
|
+
|
|
|
+#### 2.5.1 客户列表
|
|
|
+
|
|
|
+**数据来源**:`ContactInfo` 表
|
|
|
+
|
|
|
+**数据结构**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ name: string; // 客户姓名
|
|
|
+ mobile: string; // 手机号
|
|
|
+ external_userid: string; // 企微外部联系人ID
|
|
|
+ source: string; // 来源(企微/电话/网站等)
|
|
|
+ type: string; // 类型(企业成员/外部联系人)
|
|
|
+ avatar: string; // 头像
|
|
|
+ createdAt: Date;
|
|
|
+ data: {
|
|
|
+ avatar: string;
|
|
|
+ name: string;
|
|
|
+ // 其他扩展字段
|
|
|
+ };
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**显示字段**:
|
|
|
+- 客户名称
|
|
|
+- 手机号
|
|
|
+- 企微ID
|
|
|
+- 类型
|
|
|
+- 来源
|
|
|
+- 创建时间
|
|
|
+
|
|
|
+#### 2.5.2 查看客户详情
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击客户行
|
|
|
+2. 打开客户详情面板
|
|
|
+
|
|
|
+**详情面板包含**:
|
|
|
+
|
|
|
+**1. 基本信息卡片**:
|
|
|
+- 客户头像
|
|
|
+- 姓名
|
|
|
+- 手机号
|
|
|
+- 企微ID
|
|
|
+- 客户类型
|
|
|
+- 来源
|
|
|
+
|
|
|
+**2. 关联项目**:
|
|
|
+- 项目列表(该客户的所有项目)
|
|
|
+- 项目名称、状态、阶段、更新时间
|
|
|
+- 点击可跳转到项目详情
|
|
|
+
|
|
|
+**3. 所在群聊**:
|
|
|
+- 客户所在的企微群聊列表
|
|
|
+- 群聊名称、关联项目、成员数
|
|
|
+- 点击可跳转到群聊详情
|
|
|
+
|
|
|
+**4. 跟进记录**:
|
|
|
+- 活动日志(`ActivityLog` 表)
|
|
|
+- 操作人、操作类型、操作时间、备注
|
|
|
+- 按时间倒序排列
|
|
|
+
|
|
|
+**数据查询逻辑**:
|
|
|
+```typescript
|
|
|
+// 查询客户项目
|
|
|
+const projects = await Parse.Query('Project')
|
|
|
+ .equalTo('contact', customerId)
|
|
|
+ .include('assignee')
|
|
|
+ .find();
|
|
|
+
|
|
|
+// 查询客户群聊
|
|
|
+const groupContacts = await Parse.Query('GroupChatContact')
|
|
|
+ .equalTo('userid', customer.get('external_userid'))
|
|
|
+ .include('groupChat')
|
|
|
+ .include('groupChat.project')
|
|
|
+ .find();
|
|
|
+
|
|
|
+// 查询跟进记录
|
|
|
+const followUps = await Parse.Query('ActivityLog')
|
|
|
+ .equalTo('entityId', customerId)
|
|
|
+ .equalTo('module', 'customer')
|
|
|
+ .include('actor')
|
|
|
+ .descending('createdAt')
|
|
|
+ .find();
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.6 群组管理 (`/admin/groupchats`)
|
|
|
+
|
|
|
+#### 2.6.1 群组列表
|
|
|
+
|
|
|
+**数据来源**:`GroupChat` 表
|
|
|
+
|
|
|
+**数据结构**:
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ id: string;
|
|
|
+ chat_id: string; // 企微群ID
|
|
|
+ name: string; // 群名称
|
|
|
+ project: Pointer; // 关联项目
|
|
|
+ memberCount: number; // 成员数量
|
|
|
+ isDisabled: boolean; // 是否禁用
|
|
|
+ member_list: Array<{ // 成员列表
|
|
|
+ userid: string;
|
|
|
+ type: number; // 1=企业成员, 2=外部联系人
|
|
|
+ join_time: number;
|
|
|
+ }>;
|
|
|
+ createdAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**显示字段**:
|
|
|
+- 群名称
|
|
|
+- 企微群ID
|
|
|
+- 关联项目
|
|
|
+- 成员数
|
|
|
+- 状态
|
|
|
+- 操作按钮
|
|
|
+
|
|
|
+#### 2.6.2 统计企微群聊
|
|
|
+
|
|
|
+**统计维度**:
|
|
|
+- 总群聊数
|
|
|
+- 已关联项目的群聊数
|
|
|
+- 未关联项目的群聊数
|
|
|
+- 平均成员数
|
|
|
+
|
|
|
+**筛选条件**:
|
|
|
+- 关键词搜索(群名称)
|
|
|
+- 是否关联项目
|
|
|
+
|
|
|
+#### 2.6.3 关联项目
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击未关联项目的群聊
|
|
|
+2. 选择"关联项目"或"创建项目"
|
|
|
+
|
|
|
+**关联现有项目**:
|
|
|
+```typescript
|
|
|
+const groupChat = await Parse.Query('GroupChat').get(groupChatId);
|
|
|
+groupChat.set('project', project.toPointer());
|
|
|
+await groupChat.save();
|
|
|
+
|
|
|
+// 创建 ProjectGroup 关联(支持多项目多群)
|
|
|
+const projectGroup = new ProjectGroup();
|
|
|
+projectGroup.set('project', project.toPointer());
|
|
|
+projectGroup.set('groupChat', groupChat.toPointer());
|
|
|
+projectGroup.set('isPrimary', true);
|
|
|
+await projectGroup.save();
|
|
|
+```
|
|
|
+
|
|
|
+**创建新项目**:
|
|
|
+```typescript
|
|
|
+// 1. 创建项目
|
|
|
+const project = new Project();
|
|
|
+project.set('title', projectName);
|
|
|
+project.set('company', company.toPointer());
|
|
|
+project.set('status', '待分配');
|
|
|
+project.set('currentStage', '订单分配');
|
|
|
+project.set('data', {
|
|
|
+ createdBy: 'admin',
|
|
|
+ createdFrom: 'admin_groupchat',
|
|
|
+ groupChatId: groupChatId
|
|
|
+});
|
|
|
+await project.save();
|
|
|
+
|
|
|
+// 2. 关联群聊
|
|
|
+groupChat.set('project', project.toPointer());
|
|
|
+await groupChat.save();
|
|
|
+
|
|
|
+// 3. 创建 ProjectGroup
|
|
|
+const projectGroup = new ProjectGroup();
|
|
|
+projectGroup.set('project', project.toPointer());
|
|
|
+projectGroup.set('groupChat', groupChat.toPointer());
|
|
|
+projectGroup.set('isPrimary', true);
|
|
|
+await projectGroup.save();
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.6.4 查看群聊详情
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击群聊行
|
|
|
+2. 打开群聊详情面板
|
|
|
+
|
|
|
+**详情内容**:
|
|
|
+- 群名称
|
|
|
+- 企微群ID
|
|
|
+- 成员列表(姓名、类型、加入时间)
|
|
|
+- 关联项目信息
|
|
|
+- 入群二维码(如有)
|
|
|
+
|
|
|
+**数据来源**:
|
|
|
+```typescript
|
|
|
+// 从企微API获取群聊详情
|
|
|
+const chatInfo = await WxworkCorp.externalContact.groupChat.get(chat_id);
|
|
|
+```
|
|
|
+
|
|
|
+#### 2.6.5 修改群聊信息
|
|
|
+
|
|
|
+**可修改字段**:
|
|
|
+- 关联项目
|
|
|
+- 是否禁用
|
|
|
+
|
|
|
+**操作路径**:
|
|
|
+1. 点击"编辑"按钮
|
|
|
+2. 修改信息
|
|
|
+3. 保存
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、数据字段汇总
|
|
|
+
|
|
|
+### 3.1 核心数据表
|
|
|
+
|
|
|
+#### Project(项目表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ title: string; // 项目名称
|
|
|
+ company: Pointer<Company>;
|
|
|
+ contact: Pointer<ContactInfo>; // 客户
|
|
|
+ assignee: Pointer<Profile>; // 负责人
|
|
|
+ department: Pointer<Department>; // 项目组
|
|
|
+ status: string; // 状态(待分配/进行中/已完成/已取消)
|
|
|
+ currentStage: string; // 当前阶段
|
|
|
+ deadline: Date; // 截止时间
|
|
|
+ createdAt: Date;
|
|
|
+ updatedAt: Date;
|
|
|
+ isDeleted: boolean;
|
|
|
+ data: {
|
|
|
+ // 订单分配阶段
|
|
|
+ orderApproval: object; // 订单审批信息
|
|
|
+ quotation: object; // 报价信息
|
|
|
+
|
|
|
+ // 需求确认阶段
|
|
|
+ requirements: object; // 需求信息
|
|
|
+ aiAnalysis: object; // AI分析结果
|
|
|
+
|
|
|
+ // 交付执行阶段
|
|
|
+ deliveryApproval: object; // 交付审批信息
|
|
|
+ deliveryStageStatus: object; // 各阶段状态
|
|
|
+ spaceConfirmations: object; // 空间确认记录
|
|
|
+
|
|
|
+ // 售后归档阶段
|
|
|
+ payments: array; // 支付记录
|
|
|
+ totalAmount: number; // 总金额
|
|
|
+ paidAmount: number; // 已付金额
|
|
|
+
|
|
|
+ // 其他
|
|
|
+ assignedDesigners: string[]; // 分配的设计师
|
|
|
+ crossTeamCollaborators: string[]; // 跨组协作者
|
|
|
+ primaryTeamId: string; // 主要团队ID
|
|
|
+ };
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### Profile(员工表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ name: string; // 昵称
|
|
|
+ mobile: string;
|
|
|
+ userid: string; // 企微ID
|
|
|
+ roleName: string; // 身份
|
|
|
+ department: Pointer<Department>;
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDeleted: boolean;
|
|
|
+ createdAt: Date;
|
|
|
+ data: {
|
|
|
+ realname: string; // 真实姓名
|
|
|
+ avatar: string;
|
|
|
+ email: string;
|
|
|
+ position: string;
|
|
|
+ gender: string;
|
|
|
+ level: string;
|
|
|
+ skills: string[];
|
|
|
+ };
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### ContactInfo(客户表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ name: string;
|
|
|
+ mobile: string;
|
|
|
+ external_userid: string; // 企微外部联系人ID
|
|
|
+ source: string; // 来源
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDeleted: boolean;
|
|
|
+ createdAt: Date;
|
|
|
+ data: {
|
|
|
+ avatar: string;
|
|
|
+ name: string;
|
|
|
+ type: string;
|
|
|
+ };
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### Department(部门/项目组表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ name: string;
|
|
|
+ leader: Pointer<Profile>;
|
|
|
+ type: string; // 'project'
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDeleted: boolean;
|
|
|
+ createdAt: Date;
|
|
|
+ data: object;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### GroupChat(群聊表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ chat_id: string; // 企微群ID
|
|
|
+ name: string;
|
|
|
+ project: Pointer<Project>;
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDisabled: boolean;
|
|
|
+ member_list: array;
|
|
|
+ createdAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### Case(案例表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ name: string;
|
|
|
+ projectId: string;
|
|
|
+ projectName: string;
|
|
|
+ designer: string;
|
|
|
+ designerId: string;
|
|
|
+ team: string;
|
|
|
+ teamId: string;
|
|
|
+ coverImage: string;
|
|
|
+ images: string[];
|
|
|
+ area: number;
|
|
|
+ projectType: string;
|
|
|
+ spaceType: string;
|
|
|
+ renderingLevel: string;
|
|
|
+ tag: string[];
|
|
|
+ totalPrice: number;
|
|
|
+ completionDate: Date;
|
|
|
+ viewCount: number;
|
|
|
+ shareCount: number;
|
|
|
+ favoriteCount: number;
|
|
|
+ isExcellent: boolean;
|
|
|
+ isPublished: boolean;
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDeleted: boolean;
|
|
|
+ createdAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### ProjectIssue(项目问题表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ title: string;
|
|
|
+ description: string;
|
|
|
+ status: string; // 待处理/处理中/已解决/已关闭
|
|
|
+ priority: string; // 紧急/高/中/低
|
|
|
+ project: Pointer<Project>;
|
|
|
+ creator: Pointer<Profile>;
|
|
|
+ assignee: Pointer<Profile>;
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDeleted: boolean;
|
|
|
+ createdAt: Date;
|
|
|
+ updatedAt: Date;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### ProjectFile(项目文件表)
|
|
|
+```typescript
|
|
|
+{
|
|
|
+ objectId: string;
|
|
|
+ fileName: string;
|
|
|
+ fileUrl: string;
|
|
|
+ fileSize: number;
|
|
|
+ fileType: string;
|
|
|
+ category: string;
|
|
|
+ project: Pointer<Project>;
|
|
|
+ product: Pointer<Product>; // 空间
|
|
|
+ stage: string; // 阶段
|
|
|
+ uploadedBy: Pointer<Profile>;
|
|
|
+ uploadedAt: Date;
|
|
|
+ analysisResult: object; // AI分析结果
|
|
|
+ approvalStatus: string; // 审批状态
|
|
|
+ company: Pointer<Company>;
|
|
|
+ isDeleted: boolean;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、操作路径总结
|
|
|
+
|
|
|
+### 4.1 客服操作路径
|
|
|
+
|
|
|
+```
|
|
|
+客服工作台首页
|
|
|
+├── 查看项目总数 → 跳转项目列表(全部)
|
|
|
+├── 查看待分配项目 → 跳转项目列表(筛选待分配)
|
|
|
+├── 待跟进尾款项目
|
|
|
+│ └── 点击"开始跟进" → 跳转项目详情(售后归档阶段)
|
|
|
+├── 紧急事件
|
|
|
+│ └── 点击事件卡片 → 跳转对应项目阶段
|
|
|
+└── 待办任务
|
|
|
+ ├── 查看详情 → 展开问题详情
|
|
|
+ ├── 添加评论 → 在问题下评论
|
|
|
+ ├── 催办 → 发送催办通知
|
|
|
+ └── 新建问题 → 创建项目问题
|
|
|
+
|
|
|
+案例库
|
|
|
+├── 浏览案例 → 查看案例详情
|
|
|
+├── 点击数据统计 → 展开统计面板
|
|
|
+│ ├── Top 5 分享案例
|
|
|
+│ ├── 客户最喜欢风格
|
|
|
+│ └── 设计师推荐率
|
|
|
+└── 筛选搜索 → 按条件筛选案例
|
|
|
+
|
|
|
+项目列表
|
|
|
+├── 切换视图模式
|
|
|
+│ ├── 卡片视图(看板)
|
|
|
+│ ├── 列表视图
|
|
|
+│ └── 监控大盘
|
|
|
+├── 点击项目卡片 → 跳转项目详情
|
|
|
+└── 筛选排序 → 按条件筛选项目
|
|
|
+
|
|
|
+需求确认阶段
|
|
|
+├── 拖拽参考图片 → AI自动分析归类
|
|
|
+├── 填写需求信息
|
|
|
+│ ├── 全局需求
|
|
|
+│ └── 空间需求
|
|
|
+├── 点击AI生成方案 → 生成设计方案
|
|
|
+├── 展开设计助手 → AI聊天助手
|
|
|
+└── 确认需求 → 进入下一阶段
|
|
|
+
|
|
|
+交付执行阶段
|
|
|
+├── 拖拽交付图片 → 弹出AI分析弹窗
|
|
|
+├── AI自动识别阶段 → 显示分析结果
|
|
|
+├── 确认交付清单 → 文件归类到各阶段
|
|
|
+└── 上传交付清单 → 提交审批
|
|
|
+
|
|
|
+售后归档阶段
|
|
|
+├── 上传支付凭证 → AI提取金额
|
|
|
+├── 预览支付凭证 → 放大查看
|
|
|
+└── 查看尾款详情 → 显示支付记录
|
|
|
+```
|
|
|
+
|
|
|
+### 4.2 管理员操作路径
|
|
|
+
|
|
|
+```
|
|
|
+管理员后台总览
|
|
|
+├── 点击统计卡片 → 展开明细面板
|
|
|
+│ ├── 总项目数 → 项目明细
|
|
|
+│ ├── 进行中项目 → 进行中项目明细
|
|
|
+│ ├── 已完成项目 → 已完成项目明细
|
|
|
+│ ├── 设计师总数 → 设计师明细
|
|
|
+│ ├── 客户总数 → 客户明细
|
|
|
+│ └── 总收入 → 收入明细
|
|
|
+└── 查看图表 → 项目趋势图、收入趋势图
|
|
|
+
|
|
|
+项目管理
|
|
|
+├── 查看项目列表 → 表格展示
|
|
|
+├── 右键预览详情 → 弹出详情面板
|
|
|
+├── 分配设计师 → 打开分配弹窗
|
|
|
+│ ├── 选择主要负责人
|
|
|
+│ ├── 选择协作成员
|
|
|
+│ └── 保存分配
|
|
|
+├── 筛选排序 → 按条件筛选
|
|
|
+└── 跳转项目详情 → 查看完整信息
|
|
|
+
|
|
|
+项目组管理
|
|
|
+├── 查看项目组列表
|
|
|
+├── 新建项目组
|
|
|
+│ ├── 填写名称
|
|
|
+│ ├── 选择组长
|
|
|
+│ └── 保存
|
|
|
+├── 编辑项目组
|
|
|
+│ ├── 修改名称
|
|
|
+│ ├── 更换组长
|
|
|
+│ └── 保存
|
|
|
+├── 删除项目组 → 软删除
|
|
|
+└── 查看成员 → 展开成员列表
|
|
|
+
|
|
|
+员工管理
|
|
|
+├── 查看员工列表
|
|
|
+├── 查看详情 → 打开员工信息侧边栏
|
|
|
+│ ├── 基本信息标签页
|
|
|
+│ └── 项目负载标签页
|
|
|
+├── 查看任务安排 → 显示负责的项目
|
|
|
+├── 编辑信息
|
|
|
+│ ├── 修改可编辑字段
|
|
|
+│ └── 保存
|
|
|
+└── 禁用/启用员工 → 更新状态
|
|
|
+
|
|
|
+客户管理
|
|
|
+├── 查看客户列表
|
|
|
+├── 点击客户 → 打开详情面板
|
|
|
+│ ├── 基本信息
|
|
|
+│ ├── 关联项目
|
|
|
+│ ├── 所在群聊
|
|
|
+│ └── 跟进记录
|
|
|
+└── 筛选搜索 → 按条件筛选
|
|
|
+
|
|
|
+群组管理
|
|
|
+├── 查看群组列表
|
|
|
+├── 统计企微群聊 → 显示统计数据
|
|
|
+├── 关联项目
|
|
|
+│ ├── 关联现有项目
|
|
|
+│ └── 创建新项目
|
|
|
+├── 查看群聊详情 → 打开详情面板
|
|
|
+│ ├── 群信息
|
|
|
+│ ├── 成员列表
|
|
|
+│ └── 关联项目
|
|
|
+└── 修改群聊信息 → 编辑保存
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、可计算分析的数据指标
|
|
|
+
|
|
|
+### 5.1 项目维度
|
|
|
+
|
|
|
+**项目统计**:
|
|
|
+- 总项目数
|
|
|
+- 各阶段项目数(订单分配/确认需求/交付执行/售后归档)
|
|
|
+- 各状态项目数(待分配/进行中/已完成/已取消)
|
|
|
+- 平均项目周期
|
|
|
+- 项目完成率 = 已完成项目数 / 总项目数
|
|
|
+- 项目逾期率 = 逾期项目数 / 总项目数
|
|
|
+
|
|
|
+**时间分析**:
|
|
|
+- 每月新增项目数
|
|
|
+- 每月完成项目数
|
|
|
+- 各阶段平均停留时间
|
|
|
+- 项目平均周期趋势
|
|
|
+
|
|
|
+**客户分析**:
|
|
|
+- 客户项目数分布
|
|
|
+- 客户复购率
|
|
|
+- 客户满意度(从反馈表)
|
|
|
+
|
|
|
+### 5.2 设计师维度
|
|
|
+
|
|
|
+**工作量统计**:
|
|
|
+- 当前负责项目数
|
|
|
+- 已完成项目数
|
|
|
+- 平均项目周期
|
|
|
+- 负载率 = 当前项目数 / 标准负载
|
|
|
+
|
|
|
+**绩效分析**:
|
|
|
+- 项目完成率
|
|
|
+- 项目逾期率
|
|
|
+- 客户满意度
|
|
|
+- 优秀案例数
|
|
|
+- 推荐率 = 优秀案例数 / 总案例数
|
|
|
+
|
|
|
+**能力评估**:
|
|
|
+- 擅长风格(从案例标签统计)
|
|
|
+- 擅长空间类型
|
|
|
+- 平均项目金额
|
|
|
+
|
|
|
+### 5.3 案例维度
|
|
|
+
|
|
|
+**案例统计**:
|
|
|
+- 总案例数
|
|
|
+- 各风格案例数
|
|
|
+- 各空间类型案例数
|
|
|
+- 各渲染级别案例数
|
|
|
+- 平均浏览量
|
|
|
+- 平均分享量
|
|
|
+- 平均收藏量
|
|
|
+
|
|
|
+**热门分析**:
|
|
|
+- Top 5 分享案例
|
|
|
+- Top 5 收藏案例
|
|
|
+- 最受欢迎风格(按收藏数)
|
|
|
+- 最受欢迎空间类型
|
|
|
+
|
|
|
+**设计师分析**:
|
|
|
+- 各设计师案例数
|
|
|
+- 各设计师推荐率
|
|
|
+- 各设计师平均浏览量
|
|
|
+
|
|
|
+### 5.4 财务维度
|
|
|
+
|
|
|
+**收入统计**:
|
|
|
+- 总收入(已支付尾款累加)
|
|
|
+- 每月收入
|
|
|
+- 平均项目金额
|
|
|
+- 收入增长率
|
|
|
+
|
|
|
+**回款分析**:
|
|
|
+- 总应收金额
|
|
|
+- 已收金额
|
|
|
+- 未收金额
|
|
|
+- 回款率 = 已收金额 / 总应收金额
|
|
|
+- 逾期未收金额
|
|
|
+
|
|
|
+**项目金额分布**:
|
|
|
+- 各金额区间项目数
|
|
|
+- 平均项目金额趋势
|
|
|
+
|
|
|
+### 5.5 问题维度
|
|
|
+
|
|
|
+**问题统计**:
|
|
|
+- 总问题数
|
|
|
+- 各状态问题数(待处理/处理中/已解决/已关闭)
|
|
|
+- 各优先级问题数
|
|
|
+- 平均解决时间
|
|
|
+- 问题解决率
|
|
|
+
|
|
|
+**问题分析**:
|
|
|
+- 各阶段问题数分布
|
|
|
+- 各类型问题数分布
|
|
|
+- 问题高发项目
|
|
|
+- 问题高发设计师
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、总结
|
|
|
+
|
|
|
+本文档详细梳理了客服板块和管理员板块的所有功能模块、操作流程、数据字段和计算逻辑。主要特点:
|
|
|
+
|
|
|
+1. **客服板块**:以项目全生命周期管理为核心,提供工作台首页、案例库、项目列表、需求确认、交付执行、售后归档等完整功能
|
|
|
+2. **管理员板块**:以数据统计和资源管理为核心,提供总览看板、项目管理、项目组管理、员工管理、客户管理、群组管理等功能
|
|
|
+3. **数据驱动**:所有功能都基于Parse Server数据库,数据结构清晰,关联关系明确
|
|
|
+4. **AI赋能**:在需求确认和交付执行阶段集成AI分析功能,提升工作效率
|
|
|
+5. **角色权限**:不同角色有不同的操作权限和视图
|
|
|
+
|
|
|
+本文档可作为产品复盘、功能优化、培训教材的重要参考资料。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、角色权限矩阵
|
|
|
+
|
|
|
+### 7.1 功能权限对照表
|
|
|
+
|
|
|
+| 功能模块 | 客服 | 组长 | 设计师 | 管理员 |
|
|
|
+|---------|-----|------|--------|--------|
|
|
|
+| **工作台首页** | ✅ | ✅ | ✅ | ✅ |
|
|
|
+| **项目列表** | ✅ | ✅ | ✅ | ✅ |
|
|
|
+| **案例库** | ✅ | ✅ | ✅ | ✅ |
|
|
|
+| **订单分配** | ✅ | ✅审批 | ❌ | ✅ |
|
|
|
+| **需求确认** | ✅ | ✅ | ✅ | ✅ |
|
|
|
+| **交付执行** | ✅ | ✅审批 | ✅ | ✅ |
|
|
|
+| **售后归档** | ✅ | ✅ | ✅ | ✅ |
|
|
|
+| **项目管理** | ❌ | ❌ | ❌ | ✅ |
|
|
|
+| **项目组管理** | ❌ | ❌ | ❌ | ✅ |
|
|
|
+| **员工管理** | ❌ | ❌ | ❌ | ✅ |
|
|
|
+| **客户管理** | ❌ | ❌ | ❌ | ✅ |
|
|
|
+| **群组管理** | ❌ | ❌ | ❌ | ✅ |
|
|
|
+| **分配设计师** | ❌ | ✅ | ❌ | ✅ |
|
|
|
+| **审批订单** | ❌ | ✅ | ❌ | ✅ |
|
|
|
+| **审批交付** | ❌ | ✅ | ❌ | ✅ |
|
|
|
+
|
|
|
+### 7.2 数据权限
|
|
|
+
|
|
|
+**客服**:
|
|
|
+- 查看:所有项目
|
|
|
+- 编辑:自己创建的项目
|
|
|
+- 删除:❌
|
|
|
+
|
|
|
+**组长**:
|
|
|
+- 查看:所有项目
|
|
|
+- 编辑:所有项目
|
|
|
+- 删除:❌
|
|
|
+- 审批:订单分配、交付执行
|
|
|
+
|
|
|
+**设计师**:
|
|
|
+- 查看:自己负责的项目
|
|
|
+- 编辑:自己负责的项目
|
|
|
+- 删除:❌
|
|
|
+
|
|
|
+**管理员**:
|
|
|
+- 查看:所有数据
|
|
|
+- 编辑:所有数据
|
|
|
+- 删除:软删除所有数据
|
|
|
+- 审批:所有审批
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、业务流程图
|
|
|
+
|
|
|
+### 8.1 客服完整工作流程
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TD
|
|
|
+ A[客服登录系统] --> B[查看工作台首页]
|
|
|
+ B --> C{选择工作内容}
|
|
|
+
|
|
|
+ C -->|处理新咨询| D[创建新项目]
|
|
|
+ D --> E[填写客户信息]
|
|
|
+ E --> F[填写项目基本信息]
|
|
|
+ F --> G[提交订单分配]
|
|
|
+ G --> H[等待组长审批]
|
|
|
+
|
|
|
+ C -->|跟进尾款| I[查看待跟进尾款列表]
|
|
|
+ I --> J[点击开始跟进]
|
|
|
+ J --> K[进入售后归档阶段]
|
|
|
+ K --> L[查看尾款详情]
|
|
|
+ L --> M[联系客户催款]
|
|
|
+
|
|
|
+ C -->|处理紧急事件| N[查看紧急事件列表]
|
|
|
+ N --> O[点击紧急事件]
|
|
|
+ O --> P[进入对应项目阶段]
|
|
|
+ P --> Q[处理紧急事项]
|
|
|
+
|
|
|
+ C -->|处理待办任务| R[查看待办任务列表]
|
|
|
+ R --> S[点击任务详情]
|
|
|
+ S --> T{任务类型}
|
|
|
+ T -->|添加评论| U[输入评论内容]
|
|
|
+ T -->|催办| V[发送催办通知]
|
|
|
+ T -->|新建问题| W[创建项目问题]
|
|
|
+
|
|
|
+ H --> X{审批结果}
|
|
|
+ X -->|通过| Y[进入需求确认阶段]
|
|
|
+ X -->|驳回| Z[修改订单信息]
|
|
|
+ Z --> G
|
|
|
+
|
|
|
+ Y --> AA[填写需求信息]
|
|
|
+ AA --> AB[拖拽参考图片]
|
|
|
+ AB --> AC[AI自动分析]
|
|
|
+ AC --> AD[点击AI生成方案]
|
|
|
+ AD --> AE[确认需求]
|
|
|
+ AE --> AF[进入交付执行阶段]
|
|
|
+```
|
|
|
+
|
|
|
+### 8.2 管理员项目管理流程
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TD
|
|
|
+ A[管理员登录系统] --> B[查看总览看板]
|
|
|
+ B --> C[查看统计数据]
|
|
|
+ C --> D{选择管理内容}
|
|
|
+
|
|
|
+ D -->|项目管理| E[进入项目管理页面]
|
|
|
+ E --> F[查看项目列表]
|
|
|
+ F --> G{项目操作}
|
|
|
+ G -->|预览详情| H[打开详情面板]
|
|
|
+ G -->|分配设计师| I[打开分配弹窗]
|
|
|
+ I --> J[选择主要负责人]
|
|
|
+ J --> K[选择协作成员]
|
|
|
+ K --> L[保存分配]
|
|
|
+ L --> M[更新项目信息]
|
|
|
+
|
|
|
+ D -->|项目组管理| N[进入项目组管理]
|
|
|
+ N --> O{项目组操作}
|
|
|
+ O -->|新建| P[填写项目组信息]
|
|
|
+ P --> Q[选择组长]
|
|
|
+ Q --> R[保存项目组]
|
|
|
+ O -->|编辑| S[修改项目组信息]
|
|
|
+ S --> T[保存修改]
|
|
|
+ O -->|删除| U[确认删除]
|
|
|
+ U --> V[软删除项目组]
|
|
|
+
|
|
|
+ D -->|员工管理| W[进入员工管理]
|
|
|
+ W --> X{员工操作}
|
|
|
+ X -->|查看详情| Y[打开员工信息面板]
|
|
|
+ Y --> Z[查看基本信息]
|
|
|
+ Y --> AA[查看项目负载]
|
|
|
+ X -->|编辑信息| AB[修改员工信息]
|
|
|
+ AB --> AC[保存修改]
|
|
|
+ X -->|禁用/启用| AD[更新员工状态]
|
|
|
+
|
|
|
+ D -->|客户管理| AE[进入客户管理]
|
|
|
+ AE --> AF[查看客户列表]
|
|
|
+ AF --> AG[点击客户]
|
|
|
+ AG --> AH[查看客户详情]
|
|
|
+ AH --> AI[查看关联项目]
|
|
|
+ AH --> AJ[查看所在群聊]
|
|
|
+ AH --> AK[查看跟进记录]
|
|
|
+
|
|
|
+ D -->|群组管理| AL[进入群组管理]
|
|
|
+ AL --> AM[查看群组列表]
|
|
|
+ AM --> AN{群组操作}
|
|
|
+ AN -->|关联项目| AO[选择现有项目]
|
|
|
+ AN -->|创建项目| AP[填写项目信息]
|
|
|
+ AP --> AQ[保存新项目]
|
|
|
+ AQ --> AR[关联群聊]
|
|
|
+ AN -->|查看详情| AS[打开群聊详情]
|
|
|
+ AS --> AT[查看成员列表]
|
|
|
+```
|
|
|
+
|
|
|
+### 8.3 项目生命周期流程
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph LR
|
|
|
+ A[订单分配] --> B{组长审批}
|
|
|
+ B -->|通过| C[确认需求]
|
|
|
+ B -->|驳回| A
|
|
|
+
|
|
|
+ C --> D[填写需求]
|
|
|
+ D --> E[AI生成方案]
|
|
|
+ E --> F[确认需求]
|
|
|
+ F --> G[交付执行]
|
|
|
+
|
|
|
+ G --> H[白模阶段]
|
|
|
+ H --> I[软装阶段]
|
|
|
+ I --> J[渲染阶段]
|
|
|
+ J --> K[后期阶段]
|
|
|
+
|
|
|
+ K --> L[上传交付清单]
|
|
|
+ L --> M{组长审批}
|
|
|
+ M -->|通过| N[售后归档]
|
|
|
+ M -->|驳回| G
|
|
|
+
|
|
|
+ N --> O[上传支付凭证]
|
|
|
+ O --> P[确认尾款]
|
|
|
+ P --> Q[项目完成]
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 九、数据流转图
|
|
|
+
|
|
|
+### 9.1 项目数据流转
|
|
|
+
|
|
|
+```
|
|
|
+客服创建项目
|
|
|
+ ↓
|
|
|
+Project表(status: 待分配, currentStage: 订单分配)
|
|
|
+ ↓
|
|
|
+组长审批
|
|
|
+ ↓
|
|
|
+Project.data.orderApproval(status: approved)
|
|
|
+ ↓
|
|
|
+自动更新 Project(status: 进行中, currentStage: 确认需求)
|
|
|
+ ↓
|
|
|
+客服填写需求
|
|
|
+ ↓
|
|
|
+Project.data.requirements
|
|
|
+ ↓
|
|
|
+AI生成方案
|
|
|
+ ↓
|
|
|
+Project.data.aiAnalysis
|
|
|
+ ↓
|
|
|
+确认需求
|
|
|
+ ↓
|
|
|
+Project(currentStage: 交付执行)
|
|
|
+ ↓
|
|
|
+设计师上传文件
|
|
|
+ ↓
|
|
|
+ProjectFile表(stage: white_model/soft_decor/rendering/post_process)
|
|
|
+ ↓
|
|
|
+AI分析文件
|
|
|
+ ↓
|
|
|
+ProjectFile.analysisResult
|
|
|
+ ↓
|
|
|
+客服确认空间
|
|
|
+ ↓
|
|
|
+Project.data.spaceConfirmations
|
|
|
+ ↓
|
|
|
+上传交付清单
|
|
|
+ ↓
|
|
|
+Project.data.deliveryApproval(status: pending)
|
|
|
+ ↓
|
|
|
+组长审批
|
|
|
+ ↓
|
|
|
+Project.data.deliveryApproval(status: approved)
|
|
|
+ ↓
|
|
|
+自动更新 Project(currentStage: 售后归档)
|
|
|
+ ↓
|
|
|
+客服上传支付凭证
|
|
|
+ ↓
|
|
|
+Project.data.payments
|
|
|
+ ↓
|
|
|
+AI提取金额
|
|
|
+ ↓
|
|
|
+更新 Project.data.paidAmount
|
|
|
+ ↓
|
|
|
+确认尾款
|
|
|
+ ↓
|
|
|
+Project(status: 已完成)
|
|
|
+ ↓
|
|
|
+自动生成案例
|
|
|
+ ↓
|
|
|
+Case表(isPublished: false)
|
|
|
+```
|
|
|
+
|
|
|
+### 9.2 设计师分配数据流转
|
|
|
+
|
|
|
+```
|
|
|
+管理员/组长分配设计师
|
|
|
+ ↓
|
|
|
+选择主要负责人
|
|
|
+ ↓
|
|
|
+Project.assignee = Pointer<Profile>
|
|
|
+ ↓
|
|
|
+选择协作成员
|
|
|
+ ↓
|
|
|
+Project.data.assignedDesigners = [id1, id2, ...]
|
|
|
+ ↓
|
|
|
+创建 ProjectTeam 记录
|
|
|
+ ↓
|
|
|
+ProjectTeam(project, profile, role: primary/collaborator)
|
|
|
+ ↓
|
|
|
+设计师可见项目
|
|
|
+ ↓
|
|
|
+设计师工作台显示项目
|
|
|
+```
|
|
|
+
|
|
|
+### 9.3 群聊关联项目数据流转
|
|
|
+
|
|
|
+```
|
|
|
+管理员查看群组列表
|
|
|
+ ↓
|
|
|
+选择未关联项目的群聊
|
|
|
+ ↓
|
|
|
+创建新项目 或 关联现有项目
|
|
|
+ ↓
|
|
|
+Project表(新建或更新)
|
|
|
+ ↓
|
|
|
+GroupChat.project = Pointer<Project>
|
|
|
+ ↓
|
|
|
+创建 ProjectGroup 记录
|
|
|
+ ↓
|
|
|
+ProjectGroup(project, groupChat, isPrimary: true)
|
|
|
+ ↓
|
|
|
+群聊成员可见项目
|
|
|
+ ↓
|
|
|
+企微群聊中显示项目卡片
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十、关键技术实现
|
|
|
+
|
|
|
+### 10.1 AI图像分析
|
|
|
+
|
|
|
+**服务**:`ImageAnalysisService`
|
|
|
+
|
|
|
+**模型**:豆包1.6 (`fmode-1.6-cn`)
|
|
|
+
|
|
|
+**分析流程**:
|
|
|
+```typescript
|
|
|
+1. 接收图片文件
|
|
|
+2. 转换为Base64编码
|
|
|
+3. 调用豆包API
|
|
|
+4. 解析返回结果
|
|
|
+5. 提取关键信息:
|
|
|
+ - 图片质量(清晰度、亮度、对比度)
|
|
|
+ - 内容识别(类别、置信度、描述、标签)
|
|
|
+ - 技术参数(格式、色彩空间、DPI、分辨率)
|
|
|
+ - 阶段分类建议(white_model/soft_decor/rendering/post_process)
|
|
|
+6. 返回分析结果
|
|
|
+```
|
|
|
+
|
|
|
+**应用场景**:
|
|
|
+- 需求确认阶段:参考图片分类
|
|
|
+- 交付执行阶段:交付文件阶段识别
|
|
|
+- 售后归档阶段:支付凭证金额提取
|
|
|
+
|
|
|
+### 10.2 项目状态自动判断
|
|
|
+
|
|
|
+**核心函数**:`getProjectStatusByStage()`
|
|
|
+
|
|
|
+**判断逻辑**:
|
|
|
+```typescript
|
|
|
+function getProjectStatusByStage(stageId: string, currentStatus?: string): string {
|
|
|
+ // 如果已经是完成或取消状态,保持不变
|
|
|
+ if (currentStatus === '已完成' || currentStatus === '已取消') {
|
|
|
+ return currentStatus;
|
|
|
+ }
|
|
|
+
|
|
|
+ const corePhase = mapStageToCorePhase(stageId);
|
|
|
+
|
|
|
+ switch (corePhase) {
|
|
|
+ case 'order':
|
|
|
+ return '待分配';
|
|
|
+ case 'requirements':
|
|
|
+ case 'delivery':
|
|
|
+ return '进行中';
|
|
|
+ case 'aftercare':
|
|
|
+ return '已完成';
|
|
|
+ default:
|
|
|
+ return '待分配';
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**应用场景**:
|
|
|
+- 客服端项目列表
|
|
|
+- 组长端监控大盘
|
|
|
+- 管理员端项目管理
|
|
|
+- 统计数据计算
|
|
|
+
|
|
|
+### 10.3 拖拽上传
|
|
|
+
|
|
|
+**技术**:HTML5 Drag and Drop API
|
|
|
+
|
|
|
+**实现步骤**:
|
|
|
+```typescript
|
|
|
+1. 监听 dragover 事件
|
|
|
+ - event.preventDefault()
|
|
|
+ - event.dataTransfer.dropEffect = 'move'
|
|
|
+ - 显示拖拽提示
|
|
|
+
|
|
|
+2. 监听 dragleave 事件
|
|
|
+ - 隐藏拖拽提示
|
|
|
+
|
|
|
+3. 监听 drop 事件
|
|
|
+ - event.preventDefault()
|
|
|
+ - 获取文件列表:event.dataTransfer.files
|
|
|
+ - 过滤文件类型(只允许图片)
|
|
|
+ - 打开上传弹窗
|
|
|
+
|
|
|
+4. 自动触发AI分析
|
|
|
+ - 延迟500ms
|
|
|
+ - 遍历文件列表
|
|
|
+ - 调用 ImageAnalysisService.analyzeImage()
|
|
|
+ - 显示分析结果
|
|
|
+
|
|
|
+5. 确认上传
|
|
|
+ - 批量上传文件到服务器
|
|
|
+ - 保存文件记录到 ProjectFile 表
|
|
|
+ - 更新项目数据
|
|
|
+```
|
|
|
+
|
|
|
+### 10.4 审批流程
|
|
|
+
|
|
|
+**数据结构**:
|
|
|
+```typescript
|
|
|
+// 订单审批
|
|
|
+Project.data.orderApproval = {
|
|
|
+ status: 'pending' | 'approved' | 'rejected';
|
|
|
+ submittedAt: Date;
|
|
|
+ submittedBy: string;
|
|
|
+ submittedByName: string;
|
|
|
+ approvedAt?: Date;
|
|
|
+ approvedBy?: string;
|
|
|
+ approvedByName?: string;
|
|
|
+ rejectedAt?: Date;
|
|
|
+ rejectedBy?: string;
|
|
|
+ rejectedByName?: string;
|
|
|
+ rejectionReason?: string;
|
|
|
+};
|
|
|
+
|
|
|
+// 交付审批
|
|
|
+Project.data.deliveryApproval = {
|
|
|
+ status: 'pending' | 'approved' | 'rejected';
|
|
|
+ stage: 'delivery';
|
|
|
+ totalFiles: number;
|
|
|
+ types: {
|
|
|
+ white_model: number;
|
|
|
+ soft_decor: number;
|
|
|
+ rendering: number;
|
|
|
+ post_process: number;
|
|
|
+ };
|
|
|
+ submittedAt: Date;
|
|
|
+ submittedByName: string;
|
|
|
+ submittedById: string;
|
|
|
+ approvedAt?: Date;
|
|
|
+ approvedBy?: string;
|
|
|
+ approvedByName?: string;
|
|
|
+ rejectedAt?: Date;
|
|
|
+ rejectedBy?: string;
|
|
|
+ rejectedByName?: string;
|
|
|
+ rejectionReason?: string;
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+**审批流程**:
|
|
|
+```typescript
|
|
|
+1. 提交审批
|
|
|
+ - 设置 status = 'pending'
|
|
|
+ - 记录提交人和时间
|
|
|
+ - 通知组长
|
|
|
+
|
|
|
+2. 组长审批
|
|
|
+ - 查看审批详情
|
|
|
+ - 选择通过或驳回
|
|
|
+ - 填写驳回原因(如驳回)
|
|
|
+ - 保存审批结果
|
|
|
+
|
|
|
+3. 审批通过
|
|
|
+ - 设置 status = 'approved'
|
|
|
+ - 记录审批人和时间
|
|
|
+ - 自动更新项目阶段
|
|
|
+ - 通知提交人
|
|
|
+
|
|
|
+4. 审批驳回
|
|
|
+ - 设置 status = 'rejected'
|
|
|
+ - 记录驳回人、时间和原因
|
|
|
+ - 通知提交人
|
|
|
+ - 项目回退到上一阶段
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十一、常见问题与解决方案
|
|
|
+
|
|
|
+### 11.1 数据一致性问题
|
|
|
+
|
|
|
+**问题**:项目负责人显示不一致
|
|
|
+
|
|
|
+**原因**:
|
|
|
+- `Project.assignee` 字段为空
|
|
|
+- `ProjectTeam` 表中有主要负责人记录
|
|
|
+
|
|
|
+**解决方案**:
|
|
|
+```typescript
|
|
|
+// 优先从 assignee 获取,其次从 ProjectTeam 获取
|
|
|
+let assigneeName = project.get('assignee')?.get('name');
|
|
|
+if (!assigneeName || assigneeName === '未分配') {
|
|
|
+ const primaryDesigner = await getPrimaryDesignerFromProjectTeam(projectId);
|
|
|
+ if (primaryDesigner) {
|
|
|
+ assigneeName = primaryDesigner.name;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 11.2 状态判断不准确
|
|
|
+
|
|
|
+**问题**:项目状态与实际阶段不符
|
|
|
+
|
|
|
+**原因**:
|
|
|
+- 手动设置的 `status` 字段未更新
|
|
|
+- 阶段变更后状态未同步
|
|
|
+
|
|
|
+**解决方案**:
|
|
|
+```typescript
|
|
|
+// 使用自动判断函数,而不是直接读取 status 字段
|
|
|
+const autoStatus = getProjectStatusByStage(currentStage, status);
|
|
|
+```
|
|
|
+
|
|
|
+### 11.3 文件上传失败
|
|
|
+
|
|
|
+**问题**:拖拽上传后文件未保存
|
|
|
+
|
|
|
+**原因**:
|
|
|
+- 文件大小超限
|
|
|
+- 网络超时
|
|
|
+- 权限不足
|
|
|
+
|
|
|
+**解决方案**:
|
|
|
+```typescript
|
|
|
+// 1. 检查文件大小
|
|
|
+if (file.size > 10 * 1024 * 1024) {
|
|
|
+ alert('文件大小不能超过10MB');
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+// 2. 添加重试机制
|
|
|
+async function uploadWithRetry(file, maxRetries = 3) {
|
|
|
+ for (let i = 0; i < maxRetries; i++) {
|
|
|
+ try {
|
|
|
+ return await uploadFile(file);
|
|
|
+ } catch (error) {
|
|
|
+ if (i === maxRetries - 1) throw error;
|
|
|
+ await sleep(1000 * (i + 1));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 3. 检查权限
|
|
|
+const currentUser = Parse.User.current();
|
|
|
+if (!currentUser) {
|
|
|
+ alert('请先登录');
|
|
|
+ return;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 11.4 AI分析超时
|
|
|
+
|
|
|
+**问题**:AI分析长时间无响应
|
|
|
+
|
|
|
+**原因**:
|
|
|
+- 图片过大
|
|
|
+- API调用超时
|
|
|
+- 网络问题
|
|
|
+
|
|
|
+**解决方案**:
|
|
|
+```typescript
|
|
|
+// 1. 压缩图片
|
|
|
+async function compressImage(file) {
|
|
|
+ if (file.size > 2 * 1024 * 1024) {
|
|
|
+ // 压缩到2MB以下
|
|
|
+ return await imageCompression(file, {
|
|
|
+ maxSizeMB: 2,
|
|
|
+ maxWidthOrHeight: 1920
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return file;
|
|
|
+}
|
|
|
+
|
|
|
+// 2. 设置超时
|
|
|
+const analysisPromise = ImageAnalysisService.analyzeImage(file);
|
|
|
+const timeoutPromise = new Promise((_, reject) =>
|
|
|
+ setTimeout(() => reject(new Error('分析超时')), 30000)
|
|
|
+);
|
|
|
+const result = await Promise.race([analysisPromise, timeoutPromise]);
|
|
|
+
|
|
|
+// 3. 降级处理
|
|
|
+try {
|
|
|
+ const result = await analyzeImage(file);
|
|
|
+} catch (error) {
|
|
|
+ console.error('AI分析失败,使用默认分类', error);
|
|
|
+ return {
|
|
|
+ category: 'unknown',
|
|
|
+ confidence: 0,
|
|
|
+ description: '自动分类失败,请手动选择'
|
|
|
+ };
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十二、性能优化建议
|
|
|
+
|
|
|
+### 12.1 数据查询优化
|
|
|
+
|
|
|
+**问题**:项目列表加载慢
|
|
|
+
|
|
|
+**优化方案**:
|
|
|
+```typescript
|
|
|
+// 1. 使用分页
|
|
|
+query.limit(20);
|
|
|
+query.skip(page * 20);
|
|
|
+
|
|
|
+// 2. 只查询必要字段
|
|
|
+query.select('title', 'status', 'currentStage', 'deadline', 'updatedAt');
|
|
|
+
|
|
|
+// 3. 使用索引
|
|
|
+// 在Parse Server后台为常用查询字段创建索引
|
|
|
+// - status
|
|
|
+// - currentStage
|
|
|
+// - company
|
|
|
+// - assignee
|
|
|
+// - createdAt
|
|
|
+// - updatedAt
|
|
|
+
|
|
|
+// 4. 缓存查询结果
|
|
|
+const cacheKey = `projects_${status}_${page}`;
|
|
|
+let projects = cache.get(cacheKey);
|
|
|
+if (!projects) {
|
|
|
+ projects = await query.find();
|
|
|
+ cache.set(cacheKey, projects, 60); // 缓存60秒
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 12.2 文件上传优化
|
|
|
+
|
|
|
+**优化方案**:
|
|
|
+```typescript
|
|
|
+// 1. 并发上传(限制并发数)
|
|
|
+async function uploadFiles(files) {
|
|
|
+ const concurrency = 3;
|
|
|
+ const results = [];
|
|
|
+ for (let i = 0; i < files.length; i += concurrency) {
|
|
|
+ const batch = files.slice(i, i + concurrency);
|
|
|
+ const batchResults = await Promise.all(
|
|
|
+ batch.map(file => uploadFile(file))
|
|
|
+ );
|
|
|
+ results.push(...batchResults);
|
|
|
+ }
|
|
|
+ return results;
|
|
|
+}
|
|
|
+
|
|
|
+// 2. 断点续传
|
|
|
+async function uploadLargeFile(file) {
|
|
|
+ const chunkSize = 1024 * 1024; // 1MB
|
|
|
+ const chunks = Math.ceil(file.size / chunkSize);
|
|
|
+ for (let i = 0; i < chunks; i++) {
|
|
|
+ const start = i * chunkSize;
|
|
|
+ const end = Math.min(start + chunkSize, file.size);
|
|
|
+ const chunk = file.slice(start, end);
|
|
|
+ await uploadChunk(chunk, i, chunks);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 3. 压缩图片
|
|
|
+async function compressAndUpload(file) {
|
|
|
+ const compressed = await imageCompression(file, {
|
|
|
+ maxSizeMB: 2,
|
|
|
+ maxWidthOrHeight: 1920,
|
|
|
+ useWebWorker: true
|
|
|
+ });
|
|
|
+ return await uploadFile(compressed);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 12.3 前端渲染优化
|
|
|
+
|
|
|
+**优化方案**:
|
|
|
+```typescript
|
|
|
+// 1. 虚拟滚动(大列表)
|
|
|
+<cdk-virtual-scroll-viewport itemSize="80" class="project-list">
|
|
|
+ <div *cdkVirtualFor="let project of projects">
|
|
|
+ {{ project.title }}
|
|
|
+ </div>
|
|
|
+</cdk-virtual-scroll-viewport>
|
|
|
+
|
|
|
+// 2. 懒加载图片
|
|
|
+<img [src]="placeholder" [lazyLoad]="imageUrl" />
|
|
|
+
|
|
|
+// 3. 使用 OnPush 变更检测
|
|
|
+@Component({
|
|
|
+ changeDetection: ChangeDetectionStrategy.OnPush
|
|
|
+})
|
|
|
+
|
|
|
+// 4. 使用 trackBy
|
|
|
+<div *ngFor="let project of projects; trackBy: trackByProjectId">
|
|
|
+ {{ project.title }}
|
|
|
+</div>
|
|
|
+
|
|
|
+trackByProjectId(index: number, project: Project): string {
|
|
|
+ return project.id;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十三、安全性考虑
|
|
|
+
|
|
|
+### 13.1 权限控制
|
|
|
+
|
|
|
+**实现方式**:
|
|
|
+```typescript
|
|
|
+// 1. 路由守卫
|
|
|
+@Injectable()
|
|
|
+export class RoleGuard implements CanActivate {
|
|
|
+ canActivate(route: ActivatedRouteSnapshot): boolean {
|
|
|
+ const currentUser = Parse.User.current();
|
|
|
+ const requiredRole = route.data['role'];
|
|
|
+ const userRole = currentUser?.get('roleName');
|
|
|
+ return userRole === requiredRole;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 2. 数据权限
|
|
|
+async function getProjects(userId: string, role: string) {
|
|
|
+ const query = new Parse.Query('Project');
|
|
|
+
|
|
|
+ if (role === '设计师') {
|
|
|
+ // 设计师只能查看自己负责的项目
|
|
|
+ query.equalTo('assignee', userId);
|
|
|
+ } else if (role === '客服' || role === '组长') {
|
|
|
+ // 客服和组长可以查看所有项目
|
|
|
+ // 不添加额外筛选
|
|
|
+ }
|
|
|
+
|
|
|
+ return await query.find();
|
|
|
+}
|
|
|
+
|
|
|
+// 3. 操作权限
|
|
|
+function canEditProject(project: Project, user: User): boolean {
|
|
|
+ const role = user.get('roleName');
|
|
|
+ const assigneeId = project.get('assignee')?.id;
|
|
|
+
|
|
|
+ if (role === '管理员' || role === '组长') {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (role === '客服') {
|
|
|
+ const createdBy = project.get('data')?.createdBy;
|
|
|
+ return createdBy === user.id;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (role === '设计师') {
|
|
|
+ return assigneeId === user.id;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 13.2 数据验证
|
|
|
+
|
|
|
+**实现方式**:
|
|
|
+```typescript
|
|
|
+// 1. 前端验证
|
|
|
+function validateProjectData(data: any): string[] {
|
|
|
+ const errors: string[] = [];
|
|
|
+
|
|
|
+ if (!data.title || data.title.trim().length === 0) {
|
|
|
+ errors.push('项目名称不能为空');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!data.customerId) {
|
|
|
+ errors.push('请选择客户');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.deadline && new Date(data.deadline) < new Date()) {
|
|
|
+ errors.push('截止时间不能早于当前时间');
|
|
|
+ }
|
|
|
+
|
|
|
+ return errors;
|
|
|
+}
|
|
|
+
|
|
|
+// 2. 后端验证(Parse Cloud Code)
|
|
|
+Parse.Cloud.beforeSave('Project', async (request) => {
|
|
|
+ const project = request.object;
|
|
|
+
|
|
|
+ // 验证必填字段
|
|
|
+ if (!project.get('title')) {
|
|
|
+ throw new Parse.Error(400, '项目名称不能为空');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证数据格式
|
|
|
+ const deadline = project.get('deadline');
|
|
|
+ if (deadline && !(deadline instanceof Date)) {
|
|
|
+ throw new Parse.Error(400, '截止时间格式错误');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证权限
|
|
|
+ const user = request.user;
|
|
|
+ if (!user) {
|
|
|
+ throw new Parse.Error(401, '未登录');
|
|
|
+ }
|
|
|
+
|
|
|
+ const role = user.get('roleName');
|
|
|
+ if (!['客服', '组长', '管理员'].includes(role)) {
|
|
|
+ throw new Parse.Error(403, '无权限创建项目');
|
|
|
+ }
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 13.3 敏感数据保护
|
|
|
+
|
|
|
+**实现方式**:
|
|
|
+```typescript
|
|
|
+// 1. 脱敏显示
|
|
|
+function maskPhone(phone: string): string {
|
|
|
+ if (!phone || phone.length < 11) return phone;
|
|
|
+ return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
|
|
|
+}
|
|
|
+
|
|
|
+function maskIdCard(idCard: string): string {
|
|
|
+ if (!idCard || idCard.length < 18) return idCard;
|
|
|
+ return idCard.replace(/(\d{6})\d{8}(\d{4})/, '$1********$2');
|
|
|
+}
|
|
|
+
|
|
|
+// 2. 加密存储
|
|
|
+async function savePaymentInfo(data: any) {
|
|
|
+ const encrypted = await encrypt(JSON.stringify(data));
|
|
|
+ project.set('paymentInfo', encrypted);
|
|
|
+ await project.save();
|
|
|
+}
|
|
|
+
|
|
|
+async function getPaymentInfo(project: Project) {
|
|
|
+ const encrypted = project.get('paymentInfo');
|
|
|
+ const decrypted = await decrypt(encrypted);
|
|
|
+ return JSON.parse(decrypted);
|
|
|
+}
|
|
|
+
|
|
|
+// 3. 日志记录
|
|
|
+async function logSensitiveOperation(
|
|
|
+ userId: string,
|
|
|
+ action: string,
|
|
|
+ entityId: string,
|
|
|
+ details: any
|
|
|
+) {
|
|
|
+ const log = new Parse.Object('AuditLog');
|
|
|
+ log.set('user', userId);
|
|
|
+ log.set('action', action);
|
|
|
+ log.set('entityId', entityId);
|
|
|
+ log.set('details', details);
|
|
|
+ log.set('timestamp', new Date());
|
|
|
+ log.set('ip', request.ip);
|
|
|
+ await log.save();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 十四、未来扩展方向
|
|
|
+
|
|
|
+### 14.1 功能扩展
|
|
|
+
|
|
|
+**1. 智能推荐**
|
|
|
+- 根据客户需求推荐设计师
|
|
|
+- 根据项目类型推荐设计方案
|
|
|
+- 根据历史数据推荐报价
|
|
|
+
|
|
|
+**2. 数据分析**
|
|
|
+- 项目周期分析
|
|
|
+- 设计师绩效分析
|
|
|
+- 客户满意度分析
|
|
|
+- 收入趋势分析
|
|
|
+
|
|
|
+**3. 自动化流程**
|
|
|
+- 自动分配设计师(基于负载和能力)
|
|
|
+- 自动催办逾期任务
|
|
|
+- 自动生成周报/月报
|
|
|
+- 自动结算设计师费用
|
|
|
+
|
|
|
+**4. 移动端支持**
|
|
|
+- 响应式设计
|
|
|
+- 移动端专属功能
|
|
|
+- 离线支持
|
|
|
+- 推送通知
|
|
|
+
|
|
|
+### 14.2 技术升级
|
|
|
+
|
|
|
+**1. 性能优化**
|
|
|
+- 服务端渲染(SSR)
|
|
|
+- 静态站点生成(SSG)
|
|
|
+- 边缘计算(Edge Computing)
|
|
|
+- CDN加速
|
|
|
+
|
|
|
+**2. AI能力增强**
|
|
|
+- 更精准的图像识别
|
|
|
+- 自然语言处理(NLP)
|
|
|
+- 智能客服机器人
|
|
|
+- 设计方案生成
|
|
|
+
|
|
|
+**3. 数据安全**
|
|
|
+- 端到端加密
|
|
|
+- 区块链存证
|
|
|
+- 多因素认证(MFA)
|
|
|
+- 零信任架构
|
|
|
+
|
|
|
+**4. 集成能力**
|
|
|
+- 第三方设计工具集成
|
|
|
+- 财务系统集成
|
|
|
+- CRM系统集成
|
|
|
+- 项目管理工具集成
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 附录
|
|
|
+
|
|
|
+### A. 数据表完整字段清单
|
|
|
+
|
|
|
+详见第三章"数据字段汇总"
|
|
|
+
|
|
|
+### B. API接口文档
|
|
|
+
|
|
|
+详见独立API文档
|
|
|
+
|
|
|
+### C. 错误码对照表
|
|
|
+
|
|
|
+| 错误码 | 说明 | 解决方案 |
|
|
|
+|-------|------|---------|
|
|
|
+| 400 | 请求参数错误 | 检查请求参数格式 |
|
|
|
+| 401 | 未登录 | 重新登录 |
|
|
|
+| 403 | 无权限 | 联系管理员分配权限 |
|
|
|
+| 404 | 资源不存在 | 检查资源ID是否正确 |
|
|
|
+| 500 | 服务器错误 | 联系技术支持 |
|
|
|
+
|
|
|
+### D. 版本更新日志
|
|
|
+
|
|
|
+**v1.0.0** (2025-01-15)
|
|
|
+- 初始版本发布
|
|
|
+- 客服板块基础功能
|
|
|
+- 管理员板块基础功能
|
|
|
+
|
|
|
+**v1.1.0** (2025-02-01)
|
|
|
+- 新增AI图像分析功能
|
|
|
+- 优化拖拽上传体验
|
|
|
+- 修复已知问题
|
|
|
+
|
|
|
+**v1.2.0** (2025-03-01)
|
|
|
+- 新增案例库统计功能
|
|
|
+- 优化项目列表性能
|
|
|
+- 新增员工信息面板
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**文档版本**:v1.0
|
|
|
+**最后更新**:2025-01-15
|
|
|
+**维护人员**:产品团队
|
|
|
+**联系方式**:product@example.com
|
|
|
+
|