374 lines
7.8 KiB
Vue
374 lines
7.8 KiB
Vue
<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>
|
||
|