diff --git a/frontend/pages.json b/frontend/pages.json
index 2b0f39e..20f21e6 100644
--- a/frontend/pages.json
+++ b/frontend/pages.json
@@ -92,6 +92,15 @@
}
}
},
+ {
+ "path": "pages/profile/myWorks",
+ "style": {
+ "navigationStyle": "custom",
+ "app-plus": {
+ "bounce": "none"
+ }
+ }
+ },
{
"path": "pages/exhibition/exhibition",
"style": {
diff --git a/frontend/pages/components/BannerTop3.vue b/frontend/pages/components/BannerTop3.vue
index 82ce969..b6826b6 100644
--- a/frontend/pages/components/BannerTop3.vue
+++ b/frontend/pages/components/BannerTop3.vue
@@ -1,47 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 用户 :
- {{ item.owner_nickname || '未知用户' }}
-
-
-
-
-
-
-
-
+
+
+
@@ -49,17 +9,8 @@
import { ref, onMounted } from 'vue';
import { getHotRankingApi, getOssPresignedUrlApi } from '@/utils/api.js';
-const top3 = ref([]);
-const loading = ref(true);
+const emit = defineEmits(['dataLoaded']);
-const formatScore = (score) => {
- if (typeof score !== 'number' || isNaN(score) || score < 0) return '0';
- if (score >= 1000000) return (score / 1000000).toFixed(1) + 'M';
- if (score >= 1000) return (score / 1000).toFixed(1) + 'K';
- return score.toString();
-};
-
-// 获取 OSS 预签名 URL,失败时降级返回原值
const resolveOssUrl = async (fileName, type) => {
if (!fileName) return '';
try {
@@ -72,199 +23,45 @@ const resolveOssUrl = async (fileName, type) => {
};
const loadTop3 = async () => {
- loading.value = true;
try {
const res = await getHotRankingApi('total', null, 1, 3);
if (res.code === 200 && res.data?.items) {
const items = res.data.items.slice(0, 3);
- // 并发解析所有封面图和头像的 OSS 预签名 URL
- top3.value = await Promise.all(items.map(async (item) => {
+ const resolved = await Promise.all(items.map(async (item) => {
const [coverUrl, avatarUrl] = await Promise.all([
resolveOssUrl(item.cover_url || '', 'asset'),
resolveOssUrl(item.avatar_url || '', 'avatar'),
]);
return { ...item, cover_url: coverUrl, avatar_url: avatarUrl };
}));
+ emit('dataLoaded', resolved);
}
} catch (e) {
console.error('[BannerTop3] 加载失败', e?.message ?? e);
- } finally {
- loading.value = false;
}
};
+const onBannerTap = () => {
+ uni.navigateTo({ url: '/pages/rank/rank' });
+};
+
onMounted(loadTop3);
defineExpose({ reload: loadTop3 });
diff --git a/frontend/pages/components/Header.vue b/frontend/pages/components/Header.vue
index e682832..aed5133 100644
--- a/frontend/pages/components/Header.vue
+++ b/frontend/pages/components/Header.vue
@@ -12,7 +12,7 @@
-
+
@@ -26,7 +26,7 @@
-
+
@@ -40,7 +40,7 @@
-
+
@@ -58,13 +58,14 @@
+
-
+
{{ crystalBalance }}
-
+
收益 27.1/H
@@ -454,14 +455,14 @@ defineExpose({
/* --- 上层图标样式 --- */
.task-icon-box {
position: absolute;
- top: 0;
+ top: 8rpx;
/* 固定在顶部 */
left: 50%;
transform: translateX(-50%);
/* 水平居中 */
- width: 90rpx;
+ width: 88rpx;
/* 图标宽度 */
- height: 90rpx;
+ height: 88rpx;
/* 图标高度 */
z-index: 10;
/* 确保图标在文字块上面 */
@@ -475,13 +476,10 @@ defineExpose({
/* 红点样式 */
.task-red-dot {
position: absolute;
- top: 6rpx;
- right: 6rpx;
+ top: 8rpx;
+ right: 12rpx;
width: 16rpx;
height: 16rpx;
- background-color: red;
- border-radius: 50%;
- border: 2rpx solid #fff;
}
/* --- 下层文字背景块 --- */
@@ -493,42 +491,22 @@ defineExpose({
transform: translateX(-50%);
width: 88rpx;
height: 80rpx;
- background: linear-gradient(to bottom right,
- #F0E4B1 0%,
- /* 左:浅橙粉 */
- #F08399 50%,
- #B94E73 100%
- /* 右:柔粉红 */
- );
-
-
- /* 立体感核心:多层阴影 + 内阴影模拟凸起 */
- box-shadow:
- /* 外层投影 - 让按钮浮起 */
- 0 4rpx 12rpx rgba(255, 143, 158, 0.2),
- 0 2rpx 6rpx rgba(255, 143, 158, 0.15),
-
- /* 内阴影 - 模拟顶部受光 + 底部凹陷 */
- inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4),
- /* 顶部高光 */
- inset 0 -2rpx 4rpx rgba(0, 0, 0, 0.05);
- /* 底部暗部 */
- /* 粉色渐变背景,可微调 */
+ background-image: url('/static/square/gerenzhongxincangpinkuang.png');
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 5;
/* 必须比图标小,才能被覆盖 */
- box-shadow: 0 4rpx 10rpx rgba(255, 107, 187, 0.3);
- /* 可选:增加一点阴影层次感 */
}
.task-text-label {
- font-size: 18rpx;
+ font-size: 16rpx;
color: #fff;
text-shadow: 1rpx 1rpx 2rpx rgba(255, 255, 255, 0.5);
- margin-top: 24rpx;
+ margin-top: 32rpx;
}
@@ -564,17 +542,23 @@ defineExpose({
/* --- 右侧容器 --- */
.crystal-info-container {
position: relative;
- /* 自动撑开宽度 */
height: 56rpx;
width: 80rpx;
- /* 容器高度 */
border-radius: 16rpx;
- background: rgba(0, 0, 0, 0.5);
bottom: 4rpx;
padding-right: 28rpx;
padding-left: 56rpx;
}
+.crystal-bg-img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 0;
+}
+
/* --- 上层:文字内容 --- */
.crystal-text-layer {
position: relative;
@@ -618,30 +602,19 @@ defineExpose({
width: 100%;
height: 65%;
z-index: 1;
- /* 关键:层级低于文字,高于透明底色 */
background: linear-gradient(to bottom right,
#F0E4B1 0%,
- /* 左:浅橙粉 */
#F08399 50%,
#B94E7399 100%
- /* 右:柔粉红 */
);
-
- /* 立体感核心:多层阴影 + 内阴影模拟凸起 */
box-shadow:
- /* 外层投影 - 让按钮浮起 */
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
0 2rpx 6rpx rgba(255, 143, 158, 0.15),
-
- /* 内阴影 - 模拟顶部受光 + 底部凹陷 */
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4),
- /* 顶部高光 */
inset 0 -2rpx 4rpx rgba(0, 0, 0, 0.05);
- /* 底部暗部 */
border-radius: 10rpx;
-
}
.icon-item {
diff --git a/frontend/pages/profile/myWorks.vue b/frontend/pages/profile/myWorks.vue
new file mode 100644
index 0000000..447a081
--- /dev/null
+++ b/frontend/pages/profile/myWorks.vue
@@ -0,0 +1,589 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 我的在展作品
+
+
+
+
+
+
+
+
+
+
+ {{ item.like_count || 0 }}
+
+
+
+
+
+
+ {{ item.rate || '0' }}/H
+
+
+
+
+
+
+ 暂无在展作品
+
+
+
+
+
+
+
+
+ 今日点赞作品
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.status_text }}
+
+ {{ formatScore(item.score) }}
+
+
+
+
+
+
+
+ +{{ item.reward }}
+
+
+
+
+
+
+ 今日暂无点赞作品
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/pages/square/components/BannerCarousel.vue b/frontend/pages/square/components/BannerCarousel.vue
index 37a21e7..14eccd5 100644
--- a/frontend/pages/square/components/BannerCarousel.vue
+++ b/frontend/pages/square/components/BannerCarousel.vue
@@ -1,15 +1,16 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/pages/square/components/ContentTabs.vue b/frontend/pages/square/components/ContentTabs.vue
new file mode 100644
index 0000000..276a0ef
--- /dev/null
+++ b/frontend/pages/square/components/ContentTabs.vue
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+ {{ tab.emoji }}
+
+
+
+ {{ tab.label }}
+
+
+
+
+
+
+
diff --git a/frontend/pages/square/components/WaterfallGrid.vue b/frontend/pages/square/components/WaterfallGrid.vue
new file mode 100644
index 0000000..ef07590
--- /dev/null
+++ b/frontend/pages/square/components/WaterfallGrid.vue
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/pages/square/composables/useSwipe.js b/frontend/pages/square/composables/useSwipe.js
index eb8e2d9..059a659 100644
--- a/frontend/pages/square/composables/useSwipe.js
+++ b/frontend/pages/square/composables/useSwipe.js
@@ -88,7 +88,7 @@ export function useSwipe() {
inertiaRaf = rafFn(step)
}
- const getBannerBottom = () => (screenWidth.value / 750) * 496
+ const getBannerBottom = () => (screenWidth.value / 750) * 632
const onBgTouchStart = (e) => {
const touchY = e.touches[0].clientY
diff --git a/frontend/pages/square/square.vue b/frontend/pages/square/square.vue
index e00fbb2..96f9477 100644
--- a/frontend/pages/square/square.vue
+++ b/frontend/pages/square/square.vue
@@ -1,40 +1,16 @@
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
- 调试
-
+
+
-
-
+
+
+
+
+
@@ -77,22 +56,18 @@
@@ -340,29 +230,38 @@ onUnmounted(() => {
overflow: hidden;
}
-.background-strip {
- position: absolute;
- top: 0;
- left: 50%;
- height: 150%;
+/* .fall-bg{
+ background: rgba(255, 180, 180, 0.25);
+ border-radius: 48rpx;
+} */
+
+.banner-tabs-wrapper {
+ position: fixed;
+ top: 216rpx;
+ left: 0;
+ right: 0;
+ z-index: 100;
display: flex;
- z-index: 0;
- will-change: transform;
+ flex-direction: column;
+ min-height: 448rpx;
+ justify-content: space-between;
+ background: rgb(249 159 192 / 45%);;
+ /* background: rgba(212, 127, 127, 0.8); */
+ border-radius: 48rpx;
+ overflow: visible;
}
-.background-tile {
- flex-shrink: 0;
- height: 100%;
-}
+/* .tabs{
+ margin-bottom: 8rpx;
+} */
-.cabin-layer {
+.background-fixed {
position: absolute;
top: 0;
- left: 50%;
+ left: 0;
width: 100%;
height: 100%;
- z-index: 1;
- pointer-events: none;
+ z-index: 0;
}
.nav-mask {