diff --git a/api/make.js b/api/make.js index 2e86d21..813c70f 100644 --- a/api/make.js +++ b/api/make.js @@ -15,3 +15,10 @@ export const updateCard = async (data) => { data, }); }; + +export const getCardTemplateList = async (page = 1) => { + return request({ + url: "/api/blessing/card/template/list?page=" + page, + method: "GET", + }); +}; diff --git a/pages/make/index.vue b/pages/make/index.vue index 6db9211..26b5539 100644 --- a/pages/make/index.vue +++ b/pages/make/index.vue @@ -2,7 +2,11 @@ - + 新春快乐 @@ -31,6 +35,22 @@ + + + + + + 热门模板 - 查看更多 > - - + + - + {{ tpl.name }} - + 加载中... + 没有更多了 @@ -154,22 +184,6 @@ - - - - - - import { ref, onMounted } from "vue"; import { getBavBarHeight, getDeviceInfo } from "@/utils/system"; -import { createCardTmp, updateCard } from "@/api/make"; +import { createCardTmp, getCardTemplateList } from "@/api/make"; import { createCardShareToken } from "@/api/card"; import { onShareAppMessage, onLoad } from "@dcloudio/uni-app"; import { useUserStore } from "@/stores/user"; +const templatePage = ref(1); +const loadingTemplates = ref(false); +const hasMoreTemplates = ref(true); const userStore = useUserStore(); const cardId = ref(""); @@ -195,11 +212,11 @@ const targetName = ref("祝您"); const signatureName = ref(userStore?.userInfo?.nickName || "xxx"); const userAvatar = ref( userStore?.userInfo?.avatarUrl || - "https://file.lihailezzc.com/resource/b48c41054c2633c478463ac1b1f1ca23.png" + "https://file.lihailezzc.com/resource/b48c41054c2633c478463ac1b1f1ca23.png", ); const blessingText = ref( - "岁末将至,敬颂冬绥。平安喜乐,万事胜意。祝您2026年大吉大利!一马当先,前程似锦!龙马精神,阖家安康!" + "岁末将至,敬颂冬绥。平安喜乐,万事胜意。祝您2026年大吉大利!一马当先,前程似锦!龙马精神,阖家安康!", ); const textColors = ["#ffffff", "#ff3b30", "#F5A623", "#8B572A", "#000000"]; @@ -217,6 +234,7 @@ const greetingLib = [ onLoad((options) => { cardId.value = "69674f307307beac4519025f"; // createCard(); + getTemplateList(); }); const createCard = async () => { @@ -230,6 +248,53 @@ const createCard = async () => { } }; +const getTemplateList = async (isLoadMore = false) => { + if (loadingTemplates.value || (!hasMoreTemplates.value && isLoadMore)) return; + + loadingTemplates.value = true; + try { + const res = await getCardTemplateList(templatePage.value); + + // 兼容数组或对象列表格式 + const list = Array.isArray(res) ? res : res.list || []; + + if (list.length > 0) { + if (isLoadMore) { + templates.value = [...templates.value, ...list]; + } else { + templates.value = list; + // 初始加载时设置第一个为当前选中 + if (list.length > 0 && !currentTemplate.value) { + currentTemplate.value = list[0]; + } + } + + // 判断是否还有更多 + if (typeof res.hasNext !== "undefined") { + hasMoreTemplates.value = res.hasNext; + } else { + // 如果没有 hasNext 字段,根据返回数量简单判断 + hasMoreTemplates.value = list.length >= 8; // 假设每页 10 条 + } + + if (hasMoreTemplates.value) { + templatePage.value++; + } + } else { + if (!isLoadMore) templates.value = []; + hasMoreTemplates.value = false; + } + } catch (error) { + console.error("加载模板失败:", error); + } finally { + loadingTemplates.value = false; + } +}; + +const loadMoreTemplates = () => { + getTemplateList(true); +}; + onShareAppMessage(async () => { const deviceInfo = getDeviceInfo(); const shareTokenRes = await createCardShareToken({ @@ -262,33 +327,12 @@ const selectGreeting = (text) => { const tools = [ { type: "template", text: "模板", icon: "▦" }, { type: "text", text: "文字", icon: "文" }, - { type: "image", text: "图片/背景", icon: "图" }, - { type: "avatar", text: "头像挂饰", icon: "饰" }, + // { type: "image", text: "图片/背景", icon: "图" }, + // { type: "avatar", text: "头像挂饰", icon: "饰" }, ]; const activeTool = ref("template"); -const templates = ref([ - { - id: 1, - name: "金典红金", - cover: "https://file.lihailezzc.com/20260109082842_666_1.jpg", - }, - { - id: 2, - name: "富贵花开", - cover: "https://file.lihailezzc.com/20260108222141_644_1.jpg", - }, - { - id: 3, - name: "大气字法", - cover: "https://file.lihailezzc.com/20260108222141_644_1.jpg", - }, - { - id: 4, - name: "萌趣马年", - cover: "https://file.lihailezzc.com/20260109082842_666_1.jpg", - }, -]); +const templates = ref([]); const currentTemplate = ref(templates.value[0]); @@ -359,7 +403,7 @@ const saveByCanvas = async (save = true) => { // 1️⃣ 画背景 // ⭐ 先加载背景图 const [bgPath, avatarPath] = await Promise.all([ - loadImage(currentTemplate.value.cover), + loadImage(currentTemplate?.value?.imageUrl), loadImage(userAvatar.value), ]); @@ -552,7 +596,7 @@ function drawUserBubble(ctx, options) { bubbleWidth, bubbleHeight, bubbleHeight / 2, - bubbleColor + bubbleColor, ); // 2️⃣ 绘制头像 @@ -566,7 +610,7 @@ function drawUserBubble(ctx, options) { avatarY + avatarSize / 2, avatarSize / 2, 0, - Math.PI * 2 + Math.PI * 2, ); ctx.clip(); ctx.drawImage(avatarPath, avatarX, avatarY, avatarSize, avatarSize); @@ -767,46 +811,59 @@ function drawRoundRect(ctx, x, y, w, h, r, color) { } .tpl-scroll { margin-top: 12rpx; + height: 600rpx; /* 增加高度以展示纵向列表 */ } -.tpl-wrap { - display: flex; +.tpl-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 16rpx; + padding-bottom: 20rpx; } .tpl-card { - width: 180rpx; - height: 240rpx; - border-radius: 18rpx; + width: 100%; /* 自适应 grid 宽度 */ + border-radius: 12rpx; overflow: hidden; background: #fff; - margin-right: 16rpx; position: relative; - box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.06); + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06); } .tpl-card.selected { outline: 4rpx solid #ff3b30; } .tpl-cover { width: 100%; - height: 160rpx; + height: 368rpx; } .tpl-name { - font-size: 22rpx; + font-size: 20rpx; color: #333; - padding: 8rpx 12rpx; + padding: 6rpx 8rpx; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .tpl-check { position: absolute; - right: 10rpx; - top: 10rpx; - width: 36rpx; - height: 36rpx; + right: 6rpx; + top: 6rpx; + width: 32rpx; + height: 32rpx; border-radius: 50%; background: #ff3b30; color: #fff; - font-size: 22rpx; + font-size: 20rpx; display: flex; align-items: center; justify-content: center; } +.loading-more, +.no-more { + text-align: center; + font-size: 22rpx; + color: #999; + padding: 10rpx 0; +} /* 文字编辑区 */ .text-edit-section {