mrr.sj.front/pages/user/store-syr-list.vue

590 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="syr-list-page">
<!-- 自定义导航栏 -->
<custom-navbar
title="门店手艺人列表"
:show-back="true"
backgroundColor="#fff"
></custom-navbar>
<!-- 手艺人列表 -->
<scroll-view
class="syr-list-scroll"
scroll-y="true"
:style="{height: scrollViewHeight + 'px'}"
@scrolltolower="loadMore"
>
<view class="syr-list-container">
<!-- 手艺人网格列表 -->
<view class="syr-grid">
<view
v-for="(artisan, index) in artisanList"
:key="artisan.id"
class="syr-card"
@click="goArtisanDetail(artisan)"
>
<!-- 头像部分 -->
<view class="syr-avatar-container">
<image
:src="artisan.avatar || defaultAvatar"
class="syr-avatar"
mode="aspectFill"
></image>
</view>
<!-- 信息部分 -->
<view class="syr-info">
<!-- 第一行:名字和距离 -->
<view class="syr-name-row">
<text class="syr-name">{{ artisan.name }}</text>
<view class="syr-distance">
<image
src="/static/images/icons/address_icon.png"
class="distance-icon"
></image>
<text class="distance-text">{{ formatDistance(artisan.distance) }}</text>
</view>
</view>
<!-- 第二行:从业经历 -->
<view class="syr-experience-row">
<text class="syr-experience">从业经历</text>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/0a9bcad4-a3b2-457f-bdfd-d659d6b1b084.png"
class="experience-icon"
@click.stop="goQualification(artisan)"
></image>
</view>
<!-- 第三行:入驻时间 -->
<view class="syr-join-row">
<text class="syr-join">入驻{{ formatWorkingYears(artisan.working_years) }}</text>
</view>
</view>
</view>
</view>
<!-- 加载状态 -->
<view class="loading-status">
<text v-if="loading" class="loading-text">加载中...</text>
<text v-if="finished && artisanList.length > 0" class="no-more-text">~ 暂时只有这些了 ~</text>
</view>
<!-- 空状态 -->
<!-- <view v-if="!loading && artisanList.length === 0" class="empty-state">
<image
src="/static/images/common/empty.png"
class="empty-image"
></image>
<text class="empty-text">暂无手艺人</text>
</view> -->
</view>
</scroll-view>
</view>
</template>
<script>
import request from "@/utils/request";
export default {
data() {
return {
artisanList: [], // 手艺人列表
loading: false, // 加载状态
finished: false, // 是否已加载完毕
page: 1, // 当前页码
limit: 10, // 每页数量
total: 0, // 总数量
shopId: null, // 店铺ID
scrollViewHeight: 0, // 滚动区域高度
// 默认头像
defaultAvatar: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40"
};
},
onLoad(options) {
// 从路由参数获取店铺ID
if (options.shopId) {
this.shopId = options.shopId;
} else if (options.id) {
// 也可能是从店铺详情页面传过来的id
this.shopId = options.id;
}
console.log("接收到的店铺ID:", this.shopId);
// 计算滚动区域高度
this.calculateScrollHeight();
// 获取手艺人列表
this.getArtisanList();
},
onReady() {
// 页面加载完成后再计算一次高度,确保准确
setTimeout(() => {
this.calculateScrollHeight();
}, 100);
},
methods: {
// 计算滚动区域高度
calculateScrollHeight() {
const systemInfo = uni.getSystemInfoSync();
// 获取导航栏高度假设为44px可以根据实际情况调整
const navBarHeight = 44;
// 状态栏高度
const statusBarHeight = systemInfo.statusBarHeight || 0;
// 计算可用高度
this.scrollViewHeight = systemInfo.windowHeight - (navBarHeight + statusBarHeight);
},
// 获取手艺人列表
getArtisanList() {
if (this.loading || this.finished) {
return;
}
this.loading = true;
// 获取用户位置
const userLocation = this.getUserLocation();
console.log("获取到的用户位置:", userLocation);
const params = {
page: this.page,
limit: this.limit
};
if (this.shopId) {
params.sjid = this.shopId;
}
// 传递位置参数给后端
if (userLocation) {
params.userLat = userLocation.latitude;
params.userLngz = userLocation.longitude;
}
request
.post("/user/sjSyrBind/syrList", params)
.then((res) => {
console.log("手艺人列表接口返回:", res);
if (res.code === 200) {
const resultData = res.data || {};
const list = resultData.list || [];
const total = resultData.count || list.length || 0;
// 格式化数据时传入用户位置用于距离计算
const formattedList = this.formatArtisanList(list, userLocation);
console.log("格式化后的列表(包含距离):", formattedList);
if (this.page === 1) {
this.artisanList = formattedList;
} else {
this.artisanList = [...this.artisanList, ...formattedList];
}
this.total = total;
if (list.length < this.limit) {
this.finished = true;
} else {
this.page += 1;
}
} else {
console.error("接口返回错误:", res);
uni.showToast({
title: res.msg || '获取手艺人列表失败',
icon: 'none'
});
}
})
.catch((err) => {
console.error("获取手艺人列表失败:", err);
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
});
})
.finally(() => {
this.loading = false;
});
},
// 格式化手艺人列表数据
formatArtisanList(list, userLocation = null) {
if (!list || list.length === 0) {
return [];
}
// 如果没有传入用户位置,尝试获取
if (!userLocation) {
userLocation = this.getUserLocation();
}
// 模拟数据,用于调试布局
const mockData = [
{ id: 1, name: "梅子", working_years: "1年6个月", distance: 32.29 },
{ id: 2, name: "王安宇", working_years: "10年10个月", distance: 2.29 },
{ id: 3, name: "王安宇...", working_years: "10年10个月", distance: 2.29 },
{ id: 4, name: "梅子", working_years: "1年6个月", distance: 2.29 }
];
// 正式环境使用接口数据
const dataToUse = list.length > 0 ? list : mockData;
return list.map((item) => {
// 计算从业年限
let workingYears = "0年0个月";
if (item.working_years) {
workingYears = item.working_years;
} else if (item.add_time) {
// 从 add_time 计算
const createdDate = new Date(item.add_time);
const now = new Date();
const years = now.getFullYear() - createdDate.getFullYear();
const months = now.getMonth() - createdDate.getMonth();
let totalMonths = years * 12 + months;
if (totalMonths < 0) totalMonths = 0;
const formattedYears = Math.floor(totalMonths / 12);
const formattedMonths = totalMonths % 12;
workingYears = `${formattedYears}年${formattedMonths}个月`;
}
// 计算距离
let distance = null;
if (userLocation && userLocation.latitude && userLocation.longitude &&
item.latitude && item.longitude) {
try {
const lat1 = parseFloat(userLocation.latitude);
const lng1 = parseFloat(userLocation.longitude);
const lat2 = parseFloat(item.latitude);
const lng2 = parseFloat(item.longitude);
// 调用距离计算函数
distance = this.calculateDistance(lat1, lng1, lat2, lng2);
console.log(`计算距离: 用户(${lat1},${lng1}) -> 手艺人(${lat2},${lng2}) = ${distance}km`);
} catch (e) {
console.error("计算距离失败:", e);
}
}
return {
id: item.id || item.user_id || '',
name: item.name || item.nick_name || '手艺人',
avatar: item.head_photo,
working_years: workingYears,
distance: distance, // 距离字段
latitude: item.latitude, // 保留经纬度供后续使用
longitude: item.longitude,
service_count: item.service_count || 0,
good_rating: item.good_rating || '100%',
default_times: item.default_times,
work_state: item.work_state,
is_ok: item.is_ok,
is_del: item.is_del
};
});
},
// 格式化从业年限显示
formatWorkingYears(yearsStr) {
// 如果已经是格式化好的字符串,直接返回
if (typeof yearsStr === 'string') {
return yearsStr;
}
// 否则尝试转换
try {
// 假设是月份数
const months = parseInt(yearsStr);
if (!isNaN(months)) {
const y = Math.floor(months / 12);
const m = months % 12;
return `${y}年${m}个月`;
}
} catch (e) {
console.error("格式化从业年限失败:", e);
}
return "0年0个月";
},
// 添加距离计算函数Haversine公式
calculateDistance(lat1, lng1, lat2, lng2) {
// 将度转换为弧度
const toRad = (angle) => (angle * Math.PI) / 180;
const R = 6371; // 地球半径(公里)
const dLat = toRad(lat2 - lat1);
const dLng = toRad(lng2 - lng1);
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
return parseFloat(distance.toFixed(2)); // 保留2位小数
},
// 获取用户位置(修改为返回完整对象)
getUserLocation() {
let addressRes = {};
let userAdrees = uni.getStorageSync("userAdrees");
if (userAdrees) {
addressRes = userAdrees.addressRes;
} else {
addressRes = getApp().globalData.addressRes;
}
// 确保返回包含经纬度的对象
if (addressRes && addressRes.latitude && addressRes.longitude) {
return {
latitude: parseFloat(addressRes.latitude),
longitude: parseFloat(addressRes.longitude),
address: addressRes.address
};
}
return null;
},
// 格式化距离显示
formatDistance(distance) {
if (!distance && distance !== 0) {
return "距离未知";
}
// 如果是字符串,尝试转换为数字
const numDistance = typeof distance === 'string' ? parseFloat(distance) : distance;
if (isNaN(numDistance)) {
return distance;
}
// 保留两位小数
return `${numDistance.toFixed(2)}Km`;
},
// 加载更多
loadMore() {
if (!this.finished) {
this.getArtisanList();
}
},
// 跳转到手艺人(员工)详情页
goArtisanDetail(artisan) {
uni.navigateTo({
url: `/pages/user/employee-detail?id=${artisan.id}`
});
},
// 跳转到资质页面
goQualification(artisan) {
// 跳转到资质页面传递手艺人ID
uni.navigateTo({
url: `/pages/user/qualifications?id=${artisan.id}`
});
},
// 下拉刷新
onPullDownRefresh() {
// 重置页码和状态
this.page = 1;
this.finished = false;
this.artisanList = [];
// 重新加载数据
this.getArtisanList();
// 停止下拉刷新
uni.stopPullDownRefresh();
}
}
};
</script>
<style lang="less">
.syr-list-page {
background-color: #f5f5f5;
min-height: 100vh;
.syr-list-scroll {
width: 100%;
.syr-list-container {
margin: 20rpx 0;
padding: 0 35rpx;
.syr-header {
padding: 30rpx 0 20rpx;
.syr-count {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
}
.syr-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.syr-card {
width: 331rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
.syr-avatar-container {
width: 100%;
height: 327rpx;
.syr-avatar {
width: 100%;
height: 100%;
background-color: #f0f0f0;
}
}
.syr-info {
padding: 20rpx;
.syr-name-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
.syr-name {
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 34rpx;
color: #000000;
line-height: 48rpx;
text-align: left;
font-style: normal;
}
.syr-distance {
display: flex;
align-items: center;
.distance-icon {
transform: translateY(-1rpx);
width: 18rpx;
height: 21rpx;
margin-right: 6rpx;
}
.distance-text {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
}
.syr-experience-row {
display: flex;
align-items: center;
margin-bottom: 8rpx;
.experience-icon {
width: 68rpx;
height: 24rpx;
}
.syr-experience {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 26rpx;
color: #000000;
line-height: 37rpx;
text-align: left;
font-style: normal;
margin-right: 14rpx;
}
}
.syr-join-row {
display: flex;
align-items: center;
.join-icon {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
}
.syr-join {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
}
}
}
.loading-status {
padding: 40rpx 0;
text-align: center;
.loading-text {
font-size: 26rpx;
color: #999;
}
.no-more-text {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 24rpx;
color: #CECECE;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.empty-image {
width: 200rpx;
height: 200rpx;
margin-bottom: 30rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
}
}
}
}
</style>