feat: 马豆全端展示统一为整数格式

这个提交包含在:
chen
2026-09-17 15:22:07 +08:00
父节点 4ac6b9034a
当前提交 4ae2b1688c
共有 11 个文件被更改,包括 65 次插入 和 46 次删除

查看文件

@@ -282,9 +282,9 @@ class DailySettleService
'gmv' => number_format($gmv, 2, '.', ''),
'rate' => number_format($rate, 8, '.', ''),
'madow' => [
'pool' => number_format($madowPool, 2, '.', ''),
'pool' => IdentityService::formatMadow($madowPool),
'user_count' => $tasterCount,
'each' => $madowEach,
'each' => IdentityService::formatMadow($madowEach),
],
'venue' => [
'pool' => number_format($venuePool, 2, '.', ''),

查看文件

@@ -23,6 +23,7 @@ class IdentityService
$level = intval(is_array($agent) ? ($agent['level'] ?? 0) : ($agent->level ?? 0));
$isVenue = intval(is_array($agent) ? ($agent['is_venue'] ?? 0) : ($agent->is_venue ?? 0));
$isCounty = intval(is_array($agent) ? ($agent['is_county'] ?? 0) : ($agent->is_county ?? 0));
$isPartner = intval(is_array($agent) ? ($agent['is_partner'] ?? 0) : ($agent->is_partner ?? 0));
$identities = [];
$parts = [];
@@ -33,35 +34,33 @@ class IdentityService
} elseif ($level >= 2) {
$identities[] = 'maker';
$makerLevelName = '创客V' . ($level - 1);
$parts[] = $makerLevelName;
}
if ($isVenue) {
$identities[] = 'venue';
$parts[] = '酒道馆';
}
if ($isCounty) {
$identities[] = 'county';
$parts[] = '区县代理';
}
if ($isPartner) {
$identities[] = 'partner';
$parts[] = '合伙股东';
}
$isPartner = in_array('maker', $identities) || in_array('venue', $identities) || in_array('county', $identities);
if ($isPartner) {
$parts[] = '合伙股东';
if ($makerLevelName) {
$parts[] = $makerLevelName;
}
if ($isVenue) {
$parts[] = '酒道馆';
}
if ($isCounty) {
$parts[] = '区县代理';
}
} elseif ($level == 1) {
// 若无进阶角色身份且等级为1,则身份为基础品酒师
if (empty($parts) && $level == 1) {
$parts[] = '品酒师';
}
$isAdvanced = ($level >= 2) || ($isVenue == 1) || ($isCounty == 1) || ($isPartner == 1);
return [
'identities' => $identities,
'identity_text' => implode(' · ', $parts),
'is_partner' => $isPartner,
'is_partner' => (bool) $isPartner,
'is_advanced' => $isAdvanced,
'maker_level_name' => $makerLevelName,
];
}
@@ -73,7 +72,7 @@ class IdentityService
public static function formatMadow($value)
{
return number_format((float) $value, 8, '.', '');
return number_format((float) $value, 0, '.', '');
}
public static function formatRate($value)
@@ -127,7 +126,7 @@ class IdentityService
'identities' => [],
'is_partner' => false,
'maker_level_name' => '',
'madow' => '0.00000000',
'madow' => '0',
'madow_rate' => self::formatRate($baseRate),
'madow_value' => '0.00',
'voucher_available' => '0.00',
@@ -141,6 +140,7 @@ class IdentityService
'identity_text' => $full['identity_text'],
'identities' => $full['identities'],
'is_partner' => $full['is_partner'],
'is_advanced' => $full['is_advanced'] ?? false,
'maker_level_name' => $full['maker_level_name'],
'madow' => $full['madow'],
'madow_rate' => $full['madow_rate'],

查看文件

