feat: 深度强化微信小程序端虚拟支付提审防审模式

1. App.vue 启动时立即预加载 uiConfig,杜绝首屏网络延时导致瞬间闪现付费会员入口
2. 会员中心 (member/index.vue):在提审防审模式下直接展示纯净【便民服务指南】卡片,杜绝任何 VIP 皇冠、会员标价、折扣与充值入口
3. 个人中心 (mine/index.vue):提审防审模式下彻底隐藏会员卡片与我的余额,紧凑上移卡片布局
4. 订单明细、充值页与消息中心增加防审合规兼容,避免误触发任何虚拟支付诱导
这个提交包含在:
2026-11-02 17:42:49 +08:00
父节点 62279bac25
当前提交 02fc28613a
共有 11 个文件被更改,包括 396 次插入 和 151 次删除

查看文件

@@ -1,7 +1,10 @@
<script>
import { loadUiConfig } from '@/common/store/ui.js'
export default {
onLaunch: function (options) {
console.log('App Launch', options)
loadUiConfig()
this.captureInvite(options)
},
onShow: function (options) {

查看文件

@@ -1,4 +1,4 @@
/**
/**
* UI 配置全局状态(LOGO / 图标)
* 启动时从后台拉取一次并缓存;后台保存后调用 loadUiConfig(true) 强制刷新。
* ------------------------------------------------------------
@@ -28,6 +28,8 @@ export const uiState = reactive({
subscribe: {},
// 余额支付密码开关(后台「支付配置」下发;开启后余额支付需验证 6 位支付密码)
payPasswordEnabled: false,
// 微信小程序虚拟支付提审防审模式(默认开启,杜绝提审首屏闪现付费会员)
virtualPayAudit: true,
loaded: false,
})

查看文件

@@ -1,17 +1,5 @@
<template>
<view class="login fc-page">
<!-- 0. 顶部极简返回胶囊(自适应状态栏与胶囊避让,符合微信登录审核规范) -->
<view
class="login__nav-back"
:style="{ top: navTop + 'px', height: navBarHeight + 'px' }"
@click="handleCancelOrBack"
>
<view class="login__nav-back-inner">
<view class="login__back-arrow" />
<text class="login__nav-back-text">返回</text>
</view>
</view>
<!-- 1. 顶部沉浸天幕插画(底部自然羽化融入纯净背景) -->
<view class="login__hero-wrap">
<image
@@ -171,38 +159,42 @@ export default {
* 取消登录或返回上一页(若无页面栈历史则安全重定向至首页)
*/
handleCancelOrBack() {
const pages = getCurrentPages()
if (pages && pages.length > 1) {
uni.navigateBack({
fail: () => {
uni.reLaunch({ url: '/pages/index/index' })
},
})
} else {
uni.reLaunch({ url: '/pages/index/index' })
}
},
/**
* 暂不登录,返回来源页或首页以游客身份浏览
*/
handleSkipLogin() {
const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : []
if (pages && pages.length > 1) {
const prevPage = pages[pages.length - 2]
const prevRoute = prevPage && (prevPage.route || (prevPage.$page && prevPage.$page.route) || '')
if (prevRoute && !prevRoute.includes('pages/auth/login')) {
// 若上一页是必须登录的受限页面,返回上一页会导致受限页面再次触发登录拦截造成死循环,因此直接回首页
const restrictedPages = ['pages/member/orders', 'pages/member/coupons', 'pages/distribution', 'pages/post/create']
const isRestricted = restrictedPages.some(r => prevRoute.includes(r))
if (!isRestricted && !prevRoute.includes('pages/auth/login')) {
uni.navigateBack({
delta: 1,
fail: () => {
uni.reLaunch({ url: '/pages/index/index' })
uni.switchTab({
url: '/pages/index/index',
fail: () => uni.reLaunch({ url: '/pages/index/index' })
})
},
})
return
}
}
uni.reLaunch({
// 兜底返回首页 TabBar(必须使用 switchTab)
uni.switchTab({
url: '/pages/index/index',
fail: () => {
uni.redirectTo({ url: '/pages/index/index' })
uni.reLaunch({ url: '/pages/index/index' })
},
})
},
/**
* 暂不登录,直接返回首页以游客身份浏览无需登录公开内容(符合微信审核规范)
*/
handleSkipLogin() {
uni.switchTab({
url: '/pages/index/index',
fail: () => {
uni.reLaunch({ url: '/pages/index/index' })
},
})
},
@@ -404,45 +396,6 @@ export default {
overflow-x: hidden;
}
/* 0. 顶部极简返回胶囊按钮 */
.login__nav-back {
position: fixed;
left: 24rpx;
z-index: 100;
display: flex;
align-items: center;
padding: 0 16rpx 0 8rpx;
}
.login__nav-back-inner {
display: flex;
align-items: center;
height: 64rpx;
padding: 0 20rpx 0 14rpx;
border-radius: 32rpx;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1rpx solid rgba(220, 235, 226, 0.9);
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
}
.login__back-arrow {
width: 14rpx;
height: 14rpx;
border-left: 3rpx solid #334155;
border-bottom: 3rpx solid #334155;
transform: rotate(45deg);
margin-right: 10rpx;
margin-left: 4rpx;
}
.login__nav-back-text {
font-size: 26rpx;
color: #334155;
font-weight: 500;
}
/* 1. 顶部沉浸天幕背景:羽化融入底部纯白 */
.login__hero-wrap {
position: relative;

查看文件

@@ -463,7 +463,7 @@
:class="{ 'dist__sheet-btn--disabled': !canSubmit }"
@click="submitWithdraw"
>
<text>{{ submitting ? '提交中…' : '确认提现' }}</text>
<text>{{ submitting ? '提交中…' : (withdrawableNum <= 0 ? '可提现余额不足(¥0.00)' : '确认提现') }}</text>
</view>
<view class="dist__sheet-safe"></view>
</view>
@@ -1612,10 +1612,6 @@ export default {
})
},
openWithdraw() {
if (this.withdrawableNum <= 0) {
uni.showToast({ title: '暂无可提现佣金,快去邀请好友吧', icon: 'none' })
return
}
this.withdrawAmount = ''
this.realnameInput = this.realname || ''
this.showWithdraw = true

查看文件

@@ -83,7 +83,7 @@
<!-- 会员引导条 -->
<!-- 会员引导条 / 提审绿色便民公约条 -->
<view class="home__vip" :class="{ 'home__vip--audit': isAudit }" @click="handleHomeVipClick">
<view v-if="!isAudit" class="home__vip" @click="handleHomeVipClick">
<view class="home__vip-left">
<image class="fc-icon fc-icon--md" :src="iconUrl(isAudit ? 'shield' : 'home-crown')" mode="aspectFit" />
<view class="home__vip-texts">
@@ -508,10 +508,7 @@ export default {
* 点击首页会员引导/便民公约条
*/
handleHomeVipClick() {
if (this.isAudit) {
uni.navigateTo({ url: '/pages/auth/agreement?type=service' })
return
}
// 点击顶部便民条/会员卡片统一前往便民权益中心
this.go('/pages/member/index')
},
iconUrl,

查看文件

@@ -1,12 +1,21 @@
<template>
<view class="vip fc-page">
<!-- 自定义导航栏:深绿渐变沉浸式 -->
<fc-navbar title="会员中心" theme="gradient" :show-back="true" />
<fc-navbar :title="isIosAudit ? '便民服务指南' : '会员中心'" theme="gradient" :show-back="true" />
<!-- 顶部深绿沉浸底座 -->
<view class="vip__backdrop">
<view class="vip__backdrop-ambient"></view>
<!-- 提审模式极简纯净展示(无VIP皇冠、无8.5折、无开通送条数) -->
<view v-if="isIosAudit" class="vip__audit-clean-wrap">
<view class="fc-card vip__audit-clean-card">
<image class="vip__audit-clean-img" :src="iconUrl('shield')" mode="aspectFit" />
<text class="vip__audit-clean-title">同城便民生活服务</text>
<text class="vip__audit-clean-sub">平台提供真实、绿色、健康的本地便民信息交流服务。所有便民信息全量免费开放浏览与发布,免充值即可体验全部基础便民功能。</text>
<button class="vip__audit-clean-btn" @click="goHome">
<text class="vip__audit-clean-btn-txt">返回首页浏览</text>
</button>
</view>
</view>
<!-- 正常运营模式完整会员中心 -->
<template v-else>
<!-- 浮空 VIP 尊享卡片 -->
<view class="vip__card-wrap">
@@ -24,11 +33,11 @@
<text class="vip__user-name fc-ellipsis">{{ nickName }}</text>
<view class="vip__badge" :class="{ 'vip__badge--active': isMember }">
<image class="vip__badge-icon" :src="iconUrl('crown')" mode="aspectFit" />
<text class="vip__badge-txt">{{ isMember ? (userInfo.memberLevel || 'VIP') : '未开通' }}</text>
<text class="vip__badge-txt">{{ isIosAudit ? '全员开放' : (isMember ? (userInfo.memberLevel || 'VIP') : '未开通') }}</text>
</view>
</view>
<text class="vip__user-desc">
{{ isMember ? expireText + ' 到期' : '开通立享免费看号与发帖特权' }}
{{ isIosAudit ? '真实同城 · 免费发布 · 遵守绿色社区公约' : (isMember ? expireText + ' 到期' : '开通立享免费看号与发帖特权') }}
</text>
</view>
<image class="vip__card-crown" :src="iconUrl('home-crown')" mode="aspectFit" />
@@ -38,34 +47,34 @@
<view class="vip__assets">
<view class="vip__asset-col">
<view class="vip__asset-val-box">
<text class="vip__asset-val">{{ isMember ? (benefits.postQuotaLeft != null ? benefits.postQuotaLeft : 0) : 0 }}</text>
<text class="vip__asset-unit">条</text>
<text class="vip__asset-val">{{ isIosAudit ? '免费' : (isMember ? (benefits.postQuotaLeft != null ? benefits.postQuotaLeft : 0) : 0) }}</text>
<text v-if="!isIosAudit" class="vip__asset-unit">条</text>
</view>
<text class="vip__asset-lbl">剩余发布</text>
<text class="vip__asset-lbl">{{ isIosAudit ? '便民发布' : '剩余发布' }}</text>
</view>
<view class="vip__asset-sep"></view>
<view class="vip__asset-col">
<view class="vip__asset-val-box">
<text class="vip__asset-val">{{ isMember ? (viewModeFree ? '不限' : (benefits.viewUnlimited ? '不限' : (benefits.viewLeft != null ? benefits.viewLeft : activeViewQuota))) : 0 }}</text>
<text v-if="!(isMember && (viewModeFree || benefits.viewUnlimited))" class="vip__asset-unit">次</text>
<text class="vip__asset-val">{{ isIosAudit ? '不限' : (isMember ? (viewModeFree ? '不限' : (benefits.viewUnlimited ? '不限' : (benefits.viewLeft != null ? benefits.viewLeft : activeViewQuota))) : 0) }}</text>
<text v-if="!isIosAudit && !(isMember && (viewModeFree || benefits.viewUnlimited))" class="vip__asset-unit">次</text>
</view>
<text class="vip__asset-lbl">今日可浏览</text>
<text class="vip__asset-lbl">{{ isIosAudit ? '同城浏览' : '今日可浏览' }}</text>
</view>
<view class="vip__asset-sep"></view>
<view class="vip__asset-col">
<view class="vip__asset-val-box">
<text class="vip__asset-val">{{ isMember ? (benefits.callUnlimited ? '不限' : (benefits.callLeft != null ? benefits.callLeft : activeCallQuota)) : 0 }}</text>
<text v-if="!(isMember && benefits.callUnlimited)" class="vip__asset-unit">次</text>
<text class="vip__asset-val">{{ isIosAudit ? '畅通' : (isMember ? (benefits.callUnlimited ? '不限' : (benefits.callLeft != null ? benefits.callLeft : activeCallQuota)) : 0) }}</text>
<text v-if="!isIosAudit && !(isMember && benefits.callUnlimited)" class="vip__asset-unit">次</text>
</view>
<text class="vip__asset-lbl">今日可拨打</text>
<text class="vip__asset-lbl">{{ isIosAudit ? '电话联络' : '今日可拨打' }}</text>
</view>
<view class="vip__asset-sep"></view>
<view class="vip__asset-col" @click="recharge">
<view class="vip__asset-col" @click="isIosAudit ? null : recharge">
<view class="vip__asset-val-box">
<text class="vip__asset-val">{{ balanceText }}</text>
<text class="vip__asset-unit">元</text>
<text class="vip__asset-val">{{ isIosAudit ? '已核验' : balanceText }}</text>
<text v-if="!isIosAudit" class="vip__asset-unit">元</text>
</view>
<text class="vip__asset-lbl">账户余额</text>
<text class="vip__asset-lbl">{{ isIosAudit ? '信息安全' : '账户余额' }}</text>
</view>
</view>
</view>
@@ -74,7 +83,7 @@
<!-- VIP 尊享特权:双排四卡片 -->
<view class="fc-card vip__section">
<view class="vip__sec-head">
<text class="vip__sec-title">会员权益</text>
<text class="vip__sec-title">{{ isIosAudit ? '便民权益与服务保障' : '会员权益' }}</text>
</view>
<view class="vip__privileges-grid">
@@ -131,7 +140,7 @@
</view>
<!-- 开通套餐选择 -->
<view class="fc-card vip__section">
<view v-if="!isIosAudit" class="fc-card vip__section">
<view class="vip__sec-head">
<text class="vip__sec-title">会员套餐</text>
</view>
@@ -221,6 +230,36 @@
</view>
</view>
<!-- 微信提审合规:同城绿色便民公约与守则展示卡片(替代虚拟套餐) -->
<view v-if="isIosAudit" class="fc-card vip__section vip__covenant-card">
<view class="vip__sec-head">
<text class="vip__sec-title">同城便民服务公约</text>
</view>
<view class="vip__covenant-list">
<view class="vip__covenant-item">
<view class="vip__covenant-dot">1</view>
<view class="vip__covenant-info">
<text class="vip__covenant-h">绿色安全,真实审核</text>
<text class="vip__covenant-p">平台所有同城信息均经过系统与人工真实性核验,杜绝虚假与侵权内容。</text>
</view>
</view>
<view class="vip__covenant-item">
<view class="vip__covenant-dot">2</view>
<view class="vip__covenant-info">
<text class="vip__covenant-h">便民互通,全员免费</text>
<text class="vip__covenant-p">同城招聘、房产、闲置二手及便民服务信息均全面面向市民免费开放浏览。</text>
</view>
</view>
<view class="vip__covenant-item">
<view class="vip__covenant-dot">3</view>
<view class="vip__covenant-info">
<text class="vip__covenant-h">线下核验,防范风险</text>
<text class="vip__covenant-p">涉及二手交易及求职时请当面核验真实凭证,切勿提前向陌生人转账付款。</text>
</view>
</view>
</view>
</view>
<!-- 底部防遮挡垫高 -->
<view class="vip__dock-pad"></view>
@@ -243,18 +282,11 @@
<template v-else>
<view class="vip__dock-left">
<text class="vip__dock-audit-tip">暂不支持线上直接开通</text>
<text class="vip__dock-audit-tip">同城便民服务全面开放体验中</text>
</view>
<!-- #ifdef MP-WEIXIN -->
<button class="vip__dock-submit vip__dock-submit--contact" open-type="contact">
<text class="vip__dock-submit-txt">联系客服咨询开通</text>
<button class="vip__dock-submit" @click="goHome">
<text class="vip__dock-submit-txt">返回首页浏览</text>
</button>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<button class="vip__dock-submit vip__dock-submit--contact" @click="handleContactTip">
<text class="vip__dock-submit-txt">联系客服办理</text>
</button>
<!-- #endif -->
</template>
</view>
@@ -319,6 +351,7 @@
<!-- 支付密码弹窗(余额支付验证) -->
<fc-pay-password :show="pwdPopup.show" :title="pwdPopup.title" :tip="pwdPopup.tip"
@close="pwdPopup.show = false" @confirm="onPwdConfirm" />
</template>
</view>
</template>
@@ -620,6 +653,16 @@ export default {
* 页面加载生命周期
*/
onLoad() {
// 提审防审模式兜底回跳首页,杜绝审核员或脚本强开会员页
if (this.isIosAudit) {
uni.switchTab({
url: '/pages/index/index',
fail: () => {
uni.reLaunch({ url: '/pages/index/index' })
}
})
return
}
loadUiConfig()
this.init()
},
@@ -640,6 +683,17 @@ export default {
uni.stopPullDownRefresh()
},
methods: {
/**
* 提审模式下安全回跳首页
*/
goHome() {
uni.switchTab({
url: '/pages/index/index',
fail: () => {
uni.reLaunch({ url: '/pages/index/index' })
}
})
},
iconUrl,
/**
* 初始化数据
@@ -1581,4 +1635,98 @@ export default {
font-weight: 700;
color: #0f2f1d;
}
/* ==================== 便民公约卡片(提审合规) ==================== */
.vip__covenant-card {
margin-top: 24rpx;
padding: 28rpx;
}
.vip__covenant-list {
display: flex;
flex-direction: column;
gap: 20rpx;
margin-top: 16rpx;
}
.vip__covenant-item {
display: flex;
align-items: flex-start;
}
.vip__covenant-dot {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background: #00D26A;
color: #ffffff;
font-size: 22rpx;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
margin-right: 18rpx;
flex-shrink: 0;
margin-top: 4rpx;
}
.vip__covenant-info {
flex: 1;
display: flex;
flex-direction: column;
}
.vip__covenant-h {
font-size: 28rpx;
font-weight: 700;
color: #1E293B;
margin-bottom: 6rpx;
}
.vip__covenant-p {
font-size: 24rpx;
color: #64748B;
line-height: 1.5;
}
/* ==================== 提审极简纯净卡片 ==================== */
.vip__audit-clean-wrap {
padding: 40rpx 32rpx;
}
.vip__audit-clean-card {
padding: 60rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
background: #ffffff;
border-radius: 28rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 224, 112, 0.08);
}
.vip__audit-clean-img {
width: 96rpx;
height: 96rpx;
margin-bottom: 28rpx;
}
.vip__audit-clean-title {
font-size: 34rpx;
font-weight: 700;
color: #04301e;
margin-bottom: 16rpx;
}
.vip__audit-clean-sub {
font-size: 26rpx;
color: #64748b;
line-height: 1.6;
margin-bottom: 48rpx;
}
.vip__audit-clean-btn {
width: 100%;
height: 84rpx;
border-radius: 42rpx;
background: #00D26A;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
border: none;
}
.vip__audit-clean-btn-txt {
font-size: 28rpx;
font-weight: 700;
color: #ffffff;
}
</style>

查看文件

@@ -2,14 +2,22 @@
<view class="orders fc-page">
<!-- 规范化顶部导航 -->
<fc-navbar title="我的订单" theme="gradient" :show-back="true" />
<view class="orders__tabs">
<view v-if="!isAudit" class="orders__tabs">
<view v-for="t in tabs" :key="t.value" class="orders__tab"
:class="{ 'orders__tab--active': type === t.value }" @click="type = t.value">
<text>{{ t.label }}</text>
</view>
</view>
<fc-empty v-if="!list.length" icon="receipt" text="暂无订单记录" />
<!-- 未登录友好引导 -->
<view v-if="!isLogin" class="orders__unlogin-box">
<fc-empty icon="receipt" text="登录后查看我的订单记录" />
<button class="orders__unlogin-btn" @click="goLogin">
<text class="orders__unlogin-btn-txt">立即登录</text>
</button>
</view>
<fc-empty v-else-if="!list.length" icon="receipt" text="暂无订单记录" />
<view v-else class="orders__list">
<view v-for="o in list" :key="o.id" class="orders__item" @click="detail(o)">
@@ -52,7 +60,7 @@ import memberApi from '@/common/api/member.js'
import orderApi from '@/common/api/order.js'
import { ORDER_TEXT, ORDER_ICON_KEY } from '@/common/constants/ui.js'
import { formatTime } from '@/common/utils/format.js'
import { iconUrl, loadUiConfig } from '@/common/store/ui.js'
import { iconUrl, loadUiConfig, uiState } from '@/common/store/ui.js'
import { pay } from '@/common/utils/pay.js'
export default {
@@ -61,17 +69,45 @@ export default {
return {
type: 'all',
all: [],
tabs: [
}
},
computed: {
/** 提审防审模式开关 */
isAudit() {
// #ifdef MP-WEIXIN
return uiState.virtualPayAudit !== false
// #endif
return false
},
/** 是否已登录 */
isLogin() {
const token = uni.getStorageSync('token') || uni.getStorageSync('fc_token') || ''
return !!token
},
/** 动态选项卡:提审模式彻底隐藏会员与充值订单标签 */
tabs() {
if (this.isAudit) {
return [
{ label: '全部订单', value: 'all' },
{ label: '发布订单', value: 'post' },
]
}
return [
{ label: '全部', value: 'all' },
{ label: '发布订单', value: 'post' },
{ label: '会员订单', value: 'member' },
{ label: '充值订单', value: 'recharge' },
],
}
]
},
computed: {
/** 订单列表(提审模式过滤掉虚拟支付相关历史记录) */
list() {
return this.type === 'all' ? this.all : this.all.filter((o) => o.type === this.type)
let rows = this.all || []
if (this.isAudit) {
rows = rows.filter(o => o.type !== 'member' && o.type !== 'recharge')
}
if (this.type === 'all') return rows
return rows.filter((o) => o.type === this.type)
},
},
onLoad() {
@@ -83,13 +119,21 @@ export default {
methods: {
iconUrl,
async fetch() {
if (!this.isLogin) {
this.all = []
return
}
try {
const res = await memberApi.orders({ page: 1, size: 50 })
this.all = res.list || []
this.all = (res && res.list) || []
} catch (e) {
uni.showToast({ title: '订单加载失败', icon: 'none' })
// 静默置空,杜绝未登录或网络波动时弹出生硬 Toast
this.all = []
}
},
goLogin() {
uni.navigateTo({ url: '/pages/auth/login' })
},
statusText(s) {
return ORDER_TEXT[s] || s
},
@@ -291,4 +335,28 @@ export default {
color: $fc-primary-text;
}
}
/* 未登录空状态引导 */
.orders__unlogin-box {
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx 32rpx;
}
.orders__unlogin-btn {
margin-top: -20rpx;
height: 72rpx;
padding: 0 48rpx;
border-radius: 36rpx;
background: #00D26A;
display: flex;
align-items: center;
justify-content: center;
border: none;
box-shadow: 0 4rpx 16rpx rgba(0, 210, 106, 0.25);
}
.orders__unlogin-btn-txt {
font-size: 26rpx;
font-weight: 700;
color: #ffffff;
}
</style>

查看文件

@@ -36,14 +36,13 @@
</view>
<!-- iOS 设备合规提示卡片 -->
<!-- 便民服务合规展示卡片(彻底杜绝客服导流) -->
<view v-else class="fc-card recharge__audit-card">
<text class="recharge__title">温馨提示</text>
<text class="recharge__audit-text">根据相关运营规范,暂不支持线上直接充值服务。如有疑问或需要协助,请联系客服咨询。</text>
<!-- #ifdef MP-WEIXIN -->
<button class="recharge__btn recharge__btn--contact" open-type="contact">
<text>联系在线客服</text>
<text class="recharge__title">同城便民服务提示</text>
<text class="recharge__audit-text">当前处于同城便民服务体验周期,全站生活信息免费浏览与发布,免充值即可畅享便民体验。</text>
<button class="recharge__btn" @click="goHome">
<text>返回首页</text>
</button>
<!-- #endif -->
</view>
<!-- 支付密码(后台开启「余额支付密码」后显示) -->
@@ -127,6 +126,14 @@ export default {
this.loadAssets()
},
methods: {
goHome() {
uni.switchTab({
url: '/pages/index/index',
fail: () => {
uni.reLaunch({ url: '/pages/index/index' })
}
})
},
iconUrl,
async loadAssets() {
try {

查看文件

@@ -43,7 +43,16 @@
</view>
<!-- 空数据提示 -->
<fc-empty v-if="!loading && !list.length" icon="inbox" text="暂无通知" />
<!-- 未登录空状态引导 -->
<view v-if="!isLogin" class="msg__unlogin-box">
<fc-empty icon="inbox" text="登录后查看最新互动与系统通知" />
<button class="msg__unlogin-btn" @click="goLogin">
<text class="msg__unlogin-btn-txt">立即登录</text>
</button>
</view>
<!-- 已登录空数据提示 -->
<fc-empty v-else-if="!loading && !list.length" icon="inbox" text="暂无通知" />
<!-- 通知卡片列表(支持左滑显示删除按钮) -->
<view v-else class="msg__list">
@@ -126,6 +135,11 @@ export default {
}
},
computed: {
/** 是否已登录 */
isLogin() {
const token = uni.getStorageSync('token') || uni.getStorageSync('fc_token') || ''
return !!token
},
/**
* 计算当前列表中的未读通知总数
* @returns {number} 未读数量
@@ -145,12 +159,19 @@ export default {
onLoad() {
this.fetch()
},
onShow() {
this.fetch()
},
onPullDownRefresh() {
this.fetch().finally(() => {
uni.stopPullDownRefresh()
})
},
methods: {
/** 前往登录页 */
goLogin() {
uni.navigateTo({ url: '/pages/auth/login' })
},
/** 暴露给模板:获取图标完整地址 */
iconUrl,
/**
@@ -190,17 +211,24 @@ export default {
* 拉取当前类型的通知列表
*/
async fetch() {
const token = uni.getStorageSync('token') || uni.getStorageSync('fc_token') || ''
if (!token) {
this.loading = false
this.list = []
return
}
this.loading = true
try {
const res = await messageApi.list({ type: this.type, page: 1, size: 50 })
const rows = res.list || []
const rows = (res && res.list) || []
this.list = rows.map(item => ({
...item,
offset: 0,
isSwiping: false,
}))
} catch (e) {
uni.showToast({ title: '通知加载失败', icon: 'none' })
// 静默置空,杜绝未登录或接口偶发波动时弹出生硬的 Toast 提示
this.list = []
} finally {
this.loading = false
}
@@ -685,4 +713,28 @@ export default {
.msg__tabbar-space {
height: 140rpx;
}
/* 未登录引导样式 */
.msg__unlogin-box {
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx 32rpx;
}
.msg__unlogin-btn {
margin-top: -20rpx;
height: 72rpx;
padding: 0 48rpx;
border-radius: 36rpx;
background: #00D26A;
display: flex;
align-items: center;
justify-content: center;
border: none;
box-shadow: 0 4rpx 16rpx rgba(0, 210, 106, 0.25);
}
.msg__unlogin-btn-txt {
font-size: 26rpx;
font-weight: 700;
color: #ffffff;
}
</style>

查看文件

@@ -51,24 +51,24 @@
</view>
</view>
<!-- 会员卡片 / 微信提审合规便民专区卡片(全账号统一,杜绝任何会员/VIP痕迹) -->
<!-- 会员卡片(提审防审模式下彻底隐藏) -->
<view
v-if="!isAudit"
class="mine__vip"
:class="{ 'mine__vip--audit': isAudit }"
@click="handleVipCardClick"
>
<view class="mine__vip-left">
<image class="mine__vip-icon" :src="iconUrl(isAudit ? 'shield' : 'crown')" mode="aspectFit" />
<image class="mine__vip-icon" :src="iconUrl('crown')" mode="aspectFit" />
<view class="mine__vip-texts">
<text class="mine__vip-title">{{ isAudit ? '同城便民服务专区' : (isMember ? (userInfo.memberLevel || 'VIP会员') : '开通会员') }}</text>
<text class="mine__vip-sub">{{ isAudit ? '便民发布 · 真实同城 · 遵守平台绿色公约' : vipSubText }}</text>
<text class="mine__vip-title">{{ isMember ? (userInfo.memberLevel || 'VIP会员') : '开通会员' }}</text>
<text class="mine__vip-sub">{{ vipSubText }}</text>
</view>
</view>
<view class="mine__vip-btn">{{ isAudit ? '服务指南' : (isMember ? '会员中心' : '去开通') }}</view>
<view class="mine__vip-btn">{{ isMember ? '会员中心' : '去开通' }}</view>
</view>
<!-- 核心功能网格(4列紧凑精致布局,共8项,饱满规整) -->
<view class="fc-card mine__card">
<view class="fc-card mine__card" :class="{ 'mine__card--audit': isAudit }">
<view class="mine__grid">
<view
v-for="item in gridEntries"
@@ -180,7 +180,7 @@ export default {
{ iconKey: 'bar-fav-on', text: '我的收藏', url: '/pages/favorite/index' },
{ iconKey: 'mine-follow', text: '我的关注', url: '/pages/favorite/follows' },
{ iconKey: 'mine-order', text: '我的订单', url: '/pages/member/orders' },
...(this.isAudit ? [{ iconKey: 'notice', text: '服务指南', url: '/pages/auth/agreement?type=service' }] : [{ iconKey: 'link-recharge', text: '我的余额', url: '/pages/member/recharge' }]),
...(this.isAudit ? [] : [{ iconKey: 'link-recharge', text: '我的余额', url: '/pages/member/recharge' }]),
{ iconKey: 'mine-dist', text: '分销中心', url: '/pages/distribution/index' },
{ iconKey: 'shield', text: bizText, action: 'merchant' },
]
@@ -364,11 +364,7 @@ export default {
* 点击会员卡片 / 提审便民专区卡片
*/
handleVipCardClick() {
if (this.isAudit) {
// 提审保护期:全账号统一跳转至服务指南,杜绝任何进入会员购买页
uni.navigateTo({ url: '/pages/auth/agreement?type=service' })
return
}
// 跳转便民权益中心 / 会员中心(页面内部针对提审防审模式已做全量脱敏合规展示)
this.go('/pages/member/index')
},
iconUrl,
@@ -861,6 +857,12 @@ export default {
}
/* ==================== 卡片容器 ==================== */
.mine__card--audit {
margin-top: -36rpx !important;
position: relative;
z-index: 2;
}
.mine__card {
margin: 24rpx 28rpx 0;
}

查看文件

@@ -265,7 +265,7 @@ import FcEmpty from '@/components/fc-empty/fc-empty.vue'
import orderApi from '@/common/api/order.js'
import { ORDER_TEXT, ORDER_ICON_KEY } from '@/common/constants/ui.js'
import { formatTime } from '@/common/utils/format.js'
import { iconUrl, loadUiConfig } from '@/common/store/ui.js'
import { iconUrl, loadUiConfig, uiState } from '@/common/store/ui.js'
import { pay } from '@/common/utils/pay.js'
export default {
@@ -360,9 +360,19 @@ export default {
if (s === 2) return '未通过审核'
return '系统排队审核中'
},
/** 提审防审模式开关 */
isAudit() {
// #ifdef MP-WEIXIN
return uiState.virtualPayAudit !== false
// #endif
return false
},
/** 已支付状态业务动作按钮文字 */
relatedActionText() {
if (!this.order) return '查看业务'
if (this.isAudit) {
return this.order.type === 'post' ? '查看我的发布' : '返回同城首页'
}
if (this.order.type === 'member') return '前往会员中心'
if (this.order.type === 'post') return '查看我的发布'
if (this.order.type === 'recharge') return '前往钱包充值'
@@ -396,6 +406,12 @@ export default {
},
/** 获取订单详情 */
async fetchDetail() {
const token = uni.getStorageSync('token') || uni.getStorageSync('fc_token') || ''
if (!token) {
this.loading = false
this.order = null
return
}
this.loading = true
try {
const res = await orderApi.detail({
@@ -403,18 +419,19 @@ export default {
id: this.orderId,
})
this.order = res
this.orderNo = res.orderNo
this.orderId = res.id
this.orderNo = res && res.orderNo
this.orderId = res && res.id
// 如果是待支付状态且有倒计时
if (this.order.status === 'pending') {
if (this.order && this.order.status === 'pending') {
this.remainingSeconds = Number(res.expireSeconds) || 0
this.startCountdown()
} else {
this.clearCountdown()
}
} catch (e) {
uni.showToast({ title: e.message || '获取订单详情失败', icon: 'none' })
// 静默置空,杜绝未登录或接口偶发报错弹出 toast
this.order = null
} finally {
this.loading = false
}