|
@@ -35,7 +35,6 @@
|
|
|
<text class="nickname">{{ nickname || '未设置昵称' }}</text>
|
|
<text class="nickname">{{ nickname || '未设置昵称' }}</text>
|
|
|
<text v-if="roleLabel" class="role-tag">{{ roleLabel }}</text>
|
|
<text v-if="roleLabel" class="role-tag">{{ roleLabel }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <text v-if="myReferrer && myReferrer.nickname" class="referrer-line">推荐人:{{ myReferrer.nickname }}</text>
|
|
|
|
|
<view class="user-sub" v-if="memberLevel">
|
|
<view class="user-sub" v-if="memberLevel">
|
|
|
<view class="level-badge" :class="'level-' + memberLevel">{{ memberLevelText }}</view>
|
|
<view class="level-badge" :class="'level-' + memberLevel">{{ memberLevelText }}</view>
|
|
|
<text v-if="isLifetime" class="days-left">永久有效</text>
|
|
<text v-if="isLifetime" class="days-left">永久有效</text>
|
|
@@ -58,7 +57,12 @@
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- 家庭成员速览 -->
|
|
|
|
|
|
|
+ <!-- 我的推广码浮动按钮 -->
|
|
|
|
|
+ <view class="share-qr-float" @click="showShareQr">
|
|
|
|
|
+ <text class="share-qr-icon">📱</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 家族成员速览 -->
|
|
|
<view class="family-strip" v-if="familyMembers.length > 0">
|
|
<view class="family-strip" v-if="familyMembers.length > 0">
|
|
|
<view class="family-strip-header">
|
|
<view class="family-strip-header">
|
|
|
<text class="family-strip-title">我的家庭</text>
|
|
<text class="family-strip-title">我的家庭</text>
|
|
@@ -261,6 +265,41 @@
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+ <view class="share-qr-modal" v-if="showShareQrModal" @click="closeShareQrModal">
|
|
|
|
|
+ <view class="modal-mask" @click.stop />
|
|
|
|
|
+ <view class="modal-qr" @click.stop>
|
|
|
|
|
+ <view class="modal-qr-header">
|
|
|
|
|
+ <text class="modal-qr-title">我的分享海报</text>
|
|
|
|
|
+ <text class="modal-qr-close" @click="closeShareQrModal">✕</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="modal-qr-content">
|
|
|
|
|
+ <view v-if="qrLoading" class="qrcode-loading">
|
|
|
|
|
+ <text class="loading-spinner">⏳</text>
|
|
|
|
|
+ <text class="loading-text">生成中...</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view v-else="!qrBase64" class="qrcode-empty">
|
|
|
|
|
+ <text>暂无二维码</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view v-else class="qrcode-image">
|
|
|
|
|
+ <image class="qrcode-img" :src="qrBase64" mode="aspectFit"></image>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="qrcode-info">
|
|
|
|
|
+ <text class="qrcode-text">邀请码: {{ referralCode }}</text>
|
|
|
|
|
+ <text class="qrcode-desc">扫码注册,好友成为您的推荐人</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="modal-qr-actions">
|
|
|
|
|
+ <view class="action-btn copy-btn" @click="copyReferralCode">
|
|
|
|
|
+ <text class="copy-icon">📋</text>
|
|
|
|
|
+ <text class="copy-text">复制邀请码</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="action-btn share-btn" @click="shareToWechat">
|
|
|
|
|
+ <text class="share-icon">📤</text>
|
|
|
|
|
+ <text class="share-text">分享给朋友</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
<FloatingAvatar />
|
|
<FloatingAvatar />
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
@@ -273,7 +312,8 @@ import {
|
|
|
verifyPassword, getPointsBalance, getUserInfo,
|
|
verifyPassword, getPointsBalance, getUserInfo,
|
|
|
cartCount, getOrderCounts, getReferralSummary,
|
|
cartCount, getOrderCounts, getReferralSummary,
|
|
|
getProfileStats, getMyReferrer, getTeamConsumption,
|
|
getProfileStats, getMyReferrer, getTeamConsumption,
|
|
|
- getTeacherInfo, getTeacherPendingTasks, getTeacherUnreadCount
|
|
|
|
|
|
|
+ getTeacherInfo, getTeacherPendingTasks, getTeacherUnreadCount,
|
|
|
|
|
+ getReferralCode, extractReferralCode, getShareQrCode
|
|
|
} from '../../utils/api.js'
|
|
} from '../../utils/api.js'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
@@ -311,6 +351,12 @@ export default {
|
|
|
teacherStatus: 'pending',
|
|
teacherStatus: 'pending',
|
|
|
profileProgress: 0,
|
|
profileProgress: 0,
|
|
|
myReferrer: null,
|
|
myReferrer: null,
|
|
|
|
|
+ // 分享推广码
|
|
|
|
|
+ showShareQrModal: false,
|
|
|
|
|
+ referralCode: '',
|
|
|
|
|
+ qrBase64: '',
|
|
|
|
|
+ qrLoading: false,
|
|
|
|
|
+ referralCodeLoaded: false,
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
@@ -505,6 +551,81 @@ export default {
|
|
|
console.error('获取推荐人失败', e)
|
|
console.error('获取推荐人失败', e)
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ // ===== 分享推广码 =====
|
|
|
|
|
+ showShareQr() {
|
|
|
|
|
+ this.showShareQrModal = true
|
|
|
|
|
+ if (!this.referralCodeLoaded) {
|
|
|
|
|
+ this.loadReferralCode()
|
|
|
|
|
+ } else if (this.referralCode && !this.qrBase64) {
|
|
|
|
|
+ this.generateQrcode()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ closeShareQrModal() {
|
|
|
|
|
+ this.showShareQrModal = false
|
|
|
|
|
+ },
|
|
|
|
|
+ async loadReferralCode() {
|
|
|
|
|
+ if (this.referralCodeLoaded) return
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ try {
|
|
|
|
|
+ var res = await getReferralCode()
|
|
|
|
|
+ var code = extractReferralCode(res)
|
|
|
|
|
+ self.referralCode = code || ''
|
|
|
|
|
+ self.referralCodeLoaded = true
|
|
|
|
|
+ if (code) {
|
|
|
|
|
+ self.generateQrcode()
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('获取推广码失败', e)
|
|
|
|
|
+ self.referralCodeLoaded = true
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ generateQrcode() {
|
|
|
|
|
+ if (!this.referralCode) return
|
|
|
|
|
+ this.qrLoading = true
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ var scene = 'ref=' + this.referralCode
|
|
|
|
|
+ // 首页路径,扫码后进入首页并绑定推荐人
|
|
|
|
|
+ getShareQrCode('/pages/index-home/index', scene)
|
|
|
|
|
+ .then(function(res) {
|
|
|
|
|
+ if (res && res.code === 200 && res.data) {
|
|
|
|
|
+ self.qrBase64 = res.data.qrCodeBase64
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(function(e) {
|
|
|
|
|
+ console.error('生成二维码失败', e)
|
|
|
|
|
+ uni.showToast({ title: '生成失败,请重试', icon: 'none' })
|
|
|
|
|
+ })
|
|
|
|
|
+ .finally(function() {
|
|
|
|
|
+ self.qrLoading = false
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ copyReferralCode() {
|
|
|
|
|
+ if (!this.referralCode) return
|
|
|
|
|
+ uni.setClipboardData({
|
|
|
|
|
+ data: this.referralCode,
|
|
|
|
|
+ success: function() {
|
|
|
|
|
+ uni.showToast({ title: '邀请码已复制', icon: 'success' })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ shareToWechat() {
|
|
|
|
|
+ if (!this.referralCode) return
|
|
|
|
|
+ var path = '/pages/index-home/index?refCode=' + this.referralCode
|
|
|
|
|
+ uni.share({
|
|
|
|
|
+ provider: 'weixin',
|
|
|
|
|
+ scene: { type: 0 },
|
|
|
|
|
+ type: 5,
|
|
|
|
|
+ imageUrl: this.qrBase64,
|
|
|
|
|
+ path: path,
|
|
|
|
|
+ title: '浠艾福 — 邀请你加入',
|
|
|
|
|
+ success: function() {
|
|
|
|
|
+ uni.showToast({ title: '分享成功', icon: 'success' })
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: function() {
|
|
|
|
|
+ uni.showToast({ title: '分享失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
goToServiceCenter() {
|
|
goToServiceCenter() {
|
|
|
uni.navigateTo({ url: '/pages/service-center/index' })
|
|
uni.navigateTo({ url: '/pages/service-center/index' })
|
|
|
},
|
|
},
|
|
@@ -1170,4 +1291,167 @@ export default {
|
|
|
color: #FF4D4F;
|
|
color: #FF4D4F;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 分享推广码浮动按钮 */
|
|
|
|
|
+.share-qr-float {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 40rpx;
|
|
|
|
|
+ right: 30rpx;
|
|
|
|
|
+ width: 80rpx;
|
|
|
|
|
+ height: 80rpx;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.15);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ z-index: 99;
|
|
|
|
|
+}
|
|
|
|
|
+.share-qr-icon {
|
|
|
|
|
+ font-size: 40rpx;
|
|
|
|
|
+ line-height: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 分享海报弹窗 */
|
|
|
|
|
+.share-qr-modal {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ z-index: 999;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+.modal-mask {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
+}
|
|
|
|
|
+.modal-qr {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ width: 70%;
|
|
|
|
|
+ max-width: 600rpx;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 24rpx;
|
|
|
|
|
+ padding: 30rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+}
|
|
|
|
|
+.modal-qr-header {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.modal-qr-title {
|
|
|
|
|
+ font-size: 30rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+}
|
|
|
|
|
+.modal-qr-close {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ padding: 10rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.modal-qr-content {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-loading,
|
|
|
|
|
+.qrcode-empty {
|
|
|
|
|
+ width: 340rpx;
|
|
|
|
|
+ height: 340rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ background: #FAFAFA;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ border: 2rpx dashed #E5E7EB;
|
|
|
|
|
+}
|
|
|
|
|
+.loading-spinner {
|
|
|
|
|
+ font-size: 48rpx;
|
|
|
|
|
+ margin-bottom: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.loading-text {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-empty text {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-image {
|
|
|
|
|
+ width: 340rpx;
|
|
|
|
|
+ height: 340rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ border: 1rpx solid #E5E7EB;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-img {
|
|
|
|
|
+ width: 330rpx;
|
|
|
|
|
+ height: 330rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-info {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-top: 20rpx;
|
|
|
|
|
+ gap: 8rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-text {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #F97316;
|
|
|
|
|
+}
|
|
|
|
|
+.qrcode-desc {
|
|
|
|
|
+ font-size: 22rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+}
|
|
|
|
|
+.modal-qr-actions {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 20rpx;
|
|
|
|
|
+ margin-top: 24rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.action-btn {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8rpx;
|
|
|
|
|
+ padding: 24rpx;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+}
|
|
|
|
|
+.copy-btn {
|
|
|
|
|
+ background: #FFF7ED;
|
|
|
|
|
+ color: #F97316;
|
|
|
|
|
+ border: 1rpx solid #FED7AA;
|
|
|
|
|
+}
|
|
|
|
|
+.share-btn {
|
|
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+.copy-icon, .share-icon {
|
|
|
|
|
+ font-size: 40rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.copy-text, .share-text {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|