基于企业微信的设计师项目全流程管理系统,支持从客户咨询、订单分配、需求确认、交付执行到售后归档的完整生命周期管理。
角色 | Profile.role | 职责 | 主要权限 |
---|---|---|---|
客服 | 客服 |
接单、跟进、售后 | 创建项目、查看客户完整信息、发起结算 |
组员 | 组员 |
设计执行 | 上传交付物、自查质量、查看部分客户信息 |
组长 | 组长 |
审核、分配、质检 | 分配任务、审核交付物、提出Issue |
财务 | 财务 |
审核报价、确认收款 | 审核报价、确认付款凭证 |
管理员 | 管理员 |
系统管理 | 全部权限 |
功能模块 | 客服 | 组员 | 组长 | 财务 |
---|---|---|---|---|
查看客户手机号 | ✅ | ❌ | ✅ | ❌ |
创建项目 | ✅ | ❌ | ✅ | ❌ |
分配设计师 | ✅ | ❌ | ✅ | ❌ |
上传参考图 | ✅ | ✅ | ✅ | ❌ |
AI生成方案 | ✅ | ✅ | ✅ | ❌ |
上传交付物 | ❌ | ✅ | ✅ | ❌ |
审核交付物 | ❌ | ❌ | ✅ | ❌ |
提出Issue | ❌ | ❌ | ✅ | ❌ |
创建报价 | ✅ | ❌ | ✅ | ❌ |
审核报价 | ❌ | ❌ | ❌ | ✅ |
发起结算 | ✅ | ❌ | ✅ | ❌ |
确认收款 | ❌ | ❌ | ❌ | ✅ |
项目归档 | ✅ | ❌ | ✅ | ❌ |
企业微信会话
↓
项目预加载页 (WxworkSDK获取上下文)
↓
├─ 群聊入口 → 项目详情组件
└─ 联系人入口 → 客户画像组件
src/modules/project/
├── pages/
│ ├── project-loader/ # 项目预加载页面
│ │ ├── project-loader.component.ts
│ │ └── project-loader.component.html
│ ├── contact/ # 客户画像页面
│ │ ├── contact.component.ts
│ │ └── contact.component.html
│ └── project-detail/ # 项目详情页面
│ ├── project-detail.component.ts
│ ├── project-detail.component.html
│ └── components/
│ ├── stage-order/ # 订单分配阶段
│ ├── stage-requirements/ # 确认需求阶段
│ ├── stage-delivery/ # 交付执行阶段
│ └── stage-aftercare/ # 售后归档阶段
├── components/
│ ├── customer-info/ # 客户信息卡片
│ ├── reference-image-uploader/ # 参考图上传
│ ├── ai-solution-generator/ # AI方案生成
│ ├── deliverable-uploader/ # 交付物上传
│ ├── quality-checklist/ # 质量自查清单
│ └── settlement-manager/ # 结算管理
└── services/
├── project-wxwork.service.ts # 企微项目服务
├── ai-solution.service.ts # AI方案生成服务
└── deliverable.service.ts # 交付物服务
// app.routes.ts
{
path: 'wxwork/:cid',
canActivate: [WxworkAuthGuard],
children: [
// 项目预加载页
{
path: 'project-loader',
component: ProjectLoaderComponent
},
// 客户画像
{
path: 'customer/:contactId',
component: CustomerProfileComponent
},
// 项目详情(支持调试)
{
path: 'project/:projectId',
component: ProjectDetailComponent,
children: [
{ path: '', redirectTo: 'order', pathMatch: 'full' },
{ path: 'order', component: StageOrderComponent },
{ path: 'requirements', component: StageRequirementsComponent },
{ path: 'delivery', component: StageDeliveryComponent },
{ path: 'aftercare', component: StageAftercareComponent }
]
}
]
}
从企业微信会话进入时的首屏页面,负责获取企微上下文、识别用户身份、加载或创建项目。
加载页面
↓
显示骨架屏
↓
获取企微上下文 (WxworkSDK.getCurrentChatObject())
├─ 群聊场景 → GroupChat
└─ 联系人场景 → ContactInfo
↓
获取当前用户 (WxworkSDK.getCurrentUser())
↓ 得到 Profile (role决定权限)
↓
根据场景加载数据
├─ 群聊 → 查询 GroupChat.project
│ ├─ 有项目 → 跳转项目详情
│ └─ 无项目 → 显示创建项目引导
└─ 联系人 → 跳转客户画像
// project-loader.component.ts
export class ProjectLoaderComponent implements OnInit {
loading = true;
currentUser: FmodeObject | null = null; // Profile
groupChat: FmodeObject | null = null; // GroupChat
contact: FmodeObject | null = null; // ContactInfo
project: FmodeObject | null = null; // Project
async ngOnInit() {
const cid = this.route.snapshot.paramMap.get('cid')!;
const wxwork = new WxworkSDK({ cid, appId: 'crm' });
try {
// 1. 获取企微上下文
const { GroupChat, Contact } = await wxwork.getCurrentChatObject();
this.groupChat = GroupChat;
this.contact = Contact;
// 2. 获取当前用户
this.currentUser = await wxwork.getCurrentUser();
// 3. 根据场景处理
if (this.groupChat) {
await this.handleGroupChatScene();
} else if (this.contact) {
await this.handleContactScene();
}
} catch (error) {
console.error('加载失败:', error);
} finally {
this.loading = false;
}
}
async handleGroupChatScene() {
// 查询群聊关联的项目
const projectPointer = this.groupChat!.get('project');
if (projectPointer) {
// 有项目,跳转详情
this.router.navigate(['/wxwork', this.cid, 'project', projectPointer.id]);
} else {
// 无项目,显示创建引导
this.showCreateProjectGuide();
}
}
async handleContactScene() {
// 跳转客户画像
this.router.navigate(['/wxwork', this.cid, 'customer', this.contact!.id]);
}
showCreateProjectGuide() {
// 显示骨架屏 + 创建项目表单
this.showGuide = true;
this.defaultProjectName = this.groupChat!.get('name');
}
async createProject(projectName: string) {
const Project = Parse.Object.extend('Project');
const project = new Project();
project.set('title', projectName);
project.set('company', this.currentUser!.get('company'));
project.set('status', '待分配');
project.set('currentStage', '订单分配');
await project.save();
// 关联群聊
this.groupChat!.set('project', project.toPointer());
await this.groupChat!.save();
// 跳转项目详情
this.router.navigate(['/wxwork', this.cid, 'project', project.id]);
}
}
从联系人侧边栏进入,展示客户的完整画像信息,包括基础信息、所在群聊、项目列表、跟进记录等。
interface CustomerProfile {
basic: {
name: string;
mobile?: string; // 仅客服/组长可见
wechat?: string; // 仅客服/组长可见
avatar: string;
source: string; // 来源渠道
tags: string[]; // 客户标签
};
groups: GroupChatInfo[]; // 所在群聊
projects: ProjectInfo[]; // 相关项目
followUp: FollowUpRecord[]; // 跟进记录
preferences: {
style: string[];
budget: { min: number; max: number };
colorAtmosphere: string;
};
}
┌────────────────────────────┐
│ 头像 + 姓名 + 来源标签 │
├────────────────────────────┤
│ 基础信息卡片 │
│ - 手机号(权限控制) │
│ - 微信号(权限控制) │
│ - 客户类型 │
├────────────────────────────┤
│ 客户画像 │
│ - 风格偏好 │
│ - 预算范围 │
│ - 色彩氛围 │
├────────────────────────────┤
│ 所在群聊(可点击跳转) │
│ ┌──────────┐ ┌──────────┐│
│ │ 群1 - 项目A│ │ 群2 - 项目B││
│ └──────────┘ └──────────┘│
├────────────────────────────┤
│ 历史项目列表 │
│ - 项目名称 + 状态 + 进度 │
├────────────────────────────┤
│ 跟进记录时间线 │
│ - 咨询时间 │
│ - 报价时间 │
│ - 签约时间 │
└────────────────────────────┘
WxworkSDK.openChat(chatId)
跳转四大阶段流程:
订单分配 → 确认需求 → 交付执行 → 售后归档
页面头部导航:
手机端布局:
主要操作人: 客服
核心功能:
填写项目基础信息
创建报价清单
interface QuotationBreakdown {
spaces: SpaceQuotation[]; // 按空间报价
totalAmount: number;
}
interface SpaceQuotation {
space: string; // 客厅、主卧、次卧等
area: number; // 面积
items: QuotationItem[];
subtotal: number;
}
interface QuotationItem {
process: 'modeling' | 'softDecor' | 'rendering' | 'postProcess';
quantity: number; // 数量(如渲染张数)
unitPrice: number;
amount: number;
}
分配设计师
报价审核流程
页面布局:
┌────────────────────────────┐
│ 客户信息卡片 │
│ - 姓名 + 来源 + 偏好标签 │
├────────────────────────────┤
│ 项目基础信息表单 │
│ - 项目名称 │
│ - 项目类型 │
│ - 截止时间 │
├────────────────────────────┤
│ 报价清单编辑器 │
│ ┌──── 客厅 (40㎡) ────┐ │
│ │ 建模: 1套 x 2000 │ │
│ │ 软装: 1套 x 1500 │ │
│ │ 渲染: 3张 x 800 │ │
│ │ 后期: 3张 x 200 │ │
│ │ 小计: 6500元 │ │
│ └────────────────────┘ │
│ [+ 添加空间] │
│ 总计: 18,000元 │
├────────────────────────────┤
│ 设计师分配 │
│ [选择主设计师] │
│ 当前负载: 5/8个项目 │
├────────────────────────────┤
│ [提交审核] │
└────────────────────────────┘
数据存储:
// Product表 - 按空间+工序存储报价项
const product = new Parse.Object('Product');
product.set('project', projectPointer);
product.set('space', '客厅');
product.set('processType', 'modeling');
product.set('quotation', {
price: 2000,
quantity: 1,
status: '待审核'
});
主要操作人: 组长、组员
核心功能:
2.1 上传参考图
点击图片可查看大图和色彩分析
// ProjectFile表
const refImage = new Parse.Object('ProjectFile');
refImage.set('project', projectPointer);
refImage.set('fileType', 'reference');
refImage.set('fileUrl', imageUrl);
refImage.set('fileName', 'living-room-ref-01.jpg');
refImage.set('stage', '确认需求');
refImage.set('data', {
description: '现代简约风格客厅,暖色调为主',
colorAnalysis: {
primaryHue: 30,
saturation: 45,
temperature: '暖色调'
}
});
2.2 色彩分析弹窗
2.3 上传CAD图纸
.dwg
.dxf
格式2.4 其他需求录入
2.5 AI生成方案
触发条件:
调用流程:
// ai-solution.service.ts
async generateSolution(projectId: string): Promise<string> {
// 1. 收集数据
const requirement = await this.loadRequirement(projectId);
const refImages = await this.loadReferenceImages(projectId);
const colorAnalysis = await this.analyzeColors(refImages);
// 2. 构建 Prompt
const prompt = this.buildPrompt({
requirement,
colorAnalysis,
spaces: requirement.get('spaces')
});
// 3. 调用大模型
const response = await this.callLLM(prompt);
// 4. 保存方案
requirement.set('data', {
...requirement.get('data'),
aiSolution: {
content: response,
generatedAt: new Date()
}
});
await requirement.save();
return response;
}
Prompt 模板:
你是一位资深的室内设计师,请根据以下信息生成详细的设计方案分析:
## 项目信息
- 空间类型:{spaces}
- 总面积:{totalArea}㎡
- 风格偏好:{stylePreferences}
## 色彩分析
- 主色调:{primaryHue}°(色相)
- 饱和度:{saturation}%
- 色温:{temperature}
- 色彩分布:{colorDistribution}
## 客户需求
{requirements}
## 任务
请生成以下内容:
1. 整体设计风格定位(200字)
2. 色彩方案建议(每个空间)
3. 材质搭配建议
4. 家具形体建议
5. 灯光布局建议
6. 注意事项和禁忌
请以Markdown格式输出,结构清晰,便于阅读。
方案展示:
页面布局:
┌────────────────────────────┐
│ 参考图网格 │
│ ┌───┐ ┌───┐ ┌───┐ │
│ │图1│ │图2│ │图3│ [+上传]│
│ └───┘ └───┘ └───┘ │
├────────────────────────────┤
│ CAD图纸列表 │
│ 📄 原始户型图.dwg │
│ 📄 水电布局图.dwg │
│ [+ 上传CAD] │
├────────────────────────────┤
│ 需求清单 │
│ ✓ 需要大储物空间 │
│ ✓ 智能家电 │
│ [+ 添加需求] │
├────────────────────────────┤
│ [🤖 AI生成设计方案] │
├────────────────────────────┤
│ AI方案展示区(折叠) │
│ 【已生成】 │
│ > 查看完整方案 │
└────────────────────────────┘
主要操作人: 组员(上传)、组长(审核)
核心功能:
3.1 交付物上传
按报价清单的空间和工序组织:
客厅
├─ 白模 (modeling)
│ └─ [上传图片] 自查清单 状态
├─ 软装 (softDecor)
│ └─ [上传图片] 自查清单 状态
├─ 渲染 (rendering)
│ └─ [上传图片] 渲染进度 状态
└─ 后期 (postProcess)
└─ [上传图片] 自查清单 状态
主卧
├─ ...
3.2 质量自查清单
每个交付物都有对应的自查项(ProductCheck):
// 建模自查项
const modelChecks = [
'尺寸准确性',
'材质贴图正确',
'模型结构合理',
'无破面和漏洞'
];
// 渲染自查项
const renderChecks = [
'光影自然',
'色彩还原准确',
'分辨率符合要求',
'无明显瑕疵'
];
组员上传后需逐项打勾确认:
const check = new Parse.Object('ProductCheck');
check.set('project', projectPointer);
check.set('checkType', 'model');
check.set('checkedBy', currentUserPointer);
check.set('isPassed', true);
check.set('items', [
{ name: '尺寸准确性', isPassed: true, notes: '' },
{ name: '材质贴图正确', isPassed: true, notes: '' },
{ name: '模型结构合理', isPassed: false, notes: '需要调整沙发位置' }
]);
3.3 组长审核与Issue
组长可以对交付物提出Issue(ProjectIssue):
const issue = new Parse.Object('ProjectIssue');
issue.set('project', projectPointer);
issue.set('reportedBy', leaderProfilePointer);
issue.set('exceptionType', 'quality');
issue.set('severity', 'medium');
issue.set('description', '客厅渲染图色调偏冷,需要调整为暖色调');
issue.set('status', '待处理');
issue.set('data', {
relatedDeliverable: productId, // 关联的Product
relatedStage: '渲染',
space: '客厅'
});
组员在页面上会看到醒目的Issue提示,点击查看详情并处理。
3.4 发起交付
当组员完成所有交付物上传并自查通过后,可点击"发起交付"按钮:
同时发起尾款收款请求
async initiateDelivery() {
// 1. 检查完成度
const deliveryRate = await this.checkDeliveryCompleteness();
if (deliveryRate < 100) {
alert('还有交付物未完成,请检查');
return;
}
// 2. 更新项目阶段
project.set('currentStage', '尾款结算');
await project.save();
// 3. 发送企微消息
await this.wecorp.appchat.sendText(
chatId,
`【项目交付通知】\n${project.get('title')} 已完成全部设计工作,请查收成果。\n如有修改意见请及时反馈。`
);
// 4. 创建尾款结算记录
const settlement = new Parse.Object('ProjectSettlement');
settlement.set('project', projectPointer);
settlement.set('stage', '尾款');
settlement.set('amount', finalAmount);
settlement.set('status', '待结算');
settlement.set('dueDate', new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)); // 7天后
await settlement.save();
}
页面布局:
┌────────────────────────────┐
│ 交付进度总览 │
│ ████████░░ 80% │
│ 已完成 12/15 项 │
├────────────────────────────┤
│ 空间列表(可折叠) │
│ ▼ 客厅 │
│ ├─ 白模 ✓ │
│ ├─ 软装 ✓ │
│ ├─ 渲染 🔄 (进行中) │
│ └─ 后期 ⏸ (待开始) │
│ ▶ 主卧 │
│ ▶ 次卧 │
├────────────────────────────┤
│ 当前工作:客厅渲染 │
│ ┌────────────────────┐ │
│ │ [上传图片] │ │
│ │ 已上传: 3张 │ │
│ │ 渲染进度: 60% │ │
│ └────────────────────┘ │
│ 质量自查清单 │
│ ☑ 光影自然 │
│ ☑ 色彩准确 │
│ ☐ 分辨率符合要求 │
├────────────────────────────┤
│ ⚠️ Issue提醒 (2个待处理) │
│ • 客厅渲染色调需调整 │
│ • 主卧软装需补充细节 │
├────────────────────────────┤
│ [发起交付](灰色/可点击) │
└────────────────────────────┘
主要操作人: 客服
核心功能:
4.1 尾款管理
4.2 客户评价
评价维度:设计质量、服务态度、交付时效
const feedback = new Parse.Object('ProjectFeedback');
feedback.set('project', projectPointer);
feedback.set('customer', customerPointer);
feedback.set('stage', '客户评价');
feedback.set('feedbackType', 'praise');
feedback.set('rating', 5);
feedback.set('content', '设计师非常专业,效果图很满意!');
feedback.set('status', '已完成');
4.3 项目复盘
4.4 项目归档
GroupChat.project
设为 null(解除关联)项目进入历史项目列表
async archiveProject() {
// 1. 检查是否可归档
if (!this.checkCanArchive()) {
alert('请先完成尾款结算和客户评价');
return;
}
// 2. 更新项目状态
project.set('status', '已完成');
project.set('data', {
...project.get('data'),
archivedAt: new Date(),
archivedBy: currentUserPointer.id
});
await project.save();
// 3. 解除群聊关联
groupChat.set('project', null);
await groupChat.save();
// 4. 发送归档通知
await this.wecorp.appchat.sendText(
chatId,
`【项目归档通知】\n${project.get('title')} 已完成归档,感谢您的信任与支持!`
);
// 5. 返回工作台
this.router.navigate(['/wxwork', this.cid, 'project-loader']);
}
页面布局:
┌────────────────────────────┐
│ 尾款信息 │
│ 应收金额: ¥5,400 │
│ 截止日期: 2025-10-20 │
│ 状态: 已收款 ✓ │
├────────────────────────────┤
│ 付款凭证 │
│ ┌────────────────────┐ │
│ │ [查看凭证图片] │ │
│ │ 识别金额: 5400元 │ │
│ │ 付款时间: 2025-10-18│ │
│ └────────────────────┘ │
├────────────────────────────┤
│ 客户评价 │
│ ⭐⭐⭐⭐⭐ 5.0分 │
│ "设计师非常专业,效果图很│
│ 满意!交付及时。" │
├────────────────────────────┤
│ 项目复盘 │
│ [查看完整复盘报告] │
│ • 项目总评分: 92分 │
│ • 交付准时率: 100% │
│ • 客户满意度: 5.0星 │
├────────────────────────────┤
│ [📦 归档项目] │
└────────────────────────────┘
获取上下文:
// 从企微会话获取群聊或联系人
const { GroupChat, Contact, currentChat } = await wxwork.getCurrentChatObject();
if (GroupChat) {
// 群聊场景
const project = GroupChat.get('project');
} else if (Contact) {
// 联系人场景
const name = Contact.get('name');
}
获取当前用户:
// 获取当前登录的员工信息
const profile = await wxwork.getCurrentUser();
const role = profile.get('roleName'); // 客服/组员/组长
发送企微消息:
await wecorp.appchat.sendText(chatId, '消息内容');
await wecorp.appchat.sendImage(chatId, imageUrl);
创建记录:
const Project = Parse.Object.extend('Project');
const project = new Project();
project.set('title', '项目名称');
project.set('company', companyPointer);
await project.save();
查询记录:
const query = new Parse.Query('Project');
query.equalTo('company', companyId);
query.equalTo('status', '进行中');
query.include('customer', 'assignee');
const projects = await query.find();
更新记录:
project.set('currentStage', '确认需求');
await project.save();
参考示例代码 /home/ryan/workspace/nova/nova-admin/projects/ai-k12-daofa/src/modules/daofa/search/search.component.ts
import { HttpClient } from '@angular/common/http';
export class AiSolutionService {
constructor(private http: HttpClient) {}
async generateSolution(prompt: string): Promise<string> {
const response = await this.http.post<any>('https://api.example.com/v1/chat/completions', {
model: 'qwen-plus',
messages: [
{ role: 'system', content: '你是一位资深室内设计师' },
{ role: 'user', content: prompt }
],
temperature: 0.7,
max_tokens: 2000
}).toPromise();
return response.choices[0].message.content;
}
}
Ionic组件:
<ion-header>
<ion-toolbar>
<ion-title>项目详情</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-card>
<ion-card-header>
<ion-card-title>客户信息</ion-card-title>
</ion-card-header>
<ion-card-content>
...
</ion-card-content>
</ion-card>
</ion-content>
响应式布局:
.project-detail {
@media (max-width: 768px) {
// 手机端样式
.header-nav {
flex-direction: column;
}
}
}
客服在群聊打开工具
↓
项目预加载页
↓
检测无项目 → 显示创建引导
↓
填写项目名称 → 创建Project
↓
关联GroupChat.project
↓
跳转项目详情 - 订单分配阶段
组员上传参考图 → 保存到ProjectFile
↓
点击参考图 → 色彩分析 → 保存到ProjectRequirement
↓
填写需求清单
↓
点击"AI生成方案" → 调用大模型
↓
生成方案 → 保存到ProjectRequirement.data.aiSolution
↓
方案展示 → Markdown渲染
组员上传交付物 → 保存到Product
↓
填写质量自查清单 → 保存到ProductCheck
↓
组长审核 → 提出Issue(如有问题)
↓
组员修改 → 重新上传
↓
所有交付物完成 → 点击"发起交付"
↓
更新项目阶段 → 发送企微通知 → 创建尾款结算
测试场景 | 前置条件 | 操作步骤 | 预期结果 |
---|---|---|---|
从群聊创建项目 | 群聊无关联项目 | 打开工具 → 填写项目名 → 点击创建 | 项目创建成功,跳转详情页 |
重复创建检测 | 群聊已有项目 | 打开工具 | 直接跳转到现有项目详情 |
权限检查 | 非客服角色 | 打开工具 → 尝试创建项目 | 提示"无权限" |
测试场景 | 前置条件 | 操作步骤 | 预期结果 |
---|---|---|---|
首次生成方案 | 已上传参考图和需求 | 点击"AI生成方案" | 调用大模型,生成方案并展示 |
重新生成 | 已有方案 | 更新需求 → 重新生成 | 生成新方案,保留历史版本 |
缺少数据 | 未上传参考图 | 点击"AI生成方案" | 提示"请先上传参考图" |
测试场景 | 前置条件 | 操作步骤 | 预期结果 |
---|---|---|---|
上传白模图 | 在交付执行阶段 | 选择文件 → 上传 | 图片保存成功,显示在列表 |
质量自查 | 已上传交付物 | 勾选自查项 → 保存 | 自查记录保存成功 |
组长提Issue | 组长角色 | 查看交付物 → 提出问题 | Issue创建成功,组员可见 |
项目状态 (Project.status):
待分配
: 新建项目,等待分配设计师进行中
: 设计中已暂停
: 客户要求暂停已延期
: 超期已完成
: 已归档已取消
: 项目取消项目阶段 (Project.currentStage):
订单分配
确认需求
方案确认
(并列任务)
建模
软装
渲染
后期
尾款结算
客户评价
投诉处理
审核状态 (reviewStatus):
pending
: 待审核approved
: 已通过rejected
: 已驳回revision_required
: 需要修改// 权限检查辅助函数
function hasPermission(role: string, action: string): boolean {
const permissions = {
'客服': ['createProject', 'viewCustomerPhone', 'createQuotation', 'initiateSettlement'],
'组员': ['uploadDeliverable', 'qualityCheck', 'uploadReference'],
'组长': ['assignDesigner', 'reviewDeliverable', 'createIssue', 'viewCustomerPhone'],
'财务': ['approveQuotation', 'confirmPayment']
};
return permissions[role]?.includes(action) || false;
}
// 使用示例
if (!hasPermission(currentUser.get('roleName'), 'createProject')) {
alert('您没有权限创建项目');
return;
}
文档结束
如有疑问,请联系产品团队。