Browse Source

feat: page-thesis-poster;

fox
Fox-33 1 day ago
parent
commit
addecb3f20
3 changed files with 301 additions and 0 deletions
  1. +2
    -0
      pages.json
  2. +49
    -0
      pages_order/thesis/index.vue
  3. +250
    -0
      pages_order/thesis/poster.vue

+ 2
- 0
pages.json View File

@ -36,6 +36,8 @@
"path": "thesis/search" "path": "thesis/search"
}, { }, {
"path": "thesis/index" "path": "thesis/index"
}, {
"path": "thesis/poster"
}, { }, {
"path": "case/index" "path": "case/index"
}, { }, {


+ 49
- 0
pages_order/thesis/index.vue View File

@ -146,6 +146,13 @@
</view> </view>
</view> </view>
</view> </view>
<view class="flex bottom">
<view class="flex btns">
<button class="btn" @click="jumpToPoster">保存海报</button>
<button class="btn btn-share" open-type="share">分享文章</button>
</view>
</view>
</view> </view>
</template> </template>
@ -159,6 +166,13 @@
onLoad({ thesisId }) { onLoad({ thesisId }) {
this.getData(thesisId) this.getData(thesisId)
}, },
onShareAppMessage(res) {
return {
title: this.details.title,
imageUrl: this.bannerList?.[0]?.image || '',
path: `/pages_order/thesis/index?thesisId=${this.details.id}`
}
},
computed: { computed: {
bannerList() { bannerList() {
const { image } = this.details || {} const { image } = this.details || {}
@ -202,6 +216,11 @@
} }
}); });
}, },
jumpToPoster() {
uni.navigateTo({
url: `/pages_order/thesis/poster?thesisId=${this.details.id}`
})
},
}, },
} }
</script> </script>
@ -211,6 +230,7 @@
.page__view { .page__view {
padding-bottom: 62rpx; padding-bottom: 62rpx;
background: #FFFFFF; background: #FFFFFF;
padding-bottom: calc(62rpx + 110rpx + env(safe-area-inset-bottom));
} }
.swiper { .swiper {
@ -556,4 +576,33 @@
} }
} }
.bottom {
position: fixed;
left: 0;
bottom: 0;
width: 100vw;
height: 110rpx;
padding-bottom: env(safe-area-inset-bottom);
background: #FFFFFF;
box-shadow: 0px 3px 6px 0px rgba(0,0,0,0.16);
.btns {
column-gap: 34rpx;
}
.btn {
padding: 20rpx 90rpx;
font-size: 28rpx;
color: #FFFFFF;
background: #4883F9;
border-radius: 42rpx;
&-share {
background: #FFD019;
}
}
}
</style> </style>

+ 250
- 0
pages_order/thesis/poster.vue View File

@ -0,0 +1,250 @@
<template>
<view class="page__view">
<!-- 导航栏 -->
<navbar leftClick @leftClick="$utils.navigateBack" bgColor="#4883F9" color="#FFFFFF" />
<view style="width: 750rpx; height: 1184rpx; overflow: hidden;">
<canvas id="myCanvas" canvas-id="firstCanvas1" type="2d" style="width: 100%; height: 100%;"></canvas>
</view>
<view class="flex bottom">
<view class="flex">
<button class="btn" @click="saveImg">保存到手机</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
wxCodeImage: '',
baseUrl: 'https://image.hhlm1688.com/',
canvas: {},
details: {},
}
},
async onLoad({ thesisId }) {
await this.getData(thesisId)
await this.fetchQrCode()
this.draw()
},
methods: {
async getData(thesisId) {
try {
this.details = await this.$fetch('queryThesisById', { thesisId })
} catch (err) {
}
},
async fetchQrCode() {
try {
// todo: check api
this.wxCodeImage = (await this.$fetch('getInviteCode'))?.url
} catch (err) {
}
},
drawTextWithManualLineBreaks(ctx, text, x, y, maxWidth, lineHeight) {
let rows = 0
let size = 0
let lines = text.split('\n'); //
for (let lIdx = 0; lIdx < lines.length; lIdx++) {
let line = lines[lIdx]
let row = ''
for (let wIdx = 0; wIdx < line.length; wIdx++) {
let word = line[wIdx]
let metrics = ctx.measureText(row + word);
if (metrics.width > maxWidth) {
rows++
size += row.length
console.log('--rows', rows, '--size', size)
if (rows === 4 && size < text.length) {
row = row.slice(0, -2) + '......'
}
ctx.fillText(row, x, y);
row = ''
y += lineHeight
if (rows === 4) {
break
}
} else {
row += word
}
}
if (rows === 4) {
break
}
if (row) {
rows++
size += row.length
console.log('--rows', rows, '--size', size)
if (rows === 4 && size < text.length) {
row = row.slice(0, -2) + '......'
}
ctx.fillText(row, x, y);
y += lineHeight
if (rows === 4) {
break
}
}
}
},
draw() {
uni.showLoading({
title: "拼命绘画中..."
})
wx.createSelectorQuery()
.select('#myCanvas') // canvasid
.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 / 750
this.canvas = canvas
ctx.scale(dpr, dpr)
ctx.clearRect(0, 0, width, height)
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = '#999999';
const fontSize = 28 * Ratio / dpr
ctx.font = `${fontSize}px PingFangSC-regular`;
const descX = 37 * Ratio / dpr
const descY = 751 * Ratio / dpr
const maxWidth = 677 * Ratio / dpr
const lineHeight = 45 * Ratio / dpr
this.drawTextWithManualLineBreaks(ctx, this.details.paperDesc, descX, descY, maxWidth, lineHeight)
//
const paperImage = canvas.createImage()
paperImage.src = this.details.paperImage
paperImage.onload = () => {
const x = 37 * Ratio / dpr
const y = 21 * Ratio / dpr
const w = 677 * Ratio / dpr
const h = 687 * Ratio / dpr
ctx.drawImage(paperImage, x, y, w, h)
//
const coderImage = canvas.createImage()
coderImage.src = this.wxCodeImage
coderImage.onload = () => {
const x = 539 * Ratio / dpr
const y = 987 * Ratio / dpr
const size = 162 * 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__view {
background: $uni-bg-color-grey;
}
.bottom {
position: fixed;
left: 0;
bottom: 0;
width: 100vw;
height: 154rpx;
padding-bottom: env(safe-area-inset-bottom);
background: #FFFFFF;
.btn {
padding: 20rpx 77rpx;
font-size: 28rpx;
color: #FFFFFF;
background: #4883F9;
border-radius: 14rpx;
}
}
</style>

Loading…
Cancel
Save