@@ -62,7 +62,7 @@ class Dashboard extends Common
})
];
// 2. 合伙股东基础数据 (保持向下兼容)
// 2. 收益中心成员基础数据 (保持向下兼容)
$agentData = [
'total' => Agent::count(),
'today' => Agent::whereTime('createtime', 'today')->count(),
@@ -307,7 +307,7 @@ class Dashboard extends Common
'badge' => '普',
'color' => '#8c8c8c',
'user_count' => $normalUserCount,
'madow_total' => '0.00000000',
'madow_total' => '0',
'madow_cny' => '0.00',
'madow_cny_raw' => 0.0,
'reward_amount' => '0.00',
@@ -448,9 +448,9 @@ class Dashboard extends Common
foreach ($allAgents as $ag) {
$identityData = IdentityService::build($ag);
// 核心业务规范:合伙股东仅是会员体系下的专属进阶身份(创客V1~V6、酒道馆、区县代理)
// 普通会员与品酒师属于基础会员,无需自购考核,排除在股东自购掉队雷达之外
if (empty($identityData['is_partner'])) {
// 核心业务规范:进阶角色(创客V1~V6、酒道馆、区县代理、合伙股东)需按月履行自购以维持分润资格
// 普通会员与品酒师属于基础会员,无需自购考核,排除在自购掉队雷达之外
if (empty($identityData['is_advanced'])) {
continue;
}
$partnerShareholderCount++;
@@ -579,7 +579,7 @@ class Dashboard extends Common
$riskSuggestions[] = "分成支出占比 {$payoutRate}% 超出常规合理范围,请检查各层级分成与日结奖励设置。";
}
if ($warningPartnersCount > 0) {
$riskSuggestions[] = "有 {$warningPartnersCount} 位合伙股东 7 天内自购即将到期,建议及时提醒自购维持资格。";
$riskSuggestions[] = "有 {$warningPartnersCount} 位进阶成员(创客/馆/县/股东)7 天内自购即将到期,建议及时提醒自购维持资格。";
}
if ($pendingWithdrawCount > 0) {
$riskSuggestions[] = "当前有 {$pendingWithdrawCount} 笔提现申请等待审核(¥{$financeOverview['pending_withdraw_amount']}),请及时处理。";

查看文件

@@ -196,7 +196,7 @@ class Order extends Common
}
/**
* 合伙股东分成明细:即时奖列人;均分只汇总人数/人均
* 收益中心分成明细:即时奖列人;均分只汇总人数/人均
*/
protected function buildPartnerSplit($order)
{
@@ -217,7 +217,7 @@ class Order extends Common
$totalCash = 0;
$totalVoucher = 0;
// 1. 查询合伙股东即时收益流水
// 1. 查询即时收益流水
$rows = \app\admin\model\shopro\partner\Reward::with(['user'])
->where('order_id', $orderId)
->order('id', 'asc')
@@ -357,7 +357,7 @@ class Order extends Common
'user' => null,
'user_count' => 0,
'each_amount' => '0.00',
'each_madow' => '0.00000000',
'each_madow' => '0',
'total_amount' => number_format($platAmount, 2, '.', ''),
'total_madow' => \addons\shopro\service\partner\IdentityService::formatMadow($platMadow),
'amount_text' => $amountText,

查看文件

@@ -83,7 +83,7 @@ class Reward extends Common
'reward_type_text' => $reward['reward_type_text'],
'role_text' => $reward['role_text'] ?? $reward['role'],
'amount' => $reward['amount'],
'madow' => $reward['madow'],
'madow' => \addons\shopro\service\partner\IdentityService::formatMadow($reward['madow']),
'base_amount' => $reward['base_amount'],
'status_text' => $reward['status_text'],
'formula' => $reward['formula'],
@@ -92,6 +92,7 @@ class Reward extends Common
$totalAmount += array_sum(array_column($newDatas, 'amount'));
$totalMadow += array_sum(array_column($newDatas, 'madow'));
if ($pages['is_last_page']) {
$formattedTotalMadow = \addons\shopro\service\partner\IdentityService::formatMadow($totalMadow);
$newDatas[] = [
'id' => '财务合计',
'createtime' => '-',
@@ -101,10 +102,10 @@ class Reward extends Common
'reward_type_text' => '-',
'role_text' => '-',
'amount' => number_format($totalAmount, 2, '.', ''),
'madow' => number_format($totalMadow, 8, '.', ''),
'madow' => $formattedTotalMadow,
'base_amount' => '-',
'status_text' => '已汇总',
'formula' => "总现金: {$totalAmount}, 总马豆: {$totalMadow}",
'formula' => "总现金: {$totalAmount}, 总马豆: {$formattedTotalMadow}",
];
}
return $newDatas;

查看文件

@@ -20,4 +20,9 @@ class DailyReport extends Common
2 => '重跑中',
];
}
public function getMadowPoolAttr($value)
{
return \addons\shopro\service\partner\IdentityService::formatMadow($value);
}
}

查看文件

