么是三级分销系统?
假设A推荐B,B推荐C,C再推荐D,D购买了C所分享的产品之后,C能获得分佣的同时,A和B也能获得,这个就是三级分销的分佣方式,自订单产生人开始往上推三层关系人获得分佣。
常见的电商三级分销系统产品设计场景:
1:小A想参加活动,需要先注册成为会员,然后获取一个分享的商品页码或活动页码。 2:小A再通过社交媒体(朋友圈、微博等)把页面分享出去。 3:小B通过A分享的页码,注册成功。小B成为小A的下线 。
电商三级分销系统的设计重点:
小A分享的活动页面的url ,需要包含分享者的标识
如:https://localhost//register?token=xxxx,xxxx 为分享者id。
小A分享注册页面可能为https://localhost//register?token=a_id.小B进入小A的分享页面,注册时提交注册表单需要将分享者ID(a_id)提交到后台。
这时后台可以确认小B的上级是某个id。
在三级分销的用户表设计时,数据库中用户信息表只要增加一栏记录上级ID即可。
再来看第二点:分配利润
首先可对每个商品设计一个佣金的比例。
在一个商品完成支付以后, 按照如下流程来做:
1:通过注册表格, 找出购买者的3个上家ID.
2:通过支付的价格,分别算出3个上家获得的利润。
3:打钱给3个上家。(有可能直接支付,有可能按月支付等等,看商家的规则)
系统设计
一、数据库设计:
基本功能需要依赖于:用户表 、商品表、订单表、钱包表 所以需要在
用户表:
// app/model/User.js
'use strict';
module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const User = app.model.define('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30), // 用户名
pwd: STRING(30), // 密码
pid: INTEGER, // 父级id
});
return User;
};
商品表:
// app/model/Goods.js
'use strict';
module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const Goods = app.model.define('goods', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30), // 商品名称
img: STRING, // 商品图片
describe: STRING, // 商品内容
price: INTEGER, // 商品价格
gain: INTEGER, // 佣金 按商品价格百分比
});
return Goods;
};
订单表:
// app/model/Order.js
'use strict';
module.exports = app => {
const { INTEGER, DATE, TINYINT, DECIMAL } = app.Sequelize;
const Order = app.model.define('orders', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
user_id: INTEGER, // 用户id
goods_id: INTEGER, // 商品id
status:TINYINT, // 订单状态
});
return Order;
};
钱包表:
// app/model/Bill.js
'use strict';
module.exports = app => {
const { DECIMAL, INTEGER, STRING, DATE } = app.Sequelize;
const Bill = app.model.define('bills', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
balance:DECIMAL(10, 2), // 账户余额
price:STRING, // 变动的价格
user_id: INTEGER, //用户id
bz: STRING, // 备注信息
});
return Bill;
};
二、编写controller层:
// app/controller/users.js
const Controller = require('egg').Controller;
function toInt(str) {
if (typeof str === 'number') return str;
if (!str) return str;
return parseInt(str, 10) || 0;
}
class UserController extends Controller {
// 创建新用户
async create() {
const ctx = this.ctx;
const { token } = ctx.query;
const { name, age, pwd, id } = ctx.request.body;
const obj = { name, age, pwd, id };
// 判断是否有标识 此标识token是用户的上级id,填写在新用户的pid上
if (token) {
obj.pid = token;
}
const user = await ctx.model.User.create(obj);
// 给用户分配余额
await ctx.model.Bill.create({ user_id: user.id });
ctx.status = 201;
ctx.body = user;
}
}
module.exports = UserController;
// app/controller/goods.js
const Controller = require('egg').Controller;
function toInt(str) {
if (typeof str === 'number') return str;
if (!str) return str;
return parseInt(str, 10) || 0;
}
class GoodsController extends Controller {
// 创建商品
async create() {
const ctx = this.ctx;
const { name, describe, price, id, gain, img } = ctx.request.body;
const obj = { name, describe, price, id, gain, img };
const Goods = await ctx.model.Goods.create(obj);
ctx.status = 201;
ctx.body = Goods;
}
}
module.exports = GoodsController;
// app/controller/order.js
const Controller = require('egg').Controller;
function toInt(str) {
if (typeof str === 'number') return str;
if (!str) return str;
return parseInt(str, 10) || 0;
}
class OrderController extends Controller {
// 创建订单
async create() {
const ctx = this.ctx;
const { user_id, goods_id, total } = ctx.request.body;
const obj = { user_id, goods_id, total };
// 创建好订单后
const Order = await ctx.model.Order.create(obj);
// 1.商品完成购买后,系统通过注册表找出购买者的3个上级ID
const User = await ctx.model.User.findByPk(toInt(user_id));
if (!User.pid) return;
const UserList = await ctx.helper.seekPid(User.pid, 3);//该方法在工具类app/extend/helper.js
console.log(UserList);
// 2.通过支付的价格,分别算出3个上家获得的利润。
const Goods = await ctx.model.Goods.findByPk(toInt(goods_id));
const { gain, price } = Goods;
// 通过支付商品的价格来获取商品的总佣金 100 * 10 / 100 = 10
const commission = (price * gain / 100);
// 3 分别算出3个上家获得的利润。分配利润判断有几级分销人 按照分销人来分配佣金
if (UserList.length === 1) {
console.log('如果上级只有一个人则按佣金按照 100% 分');
const Bill = await ctx.model.Bill.findOne({ where: { user_id: UserList[0] } });
await ctx.model.Bill.update({
balance: Number(Bill.balance) + commission,
price: '+' + commission,
}, { where: { user_id: Bill.user_id } });
} else if (UserList.length === 2) {
console.log('如果上级有两个人则按佣金按照 30% 70% 分');
const Bill1 = await ctx.model.Bill.findOne({ where: { user_id: UserList[0] } });
await ctx.model.Bill.update({
balance: Number(Bill1.balance) + commission * 70 / 100,
price: '+' + commission * 70 / 100,
}, { where: { user_id: Bill1.user_id } });
const Bill2 = await ctx.model.Bill.findOne({ where: { user_id: UserList[1] } });
await ctx.model.Bill.update({
balance: Number(Bill2.balance) + commission * 30 / 100,
price: '+' + commission * 30 / 100,
}, { where: { user_id: Bill2.user_id } });
} else {
console.log('如果上级有三个人则按佣金按照 20% 30% 50% 分');
const Bill1 = await ctx.model.Bill.findOne({ where: { user_id: UserList[0] } });
await ctx.model.Bill.update({
balance: Number(Bill1.balance) + commission * 50 / 100,
price: '+' + commission * 50 / 100,
}, { where: { user_id: Bill1.user_id } });
const Bill2 = await ctx.model.Bill.findOne({ where: { user_id: UserList[1] } });
await ctx.model.Bill.update({
balance: Number(Bill2.balance) + commission * 30 / 100,
price: '+' + commission * 30 / 100,
}, { where: { user_id: Bill2.user_id } });
const Bill3 = await ctx.model.Bill.findOne({ where: { user_id: UserList[2] } });
await ctx.model.Bill.update({
balance: Number(Bill3.balance) + commission * 20 / 100,
price: '+' + commission * 20 / 100,
}, { where: { user_id: Bill3.user_id } });
}
ctx.status = 201;
ctx.body = Order;
}
}
module.exports = OrderController;
三、编写工具类:
因为 app/controller/order.js 中的 create 使用该方法
// app/extend/helper.js
'use strict';
module.exports = {
/**
*查找用户的pid
* @param {number} pid 用户父id
* @param {number} num 查找几个人
* @return [] 查找到的人数
*/
async seekPid(pid, num) {
const { ctx } = this;
const userList = [];
await seek(pid, num);
return userList;
async function seek(pid, num) {
if (userList.length >= num) return userList;
const User = await ctx.model.User.findByPk(pid);
if (!User.pid) return userList.push(User.id);
userList.push(User.id);
await seek(User.pid, num);
}
},
};
四、编写路由:
// app/router.js
'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
router.post('/users', controller.users.create); // 创建用户
router.post('/goods', controller.goods.create); // 创建商品
router.post('/order', controller.goods.order); // 创建订单
};
五、接口说明:
新增用户接口:
请求类型:POST 请求路径:/users 类型:x-www-form-urlencoded
query 请求参数 :
|
参数名 |
类型 |
必填 |
示例值 |
说明 |
|
token |
number |
否 |
10086 |
用户的pid上级id 推广者的标识 |
body 请求参数 :
|
参数名 |
类型 |
必填 |
示例值 |
说明 |
|
name |
string |
是 |
zhangsan |
用户名 |
|
pwd |
string |
是 |
123456 |
密码 |
新增商品接口:
请求类型:POST 请求路径:/goods 类型:x-www-form-urlencoded
body 请求参数 :
|
参数名 |
类型 |
必填 |
示例值 |
说明 |
|
name |
string |
是 |
小米手机 |
商品名称 |
|
img |
string |
否 |
img.png |
图片 |
|
describe |
string |
否 |
小米手机 |
商品描述 |
|
price |
number |
是 |
100 |
商品价格 |
|
gain |
number |
是 |
10 |
商品佣金 按总价的百分比设置 |
创建订单接口:
请求类型:POST 请求路径:/order 类型:x-www-form-urlencoded
body 请求参数 :
|
参数名 |
类型 |
必填 |
示例值 |
说明 |
|
user_id |
number |
是 |
10086 |
用户id |
|
goods_id |
number |
是 |
241 |
商品ID |
Gitee仓库地址:fenxiao: 使用Egg.js搭建的三级分销系统