diff --git a/src/pages/point-book-detail.vue b/src/pages/point-book-detail.vue
index 2916075..38eac85 100644
--- a/src/pages/point-book-detail.vue
+++ b/src/pages/point-book-detail.vue
@@ -92,7 +92,7 @@ const shareImage = async () => {
onLoad(async (options) => {
if (options.id) {
- const result = await getPointBookDetailAPI(options.id || 222);
+ const result = await getPointBookDetailAPI(options.id || 243);
record.value = result;
notes.value = result.remark || "";
const config = uni.getStorageSync("point-book-config");
@@ -281,18 +281,18 @@ onShareTimeline(async () => {
class="btns"
:style="{
gridTemplateColumns: `repeat(${
- user.id === record.user.id ? 1 : 1
+ user.id === record.user.id ? 2 : 1
}, 1fr)`,
}"
>
-
+
diff --git a/src/util.js b/src/util.js
index 8dd95d6..1e06711 100644
--- a/src/util.js
+++ b/src/util.js
@@ -194,6 +194,98 @@ export function drawRoundedRect(
}
}
+export function drawRingCircle(ctx, x, y, text, diameter = 12) {
+ const fillColor = "#ff4444";
+ const borderColor = "#ffffff";
+ const borderWidth = 1;
+ const r = diameter / 2;
+
+ // 传入的 x/y 需要减去半径和边框长度
+ const cx = x - r - borderWidth;
+ const cy = y - r - borderWidth;
+
+ // 画圆填充
+ ctx.beginPath();
+ if (typeof ctx.arc === "function") {
+ ctx.arc(cx, cy, r, 0, Math.PI * 2);
+ } else {
+ // 简易兼容:没有 arc 方法时,用圆角矩形近似
+ drawRoundedRect(ctx, cx - r, cy - r, r * 2, r * 2, r, fillColor, null, 0);
+ }
+ if (typeof ctx.setFillStyle === "function") {
+ ctx.setFillStyle(fillColor);
+ } else {
+ ctx.fillStyle = fillColor;
+ }
+
+ // 添加微弱阴影提升立体感
+ if (typeof ctx.setShadow === "function") {
+ ctx.setShadow(0, 1, 2, "rgba(0,0,0,0.25)");
+ } else {
+ ctx.shadowColor = "rgba(0,0,0,0.25)";
+ ctx.shadowBlur = 2;
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 1;
+ }
+
+ ctx.fill();
+
+ // 重置阴影,避免影响后续描边和文字
+ if (typeof ctx.setShadow === "function") {
+ ctx.setShadow(0, 0, 0, "rgba(0,0,0,0)");
+ } else {
+ ctx.shadowColor = "transparent";
+ ctx.shadowBlur = 0;
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 0;
+ }
+
+ // 画白色 1px 边框
+ if (typeof ctx.setLineWidth === "function") {
+ ctx.setLineWidth(borderWidth);
+ } else {
+ ctx.lineWidth = borderWidth;
+ }
+ if (typeof ctx.setStrokeStyle === "function") {
+ ctx.setStrokeStyle(borderColor);
+ } else {
+ ctx.strokeStyle = borderColor;
+ }
+ // 当 arc 不可用时,drawRoundedRect 已经完成边框;否则对圆描边
+ if (typeof ctx.arc === "function") {
+ ctx.stroke();
+ }
+
+ // 在圆心绘制数字,使用水平缩放实现窄体,并保持圆心居中
+ const fontSize = 9;
+ if (typeof ctx.setFontSize === "function") {
+ ctx.setFontSize(fontSize);
+ } else {
+ ctx.font = `${fontSize}px sans-serif`;
+ }
+ if (typeof ctx.setFillStyle === "function") {
+ ctx.setFillStyle("#ffffff");
+ } else {
+ ctx.fillStyle = "#ffffff";
+ }
+ ctx.save();
+ ctx.translate(cx, cy);
+ // 居中对齐
+ if (typeof ctx.setTextAlign === "function") {
+ ctx.setTextAlign("center");
+ } else {
+ ctx.textAlign = "center";
+ }
+ if (typeof ctx.setTextBaseline === "function") {
+ ctx.setTextBaseline("middle");
+ } else {
+ ctx.textBaseline = "middle";
+ }
+ ctx.scale(0.7, 1);
+ ctx.fillText(String(text ?? ""), 0, 0);
+ ctx.restore();
+}
+
// 将文本按字符拆分并依次向右绘制,每个字符有白色背景,背景宽度根据字符宽度+内边距动态计算
export function drawTextBoxesLine(
ctx,
@@ -887,10 +979,7 @@ export const generateShareImage = async (canvasId, data) => {
try {
const pointBook = uni.getStorageSync("point-book");
const arrowData = data.groups && data.groups[0] ? data.groups[0] : {};
- console.log(arrowData);
- // const hasPoint = arrowData.list.some((arrow) => arrow.x && arrow.y);
- const hasPoint = true;
- console.log("generate data:", data, pointBook);
+ const hasPoint = arrowData.list.some((arrow) => arrow.x && arrow.y);
const ctx = uni.createCanvasContext(canvasId);
const width = 375;
@@ -906,8 +995,8 @@ export const generateShareImage = async (canvasId, data) => {
const avatarUrl = await loadImage(data.user.avatar);
drawRoundImage(ctx, avatarUrl, 13, 13, 54, 54, 27, "#000", 1);
renderText(ctx, data.user.name, 18, "#000", 84, 36);
- renderText(ctx, data.recordDate, 9, "#fff", 350, 24, "center", 38);
- renderText(ctx, "今日打卡", 13, "#fff", 338, 36, "center", 38);
+ renderText(ctx, data.recordDate, 9, "#fff", 350, 24, "center", 39);
+ renderText(ctx, "今日打卡", 13, "#fff", 336, 38, "center", 39);
// 以第一个字的 x 为起点,右侧字符依次向右排列,每个字符有白色背景并留 5 像素内边距
let cursorX = 84;
cursorX = drawTextBoxesLine(
@@ -976,7 +1065,11 @@ export const generateShareImage = async (canvasId, data) => {
renderText(ctx, "落点分布", 13, "#999", 32, 242);
const bowUrl = await loadImage(pointBook.bowtargetType.iconPng);
ctx.drawImage(bowUrl, 375 * 0.08, 250, 375 * 0.84, 375 * 0.84);
- arrowData.list.forEach((arrow) => {});
+ arrowData.list.forEach((arrow, index) => {
+ const px = 375 * 0.08 + 375 * 0.84 * arrow.x;
+ const py = 250 + 375 * 0.84 * arrow.y;
+ drawRingCircle(ctx, px, py, index + 1);
+ });
}
const ringNames = ["X", 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, "M"];
const ringBarHeight = hasPoint ? 700 : 340;
@@ -1012,7 +1105,7 @@ export const generateShareImage = async (canvasId, data) => {
9,
"#333",
startX + index * (barWidth + barSpacing),
- startY - barHeight - 3
+ startY - barHeight - (hasPoint ? 6 : 3)
);
}
ctx.fillStyle = barColor(ring.rate);
@@ -1040,17 +1133,17 @@ export const generateShareImage = async (canvasId, data) => {
const pointBookQrcodeUrl = await loadImage(
"https://static.shelingxingqiu.com/attachment/2025-11-13/de7fzgghsfgqu0ytu6.png"
);
- ctx.drawImage(pointBookQrcodeUrl, 40, hasPoint ? 715 : 360, 68, 68);
- renderText(ctx, "射灵星球", 18, "#333", 120, hasPoint ? 737 : 380);
+ ctx.drawImage(pointBookQrcodeUrl, 40, hasPoint ? 715 : 358, 68, 68);
+ renderText(ctx, "射灵星球", 18, "#333", 120, hasPoint ? 734 : 380);
renderText(
ctx,
"高效记录每一箭,快来一起打卡吧!",
13,
"#999",
120,
- hasPoint ? 759 : 402
+ hasPoint ? 756 : 402
);
- renderText(ctx, "扫码打卡", 13, "#FFA118", 120, hasPoint ? 780 : 422);
+ renderText(ctx, "扫码打卡", 13, "#FFA118", 120, hasPoint ? 777 : 422);
ctx.draw();
} catch (e) {
console.error("generateShareImage 绘制失败:", e);