mrr.sj.front/pages/user/syr-detail.vue

779 lines
21 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="detail-page">
<custom-navbar title="手艺人主页" :show-back="true" backgroundColor="#fff" :show-headle="true"
headleSrc="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b04f0c1-a55e-4658-9de5-22175cce9bbc.png"
@onHeadleClick="goInvite"></custom-navbar>
<!-- 手艺人顶部首图 -->
<view class="main-image-section">
<!-- <swiper class="banner-swiper" circular :indicator-dots="false" :autoplay="false" :interval="3000"
:duration="500" indicator-active-color="#fff" indicator-color="rgba(255, 255, 255, 0.6)">
<swiper-item @click="previewImage()">
<video :src="syrdetail.video" v-if="syrdetail.video" id="myVideo" class="banner-image"
:autoplay="true" :controls="false" :muted="true" :loop="true" enable-play-gesture="true"
object-fit="cover">
</video>
<image v-else :src="headPhoto" mode="aspectFill" class="banner-image" referrer="no-referrer">
</image>
</swiper-item>
</swiper> -->
<view class="banner-swiper">
<video :src="imgVideoList.main_video.url" v-if="imgVideoList.main_video" id="myVideo"
class="banner-image" :autoplay="true" :controls="false" :muted="true" :loop="true"
enable-play-gesture="true" object-fit="cover">
</video>
<image v-else-if="!imgVideoList.main_video && imgVideoList.main_img" :src="imgVideoList.main_img.url"
mode="aspectFill" class="banner-image" referrer="no-referrer">
</image>
<image v-else src="/static/default.png" mode="aspectFill" class="banner-image" referrer="no-referrer">
</image>
<cover-view class="album flex-row-center" v-if="imgVideoList.main_video || imgVideoList.main_img">
<cover-view class="album-left flex-row-center-center">
{{ imgVideoList.main_video?"视频":"图片" }}
</cover-view>
<cover-view class="album-line">
</cover-view>
<cover-view class="album-right flex-row-center-center" @click="goAlbum">
<cover-view class="album-right-text">
<cover-view>相册</cover-view>
</cover-view>
<cover-image src="/static/images/icons/right7_13.png" class="album-right-img"></cover-image>
</cover-view>
</cover-view>
</view>
</view>
<!-- 手艺人信息卡片 -->
<view class="detail-info" :style="{transform: syrdetail.video?`translateY(0rpx)`:`translateY(-20rpx)`}">
<view class="detail-info-user">
<view class="detail-info-user__heard">
<image :src="headPhoto" mode="aspectFill" class="detail-info-user__heard__photo"
referrer="no-referrer"></image>
<view class="detail-info-user__heard__name">
<view class="detail-info-user__heard__name__text">
{{ syrdetail.name }}
</view>
<view class="detail-info-user__heard__name__time">
<view class="detail-info-user__heard__name__time__text1">
营业时间
</view>
<view class="detail-info-user__heard__name__time__text2">
{{ syrdetail.default_times }}
</view>
</view>
</view>
</view>
<view class="detail-info-user__company">
<view class="detail-info-user__company__name" @click="goQualifications">
<view class="detail-info-user__company__name__card">
<image src="/static/images/syr/company.png" mode="aspectFill"
class="detail-info-user__company__name__card__img" referrer="no-referrer"></image>
</view>
<view class="detail-info-user__company__name__text">
{{ syrdetail.for_shop }}
</view>
</view>
<view class="detail-info-user__company__reserve">
<view class="detail-info-user__company__reserve__card">
最近可约
</view>
<view class="detail-info-user__company__reserve__text">
{{ formatRelativeTime(syrdetail.earliest_reserve_time) }}
</view>
</view>
</view>
<view class="detail-info-user__adress">
<view class="detail-info-user__adress__left">
<text class="detail-info-user__adress__left__text1">店铺所在地</text>
<text class="detail-info-user__adress__left__text2">{{
syrdetail.dependency
}}</text>
</view>
<view class="detail-info-user__adress__right">
<image src="/static/images/syr/distance.png" mode="widthFix"
class="detail-info-user__adress__right__img" referrer="no-referrer"></image>
{{ syrdetail.distance }}Km
</view>
</view>
<view class="detail-info-user__introduction">
{{ syrdetail.detail }}
</view>
<image src="/static/images/syr/banner.png" mode="widthFix" class="detail-info-user__banner"
referrer="no-referrer"></image>
</view>
<view class="detail-info-shop">
<view class="detail-info-shop-title">全部项目</view>
<projectTabs :tabsPopList="tabsPopList" @clickTap="clickTap" @clickPopTap="clickPopTap"></projectTabs>
<CommonList background="transparent" ref="groupRef" :apiUrl="'/user/getserverlist'"
:listScrollHeight="`${count * 200 + 80}rpx`" @load-success-all="listSuccess">
<template #listData="{ list }">
<serviceCardList :list="list"></serviceCardList>
</template>
<!-- 空数据状态 -->
<template #empty>
<noData></noData>
</template>
</CommonList>
</view>
<evaluationList :evaluated_id="syrdetail.id" :evaluated_type="1" v-if="syrdetail.id" @goList="goList">
</evaluationList>
</view>
</view>
</template>
<script>
import {
handleImgSizeUni
} from '@/utils/service.js'
import CommonList from "@/components/common/CommonList.vue";
import request from "../../utils/request";
import projectTabs from "./components/project-tabs.vue";
import serviceCardList from "./components/serviceCardList.vue";
import evaluationList from '@/pages/evaluate/components/evaluationList';
export default {
components: {
projectTabs,
CommonList,
serviceCardList,
evaluationList
},
data() {
return {
imgVideoList: {},
videoContext: null,
count: 1,
syrdetail: {
qualifications: [],
},
distance: 12.31, //距离
queryData: {
publish_user_id: null,
server_kind: 1,
page: 1,
limit: 10,
order_type: 1,
},
tabsPopList: [],
showPopup: false,
autoShare: false,
autoShareExecuted: false
};
},
onLoad(options) {
console.log(options);
this.queryData.publish_user_id = options.id;
// 检查是否需要自动分享
if (options.autoShare === '1') {
this.autoShare = true;
}
this.getShopDetail(options.id);
this.$nextTick(() => {
this.search();
});
},
computed: {
headPhoto() {
if (this.syrdetail.head_photo == "-" || !this.syrdetail.head_photo) {
return `https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40`
} else {
return this.syrdetail.head_photo
}
}
},
methods: {
goAlbum() {
uni.navigateTo({
url: `/pages/album/index?id=${this.queryData.publish_user_id}&user_type=1`
});
},
getImgVideoList() {
request.post("/user/imgVideo/main", {
user_id: this.queryData.publish_user_id,
user_type: 1
}).then(res => {
if (res.code == 200) {
this.imgVideoList = res.data
}
})
},
goList() {
uni.navigateTo({
url: `/pages/evaluate/evaluationList?evaluated_id=${this.syrdetail.id}&evaluated_type=1`
})
},
listSuccess(e) {
if (e.count) {
this.count = e.count <= 4 ? e.count : 4
}
},
formatRelativeTime(datetime) {
// 将传入值转换为Date对象兼容字符串和Date实例
const targetDate = new Date(datetime);
// 处理无效日期:直接返回原始输入
if (isNaN(targetDate.getTime())) {
return typeof datetime === "string" ? datetime : "";
}
// 获取当前时间(本地时区)的年、月、日
const now = new Date();
const currentYear = now.getFullYear();
const currentMonth = now.getMonth(); // 月份从0开始0=1月
const currentDate = now.getDate();
// 计算明天的年、月、日(当前时间+24小时
const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
const tomorrowYear = tomorrow.getFullYear();
const tomorrowMonth = tomorrow.getMonth();
const tomorrowDate = tomorrow.getDate();
// 提取目标日期的年、月、日
const targetYear = targetDate.getFullYear();
const targetMonth = targetDate.getMonth();
const targetDay = targetDate.getDate();
// 格式化小时和分钟(确保两位数,如 9:5 → 09:05
const hours = String(targetDate.getHours()).padStart(2, "0");
const minutes = String(targetDate.getMinutes()).padStart(2, "0");
// 判断日期属于今天、明天还是其他
if (
targetYear === currentYear &&
targetMonth === currentMonth &&
targetDay === currentDate
) {
return `今天${hours}:${minutes}`;
} else if (
targetYear === tomorrowYear &&
targetMonth === tomorrowMonth &&
targetDay === tomorrowDate
) {
return `明天${hours}:${minutes}`;
} else {
// 非今天/明天返回原始输入若为Date对象则转为字符串保留原始格式
return typeof datetime === "string" ? datetime : targetDate.toString();
}
},
setShare(imageUrl) {
// 备用图片地址(常量提取,方便统一维护)
const backupImageUrl =
"https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40";
// 获取页面栈,用于返回
const pages = getCurrentPages();
// 生成分享配置的公共函数(接收图片地址,返回完整配置)
const getShareConfig = (imgUrl) => ({
provider: "weixin",
scene: "WXSceneSession",
type: 5,
title: "好友刚推了个超赞手艺人点开认识TA ~",
miniProgram: {
id: "gh_89c92e18b70b", // 小程序原始ID
path: `/subPackages/user/syr-detail?id=${this.syrdetail.id}`, // 动态路径
type: this.$store.state.wxShareType, // 版本类型
webUrl: "https://www.baidu.com/", // 降级网页地址
},
imageUrl: imgUrl, // 动态传入图片地址
success: (res) => {
console.log("分享成功:", JSON.stringify(res));
// 延迟返回并显示成功提示
setTimeout(() => {
// 返回上一页即profile页面
uni.navigateBack({
delta: 1,
success: () => {
// 在profile页面显示分享成功提示
// 使用事件总线或全局状态传递消息
uni.showToast({
title: '分享成功',
icon: 'success',
duration: 1000
});
}
});
}, 500); // 延迟0.5秒,让用户看到分享界面
},
fail: (err) => {
console.log("分享失败:", JSON.stringify(err));
uni.showToast({
title: '分享失败',
icon: 'none',
duration: 1000
});
// 分享失败也返回,但提示失败
setTimeout(() => {
uni.navigateBack({
delta: 1,
success: () => {
uni.showToast({
title: '分享失败',
icon: 'none',
duration: 2000
});
}
});
}, 1500);
},
});
// 首次分享使用传入的imageUrl
uni.share(getShareConfig(imageUrl))
.catch(() => {
// 首次失败时,自动使用备用图重试
console.log("首次分享图片无效,尝试备用图片分享...");
uni.share(getShareConfig(backupImageUrl));
});
},
async goInvite() {
let _that = this;
let imageUrl =
"https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/yh/1756713709528-717.png?x-oss-process=image/resize,p_40";
var pages = getCurrentPages();
var page = pages[pages.length - 1];
var bitmap = null;
// 获取当前页面 webview 的对象实例
var currentWebview = await page.$getAppWebview();
bitmap = await new plus.nativeObj.Bitmap("store-detail");
// 将webview内容绘制到Bitmap对象中
currentWebview.draw(
bitmap,
function() {
console.log("截屏绘制图片成功", bitmap);
bitmap.save(
"_doc/a.jpg", {},
async function(i) {
imageUrl = i.target;
try {
// 直接调用导入的函数,不要加 this
const processedUrl = await handleImgSizeUni(i.target);
console.log("处理后的图片地址:", processedUrl);
// 赋值给组件数据
imageUrl = processedUrl;
} catch (err) {
console.error("处理失败:", err);
}
_that.setShare(imageUrl);
bitmap.clear();
},
function(e) {
_that.setShare(imageUrl);
console.log("保存图片失败:" + JSON.stringify(e));
}
);
},
function(e) {
_that.setShare(imageUrl);
console.log("截屏绘制图片失败:" + JSON.stringify(e));
}
);
},
previewImage(index) {
// uni.previewImage({
// urls: this.photoList,
// current: index
// })
},
clickTap(e) {
if (e.order_type) {
this.queryData.order_type = e.order_type;
this.search();
}
},
clickPopTap(e) {
this.queryData.first_class = e;
this.search();
},
// 去资质页
goQualifications() {
uni.navigateTo({
url: `/pages/user/qualifications?id=${this.queryData.publish_user_id}`,
});
},
// 获取手艺人详情
getShopDetail(id) {
let addressRes = {};
let userAdrees = uni.getStorageSync("userAdrees");
if (userAdrees) {
addressRes = userAdrees.addressRes;
} else {
addressRes = getApp().globalData.addressRes;
}
let userLat = addressRes.latitude;
let userLngz = addressRes.longitude;
request
.post("/user/syrdetail", {
id,
userLat,
userLngz
})
.then((res) => {
this.syrdetail = res.data;
this.syrdetail.distance = this.syrdetail.distance.toFixed(2)
this.tabsPopList = [];
this.syrdetail.servers_kill.forEach((element, index) => {
let obj = {
id: element,
name: this.syrdetail.servers_kill_arr[index],
active: false,
};
this.tabsPopList.push(obj);
});
// 如果需要自动分享且未执行过
if (this.autoShare && !this.autoShareExecuted) {
this.autoShareExecuted = true;
// 等待页面渲染
setTimeout(() => {
this.autoTriggerShare();
}, 1000);
}
})
.catch((err) => {
console.log(err);
});
},
// 自动触发分享
autoTriggerShare() {
// #ifdef APP-PLUS
console.log('开始自动分享');
this.goInvite();
// #endif
// #ifdef MP-WEIXIN
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
});
uni.showToast({
title: '请点击右上角分享',
icon: 'none',
duration: 2000
});
// #endif
},
search() {
// 触发列表刷新
this.$refs.groupRef.manualRefresh(this.queryData);
},
},
};
</script>
<style lang="less">
.detail-page {
/* 主图区域 */
.main-image-section {
position: relative;
width: 750rpx;
height: 602rpx;
background-color: #999;
.banner-swiper {
width: 750rpx;
height: 602rpx;
position: relative;
.banner-image {
width: 750rpx;
height: 602rpx;
}
.album {
position: absolute;
bottom: 25rpx;
left: 20rpx;
height: 44rpx;
width: 184rpx;
background: rgba(0, 0, 0, 0.4);
border-radius: 23rpx;
.album-left {
width: 73rpx;
height: 44rpx;
background: #FFFFFF;
border-radius: 23rpx;
display: flex;
align-items: center;
justify-content: center;
line-height: 40rpx;
font-weight: 400;
font-size: 22rpx;
text-align: center;
color: #333333;
}
.album-line {
width: 2rpx;
height: 20rpx;
background: #A09C9E;
border-radius: 1rpx;
margin: 0 18rpx;
}
.album-right {
height: 44rpx;
.album-right-text {
// width: 44rpx;
// height: 44rpx;
// border-radius: 23rpx;
// min-width: 50rpx;
//line-height: 44rpx;
transform: translateY(-4rpx);
font-weight: 400;
font-size: 22rpx;
text-align: center;
color: #FFFFFF;
}
.album-right-img {
width: 8rpx;
height: 16rpx;
padding-left: 8rpx;
}
}
}
}
}
.detail-info {
transform: translateY(-20rpx);
padding: 0 20rpx;
position: relative;
.detail-info-user {
padding: 20rpx 26rpx 20rpx 30rpx;
background: #ffffff;
border-radius: 20rpx;
.detail-info-user__heard {
display: flex;
flex-wrap: nowrap;
align-items: center;
&__photo {
width: 122rpx;
height: 122rpx;
border-radius: 50%;
margin-right: 17rpx;
}
&__name {
&__text {
font-weight: 500;
font-size: 42rpx;
color: #333333;
line-height: 59rpx;
text-align: left;
font-style: normal;
}
&__time {
display: flex;
align-items: center;
flex-wrap: nowrap;
&__text1 {
font-weight: 400;
font-size: 22rpx;
color: #5b5b5b;
}
&__text2 {
margin-left: 6rpx;
font-family: DINPro, DINPro;
font-weight: 500;
font-size: 24rpx;
color: #5b5b5b;
transform: translateY(-2rpx);
}
}
}
}
.detail-info-user__company {
display: flex;
margin-top: 37rpx;
&__name {
background: #ffffff;
border-radius: 8rpx;
border: 2rpx solid #cccfd1;
padding-right: 8rpx;
display: flex;
align-items: center;
margin-right: 21rpx;
&__text {
font-weight: 400;
font-size: 20rpx;
color: #a7abae;
text-align: left;
font-style: normal;
}
&__card {
margin-right: 8rpx;
width: 39rpx;
height: 34rpx;
background: rgba(212, 215, 223, 0.2);
border-radius: 6rpx;
border: 1rpx solid rgba(169, 172, 179, 0.2);
display: flex;
align-items: center;
justify-content: center;
&__img {
width: 22rpx;
height: 21rpx;
}
}
}
&__reserve {
display: flex;
align-items: center;
background: #ffffff;
border-radius: 8rpx;
border: 2rpx solid #e8101e;
padding-right: 10rpx;
&__text {
font-family: DINPro, DINPro;
font-weight: bold;
font-size: 20rpx;
color: #e8101e;
line-height: 24rpx;
text-align: left;
font-style: normal;
}
&__card {
margin-right: 8rpx;
height: 100%;
padding: 0rpx 10rpx;
background: #ffecf0;
border-radius: 6rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 20rpx;
color: #e8101e;
text-align: left;
font-style: normal;
}
}
}
.detail-info-user__adress {
margin-top: 20rpx;
display: flex;
justify-content: space-between;
&__left {
&__text1 {
font-weight: 400;
font-size: 24rpx;
color: #a7abae;
line-height: 33rpx;
text-align: left;
font-style: normal;
margin-right: 10rpx;
}
&__text2 {
font-weight: 400;
font-size: 24rpx;
color: #333333;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
&__right {
font-weight: bold;
font-size: 24rpx;
color: #666666;
text-align: left;
font-style: normal;
display: flex;
flex-direction: row;
align-items: center;
&__img {
width: 17.5rpx;
margin-right: 9rpx;
}
}
}
.detail-info-user__introduction {
margin-top: 33rpx;
padding-top: 25rpx;
font-weight: 400;
font-size: 24rpx;
color: #666666;
line-height: 33rpx;
text-align: left;
font-style: normal;
position: relative;
background-image: url("/static/images/syr/introduction.png");
/* 背景图片不重复显示 */
background-repeat: no-repeat;
/* 背景图片位置左上角默认值可省略 */
background-position: left top;
/* 背景图片宽度为72rpx高度自适应保持比例 */
background-size: 72rpx auto;
/* 建议设置元素尺寸以确保图片可见 */
}
.detail-info-user__banner {
width: 100%;
margin-top: 30rpx;
}
}
.detail-info-shop {
padding: 20rpx;
background: #ffffff;
border-radius: 20rpx;
margin-top: 20rpx;
.detail-info-shop-title {
width: 136rpx;
height: 48rpx;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 34rpx;
color: #333333;
line-height: 48rpx;
text-align: left;
font-style: normal;
}
}
}
}
::v-deep .list-container {
padding: 0 !important;
}
.evaluationList {
margin: 20rpx 0rpx 0rpx 0rpx !important;
}
</style>