fix: metadata

This commit is contained in:
zzc
2026-02-03 05:14:31 +08:00
parent 7d0b79bd16
commit b2b59cb61a
3 changed files with 142 additions and 107 deletions

View File

@@ -1,6 +1,6 @@
<template>
<view class="record-page">
<NavBar title="我的运势记录" />
<NavBar title="我的运势记录" />
<scroll-view
scroll-y
@@ -46,7 +46,7 @@
>
<view class="item-image-box">
<image
:src="item.imageUrl"
:src="getThumbUrl(item.imageUrl)"
mode="aspectFill"
class="item-image"
/>
@@ -115,6 +115,10 @@ const getTagClass = (tag) => {
return map[tag] || "tag-gold";
};
const getThumbUrl = (url) => {
return `${url}?imageView2/1/w/340/h/600/q/80`;
};
const loadData = async () => {
if (loading.value || !hasMore.value) return;
@@ -145,14 +149,9 @@ const loadData = async () => {
};
const loadMore = () => {
console.log(666666666);
loadData();
};
const goBack = () => {
uni.navigateBack();
};
const goDetail = (item) => {
// 传递数据到详情页
const data = encodeURIComponent(JSON.stringify(item));

View File

@@ -13,7 +13,9 @@
<view class="step-num-wrap">
<view class="step-line" v-if="idx > 0"></view>
<view class="step-num">
<text v-if="activeTool === tool.type && showPanel">{{ tool.icon }}</text>
<text v-if="activeTool === tool.type && showPanel">{{
tool.icon
}}</text>
<text v-else>{{ tool.step }}</text>
</view>
</view>
@@ -62,12 +64,17 @@
fontSize: fontSize + 'rpx',
lineHeight: fontSize * 1.5 + 'rpx',
}"
>{{ targetName + "\n " + blessingText.content }}</text
>{{
(targetName || "") + "\n " + (blessingText.content || "")
}}</text
>
</view>
<view
class="user"
:style="{ left: 160 + userOffsetX + 'rpx', bottom: 40 - userOffsetY + 'rpx' }"
:style="{
left: 160 + userOffsetX + 'rpx',
bottom: 40 - userOffsetY + 'rpx',
}"
@touchstart.stop="handleUserTouchStart"
@touchmove.stop="handleUserTouchMove"
@touchend.stop="handleUserTouchEnd"
@@ -113,31 +120,45 @@
<!-- 弹出编辑面板 -->
<view class="panel-container" :class="{ show: showPanel }">
<view class="panel-mask" @tap="closePanel"></view>
<view class="panel-content" :class="{ 'glass-effect': activeTool === 'text' || activeTool === 'position' }">
<view
class="panel-content"
:class="{
'glass-effect': activeTool === 'text' || activeTool === 'position',
}"
>
<view class="panel-handle" @tap="closePanel"></view>
<!-- 标题选择区 -->
<view v-if="activeTool === 'title'" class="section">
<view class="section-title">
<text>选择标题</text>
</view>
<view class="tpl-scroll">
<view class="tpl-grid">
<view
v-for="(title, i) in titles"
:key="i"
class="tpl-card title-card"
:class="{ selected: title?.id === currentTitle?.id }"
@tap="selectTitle(title)"
>
<image :src="title.imageUrl" class="title-cover" mode="aspectFit" />
<view v-if="title?.id === currentTitle?.id" class="tpl-check"></view>
</view>
<!-- 标题选择区 -->
<view v-if="activeTool === 'title'" class="section">
<view class="section-title">
<text>选择标题</text>
</view>
<view class="tpl-scroll">
<view class="tpl-grid">
<view
v-for="(title, i) in titles"
:key="i"
class="tpl-card title-card"
:class="{ selected: title?.id === currentTitle?.id }"
@tap="selectTitle(title)"
>
<image
:src="title.imageUrl"
class="title-cover"
mode="aspectFit"
/>
<view v-if="title?.id === currentTitle?.id" class="tpl-check"
></view
>
</view>
</view>
<view v-if="loadingTitles" class="loading-more">加载中...</view>
<view
v-else-if="!hasMoreTitles && titles.length > 0"
class="no-more"
>没有更多了</view
>
</view>
<view v-if="loadingTitles" class="loading-more">加载中...</view>
<view v-else-if="!hasMoreTitles && titles.length > 0" class="no-more">没有更多了</view>
</view>
</view>
<!-- 模板区 -->
@@ -154,7 +175,11 @@
:class="{ selected: tpl?.id === currentTemplate?.id }"
@tap="applyTemplate(tpl)"
>
<image :src="tpl.imageUrl" class="tpl-cover" mode="aspectFill" />
<image
:src="tpl.imageUrl"
class="tpl-cover"
mode="aspectFill"
/>
<view class="tpl-name">{{ tpl.name }}</view>
<view v-if="tpl?.id === currentTemplate?.id" class="tpl-check"
></view
@@ -168,7 +193,6 @@
>没有更多了</view
>
</view>
</view>
<!-- 文字编辑 -->
@@ -193,7 +217,11 @@
<text class="refresh-icon"></text> 换一批
</view>
</view>
<scroll-view scroll-x class="greeting-scroll" show-scrollbar="false">
<scroll-view
scroll-x
class="greeting-scroll"
show-scrollbar="false"
>
<view class="greeting-list">
<view
v-for="(text, index) in displayedGreetings"
@@ -272,7 +300,9 @@
:style="{ background: color }"
@tap="selectedColor = color"
>
<view v-if="selectedColor === color" class="color-check"></view>
<view v-if="selectedColor === color" class="color-check"
></view
>
</view>
</view>
</view>
@@ -284,7 +314,7 @@
<text>调整位置</text>
</view>
<view class="form-item" style="margin-top: 20rpx;">
<view class="form-item" style="margin-top: 20rpx">
<text class="label">祝福语气泡 (上下)</text>
<slider
:value="bubbleOffsetY"
@@ -342,7 +372,9 @@
:style="{ background: color }"
@tap="signatureColor = color"
>
<view v-if="signatureColor === color" class="color-check"></view>
<view v-if="signatureColor === color" class="color-check"
></view
>
</view>
</view>
</view>
@@ -408,9 +440,9 @@ const titleState = ref({
const titleStyle = computed(() => {
return {
transform: `translate(${titleState.value.offsetX}rpx, ${titleState.value.offsetY}rpx) scale(${titleState.value.scale})`,
top: '40rpx',
pointerEvents: 'auto',
transition: 'none'
top: "40rpx",
pointerEvents: "auto",
transition: "none",
};
});
@@ -560,7 +592,7 @@ const fontList = [
name: "中圆",
family: "ZhongYuan",
url: "https://file.lihailezzc.com/ddcd9621740449a29c329f573bc1d0c5.woff2", // 示例地址
}
},
];
const selectedFont = ref(fontList[0]);
const loadedFonts = ref(new Set()); // 记录已加载的字体
@@ -957,69 +989,71 @@ const saveByCanvas = async (save = true) => {
});
};
// 辅助函数rpx 转 px (基于预览容器宽度 506rpx 对应 Canvas 540px)
const r2p = (rpx) => (rpx * 540) / 506;
// 辅助函数rpx 转 px (基于预览容器宽度 506rpx 对应 Canvas 540px)
const r2p = (rpx) => (rpx * 540) / 506;
try {
// 1⃣ 画背景
// ⭐ 先加载背景图
const [bgImg, avatarImg, titleImg] = await Promise.all([
loadCanvasImage(currentTemplate?.value?.imageUrl),
loadCanvasImage(userAvatar.value),
currentTitle.value ? loadCanvasImage(currentTitle.value.imageUrl) : Promise.resolve(null),
]);
try {
// 1⃣ 画背景
// ⭐ 先加载背景图
const [bgImg, avatarImg, titleImg] = await Promise.all([
loadCanvasImage(currentTemplate?.value?.imageUrl),
loadCanvasImage(userAvatar.value),
currentTitle.value
? loadCanvasImage(currentTitle.value.imageUrl)
: Promise.resolve(null),
]);
ctx.drawImage(bgImg, 0, 0, W, H);
ctx.drawImage(bgImg, 0, 0, W, H);
// 2⃣ 半透明遮罩
ctx.fillStyle = "rgba(0,0,0,0.08)";
ctx.fillRect(0, 0, W, H);
// 2⃣ 半透明遮罩
ctx.fillStyle = "rgba(0,0,0,0.08)";
ctx.fillRect(0, 0, W, H);
// 3⃣ 标题图片
if (titleImg) {
const previewBaseWidth = 400; // rpx
const drawWidth = r2p(previewBaseWidth) * titleState.value.scale;
const drawHeight = (titleImg.height / titleImg.width) * drawWidth;
// 计算绘制起点:居中 + 偏移量
const titleX = (W - drawWidth) / 2 + r2p(titleState.value.offsetX);
const titleY = r2p(40) + r2p(titleState.value.offsetY);
ctx.drawImage(titleImg, titleX, titleY, drawWidth, drawHeight);
}
// 3⃣ 标题图片
if (titleImg) {
const previewBaseWidth = 400; // rpx
const drawWidth = r2p(previewBaseWidth) * titleState.value.scale;
const drawHeight = (titleImg.height / titleImg.width) * drawWidth;
// 4⃣ 祝福语气泡
// 预览中 .bubble 有 padding: 40rpx且 .card-overlay 有 padding: 30rpx
// 意味着文字距离容器边缘至少有 70rpx
drawBubbleText(ctx, {
text: targetName.value + "\n " + blessingText.value.content,
x: 0,
y: r2p(230 + bubbleOffsetY.value),
maxWidth: r2p(bubbleMaxWidth.value), // 预览中 bubble-text 的宽度
canvasWidth: W,
fontSize: r2p(fontSize.value),
lineHeight: r2p(fontSize.value * 1.6), // 预览中是 1.6
padding: r2p(40 + 30), // 内部 padding 40 + 容器 padding 30
backgroundColor: "transparent",
textColor: selectedColor.value,
fontFamily: selectedFont.value.family,
});
// 计算绘制起点:居中 + 偏移量
const titleX = (W - drawWidth) / 2 + r2p(titleState.value.offsetX);
const titleY = r2p(40) + r2p(titleState.value.offsetY);
// 5⃣ 用户信息
// 预览中 user 是 absolute, left: 160 + offsetX, bottom: 40 - offsetY
drawUserBubble(ctx, {
x: r2p(160 + userOffsetX.value),
bottom: r2p(40 - userOffsetY.value),
canvasHeight: H,
avatarImg: avatarImg,
username: signatureName.value,
desc: "送上祝福",
textColor: signatureColor.value,
avatarSize: r2p(64),
padding: r2p(15),
fontSizeName: r2p(24),
fontSizeDesc: r2p(20),
});
ctx.drawImage(titleImg, titleX, titleY, drawWidth, drawHeight);
}
// 4⃣ 祝福语气泡
// 预览中 .bubble 有 padding: 40rpx且 .card-overlay 有 padding: 30rpx
// 意味着文字距离容器边缘至少有 70rpx
drawBubbleText(ctx, {
text: targetName.value + "\n " + blessingText.value.content,
x: 0,
y: r2p(230 + bubbleOffsetY.value),
maxWidth: r2p(bubbleMaxWidth.value), // 预览中 bubble-text 的宽度
canvasWidth: W,
fontSize: r2p(fontSize.value),
lineHeight: r2p(fontSize.value * 1.6), // 预览中是 1.6
padding: r2p(40 + 30), // 内部 padding 40 + 容器 padding 30
backgroundColor: "transparent",
textColor: selectedColor.value,
fontFamily: selectedFont.value.family,
});
// 5⃣ 用户信息
// 预览中 user 是 absolute, left: 160 + offsetX, bottom: 40 - offsetY
drawUserBubble(ctx, {
x: r2p(160 + userOffsetX.value),
bottom: r2p(40 - userOffsetY.value),
canvasHeight: H,
avatarImg: avatarImg,
username: signatureName.value,
desc: "送上祝福",
textColor: signatureColor.value,
avatarSize: r2p(64),
padding: r2p(15),
fontSizeName: r2p(24),
fontSizeDesc: r2p(20),
});
// 6⃣ 输出
uni.canvasToTempFilePath({
@@ -1209,11 +1243,11 @@ function drawUserBubble(ctx, options) {
const textX = avatarX + avatarSize + padding;
const totalTextHeight = fontSizeName + fontSizeDesc + 4;
const textStartY = drawY + (bubbleHeight - totalTextHeight) / 2;
ctx.fillStyle = textColor;
ctx.font = `${fontSizeName}px 'PingFang SC'`;
ctx.fillText(username, textX, textStartY);
ctx.font = `${fontSizeDesc}px 'PingFang SC'`;
ctx.globalAlpha = 0.6;
ctx.fillText(desc, textX, textStartY + fontSizeName + 4);
@@ -1670,7 +1704,7 @@ function drawRoundRect(ctx, x, y, w, h, r, color) {
overflow: hidden;
}
.position-section{
.position-section {
margin-bottom: 40rpx;
}
.greeting-card.active .greeting-text {
@@ -1783,8 +1817,9 @@ function drawRoundRect(ctx, x, y, w, h, r, color) {
.btn.secondary {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
color: #333;
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.05),
inset 0 0 0 2rpx #eee;
box-shadow:
0 8rpx 20rpx rgba(0, 0, 0, 0.05),
inset 0 0 0 2rpx #eee;
}
.btn.primary {

View File

@@ -28,10 +28,10 @@
</view>
</view>
<view class="row-2" v-if="isLoggedIn">
<text class="arrow-icon"></text>
<text class="stats-text"
<!-- <text class="arrow-icon"></text> -->
<!-- <text class="stats-text"
>已发送 <text class="num">3</text> 条新春祝福</text
>
> -->
</view>
<view class="row-2" v-else>
<text class="stats-text">点击登录解锁更多功能</text>
@@ -153,6 +153,7 @@ const defaultAvatarUrl =
const userInfo = computed(() => ({
nickName: userStore.userInfo.nickName || "点击登录",
avatarUrl: userStore.userInfo.avatarUrl || defaultAvatarUrl,
isVip: userStore.userInfo.isVip || false,
}));
const isLoggedIn = computed(() => !!userStore.userInfo.nickName);