- 在`bindUser`页面中新增分享海报功能,用户可保存海报到相册 - 优化绑定用户页面样式,添加背景图片和点击事件 - 新增`configPopup`组件用于展示配置信息 - 调整`myLevel`页面组件,添加`dataInfo`属性传递数据master
@ -0,0 +1,55 @@ | |||
<template> | |||
<view class="configPopup"> | |||
<up-popup :show="showConfirmOrder" mode="bottom" @close="close" :round="10" :closeable="true" | |||
:safeAreaInsetBottom="false"> | |||
<view class="content"> | |||
<up-parse :content="content"></up-parse> | |||
</view> | |||
</up-popup> | |||
</view> | |||
</template> | |||
<script> | |||
import { mapState, mapGetters } from 'vuex' | |||
export default { | |||
name: 'configPoup', | |||
data() { | |||
return { | |||
content : '', | |||
showConfirmOrder : false, | |||
} | |||
}, | |||
onShow(){ | |||
}, | |||
methods: { | |||
//打开配置信息菜单 | |||
open(key){ | |||
this.content = this.configList[key].paramValueArea | |||
this.showConfirmOrder = true | |||
}, | |||
openText(content){ | |||
this.content = content | |||
this.showConfirmOrder = true | |||
}, | |||
close(){ | |||
this.showConfirmOrder = false | |||
}, | |||
}, | |||
computed : { | |||
...mapGetters(['configList']) | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.configPopup { | |||
.content{ | |||
min-height: 50vh; | |||
max-height: 70vh; | |||
padding: 30rpx 20rpx; | |||
overflow: scroll; | |||
height: 100%; | |||
box-sizing: border-box; | |||
} | |||
} | |||
</style> |
@ -0,0 +1,193 @@ | |||
<template> | |||
<view class="page"> | |||
<navbar title="分享好友" leftClick @leftClick="$utils.navigateBack" /> | |||
<view class="flex content"> | |||
<view style="width: 598rpx; height: 1063rpx;"> | |||
<canvas id="myCanvas" canvas-id="firstCanvas1" type="2d" style="width: 100%; height: 100%;"></canvas> | |||
</view> | |||
<view class="flex btns"> | |||
<button class="flex btn btn-back" @click="$utils.navigateBack">返回</button> | |||
<button plain class="flex btn btn-save" @click="saveImg" >保存到相册</button> | |||
</view> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
import { mapState } from 'vuex' | |||
export default { | |||
data() { | |||
return { | |||
wxCodeImage: null, | |||
canvas: {}, | |||
} | |||
}, | |||
computed : { | |||
...mapState(['configList']) | |||
}, | |||
onLoad() { | |||
}, | |||
onReady() { | |||
this.fetchQrCode() | |||
}, | |||
methods: { | |||
async fetchQrCode() { | |||
try { | |||
const url = (await this.$fetch('getQrCode'))?.url | |||
this.wxCodeImage = this.$config.aliOss.url + url | |||
console.log('--wxCodeImage', this.wxCodeImage) | |||
this.draw() | |||
} catch (err) { | |||
} | |||
}, | |||
draw() { | |||
uni.showLoading({ | |||
title: "拼命绘画中..." | |||
}) | |||
wx.createSelectorQuery() | |||
.select('#myCanvas') // 绘制的canvas的id | |||
.fields({ | |||
node: true, | |||
size: true | |||
}) | |||
.exec(async (res) => { | |||
const canvas = res[0].node | |||
// 渲染上下文 | |||
const ctx = canvas.getContext('2d') | |||
// Canvas 画布的实际绘制宽高 | |||
const width = res[0].width | |||
const height = res[0].height | |||
// 初始化画布大小 | |||
const dpr = wx.getWindowInfo().pixelRatio | |||
//根据dpr调整 | |||
// dpr 2 4 | |||
// 3 6 | |||
console.log("--dpr", dpr) | |||
canvas.width = width * dpr | |||
canvas.height = height * dpr | |||
let Ratio = canvas.width / 598 | |||
this.canvas = canvas | |||
ctx.scale(dpr, dpr) | |||
ctx.clearRect(0, 0, width, height) | |||
//背景图片 | |||
const bgImage = canvas.createImage() | |||
bgImage.src = this.configList.index_lvxing || 'https://image.hhlm1688.com//upload/组3833x_1742803627396.png' | |||
bgImage.onload = () => { | |||
ctx.drawImage(bgImage, 0, 0, width, height) | |||
//二维码图片 | |||
const coderImage = canvas.createImage() | |||
coderImage.src = this.wxCodeImage | |||
coderImage.onload = () => { | |||
const x = 197 * Ratio / dpr | |||
const y = 562 * Ratio / dpr | |||
const size = 206 * Ratio / dpr | |||
ctx.drawImage(coderImage, x, y, size, size) | |||
uni.hideLoading() | |||
} | |||
} | |||
}) | |||
}, | |||
saveImg(){ | |||
this.$authorize('scope.writePhotosAlbum').then((res) => { | |||
this.imgApi() | |||
}) | |||
}, | |||
imgApi() { | |||
wx.canvasToTempFilePath({ | |||
x: 0, | |||
y: 0, | |||
width: this.canvas.width, | |||
height: this.canvas.height, | |||
canvas: this.canvas, | |||
success: (res) => { | |||
let tempFilePath = res.tempFilePath; | |||
this.saveImgToPhone(tempFilePath) | |||
}, | |||
fail: (err) => { | |||
console.log('--canvasToTempFilePath--fail', err) | |||
} | |||
}, this); | |||
}, | |||
saveImgToPhone(image) { | |||
/* 获取图片的信息 */ | |||
uni.getImageInfo({ | |||
src: image, | |||
success: function(image) { | |||
/* 保存图片到手机相册 */ | |||
uni.saveImageToPhotosAlbum({ | |||
filePath: image.path, | |||
success: function() { | |||
uni.showModal({ | |||
title: '保存成功', | |||
content: '图片已成功保存到相册', | |||
showCancel: false | |||
}); | |||
}, | |||
complete(res) { | |||
console.log(res); | |||
} | |||
}); | |||
} | |||
}); | |||
} | |||
}, | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.page { | |||
background-color: #111317; | |||
height: 100vh; | |||
} | |||
.content { | |||
margin-top: 79rpx; | |||
flex-direction: column; | |||
} | |||
.btns { | |||
justify-content: space-between; | |||
margin-top: 53rpx; | |||
width: 598rpx; | |||
} | |||
.btn { | |||
display: inline-flex; | |||
width: 280rpx; | |||
height: 90rpx; | |||
font-size: 36rpx; | |||
line-height: 1; | |||
color: #FFFFFF; | |||
border-radius: 45rpx; | |||
margin: 0; | |||
&-back { | |||
background-color: #4E5053; | |||
} | |||
&-save { | |||
background-image: linear-gradient(to right, #02DED6, #05D9A2); | |||
} | |||
} | |||
</style> |
@ -0,0 +1,209 @@ | |||
<template> | |||
<view class="page"> | |||
<view class="flex content"> | |||
<view style="width: 598rpx; height: 1063rpx;"> | |||
<canvas id="myCanvas" canvas-id="firstCanvas1" type="2d" style="width: 100%; height: 100%;"></canvas> | |||
</view> | |||
<view class="flex btns"> | |||
<button plain class="flex btn btn-save" @click="saveImg">保存到相册</button> | |||
</view> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
import { | |||
mapState | |||
} from 'vuex' | |||
import { | |||
binBaseInfo, | |||
bindCode, | |||
} from "@/api/home.js" | |||
export default { | |||
data() { | |||
return { | |||
wxCodeImage: null, | |||
canvas: {}, | |||
data : {}, | |||
baseInfo : {}, | |||
} | |||
}, | |||
computed: { | |||
...mapState(['configList']) | |||
}, | |||
onLoad() { | |||
this.baseInfo = JSON.parse(uni.getStorageSync("baseInfo")) | |||
this.getBaseInfo() | |||
}, | |||
onReady() { | |||
// this.fetchQrCode() | |||
}, | |||
methods: { | |||
async fetchQrCode() { | |||
try { | |||
const url = (await this.$fetch('getQrCode'))?.url | |||
this.wxCodeImage = this.$config.aliOss.url + url | |||
console.log('--wxCodeImage', this.wxCodeImage) | |||
this.draw() | |||
} catch (err) { | |||
} | |||
}, | |||
getBaseInfo(){ | |||
binBaseInfo(this.baseInfo.userId).then(res => { | |||
this.baseInfo = res.data | |||
}) | |||
bindCode(this.baseInfo.userId).then(res => { | |||
this.data = res.data | |||
this.draw() | |||
}) | |||
}, | |||
draw() { | |||
uni.showLoading({ | |||
title: "拼命绘画中..." | |||
}) | |||
wx.createSelectorQuery() | |||
.select('#myCanvas') // 绘制的canvas的id | |||
.fields({ | |||
node: true, | |||
size: true | |||
}) | |||
.exec(async (res) => { | |||
const canvas = res[0].node | |||
// 渲染上下文 | |||
const ctx = canvas.getContext('2d') | |||
// Canvas 画布的实际绘制宽高 | |||
const width = res[0].width | |||
const height = res[0].height | |||
// 初始化画布大小 | |||
const dpr = wx.getWindowInfo().pixelRatio | |||
//根据dpr调整 | |||
// dpr 2 4 | |||
// 3 6 | |||
console.log("--dpr", dpr) | |||
canvas.width = width * dpr | |||
canvas.height = height * dpr | |||
let Ratio = canvas.width / 598 | |||
this.canvas = canvas | |||
ctx.scale(dpr, dpr) | |||
ctx.clearRect(0, 0, width, height) | |||
//背景图片 | |||
const bgImage = canvas.createImage() | |||
bgImage.src = this.data.bj_url || | |||
'https://image.hhlm1688.com//upload/组3833x_1742803627396.png' | |||
bgImage.onload = () => { | |||
ctx.drawImage(bgImage, 0, 0, width, height) | |||
//二维码图片 | |||
const coderImage = canvas.createImage() | |||
coderImage.src = this.data.url | |||
coderImage.onload = () => { | |||
const x = 197 * Ratio / dpr | |||
const y = 562 * Ratio / dpr | |||
const size = 206 * Ratio / dpr | |||
ctx.drawImage(coderImage, x, y, size, size) | |||
uni.hideLoading() | |||
} | |||
} | |||
}) | |||
}, | |||
saveImg() { | |||
this.$authorize('scope.writePhotosAlbum').then((res) => { | |||
this.imgApi() | |||
}) | |||
}, | |||
imgApi() { | |||
wx.canvasToTempFilePath({ | |||
x: 0, | |||
y: 0, | |||
width: this.canvas.width, | |||
height: this.canvas.height, | |||
canvas: this.canvas, | |||
success: (res) => { | |||
let tempFilePath = res.tempFilePath; | |||
this.saveImgToPhone(tempFilePath) | |||
}, | |||
fail: (err) => { | |||
console.log('--canvasToTempFilePath--fail', err) | |||
} | |||
}, this); | |||
}, | |||
saveImgToPhone(image) { | |||
/* 获取图片的信息 */ | |||
uni.getImageInfo({ | |||
src: image, | |||
success: function(image) { | |||
/* 保存图片到手机相册 */ | |||
uni.saveImageToPhotosAlbum({ | |||
filePath: image.path, | |||
success: function() { | |||
uni.showModal({ | |||
title: '保存成功', | |||
content: '图片已成功保存到相册', | |||
showCancel: false | |||
}); | |||
}, | |||
complete(res) { | |||
console.log(res); | |||
} | |||
}); | |||
} | |||
}); | |||
} | |||
}, | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.page { | |||
height: 100vh; | |||
} | |||
.content { | |||
margin-top: 79rpx; | |||
flex-direction: column; | |||
} | |||
.btns { | |||
justify-content: center; | |||
margin-top: 53rpx; | |||
display: flex; | |||
} | |||
.btn { | |||
display: flex; | |||
width: 520rpx; | |||
height: 90rpx; | |||
font-size: 36rpx; | |||
line-height: 1; | |||
color: #FFFFFF; | |||
border-radius: 45rpx; | |||
margin: 0; | |||
justify-content: center; | |||
align-items: center; | |||
border: none; | |||
&-save { | |||
background: #FFBF60; | |||
} | |||
} | |||
</style> |
@ -1,63 +1,76 @@ | |||
import { getConfigList, getPetTypeList, getIncreaseServiceList } from '@/api/config/config.js' | |||
import { | |||
getConfigList, | |||
getPetTypeList, | |||
getIncreaseServiceList | |||
} from '@/api/config/config.js' | |||
const system = { | |||
state: { | |||
configList: {}, | |||
petTypeOptions: [], | |||
increaseServiceOptions: [], | |||
}, | |||
mutations: { | |||
setConfigList(state, list) { | |||
const obj = {} | |||
list.forEach(n => { | |||
obj[n.paramCode] = n; | |||
}) | |||
state.configList = obj; | |||
}, | |||
setPetTypeOptions(state, list) { | |||
state.petTypeOptions = list | |||
}, | |||
setIncreaseServiceOptions(state, list) { | |||
state.increaseServiceOptions = list | |||
}, | |||
}, | |||
actions: { | |||
async fetchConfigList({commit, state}) { | |||
try { | |||
const data = await getConfigList() | |||
commit('setConfigList', data) | |||
} catch (err) { | |||
} | |||
}, | |||
async fetchPetTypeOptions({commit, state}) { | |||
if (state.petTypeOptions.length) { | |||
return | |||
} | |||
try { | |||
const data = await getPetTypeList() | |||
commit('setPetTypeOptions', data) | |||
} catch (err) { | |||
} | |||
}, | |||
async fetchIncreaseServiceOptions({commit, state}) { | |||
if (state.increaseServiceOptions.length) { | |||
return | |||
} | |||
try { | |||
const data = await getIncreaseServiceList() | |||
commit('setIncreaseServiceOptions', data) | |||
} catch (err) { | |||
} | |||
}, | |||
} | |||
state: { | |||
configList: {}, | |||
petTypeOptions: [], | |||
increaseServiceOptions: [], | |||
}, | |||
mutations: { | |||
setConfigList(state, list) { | |||
const obj = {} | |||
list.forEach(n => { | |||
obj[n.paramCode] = n; | |||
}) | |||
state.configList = obj; | |||
}, | |||
setPetTypeOptions(state, list) { | |||
state.petTypeOptions = list | |||
}, | |||
setIncreaseServiceOptions(state, list) { | |||
state.increaseServiceOptions = list | |||
}, | |||
}, | |||
actions: { | |||
async fetchConfigList({ | |||
commit, | |||
state | |||
}) { | |||
try { | |||
const data = await getConfigList() | |||
commit('setConfigList', data) | |||
} catch (err) { | |||
} | |||
}, | |||
async fetchPetTypeOptions({ | |||
commit, | |||
state | |||
}) { | |||
if (state.petTypeOptions.length) { | |||
return | |||
} | |||
try { | |||
const data = await getPetTypeList() | |||
commit('setPetTypeOptions', data) | |||
} catch (err) { | |||
} | |||
}, | |||
async fetchIncreaseServiceOptions({ | |||
commit, | |||
state | |||
}) { | |||
if (state.increaseServiceOptions.length) { | |||
return | |||
} | |||
try { | |||
const data = await getIncreaseServiceList() | |||
commit('setIncreaseServiceOptions', data) | |||
} catch (err) { | |||
} | |||
}, | |||
} | |||
} | |||
export default system |