Files
Smart-Farm/uniapp/uni-app/claim/pages/detail.vue
2025-12-22 17:13:05 +08:00

777 lines
22 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="claim-detail" v-if="detail.id">
<view class='banner-info'>
<swiper class='banner-swiper' @change='handerSwiperChange' :autoplay="true">
<swiper-item v-for="(item,index) in bannerList" :key="index" @tap='handerBannerClick(index)'>
<image mode="aspectFill" class='banner-img' :src='item.img'></image>
<view class="banner-swiper img-bg c-base iconfont icon-zhibo abs flex-center"
v-if="bannerList[bannerCurrent].link_type == 'monitor'"></view>
</swiper-item>
</swiper>
<view class='banner-tagitem banner-tagitem_count'>{{bannerCurrent+1}}/{{bannerList.length}}</view>
<view class='banner-taglist'>
<view class='banner-tagitem'
:class="[{'banner-tagitem_active':item.type==bannerList[bannerCurrent].link_type},{'radius-10':typeList.length == 1},{'radius-left':typeList.length > 1 && index == 0},{'radius-right':typeList.length > 1 && index === typeList.length -1}]"
v-for="(item,index) in typeList" :key="index">
{{item.title}}
</view>
</view>
</view>
<view class="collage-info rel mb-md" v-if="detail.collage_data && detail.collage_data.id">
<image mode="aspectFill" class="collage-img abs" src="https://lbqny.migugu.com/admin/farm/collage.png">
</image>
<view class="collage-count abs">
<min-countdown :type="3" :targetTime="detail.collage_data.end_time * 1000" :color="primaryColor"
textColor="#fff" className="sm" @callback="countEnd">
</min-countdown>
<view class="flex-center f-icontext c-base mt-sm">距结束还剩</view>
</view>
<view class="collage-content pt-md pl-md f-icontext c-base abs">
<view class="f-lg-title"> ¥{{detail.collage_data.price}} </view>
<view class="flex-y-center">
<view class="f-caption text-delete">原价 ¥{{detail.price}} </view>
<view class="collage-num flex-center radius-4 ml-sm pl-sm pr-sm" :style="{color:primaryColor}">
{{detail.collage_data.success_num}}人团
</view>
</view>
</view>
</view>
<view class="pd-lg fill-base">
<view class="flex-center">
<!-- #ifdef MP-WEIXIN -->
<view class="max-566">
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="flex-1">
<!-- #endif -->
<view class="f-title c-title">{{detail.title}}</view>
<view class="flex-y-baseline">
<view class="price c-warning">¥{{detail.price}}</view>
<view class="f-caption c-caption ml-sm">/{{detail.unit}}</view>
</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<button open-type="share" class="clear-btn flex-center flex-column">
<i class="iconfont icon-share c-title"></i>
<view class="f-caption c-title">分享</view>
</button>
<!-- #endif -->
</view>
<view class="f-caption c-caption">
<text decode="emsp" style="word-break:break-all;">{{detail.desc}}</text>
</view>
</view>
<view class="fill-base pd-lg mt-md" v-if="detail.collage_list.length > 0">
<view class="flex-between">
<view class="f-paragraph c-title">不想自己开团? 可与下面小伙伴快速成团</view>
<view @tap="$util.goUrl({url:`/claim/pages/collage/more?id=${options.id}`})"
class="flex-y-center f-caption c-caption">
查看更多<i class="iconfont icon-right" style="font-size:24rpx"></i></view>
</view>
<view @tap="toJoin(index)" class="collage-item flex-center pt-lg pb-lg" :class="[{'b-1px-t':index!=0}]"
v-for="(item,index) in detail.collage_list" :key="index">
<image class="avatar radius" :src="item.user_info.avatarUrl"></image>
<view class="flex-1 flex-center ml-md">
<view class="flex-1 mr-md flex-between">
<view class="f-desc c-title max-150 ellipsis">{{item.user_info.nickName}}</view>
<view>
<view class="flex-between">
<view></view>
<view class="flex-y-center f-paragraph"><view class="c-warning">
{{item.surplus_num}}
</view>人成团
</view>
</view>
<view class="flex-y-center f-icontext c-caption">
<min-countdown :type="5" :targetTime="item.end_time * 1000" color="#999"
@callback="countEnd">
</min-countdown>结束
</view>
</view>
</view>
<view class="common-btn flex-center f-paragraph c-base" :style="{background:primaryColor}">去参与
</view>
</view>
</view>
</view>
<view class="count-list flex-y-center fill-base pd-lg mt-md">
<view class="count-item flex-center flex-column">
<view class="f-title c-title ellipsis">{{detail.breed}}</view>
<view class="f-caption c-caption">认养品种</view>
</view>
<view class="line"></view>
<view class="count-item flex-center flex-column">
<view class="f-title c-title ellipsis">{{detail.cycle}}</view>
<view class="f-caption c-caption">认养周期</view>
</view>
<view class="line"></view>
<view class="count-item flex-center flex-column">
<view class="f-title c-title">{{detail.output}}kg</view>
<view class="f-caption c-caption">产量</view>
</view>
</view>
<view class="mt-md pt-sm pl-lg pr-lg pb-lg fill-base f-paragraph c-title">
<view class="common-nav-title flex-center c-title">
<view class="common-line" :style="{background:primaryColor}"></view>
<view class="f-title text-bold flex-1">认养收获</view>
</view>
<view class="flex-center mt-md">
<image mode="aspectFill" lazy-load class="avatar lg box-shadow-mini radius-10"
:src="detail.harvest_cover">
</image>
<view class="flex-1 ml-lg f-paragraph c-title ellipsis">{{detail.harvest_text}}</view>
</view>
</view>
<view class="mt-md pt-sm pl-lg pr-lg pb-lg fill-base f-paragraph c-title"
v-if="detail.process && detail.process.length > 0">
<view class="common-nav-title flex-center c-title">
<view class="common-line" :style="{background:primaryColor}"></view>
<view class="f-title text-bold flex-1">认养流程</view>
</view>
<view class="flex-warp" :class="[{'mt-md':index==0},{'mt-lg':index!=0}]"
v-for="(item,index) in detail.process" :key="index">
<image mode="aspectFill" lazy-load class="avatar sm" :src="item.cover"></image>
<view class="flex-1 ml-lg">
<view class="f-paragraph c-title">{{item.title}}</view>
<view class="f-caption c-caption">{{item.time}}</view>
<view class="f-caption c-desc">{{item.sub_title}}</view>
</view>
</view>
</view>
<block v-if="list.all_count>0">
<view class="mt-md pt-sm pl-lg pr-lg fill-base f-paragraph c-title">
<view class="common-nav-title flex-center c-title">
<view class="common-line" :style="{background:primaryColor}"></view>
<view class="flex-1 flex-between">
<view class="f-title text-bold">评价{{list.all_count}}</view>
<view @tap.stop="$util.goUrl({url:`/mine/pages/evaluate/more?id=${options.id}&type=1`})"
class="flex-y-center f-paragraph c-caption">
<view>查看全部</view>
<i class="iconfont icon-right" style="font-size: 28rpx;"></i>
</view>
</view>
</view>
</view>
<block v-for="(item,index) in list.data" :key="index">
<view class="flex-warp fill-base pd-lg" :class="[{'b-1px-t':index!=0}]" v-if="index<2">
<image mode="aspectFill" lazy-load class="avatar sm radius" :src="item.user_info.avatarUrl">
</image>
<view class="flex-1 ml-lg">
<view class="flex-between">
<view class="f-paragraph c-title max-350 ellipsis">{{item.user_info.nickName}}</view>
<view class="f-icontext c-caption">{{item.create_time}}</view>
</view>
<view class="flex-warp">
<i class="iconfont icon-star-fill icon-font-color mr-sm"
:style="{backgroundImage: aindex < item.star ? '-webkit-linear-gradient(90deg, #FDCD47, #FFC000)' : '-webkit-linear-gradient(90deg, #eee, #eee)'}"
v-for="(aitem,aindex) in 5" :key="aindex"></i>
</view>
<view class="f-caption c-desc mt-md">
<text decode="emsp" style="word-break:break-all;">{{item.text || '该用户没有填写评价哦'}}</text>
</view>
<view class="flex-warp mt-md" v-if="item.imgs && item.imgs.length > 0">
<block v-for="(aitem,aindex) in item.imgs" :key="aindex">
<view class="eva-img sm radius-10 rel" v-if="aindex < 3">
<image @tap.stop="toPreviewImage(index,aindex)" mode="aspectFill"
class="eva-img sm radius-10" :src="aitem">
</image>
<view class="more f-caption c-base abs"
v-if="aindex == 2 && item.imgs.length > 3">
+{{item.imgs.length - 3}}</view>
</view>
</block>
</view>
</view>
</view>
</block>
</block>
<view class="mt-md pt-sm pl-lg pr-lg pb-lg fill-base f-paragraph c-title">
<view class="common-nav-title flex-center c-title">
<view class="common-line" :style="{background:primaryColor}"></view>
<view class="f-title text-bold flex-1">认养环境</view>
</view>
<view class="flex-center">
<image mode="aspectFill" lazy-load class="avatar mini radius" :src="detail.farmer_info.cover">
</image>
<view class="flex-1 ml-md">{{detail.farmer_info.title}}</view>
</view>
</view>
<view class="map-info rel">
<map :latitude="detail.lat" :longitude="detail.lng" :markers="detail.markers" :enable-satellite="true">
</map>
<view @tap.stop="toMap" class="farmer-title flex-center pl-md pr-sm c-base radius abs">
<view class="f-desc max-500 ellipsis">
{{detail.farmer_info.title}}
</view>
<i class="iconfont icon-right"></i>
</view>
</view>
<view class="order-count-info fill-base"
v-if="detail.machine_info.data && detail.machine_info.data.length > 0">
<view class="flex-between pt-lg pl-lg pr-lg">
<view class="flex-y-baseline f-paragraph c-caption">
<view class="c-title text-bold mr-sm">实时数据</view>
<!-- <view>更新于2021.09.10 16:24</view> -->
</view>
<!-- <i class="iconfont icon-shuaxin"></i> -->
</view>
<!-- <view class="pd-lg flex-center b-1px-b">
<view class="count-item flex-center flex-column">
<view class="f-paragraph c-title">28.7</view>
<view class="f-caption c-caption">热敏温度</view>
</view>
<view class="count-item flex-center flex-column b-1px-l b-1px-r">
<view class="f-paragraph c-title">28.7</view>
<view class="f-caption c-caption">噪声监测</view>
</view>
<view class="count-item flex-center flex-column">
<view class="f-paragraph c-title">28.7</view>
<view class="f-caption c-caption">移动监测</view>
</view>
</view> -->
<view class="pt-lg pl-lg pr-lg pb-md f-paragraph c-desc">
<view class="flex-y-baseline">
<view class="mr-md">无线温湿度</view>
<view>土壤电导率三合一</view>
</view>
<veiw class="flex-warp pb-md">
<view class="machine-item flex-warp f-desc c-caption mt-md"
v-for="(item,index) in detail.machine_info.data" :key="index">
<view class="num">{{`(${index*1+1})`}}</view>
<view class="text">{{item.text}}</view>
<view>{{item.value.length == 0 ? '无' : item.value}}</view>
</view>
</veiw>
<!-- <view class="flex-center pt-md"><i class="iconfont icon-down-bold" style="font-size: 28rpx;"></i></view> -->
</view>
</view>
<view class="mt-md pt-sm pl-lg pr-lg pb-lg fill-base f-paragraph c-title">
<view class="common-nav-title flex-center c-title">
<view class="common-line" :style="{background:primaryColor}"></view>
<view class="f-title text-bold flex-1">详细说明</view>
</view>
<view class="pt-sm" v-if="detail.text">
<parser :html="detail.text" @linkpress="linkpress" show-with-animation lazy-load>加载中...</parser>
</view>
</view>
<view class="space-max-footer"></view>
<view class="footer-btn fill-base fix">
<view class="footer-item flex-between pr-lg">
<view class="flex-warp f-caption c-title">
<view @tap.stop="$util.goUrl({url:`/pages/home`,openType:`switchTab`})"
class="flex-center flex-column pl-lg pr-lg">
<i class="iconfont icon-home"></i>
<view>首页</view>
</view>
<view @tap.stop="$util.goUrl({url:detail.farmer_info.mobile,openType:'call'})"
class="flex-center flex-column pl-md">
<i class="iconfont icon-dianhua text-bold"></i>
<view>客服</view>
</view>
</view>
<view class="flex-warp" v-if="detail.collage_data && detail.collage_data.id">
<view @tap.stop="toOrder" class="order-btn flex-center f-title c-base text-bold radius-20"
:style="{color:primaryColor,border:`1rpx solid ${primaryColor}`}">
单独认养
</view>
<view @tap.stop="toOrder(1)"
class="order-btn flex-center ml-md f-title c-base text-bold radius-20"
:style="{background:primaryColor,border:`1rpx solid ${primaryColor}`}">
去众筹
</view>
</view>
<view @tap.stop="toOrder" class="order-btn md flex-center f-title c-base text-bold radius-20"
:style="{background:primaryColor}" v-else>立即认养
</view>
</view>
<view class="space-safe"></view>
</view>
<uni-popup ref="show_collage_share" type="center">
<view class="show-collage-share">
<view class="flex-center flex-column fill-base pd-lg radius-24">
<view class="f-md-title text-bold pt-lg pb-lg" :style="{color:primaryColor}">您有一个拼团正在进行中</view>
<view class="user-list flex-center mt-lg mb-lg">
<block v-for="(item,index) in detail.user_start_collage.user_avatar" :key="index">
<view class="avatar-group lg"
v-if="index < detail.user_start_collage.success_num > 3 ? 3 : detail.user_start_collage.success_num -1">
<image mode="aspectFill" lazy-load class="abs avatar fill-body radius" :src="item">
</image>
</view>
</block>
<block v-if="detail.user_start_collage.surplus_num">
<i class="iconfont icon-more ml-sm pl-lg pr-lg"></i>
<view class="more-btn flex-center radius"><i class="iconfont icon-add"></i> </view>
</block>
</view>
<min-countdown :type="2" :targetTime="detail.user_start_collage.end_time * 1000" color="#333"
textColor="#999" bgColor="#F7F7F7" className="md" @callback="countEnd">
</min-countdown>
<view class="f-desc c-caption mt-md mb-lg">还差{{detail.user_start_collage.surplus_num}}人成团距离结束还剩
</view>
<view class="space-lg"></view>
<!-- #ifdef MP-WEIXIN -->
<button open-type="share" class="clear-btn share-btn flex-center f-sm-title"
:style="{background:primaryColor}">
邀请好友
</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view @click="toAppShare" class="share-btn flex-center f-sm-title"
:style="{background:primaryColor}">
邀请好友
</view>
<!-- #endif -->
<view class="space-lg"></view>
</view>
<i @tap="$refs.show_collage_share.close()" class="flex-center mt-lg iconfont icon-close c-base"></i>
</view>
</uni-popup>
</view>
</template>
<script>
import {
mapState,
mapMutations
} from "vuex"
export default {
components: {},
data() {
return {
options: {},
detail: {},
bannerCurrent: 0,
bannerList: [],
typeList: [],
current: 0,
param: {
page: 1,
limit: 10
},
list: {
data: []
},
loading: true,
lockTap: false,
}
},
computed: mapState({
primaryColor: state => state.config.configInfo.primaryColor,
subColor: state => state.config.configInfo.subColor,
configInfo: state => state.config.configInfo,
userInfo: state => state.user.userInfo,
haveOperItem: state => state.order.haveOperItem,
}),
onLoad(options) {
this.$util.showLoading()
this.options = options
this.updateOrderItem({
key: 'haveOperItem',
val: false
})
this.initIndex()
},
onUnload() {
if (!this.haveOperItem) return
this.$util.back()
},
onPullDownRefresh() {
// #ifndef APP-PLUS
uni.showNavigationBarLoading()
// #endif
this.initRefresh()
uni.stopPullDownRefresh()
},
onShareAppMessage(e) {
let {
id: pid
} = this.userInfo
let {
id,
title,
cover: imageUrl
} = this.detail
let path = `/claim/pages/detail?id=${id}&pid=${pid}`
this.$util.log(path)
return {
title,
imageUrl,
path,
}
},
methods: {
...mapMutations(['updateOrderItem']),
async initIndex(refresh = false) {
let {
id
} = this.options
let data = await this.$api.claim.claimInfo({
id
})
data.markers = [{
iconPath: "https://lbqnyv2.migugu.com/images/12/2018/11/A33zQycihMM33y337LH23myTqTl3tl.png",
id: 0,
latitude: data.lat,
longitude: data.lng,
width: 28,
height: 28
}]
let {
imgs = [],
monitor = [],
user_start_collage = {
id: 0
}
} = data
let bannerList = []
let typeList = []
if (imgs && imgs.length > 0) {
imgs.map((item) => {
bannerList.push({
img: item,
link: '',
link_type: "img"
})
})
typeList.push({
title: "图片",
type: "img"
})
}
if (monitor && monitor.length > 0) {
monitor.map((item) => {
bannerList.push({
img: item.cover,
link: item.id,
link_type: "monitor"
})
})
typeList.push({
title: "监控",
type: "monitor"
})
}
this.typeList = typeList
this.bannerList = bannerList
this.detail = data
this.$util.hideAll()
await this.getList()
if (user_start_collage && user_start_collage.id && !refresh) {
this.$refs.show_collage_share.open()
}
},
initRefresh() {
this.initIndex(true)
},
countEnd() {
this.$util.log("倒计时完了")
setTimeout(() => {
this.initRefresh()
}, 1000)
},
linkpress(res) {
console.log("linkpress", res);
// #ifdef APP-PLUS
this.$util.goUrl({
url: res.href,
openType: 'web'
})
// #endif
},
async getList() {
let {
list: oldList,
} = this
let {
id: goods_id,
} = this.options
let param = Object.assign({}, this.param, {
goods_id,
type: 1,
is_goods: 0
});
let newList = await this.$api.mine.goodsEvaluateList(param);
if (this.param.page == 1) {
this.list = newList
} else {
newList.data = oldList.data.concat(newList.data)
this.list = newList
}
this.loading = false
this.$util.hideAll()
},
handerSwiperChange(e) {
let {
current,
} = e.detail
this.bannerCurrent = current;
},
handerBannerClick(index) {
let item = this.bannerList[index];
let {
link_type: openType,
link: id,
img
} = item;
if (openType == 'monitor') {
let url = `/home/pages/monitor/detail?id=${id}`
this.$util.goUrl({
url
})
return
}
uni.previewImage({
current: img,
urls: [img]
})
},
async toMap() {
let {
lat,
lng,
address
} = this.detail
await this.$util.checkAuth({
type: 'userLocation'
})
await uni.getLocation({
type: 'gcj02',
})
await uni.openLocation({
latitude: lat * 1,
longitude: lng * 1,
name: address,
scale: 28
})
},
toPreviewImage(index, aindex) {
let {
imgs: urls
} = this.list.data[index]
this.$util.previewImage({
current: urls[aindex],
urls
})
},
toJoin(index) {
let {
id: cid,
claim_id,
user_id,
can_join,
} = this.detail.collage_list[index]
let {
join_times
} = this.detail.collage_data
let {
id: uid
} = this.userInfo
if (user_id == uid || !can_join) {
this.$util.showToast({
title: user_id == uid ? `不能参与自己发起的众筹哦` : `您已参与此众筹或已达到参与次数${join_times}`
})
return
}
let url = `/claim/pages/order?id=${claim_id}&cid=${cid}&type=2`
this.$util.goUrl({
url
})
},
toOrder(type = 0) {
let {
id
} = this.options
let {
collage_data = {
id: 0
},
user_start_collage = {
id: 0
}
} = this.detail
let {
id: cid = 0,
can_start,
start_times
} = collage_data
if (type == 1 && user_start_collage && user_start_collage.id) {
this.$refs.show_collage_share.open()
return
}
if (type == 1 && !can_start) {
this.$util.showToast({
title: `您已达到发起众筹次数${start_times}`
})
return
}
let url = `/claim/pages/order?id=${id}&cid=${cid}&type=${type}`
this.$util.goUrl({
url
})
}
}
}
</script>
<style lang="scss">
.claim-detail {
.collage-info {
width: 100%;
height: 143rpx;
.collage-img {
left: 0;
bottom: 0;
width: 100%;
height: 156rpx;
}
.collage-count {
right: 12rpx;
bottom: 30rpx;
}
.collage-content {
top: 0;
width: 300rpx;
height: 140rpx;
.collage-num {
min-width: 76rpx;
height: 28rpx;
background: #FFFB00;
}
}
}
.price,
.icon-share {
font-size: 42rpx;
}
.collage-item {
.avatar {
width: 68rpx;
height: 68rpx;
}
}
.count-list {
.count-item {
width: 249rpx;
.ellipsis {
max-width: 220rpx;
}
}
.line {
width: 1rpx;
height: 58rpx;
background: #CCCCCC;
opacity: 0.4;
}
}
.map-info {
map {
width: 100%;
height: 450rpx;
}
.farmer-title {
z-index: 9;
left: 15rpx;
bottom: 10rpx;
height: 50rpx;
background: rgba(0, 0, 0, 0.5);
.iconfont {
font-size: 24rpx;
}
}
}
.order-count-info {
.count-item {
width: 33.33%;
}
.machine-item {
width: 50%;
.num {
width: 50rpx;
}
.text {
width: 150rpx;
padding-right: 10rpx;
}
}
}
.footer-btn {
bottom: 0;
.footer-item {
height: 114rpx;
.iconfont {
font-size: 42rpx;
}
}
.order-btn {
width: 220rpx;
height: 78rpx;
transform: rotateZ(360deg);
}
.order-btn.md {
width: 444rpx;
}
}
.show-collage-share {
width: 640rpx;
.user-list {
.more-btn {
width: 92rpx;
height: 92rpx;
background: #F8F8F8;
border: 1px solid #DBDBDB;
.icon-add {
color: #D8D8D7
}
}
}
.share-btn {
width: 420rpx;
height: 94rpx;
color: #fff;
border-radius: 100rpx;
}
.icon-close {
font-size: 80rpx;
}
}
}
</style>