微搭低代码MBA培训管理系统16——商机管理
目录
前情回顾
在上一讲中,我们完成了公海池管理功能的开发,实现了客户资源的科学流转。
本节我们将实现商机管理功能,这是CRM系统中承接跟进管理、推动销售转化的核心模块。商机管理帮助销售人员系统性地追踪潜在成交机会,通过销售漏斗分析预测业绩。
本节目标
- 数据模型设计:创建商机表,关联客户和跟进记录
- 销售漏斗搭建:实现商机阶段推进功能
- 页面布局实现:使用低代码组件搭建商机管理界面
- 核心功能开发:包括商机的新增、编辑、阶段推进、赢单/输单处理
第一步:数据准备
1.1 数据源配置
首先,创建名为MBA_Opportunities的商机表,包含以下核心字段:
| 字段名称 | 字段标识 | 类型 | 说明 |
|---|---|---|---|
| 商机名称 | name |
单行文本 | 商机标题,如"XX公司MBA培训项目" |
| 关联客户 | customer_id |
关联关系 | 关联到MBA_Customers表 |
| 负责人 | owner_id |
关联关系 | 关联到Users表(当前销售) |
| 商机阶段 | stage |
枚举 | 初步接触/需求确认/方案报价/商务谈判/赢单/输单 |
| 预计成交金额 | amount |
数字 | 预估的成交金额(元) |
| 成交概率 | probability |
数字 | 0-100的百分比 |
| 预计成交日期 | expected_close_date |
日期 | 预计何时成交 |
| 商机来源 | source |
枚举 | 转介绍/自开拓/渠道/市场活动 |
| 竞争情况 | competitor |
多行文本 | 竞争对手信息 |
| 商机描述 | description |
多行文本 | 详细商机描述 |
| 输单原因 | lost_reason |
枚举 | 价格过高/无需求/选择竞品/其他 |
| 创建时间 | created_at |
日期时间 | 自动生成 |
| 更新时间 | updated_at |
日期时间 | 自动更新 |

第二步:页面布局搭建
2.1 页面整体布局
点击创建页面的图标
输入页面的名称"商机管理",布局选择销售布局(因为主要是销售人员使用)
切换到页面布局,选择销售布局,添加平级菜单,添加商机管理菜单
2.2 数据表格配置
在销售布局的内容插槽下添加布局组件
修改标题,改为"商机管理"
在页面布局中添加数据表格组件,数据模型选择商机表
2.3 配置查询条件
点击筛选器,给表格配置查询条件
添加具体的查询条件:
- 商机名称(模糊搜索)
- 商机阶段(下拉选择)
- 预计成交日期范围(日期范围)
- 负责人(关联选择)

2.4 配置排序字段
默认按照创建时间的倒序进行排序,最新的商机显示在最前面
2.5 配置数据筛选
显示表格数据时,默认只显示当前登录销售的商机。配置筛选条件:
- 负责人等于当前用户对象的数据标识

第三步:商机功能实现
3.1 创建新增商机弹窗
在商机管理页面添加一个弹窗组件,用于录入新的商机。
从组件库中拖拽弹窗组件到页面,设置弹窗标题为"新增商机"
在弹窗中添加表单容器组件,数据模型选择商机表
配置负责人的选中值,设置为currentUser的数据标识
在表单提交成功后跟一个弹窗关闭和数据表格刷新

