chuangte_bike_newxcx/page_shanghu/guanli/tuiguang_qrcode.vue
2026-01-28 18:00:39 +08:00

374 lines
7.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<u-navbar title="推广二维码" :border-bottom="false" :background="bgc" back-icon-color="#111827" title-color="#111827"
title-size="34" title-bold height="44"></u-navbar>
<view class="wrap">
<!-- 说明 -->
<!-- <view class="tip">
<view class="tip-left">
<u-icon name="info-circle" size="28" color="#4297F3"></u-icon>
<text class="tip-text">点击卡片可进入详情编辑</text>
</view>
<text class="tip-id">ID{{ id }}</text>
</view> -->
<!-- 二维码卡片整块可点击去详情 -->
<view class="qr-card" @click="goDetail">
<view class="qr-title">
<text class="qr-title-main">备注{{detail.remark || '未设置'}}</text>
<view class="badge" :class="[detail.status == '1' ? 'badge-on' : 'badge-off']">
{{ detail.status == '1' ? '启用' : (detail.status == '2' ? '禁用' : '未知') }}
</view>
</view>
<view class="qr-sub">
<text class="sub-item">手机号{{ detail.userPhone || '未设置' }}</text>
<text class="sub-item">分成{{ (pointInt === 0 || pointInt) ? (pointInt + '%') : '未设置' }}</text>
</view>
<view class="qr-box" @click.stop>
<canvas id="qrcode" canvas-id="qrcode" class="qr-canvas" />
</view>
<!-- <view class="qr-link" @click.stop="copyLink">
<text class="link-text">{{ qrData }}</text>
<view class="copy-btn">复制</view>
</view>
<view class="hint">
<text>提示可复制链接去定制专属二维码</text>
</view> -->
</view>
<!-- 底部按钮 -->
<view class="btn-row">
<!-- <view class="btn ghost" @click="goDetail">
<u-icon name="edit-pen" size="28" color="#4297F3"></u-icon>
<text>进入详情</text>
</view> -->
<view class="btn primary" @click="saveQrcode">
<u-icon name="download" size="28" color="#fff"></u-icon>
<text>保存二维码</text>
</view>
</view>
</view>
</view>
</template>
<script>
import UQRCode from 'uqrcodejs';
export default {
data() {
return {
bgc: {
backgroundColor: "#F7F8FA",
},
id: '',
areaId: '',
qrData: '',
detail: {},
pointInt: null
}
},
onLoad(option) {
this.id = option.id || ''
this.areaId = option.areaId || ''
if (!this.id) {
uni.showToast({
title: '缺少推广ID',
icon: 'none'
})
return
}
this.buildQrData()
if (this.qrData) {
this.generateQrcode()
}
this.getDetail()
},
methods: {
buildQrData() {
const cfg = (this.$store && this.$store.state && this.$store.state.app && this.$store.state.app.urlConfig) ? this.$store.state.app.urlConfig : {}
let prefix = cfg.areaPromotionPrefix || ''
// 兜底:如果全局没配,按你给的默认路径生成(避免 uqrcode data 为空报错)
if (!prefix) {
prefix = 'https://wx.ccttiot.com/x/t'
}
if (!prefix) {
this.qrData = ''
return
}
// 期望格式https://wx.ccttiot.com/x/t?i=2
// 如果前缀已包含参数,则用 &i= 拼接;否则用 ?i=
if (prefix.indexOf('?') === -1) {
this.qrData = prefix + '?i=' + this.id
} else if (prefix.slice(-1) === '?' || prefix.slice(-1) === '&') {
this.qrData = prefix + 'i=' + this.id
} else {
this.qrData = prefix + '&i=' + this.id
}
},
// 取详情用于展示(不影响二维码生成)
getDetail() {
if (!this.id) return
this.$u.get('/bst/areaPromotion/' + this.id).then(res => {
if (res.code === 200) {
this.detail = res.data || {}
if (this.detail.point === 0 || this.detail.point) {
this.pointInt = Math.round(this.detail.point * 100)
} else {
this.pointInt = null
}
}
})
},
generateQrcode() {
if (!this.qrData) {
uni.showToast({
title: '二维码链接为空',
icon: 'none'
})
return
}
const qr = new UQRCode();
const qrSizeRpx = 520;
const qrSizePx = uni.upx2px(qrSizeRpx);
qr.data = this.qrData;
qr.size = qrSizePx;
const ctx = uni.createCanvasContext('qrcode', this);
qr.canvasContext = ctx;
qr.make();
qr.drawCanvas();
// 二维码下方加一行说明
setTimeout(() => {
ctx.setFontSize(22);
ctx.setFillStyle('#111827');
ctx.setTextAlign('center');
ctx.fillText( qrSizePx / 2, qrSizePx + 36);
ctx.draw(true);
}, 120);
},
saveQrcode() {
uni.canvasToTempFilePath({
canvasId: 'qrcode',
x: 0,
y: 0,
width: uni.upx2px(520),
height: uni.upx2px(560),
success: (res) => {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
},
fail: () => {
uni.showToast({
title: '保存失败',
icon: 'none'
})
}
})
},
fail: () => {
uni.showToast({
title: '生成二维码失败',
icon: 'none'
})
}
})
},
copyLink() {
uni.setClipboardData({
data: this.qrData || '',
success: () => {
uni.showToast({
title: '已复制',
icon: 'success'
})
}
})
},
goDetail() {
if (!this.id) return
uni.navigateTo({
url: '/page_shanghu/guanli/tuiguang_detail?id=' + this.id + '&areaId=' + this.areaId
})
}
}
}
</script>
<style lang="scss">
page {
background: #F7F8FA;
min-height: 100vh;
}
.page {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.wrap {
padding: 24rpx 32rpx 40rpx;
}
.tip {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18rpx 20rpx;
background: #FFFFFF;
border-radius: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(17, 24, 39, 0.06);
margin-bottom: 20rpx;
.tip-left {
display: flex;
align-items: center;
}
.tip-text {
margin-left: 10rpx;
font-size: 26rpx;
color: #374151;
}
.tip-id {
font-size: 24rpx;
color: #9CA3AF;
}
}
.qr-card {
background: linear-gradient(180deg, #FFFFFF 0%, #FDFEFF 100%);
border-radius: 24rpx;
padding: 28rpx 24rpx;
box-shadow: 0 14rpx 36rpx rgba(17, 24, 39, 0.08);
border: 1rpx solid rgba(66, 151, 243, 0.12);
}
.qr-title {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10rpx;
.qr-title-main {
font-size: 34rpx;
font-weight: 700;
color: #111827;
letter-spacing: 1rpx;
}
.badge {
padding: 6rpx 16rpx;
border-radius: 999rpx;
font-size: 22rpx;
}
.badge-on {
background: linear-gradient(135deg, #E8F8EE 0%, #D4F4E2 100%);
color: #16A34A;
}
.badge-off {
background: #F3F4F6;
color: #6B7280;
}
}
.qr-sub {
display: flex;
justify-content: space-between;
margin-bottom: 18rpx;
.sub-item {
font-size: 24rpx;
color: #6B7280;
}
}
.qr-box {
width: 100%;
display: flex;
justify-content: center;
padding: 16rpx 0 8rpx;
}
.qr-canvas {
width: 520rpx;
height: 560rpx;
}
.qr-link {
margin-top: 12rpx;
background: #F9FAFB;
border-radius: 16rpx;
padding: 14rpx 16rpx;
display: flex;
align-items: center;
justify-content: space-between;
.link-text {
flex: 1;
font-size: 22rpx;
color: #4B5563;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.copy-btn {
margin-left: 14rpx;
padding: 10rpx 18rpx;
border-radius: 999rpx;
background: linear-gradient(135deg, #4297F3 0%, #2B76E5 100%);
color: #fff;
font-size: 24rpx;
}
}
.hint {
margin-top: 14rpx;
text-align: center;
font-size: 22rpx;
color: #9CA3AF;
}
.btn-row {
display: flex;
gap: 20rpx;
margin-top: 24rpx;
}
.btn {
height: 92rpx;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
font-size: 30rpx;
font-weight: 700;
text {
margin-left: 10rpx;
}
}
.ghost {
background: #FFFFFF;
border: 2rpx solid rgba(66, 151, 243, 0.35);
color: #4297F3;
}
.primary {
background: linear-gradient(135deg, #4297F3 0%, #2B76E5 100%);
color: #FFFFFF;
box-shadow: 0 10rpx 22rpx rgba(66, 151, 243, 0.28);
}
</style>