feat: update API to https://api.s-good.com
This commit is contained in:
parent
494aaa8c72
commit
bb0908e7d3
1
.env.production
Normal file
1
.env.production
Normal file
@ -0,0 +1 @@
|
|||||||
|
VITE_API_ORIGIN=https://api.s-good.com
|
||||||
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
<view class="page-section orders-hero">
|
<view class="page-section orders-hero">
|
||||||
<view class="hero-title">服务进度一目了然</view>
|
<view class="hero-title">服务进度一目了然</view>
|
||||||
<view class="hero-sub">按状态查看订单,待确认可快速开始服务,进行中可直接填写报告。</view>
|
<view v-if="userInfo.role === 'customer'" class="hero-sub">查看您的预约状态,随时掌握服务进度。</view>
|
||||||
|
<view v-else class="hero-sub">按状态查看订单,待确认可快速开始服务,进行中可直接填写报告。</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 状态 Tab -->
|
<!-- 状态 Tab -->
|
||||||
@ -39,12 +40,19 @@
|
|||||||
<text>{{ item.time }}</text>
|
<text>{{ item.time }}</text>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="userInfo.role !== 'customer'">
|
||||||
<div v-if="item.status === 'new'" class="action-btns">
|
<div v-if="item.status === 'new'" class="action-btns">
|
||||||
<button class="van-button van-button--small van-button--primary" @click="startService(item)">开始服务</button>
|
<button class="van-button van-button--small van-button--primary" @click="startService(item)">开始服务</button>
|
||||||
<button class="van-button van-button--small" @click="cancelService(item)">取消</button>
|
<button class="van-button van-button--small" @click="cancelService(item)">取消</button>
|
||||||
</div>
|
</div>
|
||||||
<button v-else-if="item.status === 'doing'" class="van-button van-button--small btn-mt" @click="goReport(item)">填写报告</button>
|
<button v-else-if="item.status === 'doing'" class="van-button van-button--small btn-mt" @click="goReport(item)">填写报告</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div v-if="item.status === 'new'" class="action-btns">
|
||||||
|
<button class="van-button van-button--small" @click="cancelService(item)">取消预约</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="filteredOrders.length === 0" class="empty"><text>暂无数据</text></view>
|
<view v-if="filteredOrders.length === 0" class="empty"><text>暂无数据</text></view>
|
||||||
|
|||||||
@ -108,7 +108,7 @@
|
|||||||
<button open-type="share" class="van-button van-button--primary van-button--round van-button--block share-btn">
|
<button open-type="share" class="van-button van-button--primary van-button--round van-button--block share-btn">
|
||||||
<AppIcon name="profile" :size="16" color="#ffffff" style="margin-right: 6px;" /> 转发给宠主
|
<AppIcon name="profile" :size="16" color="#ffffff" style="margin-right: 6px;" /> 转发给宠主
|
||||||
</button>
|
</button>
|
||||||
<button class="van-button van-button--block btn-ghost" @click="generatePoster">生成图片分享朋友圈</button>
|
<button class="van-button van-button--block btn-ghost" @click="generatePoster">生成海报 · 保存到相册</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 宠主视角 -->
|
<!-- 宠主视角 -->
|
||||||
@ -122,20 +122,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Canvas海报(隐藏,仅 H5) -->
|
<!-- Canvas 海报(H5 DOM / 小程序 2d) -->
|
||||||
<!-- #ifdef H5 -->
|
<!-- #ifdef H5 -->
|
||||||
<canvas ref="posterCanvas" style="position:fixed;top:-9999px;left:-9999px;" />
|
<canvas ref="posterCanvas" class="poster-canvas-offscreen" />
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<canvas
|
||||||
|
id="reportPosterCanvas"
|
||||||
|
type="2d"
|
||||||
|
class="poster-canvas-offscreen"
|
||||||
|
/>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted, getCurrentInstance } from 'vue'
|
||||||
import { onLoad, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
import { onLoad, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
||||||
import { getReportByToken, imgUrl } from '../../api/index.js'
|
import { getReportByToken, imgUrl } from '../../api/index.js'
|
||||||
import { formatDateTimeYMDHM } from '../../utils/datetime.js'
|
import { formatDateTimeYMDHM } from '../../utils/datetime.js'
|
||||||
|
import { drawReportPoster, POSTER_W, POSTER_H } from '../../utils/reportPosterDraw.js'
|
||||||
import AppIcon from '../../components/AppIcon.vue'
|
import AppIcon from '../../components/AppIcon.vue'
|
||||||
import { navigateTo } from '../../utils/globalState.js'
|
|
||||||
import { isLoggedIn } from '../../utils/session.js'
|
import { isLoggedIn } from '../../utils/session.js'
|
||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
@ -155,6 +162,23 @@ const afterPhotos = computed(() => {
|
|||||||
if (!reportData.value?.afterPhoto) return []
|
if (!reportData.value?.afterPhoto) return []
|
||||||
return reportData.value.afterPhoto.split(',').filter(Boolean)
|
return reportData.value.afterPhoto.split(',').filter(Boolean)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/** 转发标题:店名 + 宠物 + 服务,更易产生点击欲 */
|
||||||
|
const shareTitle = computed(() => {
|
||||||
|
const r = reportData.value
|
||||||
|
if (!r) return '宠物洗护美容报告'
|
||||||
|
const store = r.store?.name || '宠伴生活馆'
|
||||||
|
const pet = r.petName || '爱宠'
|
||||||
|
const svc = r.serviceType || '洗护美容'
|
||||||
|
return `${store}|${pet}的${svc}已完成,点击查看报告`
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 分享封面:优先服务后首图(微信要求可访问 https 图床) */
|
||||||
|
const shareCoverUrl = computed(() => {
|
||||||
|
if (afterPhotos.value.length > 0) return imgUrl(afterPhotos.value[0])
|
||||||
|
if (beforePhotos.value.length > 0) return imgUrl(beforePhotos.value[0])
|
||||||
|
return ''
|
||||||
|
})
|
||||||
const brandHeaderSafeStyle = (() => {
|
const brandHeaderSafeStyle = (() => {
|
||||||
const statusBarHeight = uni.getSystemInfoSync?.().statusBarHeight || 20
|
const statusBarHeight = uni.getSystemInfoSync?.().statusBarHeight || 20
|
||||||
return `padding-top:${statusBarHeight + 10}px;`
|
return `padding-top:${statusBarHeight + 10}px;`
|
||||||
@ -204,30 +228,25 @@ const navToStore = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onShareAppMessage(() => {
|
onShareAppMessage(() => {
|
||||||
const r = reportData.value
|
const q = routeToken.value ? `token=${encodeURIComponent(routeToken.value)}` : ''
|
||||||
const title = r ? `【${r.petName}】的洗护美容报告出炉啦!` : '宠物洗护美容报告'
|
|
||||||
const imageUrl = afterPhotos.value.length > 0
|
|
||||||
? imgUrl(afterPhotos.value[0])
|
|
||||||
: (beforePhotos.value.length > 0 ? imgUrl(beforePhotos.value[0]) : '')
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title: shareTitle.value,
|
||||||
path: `/pages/report-view/reportView?token=${routeToken.value}`,
|
path: `/pages/report-view/reportView${q ? '?' + q : ''}`,
|
||||||
imageUrl
|
imageUrl: shareCoverUrl.value || undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onShareTimeline(() => {
|
onShareTimeline(() => {
|
||||||
const r = reportData.value
|
const q = routeToken.value ? `token=${encodeURIComponent(routeToken.value)}` : ''
|
||||||
const title = r ? `【${r.petName}】的洗护美容报告出炉啦!` : '宠物洗护美容报告'
|
|
||||||
return {
|
return {
|
||||||
title,
|
title: shareTitle.value,
|
||||||
query: `token=${routeToken.value}`
|
query: q,
|
||||||
|
imageUrl: shareCoverUrl.value || undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
const loadImage = (src) => {
|
const loadImageH5 = (src) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
img.crossOrigin = 'anonymous'
|
img.crossOrigin = 'anonymous'
|
||||||
@ -239,171 +258,173 @@ const loadImage = (src) => {
|
|||||||
|
|
||||||
const generatePoster = async () => {
|
const generatePoster = async () => {
|
||||||
if (!reportData.value) return
|
if (!reportData.value) return
|
||||||
uni.showToast({ title: '正在生成海报...', icon: 'none' })
|
|
||||||
const r = reportData.value
|
const r = reportData.value
|
||||||
const canvas = posterCanvas.value
|
uni.showToast({ title: '正在生成海报...', icon: 'none' })
|
||||||
const ctx = canvas.getContext('2d')
|
const beforeUrl = beforePhotos.value[0] ? imgUrl(beforePhotos.value[0]) : ''
|
||||||
canvas.width = 750
|
const afterUrl = afterPhotos.value[0] ? imgUrl(afterPhotos.value[0]) : ''
|
||||||
canvas.height = 1100
|
|
||||||
|
|
||||||
ctx.fillStyle = '#ffffff'
|
|
||||||
ctx.fillRect(0, 0, 750, 1100)
|
|
||||||
|
|
||||||
const gradient = ctx.createLinearGradient(0, 0, 750, 300)
|
|
||||||
gradient.addColorStop(0, '#07c160')
|
|
||||||
gradient.addColorStop(1, '#10b76f')
|
|
||||||
ctx.fillStyle = gradient
|
|
||||||
ctx.fillRect(0, 0, 750, 300)
|
|
||||||
|
|
||||||
const storeName = r.store?.name || '宠伴生活馆'
|
|
||||||
const storePhone = r.store?.phone || ''
|
|
||||||
const storeAddr = r.store?.address || ''
|
|
||||||
|
|
||||||
ctx.fillStyle = '#ffffff'
|
|
||||||
ctx.font = 'bold 36px sans-serif'
|
|
||||||
ctx.textAlign = 'center'
|
|
||||||
ctx.fillText(storeName, 375, 70)
|
|
||||||
ctx.font = '20px sans-serif'
|
|
||||||
ctx.globalAlpha = 0.7
|
|
||||||
ctx.fillText('宠物服务,让爱更专业', 375, 105)
|
|
||||||
ctx.globalAlpha = 1
|
|
||||||
|
|
||||||
if (storePhone || storeAddr) {
|
|
||||||
ctx.font = '18px sans-serif'
|
|
||||||
ctx.globalAlpha = 0.85
|
|
||||||
const contactLine = [storePhone, storeAddr].filter(Boolean).join(' | ')
|
|
||||||
ctx.fillText(contactLine, 375, 138)
|
|
||||||
ctx.globalAlpha = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fillStyle = '#333333'
|
|
||||||
ctx.font = 'bold 36px sans-serif'
|
|
||||||
ctx.fillText('服务报告', 375, 220)
|
|
||||||
|
|
||||||
ctx.fillStyle = '#f8f6f3'
|
|
||||||
ctx.beginPath()
|
|
||||||
roundRect(ctx, 40, 260, 670, 220, 20)
|
|
||||||
ctx.fill()
|
|
||||||
|
|
||||||
const infoItems = [
|
|
||||||
['宠物名字', r.petName || '-'],
|
|
||||||
['服务项目', r.serviceType || '-'],
|
|
||||||
['服务时间', formatTime(r.appointmentTime) || '-'],
|
|
||||||
['服务技师', r.staffName || '-']
|
|
||||||
]
|
|
||||||
let y = 310
|
|
||||||
ctx.textAlign = 'left'
|
|
||||||
infoItems.forEach(([label, val]) => {
|
|
||||||
ctx.fillStyle = '#999999'
|
|
||||||
ctx.font = '22px sans-serif'
|
|
||||||
ctx.fillText(label, 80, y)
|
|
||||||
ctx.fillStyle = '#333333'
|
|
||||||
ctx.font = 'bold 24px sans-serif'
|
|
||||||
ctx.fillText(val, 220, y)
|
|
||||||
y += 48
|
|
||||||
})
|
|
||||||
|
|
||||||
ctx.fillStyle = '#f8f6f3'
|
|
||||||
ctx.beginPath()
|
|
||||||
roundRect(ctx, 40, 500, 670, 360, 20)
|
|
||||||
ctx.fill()
|
|
||||||
|
|
||||||
ctx.fillStyle = '#333333'
|
|
||||||
ctx.font = 'bold 24px sans-serif'
|
|
||||||
ctx.textAlign = 'center'
|
|
||||||
ctx.fillText('服务前后对比', 375, 545)
|
|
||||||
|
|
||||||
const imgY = 575
|
|
||||||
const imgH = 260
|
|
||||||
const imgW = 300
|
|
||||||
|
|
||||||
ctx.fillStyle = '#e0e0e0'
|
|
||||||
ctx.beginPath()
|
|
||||||
roundRect(ctx, 60, imgY, imgW, imgH, 16)
|
|
||||||
ctx.fill()
|
|
||||||
ctx.fillStyle = '#999999'
|
|
||||||
ctx.font = '20px sans-serif'
|
|
||||||
ctx.fillText('服务前', 210, imgY + imgH/2)
|
|
||||||
|
|
||||||
ctx.fillStyle = '#e0e0e0'
|
|
||||||
ctx.beginPath()
|
|
||||||
roundRect(ctx, 390, imgY, imgW, imgH, 16)
|
|
||||||
ctx.fill()
|
|
||||||
ctx.fillStyle = '#999999'
|
|
||||||
ctx.fillText('服务后', 540, imgY + imgH/2)
|
|
||||||
|
|
||||||
if (r.remark) {
|
|
||||||
ctx.fillStyle = '#f8f6f3'
|
|
||||||
ctx.beginPath()
|
|
||||||
roundRect(ctx, 40, 880, 670, 100, 20)
|
|
||||||
ctx.fill()
|
|
||||||
ctx.fillStyle = '#666666'
|
|
||||||
ctx.font = '22px sans-serif'
|
|
||||||
ctx.textAlign = 'left'
|
|
||||||
const remark = r.remark
|
|
||||||
if (remark.length > 30) {
|
|
||||||
ctx.fillText(remark.substring(0, 30), 70, 920)
|
|
||||||
ctx.fillText(remark.substring(30), 70, 955)
|
|
||||||
} else {
|
|
||||||
ctx.fillText(remark, 70, 930)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fillStyle = '#07c160'
|
|
||||||
ctx.font = 'bold 22px sans-serif'
|
|
||||||
ctx.textAlign = 'center'
|
|
||||||
ctx.fillText(`— ${storeName} —`, 375, 1050)
|
|
||||||
|
|
||||||
const beforeImgSrc = r.beforePhoto ? imgUrl(r.beforePhoto) : null
|
|
||||||
const afterImgSrc = r.afterPhoto ? imgUrl(r.afterPhoto) : null
|
|
||||||
const [beforeImg, afterImg] = await Promise.all([
|
const [beforeImg, afterImg] = await Promise.all([
|
||||||
beforeImgSrc ? loadImage(beforeImgSrc) : Promise.resolve(null),
|
beforeUrl ? loadImageH5(beforeUrl) : Promise.resolve(null),
|
||||||
afterImgSrc ? loadImage(afterImgSrc) : Promise.resolve(null)
|
afterUrl ? loadImageH5(afterUrl) : Promise.resolve(null)
|
||||||
])
|
])
|
||||||
|
const canvas = posterCanvas.value
|
||||||
if (beforeImg) {
|
if (!canvas) return
|
||||||
ctx.save()
|
const ctx = canvas.getContext('2d')
|
||||||
ctx.beginPath()
|
canvas.width = POSTER_W
|
||||||
roundRect(ctx, 60, imgY, imgW, imgH, 16)
|
canvas.height = POSTER_H
|
||||||
ctx.clip()
|
drawReportPoster(ctx, {
|
||||||
ctx.drawImage(beforeImg, 60, imgY, imgW, imgH)
|
storeName: r.store?.name || '',
|
||||||
ctx.restore()
|
storePhone: r.store?.phone || '',
|
||||||
}
|
storeAddr: r.store?.address || '',
|
||||||
if (afterImg) {
|
petName: r.petName || '',
|
||||||
ctx.save()
|
serviceType: r.serviceType || '',
|
||||||
ctx.beginPath()
|
timeStr: formatTime(r.appointmentTime) || '',
|
||||||
roundRect(ctx, 390, imgY, imgW, imgH, 16)
|
staffName: r.staffName || '',
|
||||||
ctx.clip()
|
remark: r.remark || '',
|
||||||
ctx.drawImage(afterImg, 390, imgY, imgW, imgH)
|
beforeImg,
|
||||||
ctx.restore()
|
afterImg
|
||||||
}
|
})
|
||||||
|
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
link.download = `服务报告_${r.petName || '宠物'}.png`
|
link.download = `服务报告_${r.petName || '宠物'}.png`
|
||||||
link.href = canvas.toDataURL('image/png')
|
link.href = canvas.toDataURL('image/png')
|
||||||
link.click()
|
link.click()
|
||||||
|
uni.showToast({ title: '已下载海报', icon: 'success' })
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
function downloadToTemp(url) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (!url) {
|
||||||
|
resolve(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.downloadFile({
|
||||||
|
url,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) resolve(res.tempFilePath)
|
||||||
|
else resolve(null)
|
||||||
|
},
|
||||||
|
fail: () => resolve(null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadCanvasImage(canvas, tempPath) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (!tempPath) {
|
||||||
|
resolve(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const img = canvas.createImage()
|
||||||
|
img.onload = () => resolve(img)
|
||||||
|
img.onerror = () => resolve(null)
|
||||||
|
img.src = tempPath
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const generatePoster = async () => {
|
||||||
|
if (!reportData.value) return
|
||||||
|
const r = reportData.value
|
||||||
|
uni.showLoading({ title: '生成海报中...', mask: true })
|
||||||
|
try {
|
||||||
|
const beforeUrl = beforePhotos.value[0] ? imgUrl(beforePhotos.value[0]) : ''
|
||||||
|
const afterUrl = afterPhotos.value[0] ? imgUrl(afterPhotos.value[0]) : ''
|
||||||
|
const [beforePath, afterPath] = await Promise.all([
|
||||||
|
downloadToTemp(beforeUrl),
|
||||||
|
downloadToTemp(afterUrl)
|
||||||
|
])
|
||||||
|
|
||||||
|
const inst = getCurrentInstance()
|
||||||
|
const proxy = inst?.proxy
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(proxy)
|
||||||
|
.select('#reportPosterCanvas')
|
||||||
|
.fields({ node: true, size: true })
|
||||||
|
.exec(async (res) => {
|
||||||
|
const canvas = res[0]?.node
|
||||||
|
if (!canvas) {
|
||||||
|
uni.showToast({ title: '画布未就绪,请重试', icon: 'none' })
|
||||||
|
resolve()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
const dpr = Math.min(uni.getSystemInfoSync().pixelRatio || 2, 3)
|
||||||
|
canvas.width = POSTER_W * dpr
|
||||||
|
canvas.height = POSTER_H * dpr
|
||||||
|
ctx.scale(dpr, dpr)
|
||||||
|
|
||||||
|
const beforeImg = await loadCanvasImage(canvas, beforePath)
|
||||||
|
const afterImg = await loadCanvasImage(canvas, afterPath)
|
||||||
|
|
||||||
|
drawReportPoster(ctx, {
|
||||||
|
storeName: r.store?.name || '',
|
||||||
|
storePhone: r.store?.phone || '',
|
||||||
|
storeAddr: r.store?.address || '',
|
||||||
|
petName: r.petName || '',
|
||||||
|
serviceType: r.serviceType || '',
|
||||||
|
timeStr: formatTime(r.appointmentTime) || '',
|
||||||
|
staffName: r.staffName || '',
|
||||||
|
remark: r.remark || '',
|
||||||
|
beforeImg,
|
||||||
|
afterImg
|
||||||
|
})
|
||||||
|
|
||||||
|
uni.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvas,
|
||||||
|
fileType: 'png',
|
||||||
|
quality: 1,
|
||||||
|
destWidth: POSTER_W,
|
||||||
|
destHeight: POSTER_H,
|
||||||
|
success: (out) => {
|
||||||
|
uni.saveImageToPhotosAlbum({
|
||||||
|
filePath: out.tempFilePath,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({ title: '已保存到相册', icon: 'success' })
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
const msg = err.errMsg || ''
|
||||||
|
if (msg.includes('auth deny') || msg.includes('authorize')) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '需要相册权限',
|
||||||
|
content: '保存海报需要授权保存到相册,请在设置中开启。',
|
||||||
|
confirmText: '去设置',
|
||||||
|
success: (m) => {
|
||||||
|
if (m.confirm) uni.openSetting({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '保存失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.showToast({ title: '导出图片失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
proxy
|
||||||
|
)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (_) {
|
||||||
|
uni.showToast({ title: '生成失败', icon: 'none' })
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef H5
|
// #ifndef H5
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
const generatePoster = () => {
|
const generatePoster = () => {
|
||||||
uni.showToast({ title: '请在微信中长按保存海报', icon: 'none' })
|
uni.showToast({ title: '请截图分享报告页', icon: 'none' })
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
// #endif
|
||||||
function roundRect(ctx, x, y, w, h, r) {
|
|
||||||
ctx.beginPath()
|
|
||||||
ctx.moveTo(x + r, y)
|
|
||||||
ctx.lineTo(x + w - r, y)
|
|
||||||
ctx.quadraticCurveTo(x + w, y, x + w, y + r)
|
|
||||||
ctx.lineTo(x + w, y + h - r)
|
|
||||||
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h)
|
|
||||||
ctx.lineTo(x + r, y + h)
|
|
||||||
ctx.quadraticCurveTo(x, y + h, x, y + h - r)
|
|
||||||
ctx.lineTo(x, y + r)
|
|
||||||
ctx.quadraticCurveTo(x, y, x + r, y)
|
|
||||||
ctx.closePath()
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
routeToken.value = options?.token || ''
|
routeToken.value = options?.token || ''
|
||||||
@ -413,6 +434,14 @@ onMounted(() => loadReport())
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.poster-canvas-offscreen {
|
||||||
|
position: fixed;
|
||||||
|
left: -9999px;
|
||||||
|
top: 0;
|
||||||
|
width: 375px;
|
||||||
|
height: 550px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.report-view { background: #f5f7fb; min-height: 100vh; }
|
.report-view { background: #f5f7fb; min-height: 100vh; }
|
||||||
.loading-wrap {
|
.loading-wrap {
|
||||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user