@@ -86,6 +86,11 @@ class Reward extends Common
return $ext['formula'] ?? '';
}
public function getMadowAttr($value)
{
return \addons\shopro\service\partner\IdentityService::formatMadow($value);
}
public function buyer()
{
return $this->belongsTo(UserModel::class, 'buyer_id', 'id')->field('id, nickname, avatar, mobile');

查看文件

@@ -1,7 +1,7 @@
# 收益中心 · 全场景关系链收益模拟与财务测算文档
> **版本**:v2.0(基于二开核心代码与真实配置)
> **编制依据**:恒联数通「收益中心」(合伙股东)底层服务组件(`addons/shopro/service/partner/`)及单元测试集(`tests/partner/`)
> **编制依据**:恒联数通「收益中心」底层服务组件(`addons/shopro/service/partner/`)及单元测试集(`tests/partner/`)
> **适用对象**:系统架构师、财务总监、风控专家、产品经理及平台管理员
---
@@ -40,10 +40,11 @@
| **即时奖** | 区县代理统筹奖 | `team_county`| 有馆分 50 元,无馆独享 100 元 | 向上首个区县代理(含买家本人自购) | 订单支付即时到账 |
| **即时奖** | 馆/县协同奖(平级)| `venue_peer` / `county_peer` | 每代 10%(`0.10`),递减级联,低于 0.10 元截断 | 获得运营奖之上的同级上位馆或县代理 | 订单支付即时到账 |
| **资产权益**| 产品兑换券计划 | `voucher_grant` | 实付金额 $\times 1.5$ 倍,按 365 天等额释放 | 买家本人(商城提货抵扣券,非提现现金) | 支付次日起按日释放 |
| **日结奖** | 全网马豆均分池 | `madow_share` | 当日 GMV $1:1$ 转换为马豆,均分给合格会员 | 过去 30 天有自购的品酒师及以上会员 | 次日 00:30 定时任务 |
| **日结奖** | 全网马豆均分池 | `madow_share` | 当日 GMV $1:1$ 转换为马豆,均分给合格会员(对外统一显示为整数) | 过去 30 天有自购的品酒师及以上会员 | 次日 00:30 定时任务 |
| **日结奖** | 酒道馆日结分红池 | `venue_share` | 全网合格单数 $\times 100$ 元,均分给合格酒道馆 | 过去 30 天有自购的酒道馆 | 次日 00:30 定时任务 |
| **日结奖** | 区县代理日结分红池| `county_share`| 全网合格单数 $\times 50$ 元,均分给合格区县代理 | 过去 30 天有自购的区县代理 | 次日 00:30 定时任务 |
| **资产增值**| 马豆浮动定价汇率 | `madow_rate` | $\text{Rate} = 0.00000075 \times N$($N$ 为全网累计完成单数) | 随全网单数单向递增,支持现金兑换 | 实时动态变动 |
| **显示规范**| 马豆数量展示规范 | `madow_display`| 统一显示为纯整数(四舍五入或向下取整),底层高精度运算防尾差 | 全平台仪表盘、列表、个人中心一致 | 全端强制规范 |
| **保活约束**| 业务活跃周期 | `active_days` | 30 天(720 小时) | 自购订单付款即刷新保活时间,未保活跳过并沉淀 | 系统级前置过滤 |
---
@@ -378,7 +379,7 @@
| 日结奖项 | 资金池形成规则 | 当日总池规模 | 参评达标人数 | 人均实际分配 | 结算账户与流向 | 财务属性 |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| **全网马豆均分池** | 当日 GMV $1:1$ 转换为马豆 | **279,600 豆** | 800 人 | **349.50000000 豆/人** | 会员马豆账户 | 平台记账资产凭证,无即时法币支出 |
| **全网马豆均分池** | 当日 GMV $1:1$ 转换为马豆 | **279,600 豆** | 800 人 | **350 豆/人 (按整数显示)** | 会员马豆账户 | 平台记账资产凭证,无即时法币支出 |
| **酒道馆平台均分池** | 当日单数 $\times 100$ 元/单 | **¥ 20,000.00** | 40 家 | **¥ 500.00 / 馆** | 佣金钱包 | 平台实发现金支出 |
| **区县代理平台均分池**| 当日单数 $\times 50$ 元/单 | **¥ 10,000.00** | 10 家 | **¥ 1,000.00 / 县** | 佣金钱包 | 平台实发现金支出 |
@@ -388,7 +389,7 @@ $$\text{Rate} = 0.00000075 \times N$$
1. **当前状态($N = 50,000$ 单)**:
- 即时汇率:$\text{Rate} = 0.00000075 \times 50,000 = \mathbf{0.0375\text{ 元/豆}}$。
- 会员当日获得 349.5 豆的理论资产价值:$349.5 \times 0.0375 \approx \mathbf{13.11\text{ 元}}$。
- 会员当日获得约 350 豆(精算值 349.5 豆)的理论资产价值:$349.5 \times 0.0375 \approx \mathbf{13.11\text{ 元}}$。
2. **中期成长($N = 200,000$ 单)**:
- 即时汇率:$\text{Rate} = 0.00000075 \times 200,000 = \mathbf{0.1500\text{ 元/豆}}$。
- 会员早期持有的 10,000 豆价值:$10,000 \times 0.15 = \mathbf{1,500.00\text{ 元}}$(资产升值 4 倍)。

查看文件

@@ -23,12 +23,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
avg_order_amount: '0.00'
},
madow: {
total_madow: '0.00000000',
total_madow: '0',
current_rate: '0.0000000000',
rate_per_wan: '0.0000',
total_madow_cny: '0.00',
history_order_n: 0,
yesterday_madow_pool: '0.00000000'
yesterday_madow_pool: '0'
},
voucher: {
total_voucher: '0.00',
@@ -113,9 +113,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
color: '#409EFF',
color1: 'rgba(64, 158, 255, 0.4)',
color2: ' rgba(64, 158, 255, 0)',
title: '合伙股东数量',
title: '成员档案数量',
tip: '今日新增人数',
footer: '本周新增股东人数',
footer: '本周新增成员人数',
},
share: {
data: {},
@@ -290,7 +290,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
orderArr: [],
splitStructure: [],
rewardDetails: [],
periodMadow: '0.00000000',
periodMadow: '0',
},
});
@@ -379,7 +379,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
chart.data.orderArr = res.data.orderArr || [];
chart.data.splitStructure = res.data.splitStructure || [];
chart.data.rewardDetails = res.data.rewardDetails || [];
chart.data.periodMadow = res.data.periodMadow || '0.00000000';
chart.data.periodMadow = res.data.periodMadow || '0';
initChart();
initSplitPie();
@@ -805,13 +805,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
} else if (item.filter_type === 'county') {
onOpenTab('shopro/commission/agent/index?is_county=1', '区县代理档案');
} else if (item.filter_type === 'partner') {
onOpenTab('shopro/commission/agent/index', '合伙股东档案');
onOpenTab('shopro/commission/agent/index?is_partner=1', '合伙股东档案');
} else if (item.filter_level === 'maker') {
onOpenTab('shopro/commission/agent/index', '创客团队档案');
} else if (item.filter_level) {
onOpenTab(`shopro/commission/agent/index?level=${item.filter_level}`, `${item.role_name}成员`);
} else {
onOpenTab('shopro/commission/agent/index', '合伙股东档案');
onOpenTab('shopro/commission/agent/index', '成员档案');
}
}

