feat: 马豆全端展示统一为整数格式
这个提交包含在:
@@ -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>
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户