处理分享后的兼容问题
This commit is contained in:
@@ -71,7 +71,10 @@ const updateHot = (value) => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const pages = getCurrentPages();
|
const pages = getCurrentPages();
|
||||||
const currentPage = pages[pages.length - 1];
|
const currentPage = pages[pages.length - 1];
|
||||||
if (currentPage.route === "pages/point-book-edit") {
|
if (
|
||||||
|
currentPage.route === "pages/point-book-edit" ||
|
||||||
|
currentPage.route === "pages/point-book-detail"
|
||||||
|
) {
|
||||||
pointBook.value = uni.getStorageSync("point-book");
|
pointBook.value = uni.getStorageSync("point-book");
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -7,19 +7,26 @@ import ScreenHint2 from "@/components/ScreenHint2.vue";
|
|||||||
import RingBarChart from "@/components/RingBarChart.vue";
|
import RingBarChart from "@/components/RingBarChart.vue";
|
||||||
|
|
||||||
import { getPointBookDetailAPI, addNoteAPI } from "@/apis";
|
import { getPointBookDetailAPI, addNoteAPI } from "@/apis";
|
||||||
|
import { generateShareCardImage } from "@/util";
|
||||||
|
|
||||||
|
import useStore from "@/store";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
const store = useStore();
|
||||||
|
const { user, device } = storeToRefs(store);
|
||||||
|
|
||||||
const selectedIndex = ref(0);
|
const selectedIndex = ref(0);
|
||||||
const showTip = ref(false);
|
const showTip = ref(false);
|
||||||
const showTip2 = ref(false);
|
const showTip2 = ref(false);
|
||||||
const showTip3 = ref(false);
|
const showTip3 = ref(false);
|
||||||
const groups = ref([]);
|
|
||||||
const data = ref({});
|
const data = ref({});
|
||||||
const targetId = ref(0);
|
const targetId = ref(0);
|
||||||
const targetSrc = ref("");
|
const targetSrc = ref("");
|
||||||
const arrows = ref([]);
|
const arrows = ref([]);
|
||||||
const notes = ref("");
|
const notes = ref("");
|
||||||
const draftNotes = ref("");
|
const draftNotes = ref("");
|
||||||
const recordId = ref("");
|
const record = ref({
|
||||||
|
groups: [],
|
||||||
|
});
|
||||||
|
|
||||||
const openTip = (index) => {
|
const openTip = (index) => {
|
||||||
if (index === 1) showTip.value = true;
|
if (index === 1) showTip.value = true;
|
||||||
@@ -37,23 +44,31 @@ const saveNote = async () => {
|
|||||||
notes.value = draftNotes.value;
|
notes.value = draftNotes.value;
|
||||||
draftNotes.value = "";
|
draftNotes.value = "";
|
||||||
showTip3.value = false;
|
showTip3.value = false;
|
||||||
if (recordId.value) {
|
if (record.value.id) {
|
||||||
await addNoteAPI(recordId.value, notes.value);
|
await addNoteAPI(record.value.id, notes.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSelect = (index) => {
|
const onSelect = (index) => {
|
||||||
selectedIndex.value = index;
|
selectedIndex.value = index;
|
||||||
data.value = groups.value[index];
|
data.value = record.value.groups[index];
|
||||||
arrows.value = groups.value[index].list.filter((item) => item.x && item.y);
|
arrows.value = record.value.groups[index].list.filter(
|
||||||
|
(item) => item.x && item.y
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
const pages = getCurrentPages();
|
const pages = getCurrentPages();
|
||||||
|
if (pages.length > 1) {
|
||||||
const currentPage = pages[pages.length - 2];
|
const currentPage = pages[pages.length - 2];
|
||||||
uni.navigateBack({
|
uni.navigateBack({
|
||||||
delta: currentPage.route === "pages/point-book" ? 1 : 2,
|
delta: currentPage.route === "pages/point-book" ? 1 : 2,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: "/pages/index",
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const ringRates = computed(() => {
|
const ringRates = computed(() => {
|
||||||
@@ -68,7 +83,7 @@ const ringRates = computed(() => {
|
|||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
const result = await getPointBookDetailAPI(options.id || 194);
|
const result = await getPointBookDetailAPI(options.id || 194);
|
||||||
recordId.value = result.id;
|
record.value = result;
|
||||||
notes.value = result.remark || "";
|
notes.value = result.remark || "";
|
||||||
const config = uni.getStorageSync("point-book-config");
|
const config = uni.getStorageSync("point-book-config");
|
||||||
config.targetOption.some((item) => {
|
config.targetOption.some((item) => {
|
||||||
@@ -78,27 +93,36 @@ onLoad(async (options) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.groups) {
|
if (result.groups) {
|
||||||
groups.value = result.groups;
|
|
||||||
data.value = result.groups[0];
|
data.value = result.groups[0];
|
||||||
arrows.value = result.groups[0].list;
|
arrows.value = result.groups[0].list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onShareAppMessage(() => {
|
onShareAppMessage(async () => {
|
||||||
|
const imageUrl = await generateShareCardImage(
|
||||||
|
"shareCanvas",
|
||||||
|
record.value.recordDate,
|
||||||
|
data.value.userTotalRing,
|
||||||
|
data.value.totalRing
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
title: "射箭打卡,今日又精进了一些~",
|
title: "射箭打卡,今日又精进了一些~",
|
||||||
path: "/pages/point-book-detail?id=" + recordId.value,
|
path: "/pages/point-book-detail?id=" + record.value.id,
|
||||||
imageUrl:
|
imageUrl,
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-12/dcqoz26q0268wxmzjg.png",
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
onShareTimeline(() => {
|
onShareTimeline(async () => {
|
||||||
|
const imageUrl = await generateShareCardImage(
|
||||||
|
"shareCanvas",
|
||||||
|
record.value.recordDate,
|
||||||
|
data.value.userTotalRing,
|
||||||
|
data.value.totalRing
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
title: "射箭打卡,今日又精进了一些~",
|
title: "射箭打卡,今日又精进了一些~",
|
||||||
query: "from=timeline",
|
query: "id=" + record.value.id,
|
||||||
imageUrl:
|
imageUrl,
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-12/dcqoz26q0268wxmzjg.png",
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -108,7 +132,7 @@ onShareTimeline(() => {
|
|||||||
:bgType="2"
|
:bgType="2"
|
||||||
bgColor="#F5F5F5"
|
bgColor="#F5F5F5"
|
||||||
:whiteBackArrow="false"
|
:whiteBackArrow="false"
|
||||||
title="分析"
|
title=""
|
||||||
:onBack="goBack"
|
:onBack="goBack"
|
||||||
>
|
>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
@@ -129,6 +153,11 @@ onShareTimeline(() => {
|
|||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view> -->
|
||||||
|
<canvas
|
||||||
|
class="share-canvas"
|
||||||
|
canvas-id="shareCanvas"
|
||||||
|
style="width: 375px; height: 300px"
|
||||||
|
></canvas>
|
||||||
<view class="detail-data">
|
<view class="detail-data">
|
||||||
<view>
|
<view>
|
||||||
<view
|
<view
|
||||||
@@ -160,7 +189,11 @@ onShareTimeline(() => {
|
|||||||
<view>总环数</view>
|
<view>总环数</view>
|
||||||
<text>{{ data.userTotalRing }}/{{ data.totalRing }}</text>
|
<text>{{ data.userTotalRing }}/{{ data.totalRing }}</text>
|
||||||
</view>
|
</view>
|
||||||
<button hover-class="none" @click="() => openTip(3)">
|
<button
|
||||||
|
hover-class="none"
|
||||||
|
@click="() => openTip(3)"
|
||||||
|
v-if="user.id === record.userId"
|
||||||
|
>
|
||||||
<image src="../static/edit.png" mode="widthFix" />
|
<image src="../static/edit.png" mode="widthFix" />
|
||||||
<text>备注</text>
|
<text>备注</text>
|
||||||
</button>
|
</button>
|
||||||
@@ -199,7 +232,7 @@ onShareTimeline(() => {
|
|||||||
}}</text>
|
}}</text>
|
||||||
</view> -->
|
</view> -->
|
||||||
<view class="ring-text-groups">
|
<view class="ring-text-groups">
|
||||||
<view v-for="(item, index) in groups" :key="index">
|
<view v-for="(item, index) in record.groups" :key="index">
|
||||||
<view v-if="selectedIndex === 0 && index !== 0">
|
<view v-if="selectedIndex === 0 && index !== 0">
|
||||||
<text>{{ index }}:</text>
|
<text>{{ index }}:</text>
|
||||||
<text>{{
|
<text>{{
|
||||||
@@ -231,9 +264,22 @@ onShareTimeline(() => {
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="btns">
|
<view
|
||||||
|
class="btns"
|
||||||
|
:style="{
|
||||||
|
gridTemplateColumns: `repeat(${
|
||||||
|
user.id === record.userId ? 2 : 1
|
||||||
|
}, 1fr)`,
|
||||||
|
}"
|
||||||
|
>
|
||||||
<button hover-class="none" @click="goBack">关闭</button>
|
<button hover-class="none" @click="goBack">关闭</button>
|
||||||
<button hover-class="none" @click="share">分享</button>
|
<button
|
||||||
|
hover-class="none"
|
||||||
|
@click="share"
|
||||||
|
v-if="user.id === record.userId"
|
||||||
|
>
|
||||||
|
分享
|
||||||
|
</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<ScreenHint2
|
<ScreenHint2
|
||||||
@@ -252,11 +298,12 @@ onShareTimeline(() => {
|
|||||||
<text>展示用户某次练习中射箭的点位</text>
|
<text>展示用户某次练习中射箭的点位</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="showTip3">
|
<block v-if="showTip3">
|
||||||
<text>笔记</text>
|
<text>备注</text>
|
||||||
<text v-if="notes">{{ notes }}</text>
|
<text v-if="notes">{{ notes }}</text>
|
||||||
<textarea
|
<textarea
|
||||||
v-if="!notes"
|
v-if="!notes"
|
||||||
v-model="draftNotes"
|
v-model="draftNotes"
|
||||||
|
maxlength="300"
|
||||||
rows="4"
|
rows="4"
|
||||||
class="notes-input"
|
class="notes-input"
|
||||||
placeholder="写下本次射箭的补充信息与心得"
|
placeholder="写下本次射箭的补充信息与心得"
|
||||||
@@ -435,7 +482,7 @@ onShareTimeline(() => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.ring-text-groups > view > view:first-child:nth-last-child(2) {
|
.ring-text-groups > view > view:first-child:nth-last-child(2) {
|
||||||
width: 82rpx;
|
width: 90rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 20rpx;
|
font-size: 20rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -476,23 +523,25 @@ onShareTimeline(() => {
|
|||||||
}
|
}
|
||||||
.btns {
|
.btns {
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 40rpx;
|
||||||
display: flex;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
column-gap: 20rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
}
|
}
|
||||||
.btns > button {
|
.btns > button {
|
||||||
width: 336rpx;
|
|
||||||
height: 84rpx;
|
height: 84rpx;
|
||||||
line-height: 84rpx;
|
line-height: 84rpx;
|
||||||
background: linear-gradient(180deg, #fbfbfb 0%, #f5f5f5 100%), #ffffff;
|
background: linear-gradient(180deg, #fbfbfb 0%, #f5f5f5 100%), #ffffff;
|
||||||
border-radius: 44rpx;
|
border-radius: 44rpx;
|
||||||
border: 2rpx solid #eeeeee;
|
border: 2rpx solid #eeeeee;
|
||||||
|
box-sizing: border-box;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
margin: 0 10rpx;
|
|
||||||
}
|
}
|
||||||
.btns > button:last-child {
|
.btns > button:nth-child(2) {
|
||||||
background: #fed847;
|
background: #fed847;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -96,9 +96,9 @@ const onSelectOption = (itemIndex, value) => {
|
|||||||
</view>
|
</view>
|
||||||
<view class="point-records">
|
<view class="point-records">
|
||||||
<ScrollList :onLoading="onListLoading">
|
<ScrollList :onLoading="onListLoading">
|
||||||
<view v-for="item in list" :key="item.id">
|
<view v-for="(item, index) in list" :key="item.id">
|
||||||
<PointRecord :data="item" :onRemove="onRemoveRecord" />
|
<PointRecord :data="item" :onRemove="onRemoveRecord" />
|
||||||
<view :style="{ height: '25rpx' }"></view>
|
<view v-if="index < list.length - 1" :style="{ height: '25rpx' }"></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="no-data" v-if="list.length === 0">暂无数据</view>
|
<view class="no-data" v-if="list.length === 0">暂无数据</view>
|
||||||
</ScrollList>
|
</ScrollList>
|
||||||
|
|||||||
@@ -332,9 +332,12 @@ onShareTimeline(() => {
|
|||||||
<view class="title" v-if="user.id">
|
<view class="title" v-if="user.id">
|
||||||
<image src="../static/point-book-title2.png" mode="widthFix" />
|
<image src="../static/point-book-title2.png" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
<block v-for="item in list" :key="item.id">
|
<block v-for="(item, index) in list" :key="item.id">
|
||||||
<PointRecord :data="item" :onRemove="onRemoveRecord" />
|
<PointRecord :data="item" :onRemove="onRemoveRecord" />
|
||||||
<view :style="{ height: '25rpx' }"></view>
|
<view
|
||||||
|
v-if="index < list.length - 1"
|
||||||
|
:style="{ height: '25rpx' }"
|
||||||
|
></view>
|
||||||
</block>
|
</block>
|
||||||
<view
|
<view
|
||||||
class="see-more"
|
class="see-more"
|
||||||
|
|||||||
221
src/util.js
221
src/util.js
@@ -454,3 +454,224 @@ export const calcRing = (bowtargetId, x, y, diameter, arrowRadius = 5) => {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const generateShareCardImage = (canvasId, date, actual, total) => {
|
||||||
|
try {
|
||||||
|
const ctx = uni.createCanvasContext(canvasId);
|
||||||
|
const imgUrl =
|
||||||
|
"https://static.shelingxingqiu.com/attachment/2025-11-04/ddzpm4tyh5vunyacsr.png";
|
||||||
|
const drawWidth = 375;
|
||||||
|
const drawHeight = 300;
|
||||||
|
// 兼容第三个参数传入 "actual/total" 的情况
|
||||||
|
let a = actual;
|
||||||
|
let t = total;
|
||||||
|
if (
|
||||||
|
(t === undefined || t === null) &&
|
||||||
|
typeof a === "string" &&
|
||||||
|
a.includes("/")
|
||||||
|
) {
|
||||||
|
const parts = a.split("/");
|
||||||
|
a = parts[0];
|
||||||
|
t = parts[1] || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.getImageInfo({
|
||||||
|
src: imgUrl,
|
||||||
|
success: (res) => {
|
||||||
|
const path = res.path || res.tempFilePath || imgUrl;
|
||||||
|
if (typeof ctx.clearRect === "function") {
|
||||||
|
ctx.clearRect(0, 0, drawWidth, drawHeight);
|
||||||
|
}
|
||||||
|
ctx.drawImage(path, 0, 0, drawWidth, drawHeight);
|
||||||
|
// 绘制左上角日期(白色,22px)
|
||||||
|
renderText(ctx, String(date || ""), 18, "#FFFFFF", 6, 20, "left");
|
||||||
|
// 居中绘制第三个参数为圆角黑底标签
|
||||||
|
const rectW = 200;
|
||||||
|
const rectH = 78;
|
||||||
|
const radius = 39;
|
||||||
|
const rectX = (drawWidth - rectW) / 2;
|
||||||
|
const rectY = (drawHeight - rectH) / 2;
|
||||||
|
ctx.save();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(rectX + radius, rectY);
|
||||||
|
ctx.lineTo(rectX + rectW - radius, rectY);
|
||||||
|
ctx.quadraticCurveTo(
|
||||||
|
rectX + rectW,
|
||||||
|
rectY,
|
||||||
|
rectX + rectW,
|
||||||
|
rectY + radius
|
||||||
|
);
|
||||||
|
ctx.lineTo(rectX + rectW, rectY + rectH - radius);
|
||||||
|
ctx.quadraticCurveTo(
|
||||||
|
rectX + rectW,
|
||||||
|
rectY + rectH,
|
||||||
|
rectX + rectW - radius,
|
||||||
|
rectY + rectH
|
||||||
|
);
|
||||||
|
ctx.lineTo(rectX + radius, rectY + rectH);
|
||||||
|
ctx.quadraticCurveTo(
|
||||||
|
rectX,
|
||||||
|
rectY + rectH,
|
||||||
|
rectX,
|
||||||
|
rectY + rectH - radius
|
||||||
|
);
|
||||||
|
ctx.lineTo(rectX, rectY + radius);
|
||||||
|
ctx.quadraticCurveTo(rectX, rectY, rectX + radius, rectY);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.setFillStyle("rgba(0,0,0,0.5)");
|
||||||
|
ctx.fill();
|
||||||
|
ctx.restore();
|
||||||
|
|
||||||
|
// 居中排版:左侧显示 actual/,右侧显示 total,再追加“环”
|
||||||
|
ctx.save();
|
||||||
|
if (typeof ctx.setTextBaseline === "function")
|
||||||
|
ctx.setTextBaseline("middle");
|
||||||
|
const centerX = rectX + rectW / 2;
|
||||||
|
const centerY = rectY + rectH / 2;
|
||||||
|
// 左半部:右对齐 actual/
|
||||||
|
renderText(ctx, `${a}/`, 40, "#FFFFFF", centerX, centerY, "right");
|
||||||
|
// 右半部:左对齐 total
|
||||||
|
renderText(
|
||||||
|
ctx,
|
||||||
|
`${t || ""}`,
|
||||||
|
30,
|
||||||
|
"#FFFFFF",
|
||||||
|
centerX,
|
||||||
|
centerY,
|
||||||
|
"left"
|
||||||
|
);
|
||||||
|
// 追加单位“环”:放在 total 文本之后 16px
|
||||||
|
const totalWidth = ctx.measureText(`${t || ""}`).width || 0;
|
||||||
|
renderText(
|
||||||
|
ctx,
|
||||||
|
"环",
|
||||||
|
20,
|
||||||
|
"#FFFFFF",
|
||||||
|
centerX + totalWidth + 5,
|
||||||
|
centerY,
|
||||||
|
"left"
|
||||||
|
);
|
||||||
|
ctx.restore();
|
||||||
|
ctx.draw(false, () => {
|
||||||
|
try {
|
||||||
|
uni.canvasToTempFilePath({
|
||||||
|
canvasId,
|
||||||
|
width: drawWidth,
|
||||||
|
height: drawHeight,
|
||||||
|
destWidth: drawWidth,
|
||||||
|
destHeight: drawHeight,
|
||||||
|
fileType: "png",
|
||||||
|
quality: 1,
|
||||||
|
success: (r) => {
|
||||||
|
const path = r.tempFilePath || r.apFilePath || r.filePath;
|
||||||
|
resolve(path);
|
||||||
|
},
|
||||||
|
fail: (err) => reject(err),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
try {
|
||||||
|
ctx.drawImage(imgUrl, 0, 0, drawWidth, drawHeight);
|
||||||
|
// 绘制左上角日期(白色,22px)
|
||||||
|
renderText(ctx, String(date || ""), 22, "#FFFFFF", 10, 22, "left");
|
||||||
|
// 居中绘制第三个参数为圆角黑底标签
|
||||||
|
const rectW = 200;
|
||||||
|
const rectH = 78;
|
||||||
|
const radius = 39;
|
||||||
|
const rectX = (drawWidth - rectW) / 2;
|
||||||
|
const rectY = (drawHeight - rectH) / 2;
|
||||||
|
ctx.save();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(rectX + radius, rectY);
|
||||||
|
ctx.lineTo(rectX + rectW - radius, rectY);
|
||||||
|
ctx.quadraticCurveTo(
|
||||||
|
rectX + rectW,
|
||||||
|
rectY,
|
||||||
|
rectX + rectW,
|
||||||
|
rectY + radius
|
||||||
|
);
|
||||||
|
ctx.lineTo(rectX + rectW, rectY + rectH - radius);
|
||||||
|
ctx.quadraticCurveTo(
|
||||||
|
rectX + rectW,
|
||||||
|
rectY + rectH,
|
||||||
|
rectX + rectW - radius,
|
||||||
|
rectY + rectH
|
||||||
|
);
|
||||||
|
ctx.lineTo(rectX + radius, rectY + rectH);
|
||||||
|
ctx.quadraticCurveTo(
|
||||||
|
rectX,
|
||||||
|
rectY + rectH,
|
||||||
|
rectX,
|
||||||
|
rectY + rectH - radius
|
||||||
|
);
|
||||||
|
ctx.lineTo(rectX, rectY + radius);
|
||||||
|
ctx.quadraticCurveTo(rectX, rectY, rectX + radius, rectY);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.setFillStyle("rgba(0,0,0,0.5)");
|
||||||
|
ctx.fill();
|
||||||
|
ctx.restore();
|
||||||
|
// 居中排版:左侧显示 actual/,右侧显示 total,再追加“环”
|
||||||
|
ctx.save();
|
||||||
|
if (typeof ctx.setTextBaseline === "function")
|
||||||
|
ctx.setTextBaseline("middle");
|
||||||
|
const centerX = rectX + rectW / 2;
|
||||||
|
const centerY = rectY + rectH / 2;
|
||||||
|
// 左半部:右对齐 actual/
|
||||||
|
renderText(ctx, `${a}/`, 40, "#FFFFFF", centerX, centerY, "right");
|
||||||
|
// 右半部:左对齐 total
|
||||||
|
renderText(
|
||||||
|
ctx,
|
||||||
|
`${t || ""}`,
|
||||||
|
35,
|
||||||
|
"#FFFFFF",
|
||||||
|
centerX,
|
||||||
|
centerY,
|
||||||
|
"left"
|
||||||
|
);
|
||||||
|
// 追加单位“环”:放在 total 文本之后 16px
|
||||||
|
const totalWidth = ctx.measureText(`${t || ""}`).width || 0;
|
||||||
|
renderText(
|
||||||
|
ctx,
|
||||||
|
"环",
|
||||||
|
20,
|
||||||
|
"#FFFFFF",
|
||||||
|
centerX + totalWidth + 5,
|
||||||
|
centerY,
|
||||||
|
"left"
|
||||||
|
);
|
||||||
|
ctx.restore();
|
||||||
|
ctx.draw(false, () => {
|
||||||
|
try {
|
||||||
|
uni.canvasToTempFilePath({
|
||||||
|
canvasId,
|
||||||
|
width: drawWidth,
|
||||||
|
height: drawHeight,
|
||||||
|
destWidth: drawWidth,
|
||||||
|
destHeight: drawHeight,
|
||||||
|
fileType: "png",
|
||||||
|
quality: 1,
|
||||||
|
success: (r) => {
|
||||||
|
const path = r.tempFilePath || r.apFilePath || r.filePath;
|
||||||
|
resolve(path);
|
||||||
|
},
|
||||||
|
fail: (err) => reject(err),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("generateShareCardImage 绘制失败:", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user