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

607 lines
16 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-home" v-if="isLoad">
<uni-nav-bar :fixed="true" :shadow="false" :statusBar="true" :onlyLeft="true" color="#fff"
:backgroundColor="scrollTop < 20 ?``:primaryColor">
<view @tap.stop="toChooseLocation" class="flex-y-center" slot="left">
<i class="iconfont icon-dingwei mr-sm"></i>
<view class=" max-400 ellipsis">
{{location.address ?location.address : isLoad ? '定位失败' : '定位中...'}}
</view>
</view>
</uni-nav-bar>
<view :style="{height:`${configInfo.navBarHeight}px`}"></view>
<view mode="aspectFill" lazy-load class="home-index-bg abs"></view>
<view @tap.stop="$util.toCheckLogin({url:`/home/pages/search`})" class="pt-md pl-md pr-md">
<search :padding="0" :radius="10" backgroundColor="rgba(240,240,240,0.2)"
searchColor="rgba(240,240,240,0.2)" frontColor="#fff" textAlign="center" placeholder="请输入商品名称"></search>
</view>
<view class="mt-lg ml-md mr-md" v-if="detail.banner.rotation.length > 0">
<banner @change="goBanner" :list="detail.banner.rotation" :margin="0" :autoplay="true" :borderRadius="25"
:height="286" :indicatorActiveColor="primaryColor"></banner>
</view>
<view @tap="$util.toCheckLogin({url:`/home/pages/welfare?type=2`})"
class="notice-info flex-center mt-md pd-md fill-base">
<image mode="aspectFill" lazy-load class="notice-img" src="/static/image/home/notice.png">
</image>
<view class="ml-sm infomation-left"></view>
<view class="flex-1 ml-md">
<swiper :autoplay="true" :circular='true' :vertical="true" class="roller-box" :interval="2000">
<swiper-item v-for="(item,index) in detail.system_list" :key="index">
<view class="roller-item flex-between f-caption c-desc">
<view class="ellipsis">{{item.title}}</view>
</view>
</swiper-item>
</swiper>
</view>
</view>
<view @tap.stop="goAbout"
class="weather-info flex-warp rel pr-md pl-md pb-md f-icontext c-desc"
v-if="detail.weather.observe.update_time">
<view class="flex-y-baseline">
<view class="flex-center mr-lg">
<view class="number">{{detail.weather.observe.degree}}°</view>
</view>
<view class="weather">{{today}} {{detail.weather.observe.weather}}</view>
</view>
<view class="flex-warp">
<view class="mr-lg">
温度变化{{`${detail.weather.forecast_24h.min_degree}°~${detail.weather.forecast_24h.max_degree}°`}}
</view>
<view class="mr-lg">风力{{detail.weather.observe.wind_power}}</view>
<view class="mr-lg">湿度{{detail.weather.observe.humidity}}%</view>
<view>气压{{detail.weather.observe.pressure}}hPa</view>
</view>
<view class="about-info flex-center abs" :style="{background:primaryColor}">
<image mode="aspectFill" lazy-load class="weather-img ml-sm mr-md"
:src="`${weather_img}${time_key}/${detail.weather.observe.weather_code}.png`">
</image>
</view>
</view>
<view class="flex-warp fill-base pb-md">
<view @tap.stop="toMenu(index)" class="menu-item flex-center flex-column pb-lg"
v-for="(item,index) in menuList" :key="index">
<image mode="aspectFill" lazy-load class="menu-img radius"
:src="`/static/image/home/${item.img_name}.png`">
</image>
<view class="f-caption c-title mt-sm">{{item.title}}</view>
</view>
</view>
<view @tap="$util.toCheckLogin({url:`/shop/pages/coupon`})"
class="advertisement-info fill-base pr-md pl-md pb-md" v-if="detail.coupon_total">
<image mode="aspectFill" lazy-load class="coupon-img"
src="/static/image/home/xrhb.png">
</image>
</view>
<view class="advertisement-info fill-base pr-md pl-md pb-md"
v-if="detail.banner.poster.length > 0">
<banner @change="goBanner" :list="detail.banner.poster" :margin="0" :autoplay="true" :borderRadius="25"
:height="285" :indicatorActiveColor="primaryColor"></banner>
</view>
<view class="mt-md pd-lg fill-base">
<view @tap="$util.toCheckLogin({url:`/shop/pages/hot-goods`})" class="flex-center">
<view class="flex-1 f-paragraph text-bold">热门商品</view>
<view class="flex-y-center c-caption f-caption">查看更多<i class="iconfont icon-right"></i></view>
</view>
<block v-for="(item,index) in detail.hot_goods" :key="index">
<view @tap.stop="goDetail(1,'hot_goods',index)" class="goods-item flex-center mt-lg">
<image mode="aspectFill" lazy-load class="cover radius-16" :src="item.cover"></image>
<view class="flex-1 ml-lg">
<view class="flex-center">
<view class="flex-1">
<view class="f-paragraph c-title mt-sm mb-sm max-400 ellipsis">{{item.goods_name}}
</view>
<view class="flex-y-baseline f-caption c-warning">¥<view class="f-title">
{{item.show_price}}
</view>
</view>
<view class="f-caption c-caption text-delete">¥{{item.show_init_price}}</view>
</view>
<image lazy-load class="add-car-img" src="/static/image/shop/add-car.png">
</image>
</view>
</view>
</view>
</block>
</view>
<view class="mt-md pt-lg pb-lg fill-base">
<view @tap="$util.toCheckLogin({url:`/shop/pages/choose-store`})" class="pl-lg pr-lg flex-center">
<view class="flex-1 f-paragraph text-bold">热门店铺</view>
<view class="flex-y-center c-caption f-caption">查看更多<i class="iconfont icon-right"></i></view>
</view>
<scroll-view scroll-x class="hot-shop-list pt-lg pl-lg" :scroll-with-animation="true"
v-if="detail.store_list.length > 0">
<block v-for="(item,index) in detail.store_list" :key="index">
<view @tap.stop="goDetail(2,'store_list',index)" class="hot-shop-item mr-lg radius-16">
<image mode="aspectFill" lazy-load class="cover box-shadow" :src="item.cover"></image>
<view class="pd-md">
<view class="flex-between f-caption c-desc">
<view class="business-tag flex-center radius-4" :style="{color:primaryColor}">营业中</view>
<view class="pl-sm ellipsis">{{item.distance}}</view>
</view>
<view class="f-paragraph c-title mt-md ellipsis-2">{{item.title}}</view>
</view>
</view>
</block>
</scroll-view>
</view>
<view class="mt-md pd-lg fill-base">
<view @tap="$util.toCheckLogin({url:`/home/pages/welfare`})" class="flex-center">
<view class="flex-1 f-paragraph text-bold">公益栏目</view>
<view class="flex-y-center c-caption f-caption">查看更多<i class="iconfont icon-right"></i></view>
</view>
<block v-for="(item,index) in detail.welfare_list" :key="index">
<view @tap.stop="goDetail(3,'welfare_list',index)" class="welfare-item flex-center mt-lg">
<image mode="aspectFill" lazy-load class="cover radius-16" :src="item.cover"></image>
<view class="flex-1 ml-lg">
<view class="f-title c-title mb-md ellipsis">{{item.title}}</view>
<view class="f-caption c-caption">{{item.create_time_text}}</view>
</view>
</view>
</block>
</view>
<view class="space-footer"></view>
</view>
</template>
<script>
import {
mapState,
mapActions,
mapMutations
} from "vuex"
import uniSegmentedControl from "@/components/uni-segmented-control.vue"
export default {
components: {
uniSegmentedControl
},
data() {
return {
scrollTop: 0,
options: {},
weather_img: `https://mat1.gtimg.com/pingjs/ext2020/weather/pc/icon/currentweather/`,
menuList: [{
id: 1,
title: '土地租赁',
img_name: 'land',
url: '/pages/land'
}, {
id: 2,
title: '农业认养',
img_name: 'claim',
url: '/pages/claim'
}, {
id: 3,
title: '视频监控',
img_name: 'monitor',
url: '/home/pages/monitor/list'
}, {
id: 4,
title: '农场商城',
img_name: 'shop',
url: '/pages/shop'
}, {
id: 5,
title: '会员充值',
img_name: 'stored',
url: '/mine/pages/balance/list'
}, {
id: 6,
title: '众筹认养',
img_name: 'collage',
url: '/claim/pages/collage/list'
}, {
id: 7,
title: '限时秒杀',
img_name: 'seckill',
url: '/shop/pages/seckill'
}, {
id: 8,
title: '积分商城',
img_name: 'integral',
url: '/shop/pages/integral/list'
}, {
id: 9,
title: '农场签到',
img_name: 'sign',
url: '/shop/pages/sign'
}, {
id: 10,
title: '积分抽奖',
img_name: 'luck',
url: '/shop/pages/luck'
}],
isLoad: false,
loading: false,
detail: {},
about_us: 0,
weather: {},
store_list: [],
today: '',
cur_time: '',
time_key: 'day'
}
},
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() {
console.log("====onload")
if (this.isLoad) return
this.initIndex()
},
async onShow() {
let cur_time = this.$util.DateToUnix(this.$util.formatTime(new Date(), 'YY-M-D h:m:s'))
let time = this.$util.DateToUnix(this.$util.formatTime(new Date(), 'YY-M-D'))
let min = time + 8 * 3600 - 1
let max = time + 19 * 3600 + 1
this.time_key = cur_time > min && cur_time < max ? 'day' : 'night'
if (!this.isLoad || this.location.lat) return
let [err, result] = await uni.getSetting()
if (err || !result.authSetting[`scope.userLocation`]) return
this.initIndex()
},
onPageScroll(e) {
this.scrollTop = e.scrollTop
},
onPullDownRefresh() {
// #ifndef APP-PLUS
uni.showNavigationBarLoading()
// #endif
this.initRefresh()
uni.stopPullDownRefresh()
},
onShareAppMessage(e) {
let {
id: pid
} = this.userInfo
let path = `/pages/home?pid=${pid}`
this.$util.log(path)
return {
title: '',
imageUrl: '',
path,
}
},
methods: {
...mapActions(['getConfigInfo']),
...mapMutations(['updateUserItem']),
async initIndex(refresh = false) {
this.cur_time = this.$util.formatTime(new Date(), 'YY-M-D')
this.today = this.$util.formatTime(new Date(), 'YY年M月D日')
if (!this.configInfo.id || refresh) {
await this.getConfigInfo()
if (this.loginType == 'apple') {
this.updateUserItem({
key: 'isShowLogin',
val: false
})
}
}
await this.getLocation()
if (!refresh) {
this.$util.showLoading()
}
let {
lat = 0,
lng = 0
} = this.location
let [detail, coupon] = await Promise.all([this.$api.home.index({
lat,
lng
}), this.$api.shop.couponList()])
detail.coupon_total = coupon.total
let {
status = 0,
data
} = detail.weather
if (status == 200) {
let {
forecast_24h
} = data
let cur_day = forecast_24h.filter(item => {
return item.time == this.cur_time
})
data.forecast_24h = cur_day.length > 0 ? cur_day[0] : []
detail.weather = data
}
this.detail = detail
this.isLoad = true
this.loading = false
this.$util.hideAll()
},
initRefresh() {
this.initIndex(true)
},
async getLocation() {
let {
location
} = this
if (!location.lat) {
try {
// #ifdef H5
// H5环境下先检查缓存的位置信息
let cachedLocation = uni.getStorageSync('cached_location');
let cacheTime = uni.getStorageSync('location_cache_time');
let now = new Date().getTime();
// 如果有缓存且缓存时间不超过30分钟直接使用缓存的位置
if (cachedLocation && cacheTime && (now - cacheTime) < 30 * 60 * 1000) {
location = cachedLocation;
} else {
// 没有缓存或缓存过期,才获取新位置
location = await this.$util.getBmapLocation();
}
// #endif
// #ifndef H5
// 非H5环境直接获取位置
location = await this.$util.getBmapLocation();
// #endif
this.updateUserItem({
key: 'location',
val: location
})
} catch (error) {
console.log('获取位置失败:', error);
// 获取位置失败时不更新location使用默认值
this.$util.showToast({
title: '获取位置失败,使用默认位置'
});
}
}
},
// 选择地区
async toChooseLocation(e) {
await this.$util.checkAuth({
type: 'userLocation'
})
let [, {
address = '',
longitude: lng = 0,
latitude: lat = 0
} = {}] = await uni.chooseLocation();
if (!lng) return
let location = {
lng,
lat,
address
}
this.updateUserItem({
key: 'location',
val: location
})
this.initRefresh()
},
toMenu(index) {
let {
title,
url,
} = this.menuList[index]
let arr = ['土地租赁', '农业认养']
let openType = arr.includes(title) ? 'switchTab' : title == '农场商城' ?
'reLaunch' : 'navigateTo'
this.$util.toCheckLogin({
url,
openType
})
},
// 轮播图/广告图跳转
goBanner(e) {
// connect_type 1店铺2文章3图片4店铺
let {
connect_type,
text_id: id = 0,
img: current
} = e.item
switch (connect_type) {
case 1:
case 2:
case 4:
let page = {
1: `/home/pages/farm/detail?id=${id}`,
2: `/home/pages/article?id=${id}&type=1`,
4: `/shop/pages/store?id=${id}`
}
let url = page[connect_type]
this.$util.toCheckLogin({
url
})
break;
case 3:
this.$util.previewImage({
current,
urls: [current]
})
break;
}
},
goAbout() {
if (!this.detail.about_us) return
this.$util.toCheckLogin({
url: `/home/pages/about`
})
},
// 商品/店铺/公益栏目详情
async goDetail(type, key, index) {
let {
id
} = this.detail[key][index]
let url = ''
switch (type) {
case 1:
url = `/shop/pages/detail?id=${id}`
break
case 2:
url = `/shop/pages/store?id=${id}`
break
case 3:
url = `/home/pages/article?id=${id}&type=2`
break
}
this.$util.toCheckLogin({
url
})
}
}
}
</script>
<style lang="scss">
.pages-home {
.icon-right {
font-size: 24rpx;
}
.menu-item {
width: 20%;
.menu-img {
width: 96rpx;
height: 96rpx;
}
}
.notice-info {
height: 110rpx;
.notice-img {
width: 128rpx;
height: 48rpx;
}
.infomation-left {
height: 48rpx;
border-right: 0.03125rem solid #e1e6ec;
}
.roller-box {
height: 40rpx;
.roller-item {
height: 40rpx;
line-height: 1;
}
}
}
.weather-info {
height: 168rpx;
background: #ffffff;
.number {
font-size: 48rpx;
color: #FEB23A;
}
.weather {
color: #FEB23A;
}
.weather-img {
width: 50rpx;
height: 50rpx;
}
.about-info {
right: 0rpx;
width: 84rpx;
height: 84rpx;
border-radius: 5000rpx;
margin-right: 30rpx;
.about-img {
width: 102rpx;
height: 25rpx;
margin: 0 8rpx;
}
.about-right-img {
width: 34rpx;
height: 25rpx;
}
}
}
.advertisement-info {
.coupon-img {
width: 100%;
height: 180rpx;
}
}
.goods-item {
.cover {
width: 180rpx;
height: 170rpx;
}
.add-car-img {
width: 70rpx;
height: 70rpx;
}
}
.hot-shop-list {
white-space: nowrap;
width: calc(100% - 30rpx);
.hot-shop-item {
width: 281rpx;
height: 353rpx;
background: #F9FAF9;
display: inline-block;
.cover {
width: 281rpx;
height: 175rpx;
border-radius: 15rpx 15rpx 0 0;
}
.business-tag {
width: 86rpx;
height: 34rpx;
background: rgba(52, 162, 99, 0.1);
}
}
}
.home-index-bg {
background: rgb(57, 181, 74);
height: 15.625rem;
width: 100%;
top: 0;
border-radius: 0 0 5% 5%;
z-index: -1;
}
.welfare-item {
.cover {
width: 180rpx;
height: 160rpx;
}
.ellipsis {
max-width: 480rpx;
}
}
}
</style>