feat:列表滚动加载
This commit is contained in:
1 parent
2383f67f98
commit
568035dee7
6 files changed
+603
-291
No files matched your search
@@ -33,6 +33,13 @@
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/detail/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<uni-nav-bar dark :fixed="true" :border="false" :height="50" background-color="transparent" left-width="360rpx" right-width="500rpx">
|
||||
<template v-slot:left>
|
||||
<uni-icons type="back" size="30" color="#ffcd32" @click="back"></uni-icons>
|
||||
<view class="nav-user-info" :style="navUserInfoStyle">
|
||||
<image class="nav-avatar" src="" mode="scaleToFill" />
|
||||
<text class="nav-name">稍后发非麻烦咖啡</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right>
|
||||
<view class="nav-bar-right">
|
||||
<view class="status">365.56km · 在线</view>
|
||||
<uni-icons type="more-filled" size="30" color="#ffcd32"></uni-icons>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<scroll-view class="page" scroll-y @scroll="onScroll">
|
||||
<view class="image" style="background-image: url(http://dummyimage.com/100x100/ac0ee3&text=其)">
|
||||
<view class="info">
|
||||
<image class="avatar" src="" />
|
||||
<view class="name">{{ "啊发发" }}</view>
|
||||
<view class="verification">真人认证</view>
|
||||
<view class="tags">
|
||||
<text class="tag">女·23岁</text>
|
||||
<text class="tag">170cm</text>
|
||||
</view>
|
||||
<view class="introduction">{{ "发哈夫哈佛哈维合法i凤凰网你" }}</view>
|
||||
</view>
|
||||
<view class="filter" :style="filterStyle"></view>
|
||||
</view>
|
||||
<view class="album">
|
||||
<view class="title">相册</view>
|
||||
<image class="photo" v-for="(item, index) in 5" :key="index" src="http://dummyimage.com/100x100/ac0ee3&text=其" />
|
||||
</view>
|
||||
<view class="evaluate">
|
||||
<view class="title">评价1+</view>
|
||||
<view class="rate">
|
||||
<view class="rate-item">
|
||||
<text>身材</text>
|
||||
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
|
||||
</view>
|
||||
<view class="rate-item">
|
||||
<text>颜值</text>
|
||||
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
|
||||
</view>
|
||||
<view class="rate-item">
|
||||
<text>耐心</text>
|
||||
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
|
||||
</view>
|
||||
<view class="rate-item">
|
||||
<text>有趣</text>
|
||||
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<moment v-for="(item, index) in 100">{{ index }}</moment>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import moment from "@/sheep/components/moment/moment.vue";
|
||||
|
||||
const scrollTop = ref(0);
|
||||
|
||||
const filterStyle = computed(() => {
|
||||
let blur = 0;
|
||||
const scrollY = scrollTop.value;
|
||||
if (scrollY >= 0) {
|
||||
blur = Math.min(1, scrollY / 300) * 10;
|
||||
}
|
||||
return {
|
||||
backdropFilter: `blur(${blur}px)`,
|
||||
};
|
||||
});
|
||||
const navUserInfoStyle = computed(() => {
|
||||
let opacity = 1;
|
||||
const scrollY = scrollTop.value;
|
||||
if (scrollY >= 0) {
|
||||
opacity = Math.min(1, scrollY / 300 < 0.4 ? 0 : scrollY / 300);
|
||||
}
|
||||
return {
|
||||
opacity,
|
||||
};
|
||||
});
|
||||
|
||||
function back() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
|
||||
function onScroll(e: any) {
|
||||
console.log(e);
|
||||
scrollTop.value = e.detail.scrollTop;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.nav-user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.nav-avatar {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: #333;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.nav-name {
|
||||
width: 140rpx;
|
||||
@include no-wrap;
|
||||
}
|
||||
}
|
||||
.nav-bar-right {
|
||||
margin-right: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.status {
|
||||
font-size: $font-size-small;
|
||||
padding: 10rpx 16rpx;
|
||||
background-color: $color-theme-d;
|
||||
border-radius: 36rpx;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
}
|
||||
.page {
|
||||
height: calc(100vh - 100rpx);
|
||||
background-color: $color-background;
|
||||
overflow: hidden;
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background-repeat: no-repeat;
|
||||
transform-origin: top;
|
||||
background-size: cover;
|
||||
position: relative;
|
||||
.info {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
.avatar {
|
||||
text-align: center;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.name {
|
||||
font-size: $font-size-large;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.verification {
|
||||
background-color: $color-theme;
|
||||
font-size: $font-size-small;
|
||||
color: black;
|
||||
padding: 8rpx;
|
||||
border-radius: 6rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-bottom: 40rpx;
|
||||
.tag {
|
||||
background-color: $color-background;
|
||||
font-size: $font-size-small;
|
||||
color: $color-theme;
|
||||
margin-right: 20rpx;
|
||||
padding: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
.introduction {
|
||||
font-size: $font-size-medium;
|
||||
}
|
||||
}
|
||||
.filter {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(7, 17, 27, 0.2);
|
||||
}
|
||||
}
|
||||
.album {
|
||||
margin: 40rpx;
|
||||
.title {
|
||||
font-size: $font-size-medium-x;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.photo {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
margin: 0 20rpx 20rpx 0;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
}
|
||||
.evaluate {
|
||||
margin: 40rpx;
|
||||
.title {
|
||||
font-size: $font-size-medium-x;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.rate {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
font-size: $font-size-medium;
|
||||
color: $color-theme;
|
||||
.rate-item {
|
||||
gap: 20rpx;
|
||||
background-color: $color-background-d;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 16rpx;
|
||||
margin-bottom: 10rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+208
-176
@@ -1,20 +1,48 @@
|
||||
<template>
|
||||
<view class="home-page">
|
||||
<view class="header">
|
||||
<uni-nav-bar
|
||||
dark
|
||||
:fixed="true"
|
||||
:border="false"
|
||||
:height="50"
|
||||
title=""
|
||||
left-text=""
|
||||
background-color="#222"
|
||||
leftWidth="140rpx"
|
||||
rightWidth="140rpx"
|
||||
>
|
||||
<view class="segmented">
|
||||
<segmented v-model="current" :items="segmentedItems"></segmented>
|
||||
</view>
|
||||
<template v-slot:left>
|
||||
<view class="location">
|
||||
<uni-icons type="location" size="24" color="#ffcd32"></uni-icons>
|
||||
<text>金华市</text>
|
||||
</view>
|
||||
<segmented class="segmented" v-model="current" :items="segmentedItems"></segmented>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right></template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<scroll-view class="user-list" scroll-y>
|
||||
<view class="user-card" v-for="user in userList" :key="user.id">
|
||||
<image class="user-image" :src="user.image" />
|
||||
<view class="home-page">
|
||||
<scroll-view
|
||||
class="user-list"
|
||||
scroll-y
|
||||
refresher-enabled
|
||||
refresher-background="#222"
|
||||
:refresher-triggered="refresherTriggered"
|
||||
:refresher-threshold="100"
|
||||
@refresherpulling="onRefresherPulling"
|
||||
@refresherrefresh="onRefresherRefresh"
|
||||
@refresherrestore="onRefresherRestore"
|
||||
@refresherabort="onRefresherAbort"
|
||||
@scrolltolower="onScrollToLower"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<view class="user-card" v-for="user in userList" :key="user.id" @click="detail">
|
||||
<image class="user-image" :src="user.avatar" />
|
||||
<view class="user-info">
|
||||
<view class="user">
|
||||
<text class="user-name">{{ user.name }}</text>
|
||||
<text class="user-status">{{ user.status }}</text>
|
||||
<text class="user-status">{{ user.status || "离线" }}</text>
|
||||
</view>
|
||||
<view class="verification">
|
||||
<text class="verify-badge">真人认证</text>
|
||||
@@ -28,13 +56,17 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多组件 -->
|
||||
<uni-load-more :status="loadMoreStatus" :content-text="loadMoreContent" @clickLoadMore="onClickLoadMore" />
|
||||
|
||||
<view style="height: 100rpx"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import segmented from "@/sheep/components/segmented/segmented.vue";
|
||||
|
||||
const current = ref(0);
|
||||
@@ -52,175 +84,173 @@ interface User {
|
||||
distance: string;
|
||||
photoCount: number;
|
||||
isVip: boolean;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
const userList = ref<User[]>([
|
||||
{
|
||||
id: 1,
|
||||
name: "晨晨",
|
||||
avatar: "/static/avatar1.jpg",
|
||||
gender: "女",
|
||||
age: 25,
|
||||
height: "168",
|
||||
weight: "45",
|
||||
occupation: "模特",
|
||||
distance: "26.4",
|
||||
photoCount: 2,
|
||||
isVip: false,
|
||||
status: "在线",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "艾伯特",
|
||||
avatar: "/static/avatar2.jpg",
|
||||
gender: "女",
|
||||
age: 25,
|
||||
height: "160",
|
||||
weight: "45",
|
||||
occupation: "学生",
|
||||
distance: "32.5",
|
||||
photoCount: 3,
|
||||
isVip: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "粒儿云",
|
||||
avatar: "/static/avatar3.jpg",
|
||||
gender: "女",
|
||||
age: 23,
|
||||
height: "170",
|
||||
weight: "50",
|
||||
occupation: "老师",
|
||||
distance: "64.6",
|
||||
photoCount: 2,
|
||||
isVip: false,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "蓝天",
|
||||
avatar: "/static/avatar4.jpg",
|
||||
gender: "女",
|
||||
age: 21,
|
||||
height: "174",
|
||||
weight: "49",
|
||||
occupation: "老师",
|
||||
distance: "64.5",
|
||||
photoCount: 3,
|
||||
isVip: true,
|
||||
},
|
||||
]);
|
||||
// 数据状态管理
|
||||
const userList = ref<User[]>([]);
|
||||
const refresherTriggered = ref(false);
|
||||
const loadMoreStatus = ref<"more" | "loading" | "noMore">("more");
|
||||
const loadMoreContent = reactive({
|
||||
contentdown: "上拉显示更多",
|
||||
contentrefresh: "正在加载...",
|
||||
contentnomore: "没有更多数据了",
|
||||
});
|
||||
|
||||
// 分页参数
|
||||
const pageInfo = reactive({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
hasMore: true,
|
||||
});
|
||||
|
||||
// 模拟数据
|
||||
const mockUsers: User[] = Array.from({ length: 70 }).map((_, index) => ({
|
||||
id: index,
|
||||
name: "山峰",
|
||||
avatar: "/static/avatar2.jpg",
|
||||
gender: "男",
|
||||
age: 30,
|
||||
height: "185",
|
||||
weight: "75",
|
||||
occupation: "健身教练",
|
||||
distance: "5.2",
|
||||
photoCount: 3,
|
||||
isVip: false,
|
||||
status: "在线",
|
||||
}));
|
||||
|
||||
// 模拟API请求
|
||||
const fetchUserList = async (page: number = 1, isRefresh: boolean = false) => {
|
||||
try {
|
||||
// 模拟网络延迟
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
const startIndex = (page - 1) * pageInfo.pageSize;
|
||||
const endIndex = startIndex + pageInfo.pageSize;
|
||||
const newUsers = mockUsers.slice(startIndex, endIndex);
|
||||
|
||||
if (isRefresh) {
|
||||
userList.value = newUsers;
|
||||
pageInfo.current = 1;
|
||||
} else {
|
||||
userList.value.push(...newUsers);
|
||||
}
|
||||
|
||||
pageInfo.current = page;
|
||||
pageInfo.total = mockUsers.length;
|
||||
pageInfo.hasMore = endIndex < mockUsers.length;
|
||||
|
||||
// 更新加载状态
|
||||
if (pageInfo.hasMore) {
|
||||
loadMoreStatus.value = "more";
|
||||
} else {
|
||||
loadMoreStatus.value = "noMore";
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("获取用户列表失败:", error);
|
||||
uni.showToast({
|
||||
title: "加载失败",
|
||||
icon: "none",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 下拉刷新事件
|
||||
const onRefresherPulling = () => {
|
||||
console.log("下拉刷新中...");
|
||||
};
|
||||
|
||||
const onRefresherRefresh = async () => {
|
||||
console.log("触发下拉刷新");
|
||||
refresherTriggered.value = true;
|
||||
|
||||
const success = await fetchUserList(1, true);
|
||||
|
||||
refresherTriggered.value = false;
|
||||
|
||||
if (success) {
|
||||
uni.showToast({
|
||||
title: "刷新成功",
|
||||
icon: "success",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onRefresherRestore = () => {
|
||||
console.log("下拉刷新复位");
|
||||
};
|
||||
|
||||
const onRefresherAbort = () => {
|
||||
console.log("下拉刷新中止");
|
||||
refresherTriggered.value = false;
|
||||
};
|
||||
|
||||
// 上拉加载更多
|
||||
const onScrollToLower = async () => {
|
||||
if (loadMoreStatus.value === "loading" || loadMoreStatus.value === "noMore") {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("触发上拉加载更多");
|
||||
loadMoreStatus.value = "loading";
|
||||
|
||||
const success = await fetchUserList(pageInfo.current + 1, false);
|
||||
|
||||
if (!success) {
|
||||
loadMoreStatus.value = "more";
|
||||
}
|
||||
};
|
||||
|
||||
// 点击加载更多
|
||||
const onClickLoadMore = () => {
|
||||
if (loadMoreStatus.value === "more") {
|
||||
onScrollToLower();
|
||||
}
|
||||
};
|
||||
|
||||
// 滚动事件
|
||||
const onScroll = (e: any) => {
|
||||
// console.log('滚动事件:', e.detail);
|
||||
};
|
||||
|
||||
// 用户详情
|
||||
function detail() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/detail/detail",
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载时获取数据
|
||||
onMounted(() => {
|
||||
fetchUserList(1, true);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.segmented {
|
||||
margin: auto;
|
||||
}
|
||||
.location {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $font-size-medium;
|
||||
}
|
||||
.home-page {
|
||||
background-color: var(--color-background);
|
||||
height: calc(100vh - 100rpx);
|
||||
.header {
|
||||
position: relative;
|
||||
height: 100rpx;
|
||||
.location {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: var(--font-size-medium);
|
||||
}
|
||||
.segmented {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 50rpx;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
background-color: $color-background;
|
||||
height: calc(100vh - 100rpx - 100rpx);
|
||||
.user-list {
|
||||
height: calc(100vh - 100rpx - 100rpx);
|
||||
height: 100%;
|
||||
.user-card {
|
||||
height: 300rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 30rpx;
|
||||
padding: 30rpx;
|
||||
.user-image {
|
||||
width: 200rpx;
|
||||
height: 300rpx;
|
||||
@@ -241,22 +271,24 @@ const userList = ref<User[]>([
|
||||
justify-content: space-between;
|
||||
margin-top: 16rpx;
|
||||
.user-name {
|
||||
font-size: var(--font-size-large);
|
||||
font-size: $font-size-large;
|
||||
font-weight: bold;
|
||||
}
|
||||
.user-status {
|
||||
background-color: var(--color-theme-d);
|
||||
font-size: var(--font-size-small);
|
||||
background-color: $color-theme-d;
|
||||
font-size: $font-size-small;
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 36rpx;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
.verification {
|
||||
margin-top: 16rpx;
|
||||
.verify-badge {
|
||||
background-color: var(--color-theme);
|
||||
font-size: var(--font-size-small);
|
||||
background-color: $color-theme;
|
||||
font-size: $font-size-small;
|
||||
color: black;
|
||||
padding: 6rpx;
|
||||
padding: 6rpx 12rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
@@ -265,11 +297,11 @@ const userList = ref<User[]>([
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--color-text-ll);
|
||||
font-size: $font-size-small;
|
||||
color: $color-text-ll;
|
||||
.tag {
|
||||
background-color: var(--color-highlight-background);
|
||||
padding: 10rpx;
|
||||
background-color: $color-highlight-background;
|
||||
padding: 10rpx 16rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-113
@@ -13,39 +13,17 @@
|
||||
<swiper-item>22</swiper-item>
|
||||
<swiper-item>33</swiper-item>
|
||||
</swiper>
|
||||
<view class="moment-item" v-for="moment in momentsList" :key="moment.id">
|
||||
<view class="user">
|
||||
<image :src="moment.userAvatar" class="avatar" />
|
||||
<view class="details">
|
||||
<view>
|
||||
<text class="username">{{ moment.username }}</text>
|
||||
<text class="verification">{{ moment.verification }}</text>
|
||||
</view>
|
||||
<view class="info">女 · 20岁 | 学生</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="text">{{ moment.content }}</text>
|
||||
<view class="images" v-if="moment.images && moment.images.length > 0">
|
||||
<image v-for="(img, index) in moment.images" :key="index" :src="img" class="moment-image" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="address">
|
||||
<uni-icons type="location" size="16" color="#B5B4BC"></uni-icons>
|
||||
<text class="city">金华市 · 365.123km</text>
|
||||
</view>
|
||||
<view class="actions">
|
||||
<view class="action-btn">
|
||||
<uni-icons type="heart" size="24" color="#B5B4BC"></uni-icons>
|
||||
<uni-icons type="heart-filled" size="24" color="#ffcd32"></uni-icons>
|
||||
<text class="text">{{ moment.likes }} 喜欢</text>
|
||||
</view>
|
||||
<view class="action-btn">
|
||||
<uni-icons type="chat" size="24" color="#B5B4BC"></uni-icons>
|
||||
<text class="text">{{ moment.comments }} 打招呼</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<moment
|
||||
v-for="item in momentsList"
|
||||
:avatar="item.avatar"
|
||||
:name="item.name"
|
||||
:verification="item.verification"
|
||||
:content="item.content"
|
||||
:images="item.images"
|
||||
:location="item.location"
|
||||
:likes="item.likes"
|
||||
:comments="item.comments"
|
||||
/>
|
||||
<view style="height: 100rpx"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -54,6 +32,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import segmented from "@/sheep/components/segmented/segmented.vue";
|
||||
import moment from "@/sheep/components/moment/moment.vue";
|
||||
|
||||
const current = ref(0);
|
||||
const segmentedItems = ["动态", "附近"];
|
||||
@@ -69,7 +48,7 @@ interface Moment {
|
||||
comments: number;
|
||||
}
|
||||
|
||||
const momentsList = ref<Moment[]>([
|
||||
const momentsList = ref<any[]>([
|
||||
{
|
||||
id: 1,
|
||||
username: "小雨",
|
||||
@@ -267,85 +246,6 @@ const momentsList = ref<Moment[]>([
|
||||
}
|
||||
.moments-list {
|
||||
height: calc(100vh - 100rpx - 100rpx);
|
||||
.moment-item {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #333;
|
||||
.user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
.avatar {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 20px;
|
||||
margin-right: 10px;
|
||||
background-color: #333;
|
||||
}
|
||||
.details {
|
||||
flex: 1;
|
||||
.username {
|
||||
font-size: $font-size-medium-x;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.verification {
|
||||
background-color: $color-theme;
|
||||
font-size: $font-size-small;
|
||||
color: black;
|
||||
padding: 4rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
.info {
|
||||
font-size: $font-size-small;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 0 20px;
|
||||
margin-bottom: 15px;
|
||||
.text {
|
||||
line-height: 1.5;
|
||||
}
|
||||
.images {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
.moment-image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 8px;
|
||||
background-color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.address {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
.city {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 60rpx;
|
||||
padding: 0 20rpx;
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
color: $color-text;
|
||||
font-size: $font-size-medium;
|
||||
.text {
|
||||
font-size: $font-size-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -113,8 +113,7 @@ const menuList = ref<MenuItem[]>([
|
||||
border-radius: 40rpx;
|
||||
padding: 8rpx 20rpx;
|
||||
.text {
|
||||
margin-left: 8rpx;
|
||||
font-size: $font-size-small;
|
||||
font-size: $font-size-medium;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<view class="moment">
|
||||
<view class="user">
|
||||
<image :src="avatar" class="avatar" />
|
||||
<view class="details">
|
||||
<view>
|
||||
<text class="username">{{ name }}</text>
|
||||
<text v-if="verification" class="verification">实人认证</text>
|
||||
</view>
|
||||
<view class="info">女 · 20岁 | 学生</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="text">{{ content }}</text>
|
||||
<view class="images" v-if="images && images.length > 0">
|
||||
<image v-for="(img, index) in images" :key="index" :src="img" class="moment-image" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="address">
|
||||
<uni-icons type="location" size="16" color="#B5B4BC"></uni-icons>
|
||||
<text class="city">{{ location }}</text>
|
||||
</view>
|
||||
<view class="actions">
|
||||
<view class="action-btn">
|
||||
<uni-icons type="heart" size="24" color="#B5B4BC"></uni-icons>
|
||||
<uni-icons type="heart-filled" size="24" color="#ffcd32"></uni-icons>
|
||||
<text class="text">{{ likes }} 喜欢</text>
|
||||
</view>
|
||||
<view class="action-btn">
|
||||
<uni-icons type="chat" size="24" color="#B5B4BC"></uni-icons>
|
||||
<text class="text">{{ comments }} 打招呼</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
withDefaults(
|
||||
defineProps<
|
||||
Partial<{
|
||||
avatar: string;
|
||||
name: string;
|
||||
verification: boolean;
|
||||
content: string;
|
||||
images: string[];
|
||||
location: string;
|
||||
likes: number | string;
|
||||
comments: number | string;
|
||||
}>
|
||||
>(),
|
||||
{
|
||||
avatar: "",
|
||||
name: "",
|
||||
verification: false,
|
||||
content: "",
|
||||
images: () => [],
|
||||
location: "",
|
||||
likes: 0,
|
||||
comments: 0,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.moment {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #333;
|
||||
.user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
.avatar {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 20px;
|
||||
margin-right: 10px;
|
||||
background-color: #333;
|
||||
}
|
||||
.details {
|
||||
flex: 1;
|
||||
.username {
|
||||
font-size: $font-size-medium-x;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.verification {
|
||||
background-color: $color-theme;
|
||||
font-size: $font-size-small;
|
||||
color: black;
|
||||
padding: 4rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
.info {
|
||||
font-size: $font-size-small;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 0 20px;
|
||||
margin-bottom: 15px;
|
||||
.text {
|
||||
line-height: 1.5;
|
||||
}
|
||||
.images {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
.moment-image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 8px;
|
||||
background-color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.address {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
.city {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 60rpx;
|
||||
padding: 0 20rpx;
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
color: $color-text;
|
||||
font-size: $font-size-medium;
|
||||
.text {
|
||||
font-size: $font-size-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user