将全局按钮的删除改为新建
修改事件,改为打开弹窗
3.2 阶段推进功能
商机管理的核心是销售漏斗,需要实现阶段推进功能。
在表格操作列添加"推进"按钮,点击后执行阶段推进
在代码区新增方法advanceStage:
export default async function advanceStage({ event, data }) {
try {
$w.utils.showLoading({ title: '处理中...' });
const opportunityId = data.target._id;
const currentStage = data.target.stage;
// 定义阶段流转顺序
const stageFlow = {
'1': '2', // 初步接触 -> 需求确认
'2': '3', // 需求确认 -> 方案报价
'3': '4', // 方案报价 -> 商务谈判
'4': '5' // 商务谈判 -> 赢单
};
const nextStage = stageFlow[currentStage];
if (!nextStage) {
$w.utils.showToast({ title: '当前阶段无法推进', icon: 'error' });
return;
}
// 更新商机阶段
await $w.cloud.callDataSource({
dataSourceName: 'MBA_Opportunities',
methodName: 'wedaUpdateV2',
params: {
filter: { where: { _id: { $eq: opportunityId } } },
data: {
stage: nextStage,
}
}
});
$w.utils.showToast({ title: '阶段推进成功', icon: 'success' });
$w.table1.refresh();
} catch (error) {
console.error('阶段推进失败:', error);
$w.utils.showToast({ title: '操作失败,请稍后重试', icon: 'error' });
} finally {
$w.utils.hideLoading();
}
}
给按钮配置点击事件,调用我们的方法,传入所在行的数据
3.3 赢单处理
在表格操作列添加"赢单"和"输单"按钮
编写赢单处理方法:
export default async function winOpportunity({ event, data }) {
try {
$w.utils.showModal({
title: '确认赢单',
content: `确定将商机【${data.target.name}】标记为赢单吗?`,
success: async (res) => {
if (res.confirm) {
await $w.utils.showLoading({ title: '处理中...' });
// 更新商机状态为赢单
await $w.cloud.callDataSource({
dataSourceName: 'MBA_Opportunities',
methodName: 'wedaUpdateV2',
params: {
filter: { where: { _id: { $eq: data.target._id } } },
data: {
stage: '5', // 赢单
probability: 100,
}
}
});
// 更新客户状态为已成交
await $w.cloud.callDataSource({
dataSourceName: 'MBA_Customers',
methodName: 'wedaUpdateV2',
params: {
filter: { where: { _id: { $eq: data.target.customer_id._id } } },
data: {
status: '3', // 已成交
}
}
});
$w.utils.showToast({ title: '恭喜赢单!', icon: 'success' });
$w.table1.refresh();
}
}
});
} catch (error) {
console.error('赢单处理失败:', error);
$w.utils.showToast({ title: '操作失败', icon: 'error' });
}
}
给按钮设置事件,调用方法,传入所在行数据
3.4 输单处理
编写输单处理方法:
export default async function confirmLose({ event, data }) {
try {
const opportunityId = $w.modal2.openInfo._id;
const lostReason = $w.textarea3.value;
if (!lostReason) {
$w.utils.showToast({ title: '请选择输单原因', icon: 'error' });
return;
}
await $w.utils.showLoading({ title: '处理中...' });
await $w.cloud.callDataSource({
dataSourceName: 'MBA_Opportunities',
methodName: 'wedaUpdateV2',
params: {
filter: { where: { _id: { $eq: opportunityId } } },
data: {
stage: '6', // 输单
lost_reason: lostReason,
probability: 0
}
}
});
$w.utils.showToast({ title: '已标记为输单', icon: 'success' });
$w.modal2.close({});
$w.table1.refresh();
} catch (error) {
console.error('输单确认失败:', error);
$w.utils.showToast({ title: '操作失败', icon: 'error' });
} finally {
$w.utils.hideLoading();
}
}
输单的时候需要输入原因,增加一个弹窗
添加多行输入组件
配置输单按钮的点击事件,打开弹窗,传入所在行数据
给弹窗的确认按钮配置点击事件,调用我们的输单方法
最终效果
销售打开商机管理模块,可以录入商机,点击推进阶段自动往下流转,点击赢单标记状态,点击输单需要录入输单原因

总结
本节我们完成了商机管理功能的开发,实现了销售过程的可视化管理:
-
数据模型设计:
- 创建了
MBA_Opportunities商机表,记录商机基本信息、阶段、金额等 - 扩展了客户表,增加商机数量和预计成交总额字段
- 创建了
-
核心功能实现:
- 商机的新增、编辑、查询功能
- 商机阶段推进功能(初步接触→需求确认→方案报价→商务谈判→赢单)
- 赢单/输单处理,自动更新客户状态
通过本讲的实现,我们构建了完整的商机管理体系,实现了销售过程的可视化管理。
下一步,我们将继续完善CRM系统的报表功能,实现销售业绩统计、客户分析等模块。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)