Files
2025-12-22 17:13:05 +08:00

376 lines
9.6 KiB
Vue
Raw Permalink 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="pages-claim" v-if="isLoad">
<fixed :refresh="refresh">
<view class="fill-base">
<banner :list="banner" :margin="0" :autoplay="true" :borderRadius="0" :height="420"
:indicatorActiveColor="primaryColor" v-if="banner.length > 0"></banner>
<view class="fill-base flex-between b-1px-b">
<view style="width: 650rpx;">
<tab @change="handerTabChange($event,'activeIndex')" :list="tabList" :activeIndex="activeIndex"
:activeColor="primaryColor" height="100rpx"></tab>
</view>
<view @tap.stop="toShowRank" class="flex-center c-caption b-1px-l" style="width: 100rpx;">
<i class="iconfont icon-down-bold" :class="[{'rotate-180':show_rank_item}]"></i>
</view>
</view>
</view>
</fixed>
<uni-popup @change="popupChange" ref="rank_item" type="top" :custom="true">
<view :style="{height: banner.length > 0 ? '520rpx':'100rpx'}"></view>
<view class="pd-lg fill-base">
<view @tap.stop="handerTabChange(index,'rankInd')" class="f-paragraph c-title"
:class="[{'mt-md':index!=0}]" :style="{color:index==rankInd?primaryColor:''}"
v-for="(item,index) in rankList" :key="index">
{{item.title}}
</view>
</view>
</uni-popup>
<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-between pt-lg pl-lg pr-lg">
<view class="flex-y-center">
<image mode="aspectFill" lazy-load class="avatar mini radius" :src="item.farmer_info.cover"></image>
<view class="ml-lg max-446 ellipsis">{{item.farmer_info.title}}</view>
</view>
<i class="iconfont icon-right c-caption" style="font-size: 28rpx;"></i>
</view>
<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-sm 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>
<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,
mapMutations
} from "vuex"
export default {
components: {},
data() {
return {
isLoad: false,
options: {},
rankInd: 0,
rankList: [{
id: 1,
title: '综合排序'
}, {
id: 2,
title: '销量优先'
}, {
id: 3,
title: '距离优先'
}],
tabList: [],
activeIndex: 0,
cate_id: 0,
banner: [],
param: {
page: 1,
},
list: {
data: []
},
loading: true,
lockTap: false,
show_rank_item: false,
refresh: 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,
location: state => state.user.location,
loginType: state => state.user.loginType,
}),
async onLoad() {
if (this.isLoad) return
this.$util.showLoading()
this.initIndex()
},
async onShow() {
if (!this.isLoad || (this.location.lat && this.rankInd != 2)) return
let [err, result] = await uni.getSetting()
if (err || !result.authSetting[`scope.userLocation`]) return
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 path = `/pages/claim?pid=${pid}`
this.$util.log(path)
return {
title: '',
imageUrl: '',
path,
}
},
methods: {
...mapActions(['getConfigInfo']),
...mapMutations(['updateUserItem']),
async initIndex(refresh = false) {
if (!this.configInfo.id || refresh) {
await this.getConfigInfo()
if (this.loginType == 'apple') {
this.updateUserItem({
key: 'isShowLogin',
val: false
})
}
}
await this.getLocation()
let [banner, cate] = await Promise.all([this.$api.claim.claimBanner({
type: 3
}), this.$api.claim
.claimCateList({
type: 2
})
])
cate.unshift({
id: 0,
title: '全部'
})
this.banner = banner
this.tabList = cate
this.isLoad = true
this.refresh = false
this.param.page = 1
this.getList()
},
initRefresh() {
this.refresh = true
this.$refs.rank_item.close()
this.initIndex(true)
},
async getLocation() {
let {
location
} = this
if (!location.lat) {
location = await this.$util.getBmapLocation()
this.updateUserItem({
key: 'location',
val: location
})
}
},
handerTabChange(index, type) {
this[type] = index
this.$refs.rank_item.close()
if (type == 'activeIndex') {
this.cate_id = this.tabList[index].id
}
this.$util.showLoading()
this.param.page = 1
this.list.data = []
this.getList()
},
toShowRank() {
let {
show_rank_item,
} = this
if (this.lockTap) return
this.lockTap = true
setTimeout(() => {
let methodModel = show_rank_item ? 'close' : 'open'
this.$refs.rank_item[methodModel]()
}, 500)
},
popupChange(e) {
let {
show
} = e
this.show_rank_item = show
setTimeout(() => {
this.lockTap = false
}, 200)
},
async getList() {
let {
list: oldList,
param,
tabList,
activeIndex,
rankList,
rankInd,
cate_id
} = this
let ind = tabList.findIndex(item => {
return item.id == cate_id
})
cate_id = ind == -1 ? 0 : cate_id
activeIndex = ind == -1 ? 0 : ind
this.cate_id = cate_id
this.activeIndex = activeIndex
let {
id: sort
} = rankList[rankInd]
if (sort == 3 && !this.location.lat) {
this.$util.hideAll()
await this.getLocation()
return
}
let {
lng = 0,
lat = 0
} = this.location
param = Object.assign({}, param, {
cate_id,
sort,
});
if (sort === 3) {
param.lat = lat
param.lng = lng
}
let newList = await this.$api.claim.claimList(param)
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 goDetail(index) {
let {
id
} = this.list.data[index]
let url = `/claim/pages/detail?id=${id}`
this.$util.toCheckLogin({
url
})
}
}
}
</script>
<style lang="scss">
.pages-claim {
.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;
}
}
}
}
}
</style>