feat:城市选择;首页广场
This commit is contained in:
1 parent
7df0107dbf
commit
d72817b8ea
17 files changed
+2342
-141
No files matched your search
@@ -5,8 +5,8 @@ SHOPRO_VERSION=v2.4.1
|
||||
SHOPRO_API_PATH=/app-api
|
||||
|
||||
# 后端接口 - 测试环境(通过 process.env.NODE_ENV == development)
|
||||
SHOPRO_DEV_BASE_URL=http://192.168.101.13:48083
|
||||
# SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
|
||||
# SHOPRO_DEV_BASE_URL=http://192.168.101.13:48083
|
||||
SHOPRO_DEV_BASE_URL = http://chatapi.zianxin.com
|
||||
|
||||
# 后端接口 - 正式环境(通过 process.env.NODE_ENV != development)
|
||||
SHOPRO_BASE_URL=http://api-dashboard.yudao.iocoder.cn
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
// fail: () => {},
|
||||
// });
|
||||
// 加载Shopro底层依赖
|
||||
// ShoproInit();
|
||||
ShoproInit();
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
||||
@@ -13,4 +13,5 @@ html {
|
||||
user-select: none;
|
||||
background-color: $color-background;
|
||||
color: $color-text;
|
||||
font-size: 14px;
|
||||
}
|
||||
+14
-4
@@ -41,12 +41,10 @@
|
||||
"root": "pages/home",
|
||||
"pages": [
|
||||
{
|
||||
"path": "address-change",
|
||||
"path": "city",
|
||||
"style": {
|
||||
"navigationBarTitleText": "城市",
|
||||
"navigationStyle": "default",
|
||||
"navigationBarBackgroundColor": "#222222",
|
||||
"navigationBarTextStyle": "white"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -58,6 +56,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/moments",
|
||||
"pages": [
|
||||
{
|
||||
"path": "publish",
|
||||
"style": {
|
||||
"navigationBarTitleText": "发布动态",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/profile",
|
||||
"pages": [
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<template>
|
||||
<view class="address-index">
|
||||
<uni-indexed-list :options="list" :showSelect="false" @click="select"></uni-indexed-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const list = [
|
||||
{
|
||||
letter: "A",
|
||||
data: ["1", "2", "3", "4", "5", "6"],
|
||||
},
|
||||
{
|
||||
letter: "B",
|
||||
data: ["1", "2", "3", "4", "5", "6"],
|
||||
},
|
||||
{
|
||||
letter: "C",
|
||||
data: ["1", "2", "3", "4", "5", "6"],
|
||||
},
|
||||
];
|
||||
|
||||
const select = () => {
|
||||
uni.switchTab({ url: "/pages/home/home" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<van-config-provider theme="dark">
|
||||
<van-nav-bar title="城市" fixed z-index="10">
|
||||
<template #left>
|
||||
<uni-icons type="back" size="30" color="#ffcd32" @click="back"></uni-icons>
|
||||
</template>
|
||||
</van-nav-bar>
|
||||
|
||||
<view class="mt-100rpx">
|
||||
<van-search v-model="cityName" shape="round" background="#222222" placeholder="搜索" />
|
||||
</view>
|
||||
|
||||
<view class="px-3 text-sm">热门城市</view>
|
||||
<view class="flex flex-wrap gap-3 my-3 mx-4">
|
||||
<text
|
||||
v-for="(item, index) in hotCity"
|
||||
:key="index"
|
||||
class="bg-color-light text-color-theme px-2 rounded-1"
|
||||
@click.stop="selectHot(item)"
|
||||
>
|
||||
{{ item.t }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<van-index-bar highlight-color="#ffcd32" :sticky-offset-top="46">
|
||||
<template v-for="(item, index) in cityIndex" :key="index">
|
||||
<van-index-anchor :index="item.letter" />
|
||||
<van-cell v-for="(v, i) in item.data" :key="i" :title="v.t" @click.stop="select(v)" />
|
||||
</template>
|
||||
</van-index-bar>
|
||||
</van-config-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
const hotCity = [
|
||||
{ t: '北京', v: 1 },
|
||||
{ t: '上海', v: 2 },
|
||||
{ t: '嘉兴', v: 3 },
|
||||
{ t: '杭州', v: 4 },
|
||||
];
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import cityIndexList, { type cityItem } from './city-index';
|
||||
// @ts-ignore
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const cityIndex = cityIndexList;
|
||||
const cityName = ref('');
|
||||
|
||||
// 选择热门城市
|
||||
const selectHot = (v: cityItem) => {
|
||||
sheep.$store('user').setUserCity(v);
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const select = (v: cityItem) => {
|
||||
sheep.$store('user').setUserCity(v);
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
function back() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
</script>
|
||||
+17
-27
@@ -16,7 +16,7 @@
|
||||
<template v-slot:left>
|
||||
<view class="location" @click="selectAddress">
|
||||
<uni-icons type="location" size="24" color="#ffcd32"></uni-icons>
|
||||
<text>{{}}</text>
|
||||
<text>{{ userCity.t || '未选择' }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right></template>
|
||||
@@ -34,14 +34,14 @@
|
||||
@scrolltolower="onScrollToLower"
|
||||
>
|
||||
<view class="user-card" v-for="user in listData" :key="user.id" @click="detail">
|
||||
<image class="user-image" :src="user.avatar" />
|
||||
<image class="user-image" :src="user.member.memberAvatar" />
|
||||
<view class="user-info">
|
||||
<view class="user">
|
||||
<text class="user-name">{{ user.name }}</text>
|
||||
<text class="user-status">{{ user.status || '离线' }}</text>
|
||||
<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="verify-badge">真人认证</text>
|
||||
<text class="px-2 rounded-full bg-color-theme-dark">真人认证</text>
|
||||
</view>
|
||||
<view class="user-details">
|
||||
<text class="tag">{{ user.gender }}·{{ user.age }}岁</text>
|
||||
@@ -62,10 +62,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import segmented from '@/sheep/components/segmented/segmented.vue';
|
||||
import makeFriendApi from '@/sheep/api/make-friend';
|
||||
import RecentApi from '@/sheep/api/member/recent';
|
||||
import useScroll from '@/sheep/hooks/use-scroll';
|
||||
// @ts-ignore
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const {
|
||||
listData,
|
||||
@@ -76,14 +78,20 @@
|
||||
onRefresherAbort,
|
||||
onScrollToLower,
|
||||
onClickLoadMore,
|
||||
} = useScroll(makeFriendApi.getMakeFriendList);
|
||||
} = useScroll(RecentApi.quickPage, {
|
||||
scene: 'DYNAMIC_RECOMMEND',
|
||||
province: '',
|
||||
city: '',
|
||||
memberId: '',
|
||||
});
|
||||
const userCity = computed(() => sheep.$store('user').userCity);
|
||||
|
||||
const current = ref(0);
|
||||
const segmentedItems = ['广场', '最近', '新人'];
|
||||
|
||||
const selectAddress = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/address-change',
|
||||
url: '/pages/home/city',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -131,27 +139,9 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 16rpx;
|
||||
.user-name {
|
||||
font-size: $font-size-large;
|
||||
font-weight: bold;
|
||||
}
|
||||
.user-status {
|
||||
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: $color-theme;
|
||||
font-size: $font-size-small;
|
||||
color: black;
|
||||
padding: 6rpx 12rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
.user-details {
|
||||
margin-top: 26rpx;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<template> 111 </template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
@@ -90,7 +90,7 @@
|
||||
align-items: center;
|
||||
background-color: $color-theme;
|
||||
border-radius: 40rpx;
|
||||
padding: 4rpx 20rpx;
|
||||
padding: 0 10rpx;
|
||||
.text {
|
||||
font-size: $font-size-medium;
|
||||
color: #333;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<uni-icons type="back" size="30" color="#ffcd32" @click="back"></uni-icons>
|
||||
</template>
|
||||
<template #right>
|
||||
<view class="bg-color-theme px-2 py-1 rounded-full c-black" @click="saveUserInfo">
|
||||
<view class="bg-color-theme px-3 py-1 rounded-full c-black" @click="saveUserInfo">
|
||||
保存
|
||||
</view>
|
||||
</template>
|
||||
@@ -19,7 +19,7 @@
|
||||
fileMediatype="image"
|
||||
limit="1"
|
||||
mode="grid"
|
||||
:imageStyles="{ width: '168rpx', height: '168rpx', borderRadius: '168rpx' }"
|
||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
||||
/>
|
||||
</view>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<van-cell-group inset>
|
||||
<van-cell title="昵称" value="输入">
|
||||
<template #value>
|
||||
<input type="text" :maxlength="12" :value="userinfo.nickname" />
|
||||
<input type="text" v-model="userinfo.nickname" :maxlength="12" />
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell
|
||||
@@ -83,10 +83,10 @@
|
||||
|
||||
<view class="mx-5 my-3 flex justify-between">
|
||||
<text>个人相册</text>
|
||||
<text>{{ userinfo.photos.length }}/9</text>
|
||||
<text>{{ userinfo.photo.length || 0 }}/9</text>
|
||||
</view>
|
||||
<view class="px-4">
|
||||
<s-uploader v-model:url="userinfo.photos" fileMediatype="image" limit="9" mode="grid" />
|
||||
<s-uploader v-model:url="userinfo.photo" fileMediatype="image" limit="9" mode="grid" />
|
||||
</view>
|
||||
<view class="h-100"></view>
|
||||
</scroll-view>
|
||||
@@ -135,9 +135,9 @@
|
||||
const columnsHeight = Array.from({ length: 100 }, (_, i) => ({
|
||||
text: i + 100 + 'cm',
|
||||
value: i + 100,
|
||||
}));
|
||||
})).reverse();
|
||||
// 体重选择器选项
|
||||
const columnsWeight = Array.from({ length: 100 }, (_, i) => ({
|
||||
const columnsWeight = Array.from({ length: 80 }, (_, i) => ({
|
||||
text: i + 20 + 'kg',
|
||||
value: i + 20,
|
||||
}));
|
||||
@@ -156,7 +156,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
// @ts-ignore
|
||||
import UserApi from '@/sheep/api/member/user';
|
||||
import sUploader from '@/sheep/components/s-uploader/s-uploader.vue';
|
||||
@@ -165,23 +165,24 @@
|
||||
// 获取用户信息
|
||||
const { data } = await UserApi.getUserInfo();
|
||||
Object.assign(userinfo, data, {
|
||||
birthday: data.birthday ?? '',
|
||||
birthday: data.birthday ? data.birthday : '',
|
||||
height: data.height ?? '',
|
||||
weight: data.weight ?? '',
|
||||
photo: data.photo?.map((item: { address: string }) => item.address),
|
||||
});
|
||||
console.log(userinfo);
|
||||
});
|
||||
|
||||
// 用户信息
|
||||
const userinfo = reactive<any>({
|
||||
avatar: [],
|
||||
avatar: '',
|
||||
nickname: '',
|
||||
birthday: '',
|
||||
height: '',
|
||||
weight: '',
|
||||
occ: '',
|
||||
description: '',
|
||||
|
||||
photos: [],
|
||||
photo: [],
|
||||
});
|
||||
const showPicker = ref(false); // 选择器显隐
|
||||
const pickerFiled = ref<'' | 'birthday' | 'height' | 'weight' | 'occ'>('');
|
||||
@@ -202,7 +203,14 @@
|
||||
showPicker.value = false;
|
||||
};
|
||||
|
||||
function saveUserInfo() {}
|
||||
// 保存用户信息
|
||||
const saveUserInfo = async () => {
|
||||
const params = {
|
||||
...userinfo,
|
||||
photo: userinfo.photo.map((url: string) => ({ resourceType: 'IMAGE', address: url })),
|
||||
};
|
||||
await UserApi.updateUser(params);
|
||||
};
|
||||
|
||||
function back() {
|
||||
uni.navigateBack();
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// import request from "@/sheep/request";
|
||||
|
||||
const mockUsers = Array.from({ length: 26 }).map((_, index) => ({
|
||||
id: index,
|
||||
name: "山峰" + (index + 1),
|
||||
avatar: "/static/avatar2.jpg",
|
||||
gender: "男",
|
||||
age: 30,
|
||||
height: "185",
|
||||
weight: "75",
|
||||
occupation: "健身教练",
|
||||
distance: "5.2",
|
||||
photoCount: 3,
|
||||
isVip: false,
|
||||
status: "在线",
|
||||
}));
|
||||
|
||||
const makeFriendApi = {
|
||||
// 获得用户收件地址列表
|
||||
// getAddressList: () => {
|
||||
// return request({
|
||||
// url: "/member/address/list",
|
||||
// method: "GET",
|
||||
// });
|
||||
// },
|
||||
|
||||
getMakeFriendList: async (page: number = 1, pageSize: number = 10) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
const startIndex = (page - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const newUsers = mockUsers.slice(startIndex, endIndex);
|
||||
|
||||
return {
|
||||
page,
|
||||
pageSize,
|
||||
total: 26,
|
||||
data: newUsers,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default makeFriendApi;
|
||||
@@ -0,0 +1,18 @@
|
||||
// @ts-ignore
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const RecentApi = {
|
||||
// 查询附近/广场
|
||||
quickPage: (data: any) => {
|
||||
return request({
|
||||
url: '/member/recent/quick-page',
|
||||
method: 'POST',
|
||||
data,
|
||||
custom: {
|
||||
showLoading: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default RecentApi;
|
||||
@@ -21,7 +21,8 @@ const UserApi = {
|
||||
custom: {
|
||||
auth: true,
|
||||
showSuccess: true,
|
||||
successMsg: '更新成功',
|
||||
showLoading: true,
|
||||
successMsg: '保存成功',
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
|
||||
export default function useScroll(fetchList: (...arg: any) => Promise<any>) {
|
||||
export default function useScroll(fetchList: (...arg: any) => Promise<any>, fetchBody: any) {
|
||||
const refresherTriggered = ref(false);
|
||||
const loadMoreContent = reactive({
|
||||
contentdown: " ",
|
||||
contentrefresh: "正在加载...",
|
||||
contentnomore: "没有更多数据了",
|
||||
contentdown: ' ',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了',
|
||||
});
|
||||
const loadMoreStatus = ref<"more" | "loading" | "noMore">("more");
|
||||
const loadMoreStatus = ref<'more' | 'loading' | 'noMore'>('more');
|
||||
const listData = ref<any[]>([]);
|
||||
const pageInfo = reactive({
|
||||
current: 1,
|
||||
@@ -22,29 +22,29 @@ export default function useScroll(fetchList: (...arg: any) => Promise<any>) {
|
||||
const loadData = async (isRefresh: boolean = false) => {
|
||||
try {
|
||||
if (pageInfo.current === 1) {
|
||||
uni.showLoading({ title: "加载中..." });
|
||||
uni.showLoading({ title: '加载中...' });
|
||||
}
|
||||
if (isRefresh) {
|
||||
pageInfo.current = 1;
|
||||
const { total, data } = await fetchList(pageInfo.current);
|
||||
listData.value = data;
|
||||
pageInfo.total = total;
|
||||
const { data } = await fetchList({ ...pageInfo, ...fetchBody });
|
||||
listData.value = data.list;
|
||||
pageInfo.total = data.total;
|
||||
} else {
|
||||
const { total, data } = await fetchList(pageInfo.current);
|
||||
listData.value.push(...data);
|
||||
pageInfo.total = total;
|
||||
const { data } = await fetchList({ ...pageInfo, ...fetchBody });
|
||||
listData.value.push(...data.list);
|
||||
pageInfo.total = data.total;
|
||||
}
|
||||
pageInfo.current = pageInfo.current + 1;
|
||||
|
||||
if (listData.value.length >= pageInfo.total) {
|
||||
loadMoreStatus.value = "noMore";
|
||||
loadMoreStatus.value = 'noMore';
|
||||
} else {
|
||||
loadMoreStatus.value = "more";
|
||||
loadMoreStatus.value = 'more';
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("加载数据失败:", error);
|
||||
console.error('加载数据失败:', error);
|
||||
return false;
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
@@ -57,28 +57,28 @@ export default function useScroll(fetchList: (...arg: any) => Promise<any>) {
|
||||
const success = await loadData(true);
|
||||
refresherTriggered.value = false;
|
||||
if (success) {
|
||||
uni.showToast({ title: "刷新成功", icon: "success" });
|
||||
uni.showToast({ title: '刷新成功', icon: 'success' });
|
||||
}
|
||||
};
|
||||
|
||||
// 下拉刷新中止
|
||||
const onRefresherAbort = () => {
|
||||
console.log("下拉刷新中止");
|
||||
console.log('下拉刷新中止');
|
||||
refresherTriggered.value = false;
|
||||
};
|
||||
|
||||
// 触发上拉加载
|
||||
const onScrollToLower = async () => {
|
||||
if (loadMoreStatus.value === "loading" || loadMoreStatus.value === "noMore") {
|
||||
if (loadMoreStatus.value === 'loading' || loadMoreStatus.value === 'noMore') {
|
||||
return;
|
||||
}
|
||||
loadMoreStatus.value = "loading";
|
||||
loadMoreStatus.value = 'loading';
|
||||
await loadData(false);
|
||||
};
|
||||
|
||||
// 点击加载更多
|
||||
const onClickLoadMore = () => {
|
||||
if (loadMoreStatus.value === "more") {
|
||||
if (loadMoreStatus.value === 'more') {
|
||||
onScrollToLower();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ const user = defineStore({
|
||||
isLogin: !!uni.getStorageSync('token'), // 登录状态
|
||||
numData: cloneDeep(defaultNumData), // 用户其他数据
|
||||
lastUpdateTime: 0, // 上次更新时间
|
||||
userCity: { t: '', v: 0 },
|
||||
}),
|
||||
|
||||
actions: {
|
||||
@@ -151,6 +152,11 @@ const user = defineStore({
|
||||
this.resetUserData();
|
||||
return !this.isLogin;
|
||||
},
|
||||
|
||||
// 设置用户城市
|
||||
setUserCity(city) {
|
||||
this.userCity = city;
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
enabled: true,
|
||||
|
||||
@@ -29,6 +29,12 @@ export default async (command: 'build' | 'serve', mode: string) => {
|
||||
hmr: {
|
||||
overlay: true,
|
||||
},
|
||||
proxy: {
|
||||
'/app-api': {
|
||||
target: env.SHOPRO_DEV_BASE_URL,
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
Reference in new issue
Block a user