optimize: avatar page share reward
This commit is contained in:
@@ -47,7 +47,6 @@
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
<!-- Decorative Elements -->
|
||||
<view class="decor-tag">🐰</view>
|
||||
<view class="card-footer-text">
|
||||
<text class="icon">🌸</text> 2026 丙午马年限定
|
||||
</view>
|
||||
@@ -59,9 +58,6 @@
|
||||
<button class="btn primary-btn" @tap="goToMake">
|
||||
<text class="icon">🎨</text> 我也要领同款制作
|
||||
</button>
|
||||
<button class="btn secondary-btn" @tap="saveImage">
|
||||
<text class="icon">📥</text> 保存到相册
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- Recommended Frames -->
|
||||
@@ -94,7 +90,27 @@
|
||||
<text>🖼</text>
|
||||
</view>
|
||||
<view class="banner-content">
|
||||
<text class="banner-title">去挑选更多壁纸</text>
|
||||
<text class="banner-title">去挑选新年壁纸</text>
|
||||
<text class="banner-desc">新年新气象,全套皮肤限时领</text>
|
||||
</view>
|
||||
<text class="banner-arrow">›</text>
|
||||
</view>
|
||||
<view class="wallpaper-banner" @tap="goToWallpaper">
|
||||
<view class="banner-icon">
|
||||
<text>🖼</text>
|
||||
</view>
|
||||
<view class="banner-content">
|
||||
<text class="banner-title">去挑选新年壁纸</text>
|
||||
<text class="banner-desc">新年新气象,全套皮肤限时领</text>
|
||||
</view>
|
||||
<text class="banner-arrow">›</text>
|
||||
</view>
|
||||
<view class="wallpaper-banner" @tap="goToWallpaper">
|
||||
<view class="banner-icon">
|
||||
<text>🖼</text>
|
||||
</view>
|
||||
<view class="banner-content">
|
||||
<text class="banner-title">去挑选新年壁纸</text>
|
||||
<text class="banner-desc">新年新气象,全套皮肤限时领</text>
|
||||
</view>
|
||||
<text class="banner-arrow">›</text>
|
||||
@@ -188,37 +204,6 @@ const previewImage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const saveImage = () => {
|
||||
if (!detailData.value?.imageUrl) return;
|
||||
|
||||
uni.showLoading({ title: "保存中..." });
|
||||
uni.downloadFile({
|
||||
url: detailData.value.imageUrl,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
// uni.hideLoading();
|
||||
uni.showToast({ title: "保存成功", icon: "success" });
|
||||
},
|
||||
fail: () => {
|
||||
// uni.hideLoading();
|
||||
uni.showToast({ title: "保存失败", icon: "none" });
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// uni.hideLoading();
|
||||
uni.showToast({ title: "下载失败", icon: "none" });
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
// uni.hideLoading();
|
||||
uni.showToast({ title: "下载失败", icon: "none" });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const goToMake = () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages/avatar/index",
|
||||
|
||||
@@ -6,17 +6,21 @@
|
||||
</view>
|
||||
<view class="preview-card">
|
||||
<view class="preview-square">
|
||||
<image class="avatar-img" :src="currentAvatar" mode="aspectFill" />
|
||||
<image
|
||||
class="avatar-img"
|
||||
:src="currentAvatar?.imageUrl"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<image
|
||||
v-if="selectedFrame"
|
||||
class="frame-img"
|
||||
:src="selectedFrame"
|
||||
:src="selectedFrame?.imageUrl"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<image
|
||||
v-if="selectedDecor"
|
||||
class="decor-img"
|
||||
:src="selectedDecor"
|
||||
:src="selectedDecor?.imageUrl"
|
||||
mode="aspectFit"
|
||||
:style="decorStyle"
|
||||
@touchstart.stop="onTouchStart"
|
||||
@@ -58,7 +62,11 @@
|
||||
:class="{ active: currentAvatar === item }"
|
||||
@tap="currentAvatar = item"
|
||||
>
|
||||
<image :src="item" class="avatar-thumb" mode="aspectFill" />
|
||||
<image
|
||||
:src="item.imageUrl"
|
||||
class="avatar-thumb"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-if="currentAvatar === item" class="check">✔</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -88,7 +96,7 @@
|
||||
:class="{ active: selectedFrame === frame }"
|
||||
@tap="toggleFrame(frame)"
|
||||
>
|
||||
<image :src="frame" class="grid-img" mode="aspectFill" />
|
||||
<image :src="frame.imageUrl" class="grid-img" mode="aspectFill" />
|
||||
<view v-if="selectedFrame === frame" class="check">✔</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -101,7 +109,7 @@
|
||||
:class="{ active: selectedDecor === decor }"
|
||||
@tap="selectedDecor = decor"
|
||||
>
|
||||
<image :src="decor" class="grid-img" mode="aspectFit" />
|
||||
<image :src="decor.imageUrl" class="grid-img" mode="aspectFit" />
|
||||
<view v-if="selectedDecor === decor" class="check">✔</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -136,7 +144,7 @@
|
||||
class="popup-item"
|
||||
@tap="selectMoreAvatar(item)"
|
||||
>
|
||||
<image :src="item" class="popup-img" mode="aspectFill" />
|
||||
<image :src="item.imageUrl" class="popup-img" mode="aspectFill" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="loading" class="loading-text">加载中...</view>
|
||||
@@ -191,9 +199,9 @@ const decorPage = ref(1);
|
||||
const decorHasNext = ref(true);
|
||||
const decorLoading = ref(false);
|
||||
|
||||
const currentAvatar = ref("");
|
||||
const selectedFrame = ref("");
|
||||
const selectedDecor = ref("");
|
||||
const currentAvatar = ref(null);
|
||||
const selectedFrame = ref(null);
|
||||
const selectedDecor = ref(null);
|
||||
const activeTab = ref("frame");
|
||||
|
||||
// More Popup logic
|
||||
@@ -210,7 +218,12 @@ const loadFrames = async () => {
|
||||
const res = await getAvatarFrameList(framePage.value);
|
||||
const list = res?.list || [];
|
||||
if (list.length > 0) {
|
||||
frames.value.push(...list.map((item) => item.imageUrl));
|
||||
frames.value.push(
|
||||
...list.map((item) => ({
|
||||
id: item.id,
|
||||
imageUrl: item.imageUrl,
|
||||
})),
|
||||
);
|
||||
framePage.value++;
|
||||
}
|
||||
if (typeof res.hasNext !== "undefined") {
|
||||
@@ -232,7 +245,12 @@ const loadDecors = async () => {
|
||||
const res = await getAvatarDecorList(decorPage.value);
|
||||
const list = res?.list || [];
|
||||
if (list.length > 0) {
|
||||
decors.value.push(...list.map((item) => item.imageUrl));
|
||||
decors.value.push(
|
||||
...list.map((item) => ({
|
||||
id: item.id,
|
||||
imageUrl: item.imageUrl,
|
||||
})),
|
||||
);
|
||||
decorPage.value++;
|
||||
}
|
||||
if (typeof res.hasNext !== "undefined") {
|
||||
@@ -253,7 +271,9 @@ const initSystemAvatars = async () => {
|
||||
const list = res?.list || [];
|
||||
if (list.length > 0) {
|
||||
// 取前3个展示在首页
|
||||
systemAvatars.value = list.slice(0, 3).map((item) => item.imageUrl);
|
||||
systemAvatars.value = list
|
||||
.slice(0, 3)
|
||||
.map((item) => ({ id: item.id, imageUrl: item.imageUrl }));
|
||||
// 默认选中第一个
|
||||
if (systemAvatars.value.length > 0) {
|
||||
currentAvatar.value = systemAvatars.value[0];
|
||||
@@ -301,7 +321,10 @@ const loadMoreAvatars = async () => {
|
||||
const list = res?.list || [];
|
||||
|
||||
if (list.length > 0) {
|
||||
const newAvatars = list.map((item) => item.imageUrl);
|
||||
const newAvatars = list.map((item) => ({
|
||||
id: item.id,
|
||||
imageUrl: item.imageUrl,
|
||||
}));
|
||||
moreAvatars.value.push(...newAvatars);
|
||||
page.value++;
|
||||
}
|
||||
@@ -328,14 +351,14 @@ const createAvatarId = () => {
|
||||
return id;
|
||||
};
|
||||
|
||||
const selectMoreAvatar = (url) => {
|
||||
currentAvatar.value = url;
|
||||
const selectMoreAvatar = (item) => {
|
||||
currentAvatar.value = item;
|
||||
closeMorePopup();
|
||||
};
|
||||
|
||||
const toggleFrame = (frame) => {
|
||||
if (selectedFrame.value === frame) {
|
||||
selectedFrame.value = "";
|
||||
selectedFrame.value = null;
|
||||
} else {
|
||||
selectedFrame.value = frame;
|
||||
}
|
||||
@@ -424,7 +447,10 @@ const useWeChatAvatar = () => {
|
||||
if (!isLoggedIn.value) {
|
||||
loginPopupRef.value.open();
|
||||
} else {
|
||||
currentAvatar.value = userStore.userInfo.avatarUrl;
|
||||
currentAvatar.value = {
|
||||
id: "wechat_" + Date.now(),
|
||||
imageUrl: userStore.userInfo.avatarUrl,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -460,15 +486,15 @@ const saveByCanvas = async (save = true) => {
|
||||
const size = 600;
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
const avatarPath = await loadCanvasImage(currentAvatar.value);
|
||||
const avatarPath = await loadCanvasImage(currentAvatar.value.imageUrl);
|
||||
ctx.clearRect(0, 0, size, size);
|
||||
ctx.drawImage(avatarPath, 0, 0, size, size);
|
||||
if (selectedFrame.value) {
|
||||
const framePath = await loadCanvasImage(selectedFrame.value);
|
||||
const framePath = await loadCanvasImage(selectedFrame.value.imageUrl);
|
||||
ctx.drawImage(framePath, 0, 0, size, size);
|
||||
}
|
||||
if (selectedDecor.value) {
|
||||
const decorPath = await loadCanvasImage(selectedDecor.value);
|
||||
const decorPath = await loadCanvasImage(selectedDecor.value.imageUrl);
|
||||
ctx.save();
|
||||
// 映射 rpx 坐标到 Canvas 坐标 (假设 1rpx = 1 unit for 600x600 canvas logic)
|
||||
// Canvas size is 600, Preview is 600rpx. Ratio is 1:1 in logical space.
|
||||
@@ -553,7 +579,10 @@ const saveAndUse = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
saveByCanvas();
|
||||
const tempPath = saveByCanvas(true);
|
||||
const id = createAvatarId();
|
||||
saveRecordRequest(tempPath, id, "avatar_download");
|
||||
completeCardInfo(id);
|
||||
return;
|
||||
// 调用avatarDownloadRecord API记录下载次数
|
||||
// await avatarDownloadRecord({
|
||||
@@ -605,7 +634,13 @@ const saveAndUse = async () => {
|
||||
const completeCardInfo = async (id) => {
|
||||
const tempPath = await saveByCanvas(false);
|
||||
const imageUrl = await uploadImage(tempPath);
|
||||
avatarCreateComplete({ id, imageUrl, avatarId: id });
|
||||
avatarCreateComplete({
|
||||
id,
|
||||
imageUrl,
|
||||
avatarId: currentAvatar?.value?.id,
|
||||
decorId: selectedDecor?.value?.id,
|
||||
frameId: selectedFrame?.value?.id,
|
||||
});
|
||||
};
|
||||
|
||||
onShareAppMessage(async () => {
|
||||
|
||||
Reference in New Issue
Block a user