查看文件

@@ -5,7 +5,7 @@
<view class="card-head ss-flex ss-col-center">
<view class="card-title">马豆数量</view>
</view>
<view class="money-num ss-m-t-24">{{ state.info.madow || '0' }}</view>
<view class="money-num ss-m-t-24">{{ formatInt(state.info.madow) }}</view>
<view class="card-sub ss-m-t-16">
当前汇率 1 马豆 = {{ state.info.madow_rate || '0' }} 元
</view>
@@ -29,7 +29,7 @@
<view class="title-box ss-flex ss-row-between ss-m-b-12">
<text class="title">每日贡献马豆</text>
<view class="money">
<text class="add">+{{ item.madow || item.amount || '0' }}</text>
<text class="add">+{{ formatInt(item.madow || item.amount) }}</text>
</view>
</view>
<view class="desc">
@@ -77,6 +77,12 @@
showHelp: false,
});
function formatInt(val) {
if (val === '' || val === null || val === undefined || val === '--') return '0';
const num = Math.floor(parseFloat(val) || 0);
return String(num);
}
function pickList(payload) {
if (!payload) return [];
if (Array.isArray(payload)) return payload;

查看文件

@@ -82,7 +82,8 @@
const displayMadow = computed(() => {
const value = userInfo.value?.madow;
if (value === '' || value === null || value === undefined || value === '--') return '0';
return value;
const num = Math.floor(parseFloat(value) || 0);
return String(num);
});
</script>