Compare commits

..

4 Commits

Author SHA1 Message Date
zzc
87877d147d fix: avatar chose 2026-01-25 23:28:03 +08:00
zzc
d496f5a03c fix: avatar chose 2026-01-25 23:03:26 +08:00
zzc
9b958bdb3c fix: avatar chose 2026-01-25 23:00:05 +08:00
zzc
779a356c0b fix: avatar 2026-01-25 22:49:50 +08:00
4 changed files with 299 additions and 20 deletions

16
.hbuilderx/launch.json Normal file
View File

@@ -0,0 +1,16 @@
{ // launch.json 配置了启动调试时相关设置configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数remote代表前端连云端云函数
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}

View File

@@ -1,5 +1,27 @@
import { request } from "@/utils/request.js";
export const getAvatarSystemList = async (page = 1) => {
return request({
url: `/api/blessing/avatar/system/list?page=${page}`,
method: "GET",
});
};
export const getAvatarDecorList = async (page = 1) => {
return request({
url: `/api/blessing/avatar/decor/list?page=${page}`,
method: "GET",
});
};
export const getAvatarFrameList = async (page = 1) => {
return request({
url: `/api/blessing/avatar/frame/list?page=${page}`,
method: "GET",
});
};
export const avatarDownloadRecord = async (data) => {
return request({
url: "/api/blessing/avatar/download",

View File

@@ -40,6 +40,10 @@
<view class="section">
<view class="section-header">
<text class="section-title">选择底图</text>
<view class="more-btn" @tap="openMorePopup">
<text>查看更多</text>
<text class="arrow"></text>
</view>
</view>
<scroll-view scroll-x class="avatar-scroll" show-scrollbar="false">
<view class="avatar-list">
@@ -110,12 +114,42 @@
<!-- Login Popup -->
<LoginPopup ref="loginPopupRef" @logind="handleLogind" />
<!-- More Avatar Popup -->
<uni-popup ref="morePopup" type="bottom" background-color="#fff">
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">选择头像</text>
<view class="close-btn" @tap="closeMorePopup"></view>
</view>
<scroll-view
scroll-y
class="popup-scroll"
@scrolltolower="loadMoreAvatars"
>
<view class="popup-grid">
<view
v-for="(item, i) in moreAvatars"
:key="i"
class="popup-item"
@tap="selectMoreAvatar(item)"
>
<image :src="item" class="popup-img" mode="aspectFill" />
</view>
</view>
<view v-if="loading" class="loading-text">加载中...</view>
<view v-if="!hasMore && moreAvatars.length > 0" class="no-more-text">
没有更多了
</view>
</scroll-view>
</view>
</uni-popup>
</view>
</template>
<script setup>
import { ref, computed } from "vue";
import { onShareAppMessage } from "@dcloudio/uni-app";
import { onShareAppMessage, onLoad, onReachBottom } from "@dcloudio/uni-app";
import { getBavBarHeight, getDeviceInfo } from "@/utils/system";
import { useUserStore } from "@/stores/user";
import {
@@ -123,34 +157,167 @@ import {
getShareReward,
abilityCheck,
} from "@/api/system.js";
import { avatarDownloadRecord } from "@/api/avatar.js";
import {
avatarDownloadRecord,
getAvatarSystemList,
getAvatarFrameList,
getAvatarDecorList,
} from "@/api/avatar.js";
const userStore = useUserStore();
const loginPopupRef = ref(null);
const isLoggedIn = computed(() => !!userStore.userInfo.nickName);
const systemAvatars = [
"https://file.lihailezzc.com/20260109082842_666_1.jpg",
"https://file.lihailezzc.com/20260108222141_644_1.jpg",
"https://file.lihailezzc.com/9a929a32-439f-453b-b603-fda7b04cbe08.png",
];
const frames = [
"https://file.lihailezzc.com/6.png",
"https://file.lihailezzc.com/7.png",
"https://file.lihailezzc.com/yunshi.png",
"https://file.lihailezzc.com/x_CURXRzG4wHF2dp_zu_r-removebg-preview.png",
];
const decors = [
"https://file.lihailezzc.com/6.png",
"https://file.lihailezzc.com/7.png",
];
const systemAvatars = ref([]);
const frames = ref([]);
const decors = ref([]);
const currentAvatar = ref(systemAvatars[0]);
// Pagination states
const framePage = ref(1);
const frameHasNext = ref(true);
const frameLoading = ref(false);
const decorPage = ref(1);
const decorHasNext = ref(true);
const decorLoading = ref(false);
const currentAvatar = ref("");
const selectedFrame = ref("");
const selectedDecor = ref("");
const activeTab = ref("frame");
// More Popup logic
const morePopup = ref(null);
const moreAvatars = ref([]);
const page = ref(1);
const hasMore = ref(true);
const loading = ref(false);
const loadFrames = async () => {
if (frameLoading.value || !frameHasNext.value) return;
frameLoading.value = true;
try {
const res = await getAvatarFrameList(framePage.value);
const list = res?.list || [];
if (list.length > 0) {
frames.value.push(...list.map((item) => item.imageUrl));
framePage.value++;
}
if (typeof res.hasNext !== "undefined") {
frameHasNext.value = res.hasNext;
} else {
if (list.length < 10) frameHasNext.value = false;
}
} catch (e) {
console.error(e);
} finally {
frameLoading.value = false;
}
};
const loadDecors = async () => {
if (decorLoading.value || !decorHasNext.value) return;
decorLoading.value = true;
try {
const res = await getAvatarDecorList(decorPage.value);
const list = res?.list || [];
if (list.length > 0) {
decors.value.push(...list.map((item) => item.imageUrl));
decorPage.value++;
}
if (typeof res.hasNext !== "undefined") {
decorHasNext.value = res.hasNext;
} else {
if (list.length < 10) decorHasNext.value = false;
}
} catch (e) {
console.error(e);
} finally {
decorLoading.value = false;
}
};
const initSystemAvatars = async () => {
try {
const res = await getAvatarSystemList(1);
const list = res?.list || [];
if (list.length > 0) {
// 取前3个展示在首页
systemAvatars.value = list.slice(0, 3).map((item) => item.imageUrl);
// 默认选中第一个
if (systemAvatars.value.length > 0) {
currentAvatar.value = systemAvatars.value[0];
}
}
} catch (e) {
console.error("Failed to load system avatars:", e);
}
};
onLoad(() => {
initSystemAvatars();
loadFrames();
loadDecors();
});
onReachBottom(() => {
if (activeTab.value === "frame") {
loadFrames();
} else if (activeTab.value === "decor") {
loadDecors();
}
});
const openMorePopup = () => {
morePopup.value.open();
if (moreAvatars.value.length === 0) {
// 重新加载第一页,因为 systemAvatars 只取了前3个
// 这里我们简单处理:重新请求第一页作为更多列表的开始
// 或者你可以复用 systemAvatars 的数据,然后 page 从 2 开始请求
// 为了逻辑简单和数据一致性,这里选择重新请求第一页填充更多列表
loadMoreAvatars();
}
};
const closeMorePopup = () => {
morePopup.value.close();
};
const loadMoreAvatars = async () => {
if (loading.value || !hasMore.value) return;
loading.value = true;
try {
const res = await getAvatarSystemList(page.value);
const list = res?.list || [];
if (list.length > 0) {
const newAvatars = list.map((item) => item.imageUrl);
moreAvatars.value.push(...newAvatars);
page.value++;
}
// 根据接口返回的 hasNext 字段判断是否还有更多数据
// 如果接口没有返回 hasNext则降级使用列表长度判断假设每页10条
if (typeof res.hasNext !== "undefined") {
hasMore.value = res.hasNext;
} else {
if (list.length < 10) {
hasMore.value = false;
}
}
} catch (e) {
console.error(e);
} finally {
loading.value = false;
}
};
const selectMoreAvatar = (url) => {
currentAvatar.value = url;
closeMorePopup();
};
const toggleFrame = (frame) => {
if (selectedFrame.value === frame) {
selectedFrame.value = "";
@@ -598,4 +765,77 @@ const loadImage = (url) => {
left: -9999px;
top: -9999px;
}
/* More Popup Styles */
.more-btn {
margin-left: auto;
font-size: 24rpx;
color: #999;
display: flex;
align-items: center;
}
.arrow {
font-size: 32rpx;
margin-left: 4rpx;
line-height: 1;
position: relative;
top: -2rpx;
}
.popup-content {
background: #fff;
border-radius: 24rpx 24rpx 0 0;
height: 60vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.popup-header {
padding: 32rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
border-bottom: 2rpx solid #f5f5f5;
}
.popup-title {
font-size: 32rpx;
font-weight: 600;
}
.close-btn {
position: absolute;
right: 32rpx;
top: 50%;
transform: translateY(-50%);
font-size: 32rpx;
color: #999;
padding: 10rpx;
}
.popup-scroll {
flex: 1;
height: 0;
}
.popup-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20rpx;
padding: 24rpx;
}
.popup-item {
aspect-ratio: 1;
border-radius: 16rpx;
overflow: hidden;
background: #f5f5f5;
}
.popup-img {
width: 100%;
height: 100%;
}
.loading-text,
.no-more-text {
text-align: center;
padding: 24rpx;
color: #999;
font-size: 24rpx;
}
</style>

View File

@@ -1,6 +1,7 @@
// const BASE_URL = 'https://apis.lihailezzc.com'
// const BASE_URL = 'http://127.0.0.1:3999'
const BASE_URL = "http://192.168.1.3:3999";
const BASE_URL = 'http://127.0.0.1:3999'
// const BASE_URL = "http://192.168.1.3:3999";
// const BASE_URL = "http://192.168.31.253:3999";
import { useUserStore } from "@/stores/user";
// 环境区分