feat: 新增会员浏览/拨打额度并优化无图展示逻辑

新增会员每日浏览完整信息和拨打电话的额度配置,调整付费查看接口描述为解锁完整信息,优化帖子无图时的兜底展示逻辑,修复图片加载路径问题,删除废弃工具脚本。
这个提交包含在:
2026-10-28 11:06:39 +08:00
父节点 bb6418f51b
当前提交 111054d984
共有 179 个文件被更改,包括 931 次插入 和 6265 次删除

查看文件

@@ -17,7 +17,7 @@ use app\common\library\DistributionService;
class Member extends V1
{
/**
* M1 会员套餐(套餐价格 + 赠送发帖数 + 每日免费看次数 + 超额发帖折扣 一体化返回)
* M1 会员套餐(套餐价格 + 赠送发帖数 + 每日浏览/拨打次数 + 超额发帖折扣 一体化返回)
* GET /api/v1/member/plans
* 规则:仅 enabled=1,按 sort asc
*/
@@ -30,7 +30,8 @@ class Member extends V1
$list = [];
foreach ($rows as $row) {
$freeViewQuota = isset($row['free_view_quota']) ? max(0, (int)$row['free_view_quota']) : 20;
$viewQuota = isset($row['view_quota']) ? max(0, (int)$row['view_quota']) : 20;
$callQuota = isset($row['call_quota']) ? max(0, (int)$row['call_quota']) : 30;
$discountNum = isset($row['post_discount']) ? \app\common\library\FcConfig::parseDiscountNum($row['post_discount']) : 8.0;
$list[] = [
'planId' => (string)$row['plan_code'],
@@ -40,8 +41,10 @@ class Member extends V1
'days' => (int)$row['days'],
'tag' => (string)$row['tag'],
'postQuota' => isset($row['post_quota']) ? (int)$row['post_quota'] : 0,
'freeViewQuota' => $freeViewQuota,
'freeViewUnlimited' => ($freeViewQuota === 0),
'viewQuota' => $viewQuota,
'viewUnlimited' => ($viewQuota === 0),
'callQuota' => $callQuota,
'callUnlimited' => ($callQuota === 0),
'postDiscountNum' => $discountNum,
'postDiscount' => \app\common\library\FcConfig::formatDiscountText($discountNum),
'benefits' => \app\common\library\FcConfig::buildPlanBenefits($row),
@@ -61,8 +64,10 @@ class Member extends V1
$ext = $me ? $this->ext($me['id']) : null;
$benefitCfg = \app\common\library\FcConfig::resolveMemberBenefit($ext);
$freeViewQuota = (int)$benefitCfg['freeView'];
$freeViewUnlimited = ($freeViewQuota === 0);
$viewQuota = (int)$benefitCfg['viewQuota'];
$viewUnlimited = ($viewQuota === 0);
$callQuota = (int)$benefitCfg['callQuota'];
$callUnlimited = ($callQuota === 0);
$postDiscountNum = (float)$benefitCfg['postDiscountNum'];
$postDiscount = (string)$benefitCfg['postDiscount'];
$benefits = (array)$benefitCfg['benefits'];
@@ -79,8 +84,10 @@ class Member extends V1
$viewMode = ($viewModeRaw === 'free' || $payViewPrice <= 0) ? 'free' : 'paid';
$isMember = false;
$freeViewUsed = 0;
$freeViewLeft = 0;
$viewUsed = 0;
$viewLeft = 0;
$callUsed = 0;
$callLeft = 0;
$postQuotaLeft = 0;
$memberExpireAt = null;
@@ -89,15 +96,27 @@ class Member extends V1
$isMember = (int)$ext['is_member'] === 1
&& !empty($ext['member_expiretime']) && (int)$ext['member_expiretime'] > $now;
$today = date('Y-m-d');
$freeViewUsed = ((string)$ext['free_view_date'] === $today) ? (int)$ext['free_view_used'] : 0;
$freeViewLeft = $isMember ? ($freeViewUnlimited ? -1 : max(0, $freeViewQuota - $freeViewUsed)) : 0;
if ($isMember) {
$viewUsed = (int)Db::name('fc_view_log')
->where('user_id', (int)$me['id'])
->where('view_date', $today)
->count();
$viewLeft = $viewUnlimited ? -1 : max(0, $viewQuota - $viewUsed);
$callUsed = (int)Db::name('fc_call_log')
->where('user_id', (int)$me['id'])
->where('call_date', $today)
->count();
$callLeft = $callUnlimited ? -1 : max(0, $callQuota - $callUsed);
}
$postQuotaLeft = $this->quotaLeft($ext);
$memberExpireAt = !empty($ext['member_expiretime']) ? $this->iso($ext['member_expiretime']) : null;
}
$this->ok([
'freeView' => $freeViewQuota,
'freeViewUnlimited' => $freeViewUnlimited,
'viewQuota' => $viewQuota,
'viewUnlimited' => $viewUnlimited,
'callQuota' => $callQuota,
'callUnlimited' => $callUnlimited,
'postDiscountNum' => $postDiscountNum,
'postDiscount' => $postDiscount,
'maxPlanQuota' => $maxPlanQuota,
@@ -105,9 +124,10 @@ class Member extends V1
'viewMode' => $viewMode,
'benefits' => $benefits,
'isMember' => $isMember,
'freeViewQuota' => $freeViewQuota,
'freeViewUsed' => $freeViewUsed,
'freeViewLeft' => $freeViewLeft,
'viewUsed' => $viewUsed,
'viewLeft' => $viewLeft,
'callUsed' => $callUsed,
'callLeft' => $callLeft,
'postQuotaLeft' => $postQuotaLeft,
'memberExpireAt' => $memberExpireAt,
]);
@@ -276,7 +296,6 @@ class Member extends V1
}
$days = $plan ? max(0, (int)$plan['days']) : 30;
$quota = $plan && isset($plan['post_quota']) ? max(0, (int)$plan['post_quota']) : 0;
$freeViewQuota = $plan && isset($plan['free_view_quota']) ? max(0, (int)$plan['free_view_quota']) : 20;
$postDiscount = $plan && isset($plan['post_discount']) ? round((float)$plan['post_discount'], 1) : 8.0;
$level = $plan ? (string)$plan['name'] : '会员';
@@ -299,7 +318,6 @@ class Member extends V1
'is_member' => 1,
'member_level' => $level,
'member_expiretime' => $expire,
'free_view_quota' => $freeViewQuota,
'post_quota_left' => $left,
'post_quota_expire' => $expire,
'post_discount' => $postDiscount,
@@ -415,13 +433,18 @@ class Member extends V1
];
}
$ext = $this->ext($user['id']);
$isMember = (int)$ext['is_member'] === 1
&& !empty($ext['member_expiretime']) && (int)$ext['member_expiretime'] > $now;
$this->ok([
'balance' => (float)$user['money'],
'isMember' => $isMember,
'coupons' => $coupons,
'couponCount' => count($coupons),
'points' => (int)$user['score'],
'payPasswordEnabled' => (int)$this->cfg('pay.payPasswordEnabled', 0) === 1,
'hasPayPassword' => (string)$this->ext($user['id'])['pay_password'] !== '',
'hasPayPassword' => (string)$ext['pay_password'] !== '',
]);
}