feat:发布动态页面;部分样式修改

This commit is contained in:
ctw committed 2025-11-17 11:49:30 +08:00
1 parent d72817b8ea
commit 36947f692d
7 files changed
+288 -446

No files matched your search

+4
View File
@@ -15,3 +15,7 @@ html {
color: $color-text;
font-size: 14px;
}
:root {
--van-back-top-background: red;
}
+91 -219
View File
@@ -1,98 +1,104 @@
<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>
<van-config-provider theme="dark">
<van-nav-bar title="">
<template #left>
<uni-icons type="back" size="30" color="#ffcd32" @click="back"></uni-icons>
<view class="flex items-center" :style="navUserInfoStyle">
<image class="size-70rpx bg-#333 rounded-full mr-1" src="" mode="scaleToFill" />
<text class="truncate">稍后发非麻烦咖啡</text>
</view>
</template>
<template #right>
<view class="flex items-center">
<view class="py-1 px-2 text-xs bg-color-theme-dark rounded-full mr-3">
365.56km · 在线
</view>
<uni-icons type="more-filled" size="28" color="#ffcd32"></uni-icons>
</view>
</template>
</van-nav-bar>
<scroll-view
class="page"
scroll-y
refresher-enabled
refresher-background="#222"
:refresher-triggered="refresherTriggered"
:refresher-threshold="100"
@refresherrefresh="onRefresherRefresh"
@refresherabort="onRefresherAbort"
@scrolltolower="onScrollToLower"
@scroll="onScroll"
>
<view class="image" style="background-image: url(http://dummyimage.com/100x100/ac0ee3)">
<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>
<scroll-view
style="height: calc(100vh - 100rpx)"
scroll-y
refresher-enabled
refresher-background="#222"
:refresher-triggered="refresherTriggered"
:refresher-threshold="100"
@refresherrefresh="onRefresherRefresh"
@refresherabort="onRefresherAbort"
@scrolltolower="onScrollToLower"
@scroll="onScroll"
>
<view class="w-full h-600rpx relative">
<image
class="w-full h-full absolute inset-0"
src="http://dummyimage.com/100x100/ac0ee3"
mode="aspectFill"
/>
<view class="absolute bottom-40rpx left-0 right-0 flex flex-col items-center z-100 w-full">
<image
class="text-center size-150rpx rounded-full bg-#333 mb-20rpx"
src="http://dummyimage.com/100x100/ac0ee3"
mode="aspectFill"
/>
<view class="text-sm mb-20rpx">{{ '啊发发' }}</view>
<view class="bg-color-theme text-sm c-black px-2 rounded-1 mb-20rpx">真人认证</view>
<view class="flex flex-wrap justify-center mb-20rpx">
<text class="px-2 rounded-1 mr-2 text-sm bg-#222 text-color-theme">女·23岁</text>
<text class="px-2 rounded-1 mr-2 text-sm bg-#222 text-color-theme">170cm</text>
</view>
<view class="text-sm">{{ '发哈夫哈佛哈维合法i凤凰网你' }}</view>
</view>
<view class="introduction">{{ '发哈夫哈佛哈维合法i凤凰网你' }}</view>
<view class="absolute z-10 top-0 left-0 size-full bg-#33333333" :style="filterStyle"></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"
<view class="m-4">
<view class="my-2 text-size-base">相册</view>
<image
class="size-140rpx rounded-1 mr-2 mb-1"
v-for="(item, index) in 5"
:key="index"
src="http://dummyimage.com/100x100/ac0ee3"
/>
</view>
<view class="m-4">
<view class="my-2 text-base">评价1+</view>
<view class="flex justify-around flex-wrap text-color-theme text-base">
<view class="bg-color-dark flex items-center px-2 py-1 mb-2 rounded-2 gap-2">
<text>身材</text>
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
</view>
<view class="bg-color-dark flex items-center px-2 py-1 mb-2 rounded-2 gap-2">
<text>颜值</text>
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
</view>
<view class="bg-color-dark flex items-center px-2 py-1 mb-2 rounded-2 gap-2">
<text>耐心</text>
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
</view>
<view class="bg-color-dark flex items-center px-2 py-1 mb-2 rounded-2 gap-2">
<text>有趣</text>
<uni-rate :value="2" :touchable="false" :readonly="true" size="18" />
</view>
</view>
</view>
<moment v-for="(item, index) in listData">{{ index }}</moment>
<uni-load-more
:status="loadMoreStatus"
:content-text="loadMoreContent"
@clickLoadMore="onClickLoadMore"
/>
</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 listData">{{ index }}</moment>
<uni-load-more
:status="loadMoreStatus"
:content-text="loadMoreContent"
@clickLoadMore="onClickLoadMore"
/>
<view style="height: 100rpx"></view>
</scroll-view>
<view style="height: 100rpx"></view>
</scroll-view>
</van-config-provider>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import moment from '@/sheep/components/moment/moment.vue';
import makeFriendApi from '@/sheep/api/make-friend';
import useScroll from '@/sheep/hooks/use-scroll';
import RecentApi from '@/sheep/api/member/recent';
const {
listData,
@@ -103,7 +109,7 @@
onRefresherAbort,
onScrollToLower,
onClickLoadMore,
} = useScroll(makeFriendApi.getMakeFriendList);
} = useScroll(RecentApi.quickPage);
const scrollTop = ref(0);
@@ -136,137 +142,3 @@
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>
+78 -115
View File
@@ -1,64 +1,81 @@
<template>
<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" @click="selectAddress">
<uni-icons type="location" size="24" color="#ffcd32"></uni-icons>
<text>{{ userCity.t || '未选择' }}</text>
<van-config-provider theme="dark">
<uni-nav-bar
dark
:fixed="true"
:border="false"
:height="50"
title=""
left-text=""
background-color="#222"
leftWidth="180rpx"
rightWidth="180rpx"
>
<view class="m-auto">
<segmented v-model="current" :items="segmentedItems" @change="segmentedChange" />
</view>
</template>
<template v-slot:right></template>
</uni-nav-bar>
<template v-slot:left>
<view class="flex items-center text-size-base" @click="selectAddress">
<uni-icons type="location" size="24" color="#ffcd32"></uni-icons>
<text class="truncate">{{ userCity.t || '未选择' }}</text>
</view>
</template>
<template v-slot:right></template>
</uni-nav-bar>
<scroll-view
class="user-list"
scroll-y
refresher-enabled
refresher-background="#222"
:refresher-triggered="refresherTriggered"
:refresher-threshold="100"
@refresherrefresh="onRefresherRefresh"
@refresherabort="onRefresherAbort"
@scrolltolower="onScrollToLower"
>
<view class="user-card" v-for="user in listData" :key="user.id" @click="detail">
<image class="user-image" :src="user.member.memberAvatar" />
<view class="user-info">
<view class="user">
<text class="text-lg">{{ user.member.memberNickname }}</text>
<text class="px-2 rounded-full bg-color-theme-dark">{{ '在线' }}</text>
</view>
<view class="verification">
<text class="px-2 rounded-full bg-color-theme-dark">真人认证</text>
</view>
<view class="user-details">
<text class="tag">{{ user.gender }}·{{ user.age }}岁</text>
<text class="tag">{{ user.height }}cm</text>
<text class="tag">{{ user.weight }}kg</text>
<text class="tag">{{ user.occupation }}</text>
<text class="tag">{{ user.distance }}km</text>
<scroll-view
style="height: calc(100vh - 100rpx - 100rpx)"
scroll-y
refresher-enabled
refresher-background="#222"
:refresher-triggered="refresherTriggered"
:refresher-threshold="100"
@refresherrefresh="onRefresherRefresh"
@refresherabort="onRefresherAbort"
@scrolltolower="onScrollToLower"
>
<view class="flex px-6 py-2" v-for="user in listData" :key="user.id" @click="detail">
<image
class="w-200rpx h-300rpx mr-3 rounded-2 bg-#777"
:src="user.member.memberAvatar"
mode="aspectFill"
/>
<view class="flex-1">
<view class="flex justify-between items-center">
<text class="text-size-base">{{ user.member.memberNickname }}</text>
<text class="px-2 rounded-full text-size-sm bg-color-theme-dark">{{ '在线' }}</text>
</view>
<view class="mt-2">
<text class="px-2 text-xs c-black rounded-full bg-color-theme-dark">真人认证</text>
</view>
<view class="mt-2 flex flex-wrap gap-3">
<text class="bg-#333 text-color-theme text-xs px-2 rounded-1">
{{ user.gender || '未知性别' }}·{{ user.member.memberAge }}岁
</text>
<text class="bg-#333 text-color-theme text-xs px-2 rounded-1"
>{{ user.member.memberHeight }}cm</text
>
<text class="bg-#333 text-color-theme text-xs px-2 rounded-1"
>{{ user.member.memberWeight }}kg</text
>
<text class="bg-#333 text-color-theme text-xs px-2 rounded-1">
{{ user.member.memberOcc }}
</text>
<text class="bg-#333 text-color-theme text-xs px-2 rounded-1">
{{ user.issueCity }}km
</text>
</view>
</view>
</view>
</view>
<uni-load-more
:status="loadMoreStatus"
:content-text="loadMoreContent"
@clickLoadMore="onClickLoadMore"
/>
<view style="height: 100rpx"></view>
</scroll-view>
<uni-load-more
:status="loadMoreStatus"
:content-text="loadMoreContent"
@clickLoadMore="onClickLoadMore"
/>
<view style="height: 100rpx"></view>
<van-back-top right="6vw" bottom="10vh" />
</scroll-view>
</van-config-provider>
</template>
<script setup lang="ts">
@@ -100,63 +117,9 @@
url: '/pages/home/detail',
});
};
</script>
<style scoped lang="scss">
.segmented {
margin: auto;
}
.location {
display: flex;
align-items: center;
font-size: $font-size-medium;
}
.user-list {
background-color: $color-background;
height: calc(100vh - 100rpx - 100rpx);
.user-card {
height: 300rpx;
display: flex;
justify-content: center;
align-items: center;
padding: 30rpx;
.user-image {
width: 200rpx;
height: 300rpx;
margin-right: 20rpx;
border-radius: 16rpx;
background-color: #777777;
}
.user-info {
flex: 1;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: start;
.user {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16rpx;
}
.verification {
margin-top: 16rpx;
}
.user-details {
margin-top: 26rpx;
display: flex;
flex-wrap: wrap;
gap: 20rpx;
font-size: $font-size-small;
color: $color-text-ll;
.tag {
background-color: $color-highlight-background;
padding: 10rpx 16rpx;
border-radius: 6rpx;
}
}
}
}
}
</style>
const segmentedChange = ({ currentIndex }: { currentIndex: number }) => {
console.log(segmentedItems[currentIndex]);
onRefresherRefresh();
};
</script>
+46 -36
View File
@@ -1,7 +1,7 @@
<template>
<view class="header">
<segmented class="segmented" v-model="current" :items="segmentedItems"></segmented>
<view class="camera">
<view class="camera" @click="goPublish">
<uni-icons type="camera" size="24" color="#ffcd32"></uni-icons>
</view>
</view>
@@ -33,51 +33,61 @@
:likes="item.likes"
:comments="item.comments"
/>
<uni-load-more :status="loadMoreStatus" :content-text="loadMoreContent" @clickLoadMore="onClickLoadMore" />
<uni-load-more
:status="loadMoreStatus"
:content-text="loadMoreContent"
@clickLoadMore="onClickLoadMore"
/>
<view style="height: 100rpx"></view>
</scroll-view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import segmented from "@/sheep/components/segmented/segmented.vue";
import moment from "@/sheep/components/moment/moment.vue";
import makeFriendApi from "@/sheep/api/make-friend";
import useScroll from "@/sheep/hooks/use-scroll";
import { ref } from 'vue';
import segmented from '@/sheep/components/segmented/segmented.vue';
import moment from '@/sheep/components/moment/moment.vue';
import useScroll from '@/sheep/hooks/use-scroll';
import RecentApi from '@/sheep/api/member/recent';
const {
listData,
refresherTriggered,
loadMoreContent,
loadMoreStatus,
onRefresherRefresh,
onRefresherAbort,
onScrollToLower,
onClickLoadMore,
} = useScroll(makeFriendApi.getMakeFriendList);
const {
listData,
refresherTriggered,
loadMoreContent,
loadMoreStatus,
onRefresherRefresh,
onRefresherAbort,
onScrollToLower,
onClickLoadMore,
} = useScroll(RecentApi.quickPage);
const current = ref(0);
const segmentedItems = ["动态", "附近"];
const current = ref(0);
const segmentedItems = ['动态', '附近'];
const goPublish = () => {
uni.navigateTo({
url: '/pages/moments/publish',
});
};
</script>
<style scoped lang="scss">
.header {
position: relative;
height: 100rpx;
.segmented {
position: absolute;
left: 30rpx;
top: 50rpx;
transform: translateY(-50%);
.header {
position: relative;
height: 100rpx;
.segmented {
position: absolute;
left: 30rpx;
top: 50rpx;
transform: translateY(-50%);
}
.camera {
position: absolute;
top: 50rpx;
transform: translateY(-50%);
right: 30rpx;
}
}
.camera {
position: absolute;
top: 50rpx;
transform: translateY(-50%);
right: 30rpx;
.moments-list {
height: calc(100vh - 100rpx - 100rpx);
}
}
.moments-list {
height: calc(100vh - 100rpx - 100rpx);
}
</style>
+22 -2
View File
@@ -1,3 +1,23 @@
<template> 111 </template>
<template>
<van-config-provider theme="dark">
<van-nav-bar title="发布动态" fixed>
<template #left>
<uni-icons type="back" size="30" color="#ffcd32" @click="back"></uni-icons>
</template>
<template #right>
<view class="bg-color-theme px-3 py-1 rounded-full c-black" @click="publishMoments">
发布
</view>
</template>
</van-nav-bar>
</van-config-provider>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
// 发布
const publishMoments = () => {};
function back() {
uni.navigateBack();
}
</script>
+46 -73
View File
@@ -1,45 +1,10 @@
<script setup lang="ts">
import { computed } from "vue";
const props = withDefaults(
defineProps<{
items?: string[];
modelValue?: number;
}>(),
{
items: () => [],
modelValue: 0,
}
);
const emit = defineEmits<{
(e: "update:modelValue", index: number): void;
(e: "onChange", target: { currentIndex: number }): void;
}>();
const activeStyle = computed(() => {
const x = 60 * props.modelValue;
return {
transform: `translate3d(${x}px, 0, 0)`,
};
});
const segmentedWidth = computed(() => {
return { width: `${props.items.length * 60}px` };
});
function segmentedItem(index: number) {
if (props.modelValue === index) return;
emit("update:modelValue", index);
emit("onChange", {
currentIndex: index,
});
}
</script>
<template>
<view class="segmentedes" :style="segmentedWidth">
<view
class="flex items-center relative mx-auto border-1 border-solid border-#666 rounded-full overflow-hidden"
:style="segmentedWidth"
>
<view
class="segmented-item"
class="relative z-10 flex-1 h-50rpx line-height-50rpx text-center text-sm active:text-color-theme"
v-for="(item, index) in items"
:key="item"
:class="{ active: modelValue === index }"
@@ -47,40 +12,48 @@ function segmentedItem(index: number) {
>
<text>{{ item }}</text>
</view>
<div class="active-bar" :style="activeStyle"></div>
<div
class="absolute left-0 top-0 h-full bg-color-theme-dark rounded-full transform duration-100"
:style="activeStyle"
></div>
</view>
</template>
<style scoped lang="scss">
.segmentedes {
display: flex;
position: relative;
align-items: center;
margin: 0 auto;
border: 1px solid $color-highlight-background;
border-radius: 5px;
.segmented-item {
position: relative;
z-index: 10;
flex: 1;
height: 30px;
line-height: 30px;
text-align: center;
font-size: $font-size-medium;
color: $color-text-d;
&.active {
color: $color-text;
}
<script setup lang="ts">
import { computed } from 'vue';
const props = withDefaults(
defineProps<{
items?: string[];
modelValue?: number;
}>(),
{
items: () => [],
modelValue: 0,
},
);
const emit = defineEmits<{
(e: 'update:modelValue', index: number): void;
(e: 'change', target: { currentIndex: number }): void;
}>();
const activeStyle = computed(() => {
const x = 50 * props.modelValue;
return {
width: `${50}px`,
transform: `translate3d(${x}px, 0, 0)`,
};
});
const segmentedWidth = computed(() => {
return { width: `${props.items.length * 50}px` };
});
function segmentedItem(index: number) {
if (props.modelValue === index) return;
emit('update:modelValue', index);
emit('change', {
currentIndex: index,
});
}
.active-bar {
position: absolute;
left: 0;
top: 0;
width: 60px;
height: 30px;
transition: transform 0.3s;
border-radius: 5px;
background: $color-highlight-background;
}
}
</style>
</script>
+1 -1
View File
@@ -1,6 +1,6 @@
import { onMounted, reactive, ref } from 'vue';
export default function useScroll(fetchList: (...arg: any) => Promise<any>, fetchBody: any) {
export default function useScroll(fetchList: (...arg: any) => Promise<any>, fetchBody: any = {}) {
const refresherTriggered = ref(false);
const loadMoreContent = reactive({
contentdown: ' ',