472 lines
11 KiB
Vue
472 lines
11 KiB
Vue
<template>
|
||
<view class="service-list">
|
||
<!-- 循环渲染列表项 -->
|
||
<view class="service-item-wrapper" v-for="(item, index) in listWithShortTitle" :key="index" @click="goServerDetail(item)">
|
||
<!-- 上半部分:手艺人/门店信息 -->
|
||
<view class="artisan-row" v-if="hasArtisanOrShop(item)">
|
||
<!-- 手艺人头像:只有有手艺人头像时才显示 -->
|
||
<image class="artisan-avatar" v-if="hasArtisanAvatar(item)" :src="getArtisanAvatar(item)" mode="aspectFill"></image>
|
||
|
||
<view class="artisan-info">
|
||
<!-- 手艺人名字 -->
|
||
<text class="artisan-name" v-if="hasArtisanName(item)">{{ getArtisanName(item) }}</text>
|
||
|
||
<!-- 分隔线:只有当手艺人名字和门店名字都存在时才显示 -->
|
||
<text class="separator" v-if="hasArtisanName(item) && hasShopName(item)"> | </text>
|
||
|
||
<!-- 门店名字 -->
|
||
<text class="shop-name" v-if="hasShopName(item)">{{ getShopName(item) }}</text>
|
||
|
||
<image class="artisan-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/f49ad42d-3581-4287-9815-35a13ac555bd.png" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 下半部分:原有卡片 -->
|
||
<view class="service-item">
|
||
<view class="avatar_box">
|
||
<view class="tag_kind">{{
|
||
item.server_kind == 1 ? "到家" : item.server_kind == 2 ? "到店" : item.server_kind == 2 ? "到店" : item.server_kind == 3 ? "上门\到店" : ""
|
||
}}</view>
|
||
<image class="avatar" :src="getServiceImage(item)" mode="aspectFill"></image>
|
||
</view>
|
||
|
||
<!-- 右侧信息区 -->
|
||
<view class="item-right">
|
||
<view class="top-info">
|
||
<view class="name-wrapper">
|
||
<image class="service-title-type" mode="widthFix" src="@/static/images/shop/pintuan/group2.png"
|
||
v-if="item.team_buy && Object.keys(item.team_buy).length != 0"></image>
|
||
<text class="name" :style="{width:item.team_buy && Object.keys(item.team_buy).length != 0?`180rpx`:`240rpx`}">{{ item.title }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 服务标签 -->
|
||
<view class="services">
|
||
<view class="service-tag">
|
||
<view class="price">¥{{ item.server_price }}</view>
|
||
<view class="split"></view>
|
||
<view class="server_time">服务时长:{{ item.server_time }}分钟</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="distance">
|
||
<image class="position"
|
||
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e37b3bd7-841f-4d57-a11a-2365c81f740e" />
|
||
<text>{{ formatDistance(item.distance) }}</text>
|
||
</view>
|
||
|
||
<!-- 可预约时间 -->
|
||
<view class="time_box">
|
||
<view class="time">销量
|
||
<text class="num">{{ item.sales_num }}</text>
|
||
</view>
|
||
<view class="order-btn" >{{ btnText }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: "ServiceListItem",
|
||
props: {
|
||
list: {
|
||
type: Array,
|
||
default: () => [],
|
||
},
|
||
btnText: {
|
||
type: String,
|
||
default: "去下单",
|
||
}
|
||
},
|
||
methods: {
|
||
// 检查是否有手艺人或门店信息
|
||
hasArtisanOrShop(item) {
|
||
return this.hasArtisanName(item) || this.hasShopName(item);
|
||
},
|
||
|
||
// 检查是否有手艺人头像
|
||
hasArtisanAvatar(item) {
|
||
return item.user_syr && item.user_syr.head_photo && item.user_syr.head_photo.trim() !== '';
|
||
},
|
||
|
||
// 获取手艺人头像
|
||
getArtisanAvatar(item) {
|
||
if (this.hasArtisanAvatar(item)) {
|
||
return item.user_syr.head_photo;
|
||
}
|
||
return "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40";
|
||
},
|
||
|
||
// 检查是否有手艺人名字
|
||
hasArtisanName(item) {
|
||
return item.user_syr && item.user_syr.name && item.user_syr.name.trim() !== '';
|
||
},
|
||
|
||
// 获取手艺人名字
|
||
getArtisanName(item) {
|
||
if (this.hasArtisanName(item)) {
|
||
return item.user_syr.name;
|
||
}
|
||
// 如果没有手艺人名字,检查是否有门店名字作为备选
|
||
if (this.hasShopName(item)) {
|
||
return item.user_sj.name;
|
||
}
|
||
return "";
|
||
},
|
||
|
||
// 检查是否有门店名字
|
||
hasShopName(item) {
|
||
return item.user_sj && item.user_sj.name && item.user_sj.name.trim() !== '';
|
||
},
|
||
|
||
// 获取门店名字
|
||
getShopName(item) {
|
||
if (this.hasShopName(item)) {
|
||
return item.user_sj.name;
|
||
}
|
||
return "";
|
||
},
|
||
|
||
// 获取服务图片
|
||
getServiceImage(item) {
|
||
if (item.photo && item.photo.length > 0 && item.photo[0] && item.photo[0].trim() !== '') {
|
||
return item.photo[0];
|
||
}
|
||
// 如果没有图片,返回默认图片
|
||
return "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/default-service.png";
|
||
},
|
||
|
||
// 格式化距离显示
|
||
formatDistance(distance) {
|
||
if (!distance && distance !== 0) return "距离未知";
|
||
|
||
// 如果距离小于1公里,显示米
|
||
if (distance < 1) {
|
||
return (distance * 1000).toFixed(0) + "m";
|
||
}
|
||
// 如果距离大于等于1公里,显示公里
|
||
return distance.toFixed(2) + "km";
|
||
},
|
||
|
||
formatTimeToRelative(timeStr) {
|
||
const [datePart, timePart] = timeStr.split(" ");
|
||
const [year, month, day] = datePart.split("-").map(Number);
|
||
const [hours, minutes] = timePart.split(":").map(Number);
|
||
|
||
const inputDate = new Date(year, month - 1, day, hours, minutes);
|
||
const today = new Date();
|
||
today.setHours(0, 0, 0, 0);
|
||
|
||
const tomorrow = new Date(today);
|
||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||
|
||
const inputDateOnly = new Date(inputDate);
|
||
inputDateOnly.setHours(0, 0, 0, 0);
|
||
|
||
const timeFormat = `${hours.toString().padStart(2, "0")}:${minutes
|
||
.toString()
|
||
.padStart(2, "0")}`;
|
||
|
||
if (inputDateOnly.getTime() === today.getTime()) {
|
||
return `今${timeFormat}`;
|
||
} else if (inputDateOnly.getTime() === tomorrow.getTime()) {
|
||
return `明${timeFormat}`;
|
||
} else {
|
||
return timeStr;
|
||
}
|
||
},
|
||
|
||
goServerDetail(item) {
|
||
if (item.team_buy && Object.keys(item.team_buy).length != 0) {
|
||
uni.navigateTo({
|
||
url: `/pages/groupBuy/detail?id=${item.id}`,
|
||
});
|
||
} else {
|
||
uni.navigateTo({
|
||
url: `/pages/service/detail?id=${item.id}`
|
||
})
|
||
}
|
||
},
|
||
},
|
||
computed: {
|
||
listWithShortTitle() {
|
||
return this.list.map(item => {
|
||
return {
|
||
...item
|
||
};
|
||
});
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.service-item-wrapper {
|
||
display: flex;
|
||
flex-direction: column;
|
||
background-color: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
/* 手艺人信息行 */
|
||
.artisan-row {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 10rpx 20rpx;
|
||
margin-top: 10rpx;
|
||
width: 100%;
|
||
}
|
||
|
||
.artisan-avatar {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border-radius: 50%;
|
||
margin-right: 16rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.artisan-info {
|
||
display: flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.artisan-name {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: #333333;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.separator {
|
||
font-size: 24rpx;
|
||
color: #dddddd;
|
||
margin: 0 8rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.shop-name {
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
flex: 0 1 auto;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
margin: 0;
|
||
}
|
||
|
||
.artisan-icon {
|
||
width: 8rpx;
|
||
height: 14rpx;
|
||
flex-shrink: 0;
|
||
flex: 0 0 auto;
|
||
margin-left: 8rpx;
|
||
}
|
||
|
||
/* 列表容器 */
|
||
.service-list {
|
||
padding: 20rpx 20rpx 0rpx 20rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20rpx;
|
||
/* #ifdef MP-WEIXIN */
|
||
transform: scale(1.13);
|
||
/* #endif */
|
||
}
|
||
|
||
/* 单个列表项 */
|
||
.service-item {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
padding: 10rpx 20rpx 20rpx 20rpx;
|
||
background-color: transparent;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.avatar_box {
|
||
width: 218rpx;
|
||
height: 218rpx;
|
||
background: #935858;
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
margin-right: 30rpx;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
|
||
.tag_kind {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
z-index: 100;
|
||
text-align: center;
|
||
padding: 0 8rpx;
|
||
height: 38rpx;
|
||
line-height: 38rpx;
|
||
background: linear-gradient(124deg, #f52540 0%, #e8101e 100%);
|
||
border-radius: 12rpx 2rpx 12rpx 2rpx;
|
||
font-size: 22rpx;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
|
||
/* 头像样式 */
|
||
.avatar {
|
||
width: 218rpx;
|
||
height: 218rpx;
|
||
}
|
||
|
||
/* 右侧信息容器 */
|
||
.item-right {
|
||
flex: 1;
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
/* 使用space-between让底部内容对齐 */
|
||
justify-content: space-between;
|
||
/* 设置最小高度与左侧图片相同 */
|
||
min-height: 218rpx;
|
||
}
|
||
|
||
/* 姓名 + 距离 行 */
|
||
.top-info {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 7rpx;
|
||
gap: 20rpx; // 减小间距
|
||
overflow: hidden;
|
||
}
|
||
|
||
.name-wrapper {
|
||
flex: 1; // 占据剩余空间
|
||
display: flex;
|
||
align-items: center;
|
||
min-width: 0;
|
||
max-width: 100%;
|
||
overflow: hidden;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.name {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 500;
|
||
line-height: 34rpx;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
flex: 1; // 占据剩余空间
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
// white-space: nowrap; // 确保单行显示
|
||
display: block;
|
||
width: 100%;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.distance {
|
||
display: flex;
|
||
align-items: center;
|
||
line-height: 33rpx;
|
||
gap: 6rpx;
|
||
font-family: DINPro, DINPro;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
flex-shrink: 0;
|
||
margin-top: 8rpx;
|
||
}
|
||
|
||
.position {
|
||
width: 19rpx;
|
||
height: 21rpx;
|
||
}
|
||
|
||
/* 服务标签容器 */
|
||
.services {
|
||
display: flex;
|
||
gap: 10rpx 0;
|
||
flex-wrap: wrap;
|
||
// margin-bottom: 26rpx;
|
||
}
|
||
|
||
.service-tag {
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.price {
|
||
font-weight: 700;
|
||
font-size: 26rpx;
|
||
color: #e8101e;
|
||
font-family: DINPro, DINPro;
|
||
}
|
||
|
||
.server_time {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
line-height: 34rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
|
||
.split {
|
||
width: 2rpx;
|
||
height: 20rpx;
|
||
background: #666666;
|
||
margin: 0 10rpx;
|
||
}
|
||
}
|
||
|
||
.time_box {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-end;
|
||
padding-bottom: 0;
|
||
margin-top: auto;
|
||
}
|
||
|
||
/* 可预约时间 */
|
||
.time {
|
||
font-size: 26rpx;
|
||
color: #999999;
|
||
|
||
.num {
|
||
font-family: DINPro, DINPro;
|
||
font-weight: 400;
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
}
|
||
}
|
||
|
||
/* 下单按钮 */
|
||
.order-btn {
|
||
line-height: 60rpx;
|
||
height: 60rpx;
|
||
padding: 0rpx 20rpx;
|
||
background: linear-gradient(107deg, #f84c63 0%, #e8101e 100%);
|
||
border-radius: 30rpx;
|
||
text-align: center;
|
||
color: #fff;
|
||
font-size: 25rpx;
|
||
/* 修改:确保按钮与底部对齐 */
|
||
align-self: flex-end;
|
||
}
|
||
|
||
.service-title-type {
|
||
width: 56rpx;
|
||
height: 28rpx; // 添加固定高度,保持图片比例
|
||
flex-shrink: 0; // 防止图片被压缩
|
||
display: block; // 确保图片正确显示
|
||
}
|
||
</style> |