在 tigshop 单商户版里翻分销功能,会看到一个挺微妙的状态。php/app/model/salesman/ 下 Salesman、SalesmanOrder、SalesmanCustomer、SalesmanProduct 这些模型都在,表结构也齐;但 php/app/api/controller/ 里没有 salesman 目录,php/app/service/admin/ 下也没有 salesman 这一层。
也就是说,分销中心是 Pro 功能,开源版只给你留了数据层,C 端一个接口没有。官网功能清单里"多级分销、分销中心、推广海报"后面确实都标着 (Pro)。
这次客户只要个最简单的一级返佣加"我的分销中心",没必要为这个上 Pro。我照着 model 已有的字段,把 C 端接口补了出来。
先认字段
建表的功夫省了,salesman_order 表该有的都定义好了。翻一下实际列名,别想当然:
-- salesman_order 实际字段(数据库里已有)
salesman_order_id int -- 主键
order_id int -- 订单ID
salesman_id int -- 分销员ID
amount decimal(10,2)-- 收益总额(注意是 amount,不是 commission_amount)
order_amount decimal(10,2)-- 订单商品金额
status tinyint -- 0待结算 1已结算
salesman_settlement_data text -- 结算配置快照(json)
我一开始按习惯写了 commission_amount,跑起来报字段不存在,翻表才发现佣金列叫 amount。SalesmanCustomer 记录"谁是谁拉来的",salesman_id 对 user_id,绑定关系一有,返佣就有依据。
补 C 端 Service
tigshop 前台 Service 放 php/app/service/front/,新建 salesman/SalesmanCenterService.php,把"我的分销数据"聚合出来:
<?php
namespace app\service\front\salesman;
use app\model\salesman\Salesman;
use app\model\salesman\SalesmanOrder;
use app\model\salesman\SalesmanCustomer;
class SalesmanCenterService
{
// 分销中心首页数据
public function overview(int $userId): array
{
$salesman = Salesman::where('user_id', $userId)->find();
if (!$salesman) {
return ['is_salesman' => 0];
}
$sid = $salesman->salesman_id;
return [
'is_salesman' => 1,
'salesman_id' => $sid,
'customer_count' => SalesmanCustomer::where('salesman_id', $sid)->count(),
'total_commission'=> SalesmanOrder::where('salesman_id', $sid)
->where('status', 1)->sum('amount'),
'wait_commission' => SalesmanOrder::where('salesman_id', $sid)
->where('status', 0)->sum('amount'),
];
}
// 我的返佣订单
public function orderList(int $userId, int $page, int $size): array
{
$salesman = Salesman::where('user_id', $userId)->find();
if (!$salesman) return ['records' => [], 'total' => 0];
$query = SalesmanOrder::where('salesman_id', $salesman->salesman_id)
->with(['orderUserInfo'])
->order('salesman_order_id', 'desc');
return [
'records' => $query->page($page, $size)->select(),
'total' => $query->count(),
];
}
}
orderUserInfo 是 SalesmanOrder 模型里现成的关联,能带出订单号、金额这些,不用自己 join。
补 C 端 Controller
照 tigshop 现有 controller 的写法:继承 IndexBaseController、构造注入 Service、返回 $this->success()。用户 id 直接从 request()->userId 取,跟 Address 那些控制器一致:
<?php
namespace app\api\controller\user;
use app\api\IndexBaseController;
use app\service\front\salesman\SalesmanCenterService;
use think\App;
use think\Response;
class Salesman extends IndexBaseController
{
protected SalesmanCenterService $service;
public function __construct(App $app, SalesmanCenterService $service)
{
parent::__construct($app);
$this->service = $service;
}
public function center(): Response
{
$this->checkLogin();
return $this->success($this->service->overview(request()->userId));
}
public function orderList(): Response
{
$this->checkLogin();
$page = $this->request->all('page/d', 1);
$size = $this->request->all('size/d', 15);
return $this->success($this->service->orderList(request()->userId, $page, $size));
}
}
挂路由
跟着 php/app/api/route/user.php 里 address / aftersales 那几组的写法加一段:
Route::group('salesman', function () {
Route::get('center', 'user.salesman/center');
Route::get('orderList', 'user.salesman/orderList');
})->middleware([\app\api\middleware\CheckLogin::class]);
返佣在哪触发
绑定关系有了,得在订单支付成功后记一笔返佣。tigshop 的支付回调在 php/app/api/controller/order/Pay.php 的 notify,成功后我加了个钩子写 salesman_order:
// 支付成功后:给上级分销员记一笔待结算
$customer = SalesmanCustomer::where('user_id', $order['user_id'])->find();
if ($customer) {
SalesmanOrder::create([
'salesman_id' => $customer->salesman_id,
'order_id' => $order['order_id'],
'amount' => bcmul($order['total_amount'], '0.10', 2), // 一级 10%
'status' => 0, // 待结算,确认收货后再转 1
]);
}
字段用 amount,别再写成 commission_amount。确认收货或者售后期过了,再跑个定时任务把 status 从 0 改成 1,宝塔计划任务加个 php think 命令定时扫一遍就行。
前端 Uniapp 分销中心页
Uniapp 的 api 定义统一放 view/Tigshop-Uniapp/src/api,我加了个 salesman.ts:
// src/api/salesman.ts
import request from '@/utils/request'
export const getSalesmanCenter = () => request.get('/api/user/salesman/center')
export const getSalesmanOrders = (page = 1) =>
request.get('/api/user/salesman/orderList', {
page })
页面 src/pages/salesman/center.vue 拉数据展示:
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { getSalesmanCenter } from '@/api/salesman'
const info = ref<any>({})
onMounted(async () => { info.value = (await getSalesmanCenter()).data })
</script>
<template>
<view v-if="info.is_salesman" class="center">
<view>累计佣金:{
{ info.total_commission }}</view>
<view>待结算:{
{ info.wait_commission }}</view>
<view>我的客户:{
{ info.customer_count }} 人</view>
</view>
<view v-else>你还不是分销员</view>
</template>
这只补了一级返佣加分销中心,多级、团队、推广素材那些还是 Pro 的完整功能。但客户只想给老客户开个返佣的话,这几处改完就能跑。model 层留得全,补 C 端不用建表;真要做多级,可以顺着 SalesmanOrder 的 salesman_settlement_data 这个 json 字段往里塞层级快照。