同步
This commit is contained in:
@@ -9,8 +9,8 @@ const { checkAndExecute } = require('./utils/ruleEngine.js')
|
||||
App({
|
||||
globalData: {
|
||||
// API 基础地址(切换环境时注释/取消注释)
|
||||
baseUrl: 'https://soulapi.quwanzhi.com',
|
||||
// baseUrl: 'http://localhost:8080', // 本地调试
|
||||
// baseUrl: 'https://soulapi.quwanzhi.com',
|
||||
baseUrl: 'http://localhost:8080', // 本地调试
|
||||
// baseUrl: 'https://souldev.quwanzhi.com', // 测试环境
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@ Page({
|
||||
detail: null,
|
||||
loading: true,
|
||||
paying: false,
|
||||
isInitiator: false // 是否发起人,发起人看到「分享给好友」UI,好友看到「帮他付款」
|
||||
isInitiator: false,
|
||||
requesterMsg: '',
|
||||
amountDisplay: '0.00' // 预格式化金额,WXML 中 toFixed 可能不生效
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
@@ -35,7 +37,13 @@ Page({
|
||||
if (res && res.success) {
|
||||
const myId = app.globalData.userInfo?.id || ''
|
||||
const isInitiator = !!myId && res.initiatorUserId === myId
|
||||
this.setData({ detail: res, loading: false, isInitiator })
|
||||
const requesterMsg = isInitiator
|
||||
? '分享给好友,好友打开后即可为你完成支付。'
|
||||
: (res.initiatorMsg || `" 请帮我代付「${res.sectionTitle || res.description || '该商品'}」,非常感谢! "`)
|
||||
const amountDisplay = (res.amount != null && res.amount !== '')
|
||||
? Number(res.amount).toFixed(2)
|
||||
: '0.00'
|
||||
this.setData({ detail: res, loading: false, isInitiator, requesterMsg, amountDisplay })
|
||||
} else {
|
||||
this.setData({ loading: false })
|
||||
wx.showToast({ title: res?.error || '加载失败', icon: 'none' })
|
||||
@@ -47,14 +55,24 @@ Page({
|
||||
},
|
||||
|
||||
async doPay() {
|
||||
if (!app.globalData.isLoggedIn || !app.globalData.userInfo) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
setTimeout(() => wx.switchTab({ url: '/pages/my/my' }), 1500)
|
||||
return
|
||||
}
|
||||
const openId = app.globalData.openId || ''
|
||||
// 优先尝试静默获取 openId(有会话时可直接发起支付)
|
||||
let openId = app.globalData.openId || wx.getStorageSync('openId')
|
||||
if (!openId) {
|
||||
wx.showToast({ title: '请先完成微信授权', icon: 'none' })
|
||||
wx.showLoading({ title: '获取支付凭证...', mask: true })
|
||||
openId = await app.getOpenId()
|
||||
wx.hideLoading()
|
||||
}
|
||||
if (!openId) {
|
||||
const { confirm } = await new Promise(r => {
|
||||
wx.showModal({
|
||||
title: '请先登录',
|
||||
content: '登录后可帮他完成代付',
|
||||
confirmText: '去登录',
|
||||
cancelText: '取消',
|
||||
success: res => r(res)
|
||||
})
|
||||
})
|
||||
if (confirm) wx.switchTab({ url: '/pages/my/my' })
|
||||
return
|
||||
}
|
||||
const { requestSn, detail } = this.data
|
||||
@@ -98,7 +116,22 @@ Page({
|
||||
if (e.errMsg && e.errMsg.includes('cancel')) {
|
||||
wx.showToast({ title: '已取消支付', icon: 'none' })
|
||||
} else {
|
||||
wx.showToast({ title: e.message || e.error || '支付失败', icon: 'none' })
|
||||
const errMsg = e.message || e.error || '支付失败'
|
||||
const isPrepayError = /prepay_id|创建订单|支付请求/i.test(errMsg)
|
||||
if (isPrepayError) {
|
||||
const { confirm } = await new Promise(r => {
|
||||
wx.showModal({
|
||||
title: '订单创建失败',
|
||||
content: errMsg + '\n\n是否重新创建订单并重试?',
|
||||
confirmText: '重新创建订单',
|
||||
cancelText: '取消',
|
||||
success: res => r(res)
|
||||
})
|
||||
})
|
||||
if (confirm) this.doPay()
|
||||
} else {
|
||||
wx.showToast({ title: errMsg, icon: 'none' })
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -107,6 +140,20 @@ Page({
|
||||
app.goBackOrToHome()
|
||||
},
|
||||
|
||||
goToInitiatorProfile() {
|
||||
const { detail } = this.data
|
||||
if (!detail?.initiatorUserId) return
|
||||
wx.navigateTo({ url: `/pages/member-detail/member-detail?id=${detail.initiatorUserId}` })
|
||||
},
|
||||
|
||||
goToArticle() {
|
||||
const { detail } = this.data
|
||||
if (!detail || detail.productType !== 'section' || !detail.productId) return
|
||||
const mid = detail.productMid || app.getSectionMid?.(detail.productId)
|
||||
const q = mid ? `mid=${mid}` : `id=${detail.productId}`
|
||||
wx.navigateTo({ url: `/pages/read/read?${q}` })
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
const { requestSn } = this.data
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- Soul创业派对 - 代付详情页(美团式:发起人看到分享入口,好友看到帮他付款) -->
|
||||
<!-- Soul创业派对 - 代付详情页(参考 yulan:代付视角+发起视角,忽略 nav) -->
|
||||
<view class="page">
|
||||
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
|
||||
<view class="nav-content">
|
||||
@@ -20,50 +20,55 @@
|
||||
</view>
|
||||
</block>
|
||||
<block wx:elif="{{detail}}">
|
||||
<!-- 营销:章节标题+内容预览,吸引代付人 -->
|
||||
<view class="article-preview" wx:if="{{detail.sectionTitle || detail.contentPreview}}">
|
||||
<text class="article-title">{{detail.sectionTitle || detail.description || '代付商品'}}</text>
|
||||
<text class="article-content" wx:if="{{detail.contentPreview}}">{{detail.contentPreview}}</text>
|
||||
</view>
|
||||
<view class="card">
|
||||
<view class="card-header">
|
||||
<view class="card-badge">代付订单</view>
|
||||
<text class="initiator" wx:if="{{!isInitiator}}">{{detail.initiatorNickname || '好友'}} 请你帮忙付款</text>
|
||||
<text class="initiator" wx:else>分享给好友,好友帮你付款</text>
|
||||
</view>
|
||||
<view class="card-divider"></view>
|
||||
<view class="card-body">
|
||||
<view class="row product-row" wx:if="{{!detail.contentPreview}}">
|
||||
<text class="label">商品</text>
|
||||
<text class="value product-desc">{{detail.sectionTitle || detail.description || '-'}}</text>
|
||||
<!-- 产品 Hero 卡片(订单详情) -->
|
||||
<section class="hero-card">
|
||||
<view class="hero-glow"></view>
|
||||
<view class="hero-inner">
|
||||
<view class="hero-decor">
|
||||
<image class="hero-decor-img" src="/assets/icons/info.svg" mode="aspectFit"/>
|
||||
</view>
|
||||
<view class="row amount-row">
|
||||
<text class="label">金额</text>
|
||||
<text class="amount">¥{{detail.amount ? detail.amount.toFixed(2) : '0.00'}}</text>
|
||||
<view class="hero-badge">订单详情</view>
|
||||
<text class="hero-title">{{detail.sectionTitle || detail.description || '代付商品'}}</text>
|
||||
<text class="hero-desc" wx:if="{{detail.contentPreview}}">{{detail.contentPreview}}</text>
|
||||
<view class="hero-footer">
|
||||
<view class="hero-amount-wrap">
|
||||
<text class="hero-amount-label">应付金额</text>
|
||||
<view class="hero-amount-row">
|
||||
<text class="hero-currency">¥</text>
|
||||
<text class="hero-amount">{{amountDisplay}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hero-arrow-wrap" bindtap="goToArticle" wx:if="{{detail.productType === 'section' && detail.productId}}">
|
||||
<image class="hero-arrow" src="/assets/icons/arrow-right.svg" mode="aspectFit"/>
|
||||
</view>
|
||||
<view class="hero-arrow-wrap hero-arrow-placeholder" wx:else></view>
|
||||
</view>
|
||||
</view>
|
||||
</section>
|
||||
|
||||
<!-- 发起人信息 -->
|
||||
<section class="requester-card">
|
||||
<view class="requester-header" bindtap="goToInitiatorProfile">
|
||||
<view class="requester-avatar">
|
||||
<image wx:if="{{detail.initiatorAvatar}}" class="avatar-img" src="{{detail.initiatorAvatar}}" mode="aspectFill"/>
|
||||
<image wx:else class="avatar-img icon-avatar" src="/assets/icons/user.svg" mode="aspectFit"/>
|
||||
</view>
|
||||
<view class="requester-info">
|
||||
<text class="requester-name">{{detail.initiatorNickname || '好友'}}</text>
|
||||
<text class="requester-label">发起代付请求</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="requester-msg-wrap">
|
||||
<view class="requester-msg-bar"></view>
|
||||
<text class="requester-msg">{{requesterMsg}}</text>
|
||||
</view>
|
||||
</section>
|
||||
|
||||
<!-- 安全徽章 -->
|
||||
<view class="security-badge">
|
||||
<text class="security-icon">🛡</text>
|
||||
<text class="security-text">安全支付保障 · 资金由平台托管</text>
|
||||
</view>
|
||||
<!-- 发起人:分享给好友 -->
|
||||
<block wx:if="{{isInitiator}}">
|
||||
<view class="tips">
|
||||
<text class="tips-icon">💡</text>
|
||||
<text>分享给好友,好友打开后点击「帮他付款」即可为你代付</text>
|
||||
</view>
|
||||
<button class="pay-btn share-btn" open-type="share">
|
||||
<image class="btn-icon-img" src="/assets/icons/share.svg" mode="aspectFit"/>
|
||||
<text>分享给好友</text>
|
||||
</button>
|
||||
</block>
|
||||
<!-- 好友:帮他付款 -->
|
||||
<block wx:else>
|
||||
<view class="tips">
|
||||
<text class="tips-icon">✓</text>
|
||||
<text>付款后,{{detail.initiatorNickname || '好友'}}将获得对应权益</text>
|
||||
</view>
|
||||
<button class="pay-btn" bindtap="doPay" disabled="{{paying}}">
|
||||
{{paying ? '支付中...' : '帮他付款'}}
|
||||
</button>
|
||||
</block>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<view class="empty">
|
||||
@@ -71,4 +76,34 @@
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 底部浮动操作栏 -->
|
||||
<view class="footer-bar" wx:if="{{detail && !loading}}">
|
||||
<view class="footer-bg"></view>
|
||||
<view class="footer-inner">
|
||||
<view class="footer-summary">
|
||||
<text class="footer-label">合计</text>
|
||||
<text class="footer-amount">
|
||||
<text class="footer-currency">¥</text>{{amountDisplay}}
|
||||
</text>
|
||||
</view>
|
||||
<!-- 发起人:分享给好友 -->
|
||||
<button wx:if="{{isInitiator}}" class="footer-btn share-btn" open-type="share">
|
||||
<image class="btn-icon" src="/assets/icons/share.svg" mode="aspectFit"/>
|
||||
<text>发送给好友</text>
|
||||
</button>
|
||||
<!-- 好友:帮他付款 -->
|
||||
<button wx:else class="footer-btn pay-btn" bindtap="doPay" disabled="{{paying}}">
|
||||
<image class="btn-icon" src="/assets/icons/wallet.svg" mode="aspectFit"/>
|
||||
<text>{{paying ? '支付中...' : '立即帮他付款'}}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 背景光效 -->
|
||||
<view class="bg-effects">
|
||||
<view class="bg-glow bg-glow-1"></view>
|
||||
<view class="bg-glow bg-glow-2"></view>
|
||||
<view class="bg-dots"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* Soul创业派对 - 代付详情页 */
|
||||
/* Soul创业派对 - 代付详情页(参考 yulan 深色主题、青绿主色) */
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #0a0a0a 0%, #000 40%, #000 100%);
|
||||
background: #050505;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
@@ -10,10 +11,10 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: rgba(0, 0, 0, 0.92);
|
||||
backdrop-filter: blur(20rpx);
|
||||
-webkit-backdrop-filter: blur(20rpx);
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.06);
|
||||
background: rgba(5, 5, 5, 0.6);
|
||||
backdrop-filter: blur(40rpx);
|
||||
-webkit-backdrop-filter: blur(40rpx);
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
@@ -32,7 +33,6 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.nav-back:active {
|
||||
@@ -45,16 +45,18 @@
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
letter-spacing: 0.5rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20rpx;
|
||||
padding: 24rpx 24rpx 200rpx;
|
||||
}
|
||||
|
||||
/* 加载 */
|
||||
.loading-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -66,8 +68,8 @@
|
||||
.loading-spinner {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border: 4rpx solid rgba(0, 206, 209, 0.2);
|
||||
border-top-color: #00CED1;
|
||||
border: 4rpx solid rgba(20, 184, 166, 0.2);
|
||||
border-top-color: #14b8a6;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
@@ -82,28 +84,72 @@
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
/* 营销:章节标题+内容预览,与订单卡片统一风格 */
|
||||
.article-preview {
|
||||
background: linear-gradient(145deg, #1a1a1c 0%, #141416 100%);
|
||||
border-radius: 24rpx;
|
||||
/* 产品 Hero 卡片 */
|
||||
.hero-card {
|
||||
position: relative;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.hero-glow {
|
||||
position: absolute;
|
||||
inset: -4rpx;
|
||||
background: linear-gradient(180deg, rgba(20, 184, 166, 0.2) 0%, transparent 100%);
|
||||
border-radius: 40rpx;
|
||||
filter: blur(24rpx);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.hero-inner {
|
||||
position: relative;
|
||||
background: rgba(24, 24, 27, 0.8);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 40rpx;
|
||||
padding: 48rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-decor {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
border: 1rpx solid rgba(0, 206, 209, 0.1);
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.article-title {
|
||||
.hero-decor-img {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
display: inline-block;
|
||||
font-size: 20rpx;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.2em;
|
||||
color: #14b8a6;
|
||||
background: rgba(20, 184, 166, 0.1);
|
||||
border: 1rpx solid rgba(20, 184, 166, 0.2);
|
||||
padding: 6rpx 24rpx;
|
||||
border-radius: 999rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.3;
|
||||
letter-spacing: -0.5rpx;
|
||||
margin: 0 0 16rpx;
|
||||
}
|
||||
|
||||
.article-content {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
line-height: 1.65;
|
||||
.hero-desc {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
@@ -111,154 +157,325 @@
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
/* 订单卡片:与文章预览统一圆角、边距 */
|
||||
.card {
|
||||
background: linear-gradient(145deg, #1a1a1c 0%, #141416 100%);
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24rpx;
|
||||
border: 1rpx solid rgba(0, 206, 209, 0.1);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.card-badge {
|
||||
display: inline-block;
|
||||
font-size: 22rpx;
|
||||
color: rgba(0, 206, 209, 0.9);
|
||||
background: rgba(0, 206, 209, 0.08);
|
||||
padding: 6rpx 14rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 12rpx;
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
|
||||
.initiator {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
line-height: 1.4;
|
||||
letter-spacing: 0.3rpx;
|
||||
}
|
||||
|
||||
.card-divider {
|
||||
height: 1rpx;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
|
||||
margin: 0 24rpx;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 20rpx 24rpx 24rpx;
|
||||
}
|
||||
|
||||
.row {
|
||||
.hero-footer {
|
||||
margin-top: 40rpx;
|
||||
padding-top: 32rpx;
|
||||
border-top: 1rpx solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.hero-amount-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.hero-amount-label {
|
||||
font-size: 20rpx;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.hero-amount-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.hero-currency {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #14b8a6;
|
||||
}
|
||||
|
||||
.hero-amount {
|
||||
font-size: 60rpx;
|
||||
font-weight: 700;
|
||||
font-family: 'JetBrains Mono', 'SF Mono', monospace;
|
||||
color: #fff;
|
||||
letter-spacing: -1rpx;
|
||||
}
|
||||
|
||||
.hero-arrow-wrap {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 32rpx;
|
||||
background: rgba(20, 184, 166, 0.1);
|
||||
border: 1rpx solid rgba(20, 184, 166, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.hero-arrow {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
filter: invert(72%) sepia(45%) saturate(800%) hue-rotate(130deg);
|
||||
}
|
||||
|
||||
/* 发起人信息卡片 */
|
||||
.requester-card {
|
||||
background: rgba(24, 24, 27, 0.3);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.05);
|
||||
border-radius: 48rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
flex-shrink: 0;
|
||||
width: 80rpx;
|
||||
}
|
||||
|
||||
.product-row .value {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
line-height: 1.5;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.product-desc {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.amount-row {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.amount-row .amount {
|
||||
font-size: 44rpx;
|
||||
font-weight: 700;
|
||||
color: #00CED1;
|
||||
letter-spacing: 1rpx;
|
||||
text-shadow: 0 0 24rpx rgba(0, 206, 209, 0.3);
|
||||
}
|
||||
|
||||
/* 提示文案 */
|
||||
.tips {
|
||||
.requester-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10rpx;
|
||||
padding: 0 4rpx 24rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
line-height: 1.5;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.tips-icon {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
opacity: 0.8;
|
||||
.requester-header:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* 主按钮 */
|
||||
.pay-btn {
|
||||
width: 100%;
|
||||
.requester-avatar {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
line-height: 96rpx;
|
||||
background: linear-gradient(135deg, #00CED1 0%, #18a8a8 50%, #20B2AA 100%);
|
||||
color: #fff;
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 50rpx;
|
||||
border: none;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 206, 209, 0.35);
|
||||
transition: opacity 0.2s, transform 0.1s;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, #3f3f46 0%, #18181b 100%);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pay-btn:active {
|
||||
opacity: 0.92;
|
||||
transform: scale(0.99);
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pay-btn[disabled] {
|
||||
opacity: 0.6;
|
||||
transform: none;
|
||||
.icon-avatar {
|
||||
padding: 24rpx;
|
||||
filter: brightness(0) invert(0.6);
|
||||
}
|
||||
|
||||
.share-btn {
|
||||
.requester-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.requester-name {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.requester-label {
|
||||
font-size: 20rpx;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.requester-msg-wrap {
|
||||
position: relative;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.requester-msg-bar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 4rpx;
|
||||
background: rgba(20, 184, 166, 0.3);
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
|
||||
.requester-msg {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
font-style: italic;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 安全徽章 */
|
||||
.security-badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
padding: 32rpx 0;
|
||||
}
|
||||
|
||||
.btn-icon-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
filter: brightness(0) invert(1);
|
||||
.security-icon {
|
||||
font-size: 32rpx;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.security-text {
|
||||
font-size: 20rpx;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
color: rgba(255, 255, 255, 0.35);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding: 120rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
/* 底部浮动操作栏 */
|
||||
.footer-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.footer-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(24, 24, 27, 0.9);
|
||||
backdrop-filter: blur(40rpx);
|
||||
-webkit-backdrop-filter: blur(40rpx);
|
||||
border-top: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 50rpx;
|
||||
box-shadow: 0 -20rpx 100rpx rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.footer-inner {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
padding: 24rpx 24rpx 24rpx 48rpx;
|
||||
}
|
||||
|
||||
.footer-summary {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.footer-label {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.footer-amount {
|
||||
font-size: 40rpx;
|
||||
font-weight: 700;
|
||||
font-family: 'JetBrains Mono', 'SF Mono', monospace;
|
||||
color: #fff;
|
||||
letter-spacing: -1rpx;
|
||||
}
|
||||
|
||||
.footer-currency {
|
||||
font-size: 28rpx;
|
||||
color: #14b8a6;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.footer-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
padding: 32rpx 48rpx;
|
||||
border-radius: 36rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
border: none;
|
||||
box-shadow: 0 16rpx 40rpx rgba(20, 184, 166, 0.3);
|
||||
}
|
||||
|
||||
.footer-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.share-btn {
|
||||
background: #14b8a6;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.pay-btn {
|
||||
background: #14b8a6;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.pay-btn[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.footer-btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.share-btn .btn-icon,
|
||||
.pay-btn .btn-icon {
|
||||
filter: brightness(0);
|
||||
}
|
||||
|
||||
/* 背景光效 */
|
||||
.bg-effects {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.bg-glow {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
filter: blur(150rpx);
|
||||
}
|
||||
|
||||
.bg-glow-1 {
|
||||
top: -20%;
|
||||
left: -10%;
|
||||
width: 80%;
|
||||
height: 60%;
|
||||
background: rgba(20, 184, 166, 0.05);
|
||||
animation: pulse-slow 8s infinite;
|
||||
}
|
||||
|
||||
.bg-glow-2 {
|
||||
bottom: -10%;
|
||||
right: -10%;
|
||||
width: 60%;
|
||||
height: 50%;
|
||||
background: rgba(20, 184, 166, 0.05);
|
||||
}
|
||||
|
||||
@keyframes pulse-slow {
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 0.6; }
|
||||
}
|
||||
|
||||
.bg-dots {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: radial-gradient(rgba(255,255,255,0.02) 1rpx, transparent 1rpx);
|
||||
background-size: 64rpx 64rpx;
|
||||
}
|
||||
|
||||
@@ -24,19 +24,12 @@
|
||||
"miniprogram": {
|
||||
"list": [
|
||||
{
|
||||
"name": "pages/gift-pay/detail",
|
||||
"name": "代付",
|
||||
"pathName": "pages/gift-pay/detail",
|
||||
"query": "requestSn=GPRMP20260317114238341300",
|
||||
"query": "requestSn=GPRMP20260317145140501100",
|
||||
"scene": null,
|
||||
"launchMode": "default"
|
||||
},
|
||||
{
|
||||
"name": "pages/read/read",
|
||||
"pathName": "pages/read/read",
|
||||
"query": "mid=219",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "唤醒",
|
||||
"pathName": "pages/read/read",
|
||||
@@ -57,13 +50,6 @@
|
||||
"query": "mid=20",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "pages/read/read",
|
||||
"pathName": "pages/read/read",
|
||||
"query": "mid=1",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
210
miniprogram/yulan.html
Normal file
210
miniprogram/yulan.html
Normal file
@@ -0,0 +1,210 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>代付页面预览 - Premium FriendPay</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;900&family=JetBrains+Mono:wght@700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: #050505;
|
||||
color: white;
|
||||
margin: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.font-mono {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
@keyframes pulse-slow {
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 0.6; }
|
||||
}
|
||||
.animate-pulse-slow {
|
||||
animation: pulse-slow 8s infinite;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="text/babel">
|
||||
const { useState, useEffect } = React;
|
||||
|
||||
// Simple Icon component to wrap Lucide
|
||||
const Icon = ({ name, className }) => {
|
||||
useEffect(() => {
|
||||
lucide.createIcons();
|
||||
}, [name]);
|
||||
return <i data-lucide={name} className={className}></i>;
|
||||
};
|
||||
|
||||
function App() {
|
||||
const [viewMode, setViewMode] = useState('payer');
|
||||
|
||||
const content = {
|
||||
payer: {
|
||||
title: '帮他付款',
|
||||
productName: 'AI 提效实战课:从入门到精通',
|
||||
productDesc: '第 123 场直播回放 · 包含所有课件与实战案例',
|
||||
requesterName: '好**',
|
||||
requesterMsg: '“ 这门课对我很有帮助,希望能帮我代付一下,非常感谢! ”',
|
||||
amount: '199.00',
|
||||
buttonText: '立即帮他付款',
|
||||
buttonIcon: 'credit-card',
|
||||
},
|
||||
requester: {
|
||||
title: '找朋友代付',
|
||||
productName: '3000万流水如何跑出来 (退税模式解析)',
|
||||
productDesc: '深度解析企业退税合规与流水结构优化',
|
||||
requesterName: '你自己',
|
||||
requesterMsg: '分享给好友,好友打开后即可为你完成支付。',
|
||||
amount: '299.00',
|
||||
buttonText: '发送给好友',
|
||||
buttonIcon: 'share-2',
|
||||
}
|
||||
};
|
||||
|
||||
const current = content[viewMode];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col relative overflow-x-hidden">
|
||||
{/* View Switcher */}
|
||||
<div className="fixed top-6 left-1/2 -translate-x-1/2 z-50 flex bg-zinc-900/80 backdrop-blur-xl rounded-full p-1 border border-white/5 shadow-2xl">
|
||||
<button
|
||||
onClick={() => setViewMode('payer')}
|
||||
className={`px-5 py-2 rounded-full text-xs font-bold tracking-wide transition-all duration-300 ${viewMode === 'payer' ? 'bg-[#14b8a6] text-black shadow-[0_0_15px_rgba(20,184,166,0.4)]' : 'text-zinc-500 hover:text-zinc-300'}`}
|
||||
>
|
||||
代付视角
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setViewMode('requester')}
|
||||
className={`px-5 py-2 rounded-full text-xs font-bold tracking-wide transition-all duration-300 ${viewMode === 'requester' ? 'bg-[#14b8a6] text-black shadow-[0_0_15px_rgba(20,184,166,0.4)]' : 'text-zinc-500 hover:text-zinc-300'}`}
|
||||
>
|
||||
发起视角
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="max-w-md mx-auto w-full min-h-screen flex flex-col relative">
|
||||
{/* Navigation */}
|
||||
<header className="px-6 py-8 flex items-center justify-between sticky top-0 bg-[#050505]/60 backdrop-blur-xl z-10">
|
||||
<button className="w-10 h-10 flex items-center justify-center bg-zinc-900/50 border border-white/5 rounded-full hover:bg-zinc-800 transition-colors">
|
||||
<Icon name="chevron-left" className="w-5 h-5" />
|
||||
</button>
|
||||
<h1 className="text-sm font-bold uppercase tracking-[0.2em] text-zinc-400">{current.title}</h1>
|
||||
<div className="flex items-center gap-2 bg-zinc-900/50 border border-white/5 rounded-full px-3 py-1.5">
|
||||
<Icon name="more-horizontal" className="w-4 h-4 text-zinc-500" />
|
||||
<div className="w-[1px] h-3 bg-white/10" />
|
||||
<Icon name="circle" className="w-3 h-3 fill-white text-white" />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="flex-1 px-6 pb-40 space-y-8">
|
||||
{/* Product Hero Card */}
|
||||
<section className="relative group">
|
||||
<div className="absolute -inset-0.5 bg-gradient-to-b from-[#14b8a6]/20 to-transparent rounded-[2rem] blur-xl opacity-50"></div>
|
||||
<div className="relative bg-zinc-900/80 border border-white/10 rounded-[2rem] p-8 overflow-hidden transition-all duration-500 hover:border-[#14b8a6]/30">
|
||||
<div className="absolute top-0 right-0 p-6 opacity-10">
|
||||
<Icon name="info" className="w-12 h-12" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="inline-block px-3 py-1 rounded-full bg-[#14b8a6]/10 border border-[#14b8a6]/20 text-[#14b8a6] text-[10px] font-black uppercase tracking-widest">
|
||||
订单详情
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold leading-tight tracking-tight">
|
||||
{current.productName}
|
||||
</h2>
|
||||
<p className="text-zinc-400 text-sm font-medium">
|
||||
{current.productDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 pt-8 border-t border-white/5 flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<p className="text-[10px] uppercase tracking-widest text-zinc-500 font-bold">应付金额</p>
|
||||
<div className="flex items-baseline gap-1">
|
||||
<span className="text-[#14b8a6] text-lg font-bold">¥</span>
|
||||
<span className="text-3xl font-mono font-bold tracking-tighter">{current.amount}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#14b8a6]/10 border border-[#14b8a6]/20 flex items-center justify-center">
|
||||
<Icon name="arrow-right" className="w-5 h-5 text-[#14b8a6]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Requester Info */}
|
||||
<section className="bg-zinc-900/30 border border-white/5 rounded-3xl p-6 space-y-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 rounded-full bg-gradient-to-br from-zinc-700 to-zinc-900 border border-white/10 flex items-center justify-center shadow-inner">
|
||||
<Icon name="user" className="w-6 h-6 text-zinc-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-bold text-zinc-200">{current.requesterName}</h4>
|
||||
<p className="text-[10px] uppercase tracking-widest text-zinc-500 font-bold">发起代付请求</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="absolute left-0 top-0 bottom-0 w-1 bg-[#14b8a6]/30 rounded-full" />
|
||||
<p className="pl-5 text-zinc-400 text-sm italic leading-relaxed">
|
||||
{current.requesterMsg}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Security Badge */}
|
||||
<div className="flex items-center justify-center gap-2 py-4">
|
||||
<Icon name="shield-check" className="w-4 h-4 text-[#14b8a6]/60" />
|
||||
<span className="text-[10px] uppercase tracking-[0.2em] text-zinc-600 font-bold">
|
||||
安全支付保障 · 资金由平台托管
|
||||
</span>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/* Floating Action Bar */}
|
||||
<footer className="fixed bottom-0 left-0 right-0 p-8 z-20">
|
||||
<div className="max-w-md mx-auto relative">
|
||||
<div className="absolute inset-0 bg-zinc-900/80 backdrop-blur-2xl border border-white/10 rounded-[2.5rem] shadow-[0_20px_50px_rgba(0,0,0,0.5)]" />
|
||||
|
||||
<div className="relative p-3 flex items-center gap-4">
|
||||
<div className="flex-1 pl-6">
|
||||
<p className="text-[10px] uppercase tracking-widest text-zinc-500 font-bold mb-0.5">合计</p>
|
||||
<p className="text-xl font-mono font-bold tracking-tighter">
|
||||
<span className="text-[#14b8a6] text-sm mr-1">¥</span>
|
||||
{current.amount}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="bg-[#14b8a6] hover:bg-[#0d9488] text-black font-black px-8 py-4 rounded-[1.8rem] flex items-center justify-center transition-all shadow-[0_8px_20px_rgba(20,184,166,0.3)] active:scale-95"
|
||||
>
|
||||
<Icon name={current.buttonIcon} className="w-5 h-5 mr-2" />
|
||||
<span className="text-sm uppercase tracking-wider">{current.buttonText}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* Ambient Background Effects */}
|
||||
<div className="fixed top-0 left-0 w-full h-full overflow-hidden pointer-events-none -z-10">
|
||||
<div className="absolute top-[-20%] left-[-10%] w-[80%] h-[60%] bg-[#14b8a6]/5 blur-[150px] rounded-full animate-pulse-slow" />
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[60%] h-[50%] bg-[#14b8a6]/5 blur-[120px] rounded-full" />
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full h-full opacity-[0.02] bg-[radial-gradient(#fff_1px,transparent_1px)] [background-size:32px_32px]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(<App />);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user