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

526 lines
14 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="land-order-detail" v-if="detail.id">
<fixed>
<uni-nav-bar :fixed="false"
:shadow="false" :statusBar="true" color="#fff" backgroundColor="none"
:leftIcon="options.pid?'iconshouye':'icon-left'" title="农场详情">
</uni-nav-bar>
<image mode="aspectFill" lazy-load class="common-bg abs"
:style="{height: `${configInfo.navBarHeight + 104}px`}" src="https://lbqny.migugu.com/admin/farm/bg-cash.png"></image>
<view class="common-top-img"></view>
<view class="common-top-info rel fill-base">
<view class="top-box abs">
<view @tap.stop="$util.goUrl({url:`/home/pages/farm/info?id=${options.id}`})"
class="farm-item fill-base flex-center ml-md mr-md pd-lg box-shadow radius-24">
<image mode="aspectFill" lazy-load class="cover box-shadow radius-24" :src="detail.cover">
</image>
<view class="flex-1 ml-lg">
<view class="flex-y-center f-title c-title mt-sm mb-sm">
<view class="max-title ellipsis">{{detail.title}}</view>
<view class="status-btn flex-center c-caption ml-sm radius-10"
:class="[{'fill-space':detail.is_open == 0},{'fill-body':detail.is_open == 1}]"
:style="{color:detail.is_open == 1?primaryColor:''}">
{{detail.is_open == 1?'营业中':'闭店中'}}
</view>
</view>
<view class="flex-between">
<view class="star-fill-info rel">
<view class="flex-warp star rel">
<view class="item-star flex-center" v-for="(aitem,aindex) in 5" :key="aindex">
<i class="iconfont icon-star-bold-fill"></i>
</view>
</view>
<view class="star-fill abs" :style="{width: detail.star_percent}">
<view class="flex-warp">
<view class="item-star flex-center" v-for="(aitem,aindex) in 5" :key="aindex">
<i class="iconfont icon-star-bold-fill icon-font-color"
:style="{backgroundImage: '-webkit-linear-gradient(90deg, #FDCD47, #FFC000)'}"></i>
</view>
</view>
</view>
</view>
<i class="iconfont icon-right"></i>
</view>
<view @tap.stop="toMap" class="flex-y-center f-caption c-caption mt-sm"><i
class="iconfont icon-dingwei mr-sm"></i>
<view class="addr-text ellipsis">{{detail.address}}</view>
</view>
</view>
</view>
</view>
</view>
<view class="space-sm fill-base"></view>
<tab @change="handerTabChange" :list="tabList" :activeIndex="activeIndex" :activeColor="primaryColor"
:width="100/tabList.length + '%'" height="100rpx"></tab>
<view class="b-1px-b"></view>
</fixed>
<block v-if="tabList[activeIndex].id == 1">
<view class="flex-warp">
<view @tap.stop="goDetail(index)" class="goods-item fill-base mt-md ml-md box-shadow radius-16"
v-for="(item,index) in list.data" :key="index">
<image mode="aspectFill" lazy-load class="cover" :src="item.cover"></image>
<view class="pd-md">
<view class="f-paragraph c-title ellipsis">{{item.goods_name}}</view>
<view class="flex-y-baseline">
<view class="f-title c-warning">¥{{item.show_price}}</view>
<view class="f-caption c-caption text-delete ml-sm">¥{{item.show_init_price}}</view>
</view>
<view class="f-caption c-caption">已售 {{item.all_sale_count}}</view>
</view>
</view>
</view>
</block>
<block v-if="tabList[activeIndex].id == 2">
<view @tap.stop="goDetail(index)" class="land-item fill-base mt-md ml-md mr-md box-shadow radius-16"
v-for="(item,index) in list.data" :key="index">
<image mode="aspectFill" lazy-load class="cover" :src="item.cover"></image>
<view class="pd-lg">
<view class="f-title c-title">{{item.title}}</view>
<view class="f-caption c-caption ellipsis-2">
<text decode="emsp" style="word-break:break-all;">{{item.desc}}</text>
</view>
<view class="flex-between mt-md">
<view class="flex-y-baseline">
<view class="f-lg-title c-warning">¥{{item.min_price}}</view>
<view class="f-caption c-caption ml-sm"></view>
</view>
<view class="common-btn flex-center f-paragraph c-base radius-4"
:style="{background:primaryColor}">
立即租赁</view>
</view>
</view>
</view>
</block>
<block v-if="tabList[activeIndex].id == 3">
<view @tap.stop="goDetail(index)" class="claim-item fill-base mt-md ml-md mr-md box-shadow radius-24"
v-for="(item,index) in list.data" :key="index">
<view class="flex-center pd-lg">
<image mode="aspectFill" lazy-load class="cover fill-body radius-24" :src="item.cover"></image>
<view class="flex-1 ml-lg max-380">
<view class="f-title c-title ellipsis-2">{{item.title}}</view>
<view class="f-paragraph c-title">{{`${item.start_time} ${item.end_time}`}}</view>
<view class="flex-between mt-sm mb-md">
<view class="line-item rel">
<view class="cur abs" :style="{width: item.precent}"></view>
</view>
<view class="c-caption" style="font-size: 20rpx;">已认养{{item.precent}}</view>
</view>
<view class="count-list flex-warp">
<view class="count-item">
<view class="flex-y-center f-caption c-caption">
<view class="dot radius"></view>品种
</view>
<view class="f-paragraph c-title ellipsis">{{item.breed}}</view>
</view>
<view class="count-item">
<view class="flex-y-center f-caption c-caption">
<view class="dot radius"></view>周期
</view>
<view class="f-paragraph c-title ellipsis">{{item.cycle}}</view>
</view>
<view class="count-item">
<view class="flex-y-center f-caption c-caption">
<view class="dot radius"></view>产量
</view>
<view class="f-paragraph c-title">{{item.output}}kg</view>
</view>
</view>
</view>
</view>
<view class="flex-between ml-lg mr-lg pt-lg pb-lg b-1px-t">
<view class="flex-y-baseline">
<view class="f-lg-title c-warning">¥{{item.price}}</view>
<view class="f-caption c-caption ml-sm">/{{item.unit}}</view>
</view>
<view class="common-btn flex-center f-paragraph c-base radius-4" :style="{background:primaryColor}">
立即认养</view>
</view>
<view class="flex-y-center pl-lg pr-lg pb-lg">
<view class="flex-warp">
<block v-for="(item,index) in item.count.user_list" :key="index">
<view class="avatar-group" v-if="index<6">
<image mode="aspectFill" lazy-load class="abs avatar fill-body radius"
:src="item.avatarUrl"></image>
</view>
</block>
</view>
<view class="flex-y-center f-caption c-title pr-lg" :class="[{'ml-lg':item.count.user_count>0}]"
style="height: 48rpx;">
已有{{item.count.user_count}}人参与</view>
</view>
</view>
</block>
<block v-if="tabList[activeIndex].id == 4">
<view class="flex-warp ml-md mr-md">
<view @tap.stop="goDetail(index)" class="monitor-item rel fill-base box-shadow radius-16"
:class="[{'mr-md':index%2==0}]" v-for="(item,index) in list.data" :key="index">
<view class="live-item flex-center abs">
<image mode="aspectFill" lazy-load class="live-img" src="/static/image/home/live.png"></image>
<view class="f-icontext c-base">LIVE</view>
</view>
<view class="view-item flex-center abs c-base">
<i class="iconfont icon-chakan mr-sm"></i>
<view class="f-icontext">{{item.iv || 0}}</view>
</view>
<image mode="aspectFill" lazy-load class="cover" :src="item.cover"></image>
<view class="content">
<view class="f-paragraph c-title ellipsis">{{item.title}}</view>
<view class="flex-y-center f-caption c-caption"><i class="iconfont icon-dingwei mr-sm"></i>
<view class="max-300 ellipsis">{{item.address}}</view>
</view>
</view>
</view>
</view>
</block>
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
</load-more>
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
<view class="space-footer"></view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from "vuex"
export default {
components: {},
data() {
return {
options: {},
detail: {},
activeIndex: 0,
tabList: [{
id: 1,
title: '商品'
}, {
id: 2,
title: '土地',
}, {
id: 3,
title: '认养',
}, {
id: 4,
title: '监控',
}],
param: {
page: 1,
},
list: {
data: []
},
loading: true,
popupInfo: {},
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,
}),
onLoad(options) {
this.$util.showLoading()
this.options = options
this.initIndex()
},
onPullDownRefresh() {
// #ifndef APP-PLUS
uni.showNavigationBarLoading()
// #endif
this.initRefresh()
uni.stopPullDownRefresh()
},
onReachBottom() {
if (this.list.current_page >= this.list.last_page || this.loading) return
this.param.page = this.param.page + 1
this.loading = true
this.getList()
},
onShareAppMessage(e) {
let {
id: pid
} = this.userInfo
let {
id,
title,
cover: imageUrl
} = this.detail
let path = `/home/pages/farm/detail?id=${id}&pid=${pid}`
this.$util.log(path)
return {
title,
imageUrl,
path,
}
},
methods: {
...mapActions(['getConfigInfo']),
async initIndex() {
let {
id
} = this.options
let data = await this.$api.home.farmerInfo({
id
})
data.is_open = 1
data.star_percent = (data.star * 1 / 5 * 100).toFixed(2) + '%'
this.detail = data
this.getList()
this.$util.hideAll()
},
initRefresh() {
this.param.page = 1
this.initIndex()
},
handerTabChange(index) {
this.activeIndex = index
this.$util.showLoading()
this.param.page = 1
this.list.data = []
this.getList()
},
async getList() {
let {
list: oldList,
tabList,
activeIndex
} = this
let param = this.$util.deepCopy(this.param)
let {
id: farmer_id
} = this.options
let {
id
} = tabList[activeIndex]
if (id === 4) {
param.sort = 1
}
param = Object.assign({}, param, {
farmer_id,
});
let method = {
1: {
key: 'shop',
model: 'goodsList'
},
2: {
key: 'land',
model: 'landList'
},
3: {
key: 'claim',
model: 'claimList'
},
4: {
key: 'home',
model: 'monitorList'
}
}
let {
key,
model
} = method[id]
let newList = await this.$api[key][model](param)
if (id == 3) {
newList.data.map(item => {
let {
stock,
sale_num
} = item
item.precent = (sale_num / (stock + sale_num) * 100).toFixed(2) + '%'
})
}
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()
},
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
})
},
goDetail(index) {
let {
id
} = this.list.data[index]
let {
id: type
} = this.tabList[this.activeIndex]
let arr = {
1: '/shop/pages/detail',
2: '/land/pages/detail',
3: '/claim/pages/detail',
4: '/home/pages/monitor/detail',
}
let url = `${arr[type]}?id=${id}`
this.$util.goUrl({
url
})
}
}
}
</script>
<style lang="scss">
.land-order-detail {
.farm-item {
.cover {
width: 160rpx;
height: 160rpx;
}
.icon-dingwei,
.icon-right {
font-size: 24rpx;
}
.status-btn {
width: 80rpx;
height: 36rpx;
font-size: 20rpx;
}
.max-title {
max-width: 370rpx;
}
.addr-text {
max-width: 420rpx;
}
}
.goods-item {
width: 345rpx;
.cover {
width: 345rpx;
height: 345rpx;
border-radius: 15rpx 15rpx 0 0;
}
}
.land-item {
.cover {
width: 100%;
height: 345rpx;
border-radius: 15rpx 15rpx 0 0;
}
}
.claim-item {
.cover {
width: 240rpx;
height: 240rpx;
}
.line-item {
width: 230rpx;
height: 15rpx;
background: rgba(112, 152, 64, 0.2);
border-radius: 8rpx;
.cur {
top: 0;
left: 0;
height: 15rpx;
background: linear-gradient(0deg, #709840 0%, #91C84E 100%);
border-radius: 8rpx;
}
}
.count-list {
.count-item {
width: 33.33%;
.dot {
width: 10rpx;
height: 10rpx;
background: #B3D465;
margin-right: 10rpx;
}
}
}
}
.monitor-item {
width: 345rpx;
margin-top: 24rpx;
.live-item {
top: 10rpx;
left: 10rpx;
width: 109rpx;
height: 38rpx;
background: rgba(0, 0, 0, 0.3);
border-radius: 18rpx;
.live-img {
top: 0;
width: 38rpx;
height: 38rpx;
}
.f-icontext {
margin-left: 10rpx;
width: 61rpx;
}
}
.view-item {
top: 0;
right: 0;
width: 137rpx;
height: 51rpx;
background: rgba(0, 0, 0, 0.3);
border-radius: 0 15rpx 0 0;
}
.cover {
width: 345rpx;
height: 190rpx;
border-radius: 15rpx 15rpx 0 0;
}
.content {
padding: 24rpx;
.iconfont {
font-size: 26rpx;
}
}
}
}
</style>