Files
frontend-app/pages/home/home.vue
T
2025-08-06 22:24:53 +08:00

876 lines
24 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="home_warp">
<!-- 带背景的头部 -->
<view class="home_header_warp"></view>
<view class="home_content_z_warp">
<view class="header_title_warp">
<!-- <up-image src="/static/home/logo.png" width="86" height="30" bgColor="#f1f6ff00"></up-image> -->
<!-- <view class="header_right_warp"> -->
<view class="language_warp" style="width: 100%;justify-content: flex-start;" @click="jumpSearch">
<view style="margin-top: 10rpx;">
<up-image src="/static/home/search_b.png" width="20" height="20" bgColor="#f1f6ff00"></up-image>
</view>
<text class="search_msg_warp">搜索</text>
</view>
<!-- <view class="language_warp" @click="languageShow = true">
<text>CN</text>
<up-image src="/static/common/down.png" width="10" height="10" bgColor="#f1f6ff00"></up-image>
</view> -->
<!-- </view> -->
</view>
<!-- banner图 -->
<!-- <view style="padding: 0 30rpx;">
<up-swiper
:list="swiperList"
height="120"
radius="10"
@change="e => currentNum = e.current"
bgColor="#ffffff00"
>
<template #indicator>
<view
class="indicator-num"
>
<text class="indicator-num__text">{{ currentNum + 1 }}/{{ swiperList.length }}</text>
</view>
</template>
</up-swiper>
</view> -->
<!-- logo分类 -->
<view class="logo_banner">
<view style="padding: 20rpx 0 0 20rpx;">
<up-image src="/static/home/logo_banner.png" width="108" height="16" bgColor="#f1f6ff00"></up-image>
<view class="logo_banner_title">TB聚合商城</view>
<view class="logo_banner_msg">MALL+RWA+DAO的共创共享全球产业生态</view>
</view>
<up-image src="https://cex-pub.s3.ap-southeast-1.amazonaws.com/static/logo_banner2.png" width="140" height="98"
bgColor="#f1f6ff00"></up-image>
</view>
<!-- 分类 -->
<view class="home_sort_warp">
<view class="sort_comm_warp" v-if="sortList && sortList.length !== 0">
<view v-for="item in sortList" :key="item.id" class="sort_item_comm" @click="jumpSort(item)">
<up-image :src="item.icon" width="40" height="32" bgColor="#f1f6ff00"></up-image>
<view class="sort_item_title_comm">{{ item.name }}</view>
</view>
</view>
<view v-else class="not_order_warp">
<up-image src="https://cex-pub.s3.ap-southeast-1.amazonaws.com/static/not_order.png" width="80" height="80"
bgColor="#f1f6ff00"></up-image>
<view class="not_order_msg_warp">暂无分类</view>
</view>
</view>
<!-- 带灰色背景的内容 -->
<view class="home_content_warp">
<!-- 爆款专区-->
<view class="product_comm hx_warp" v-if="faddishProduct && faddishProduct.length !== 0">
<view class="product_title">
<view class="product_title_left">
<text class="product_title_yp">信任桥优品</text>
<up-image src="/static/home/youxuan.png" width="10" height="10" bgColor="#f1f6ff00"></up-image>
<text style="margin-left: 6rpx;color: #FFFFFF;">品牌5折秒杀福利</text>
</view>
<view class="product_title_f" style="font-weight: bold;" @click="jumpWelcome">
<text style="">立即抢购</text>
<view style="margin: 6rpx 0 0 6rpx;"><up-image src="/static/common/right_y_st3.png" width="12" height="12"
bgColor="#f1f6ff00"></up-image></view>
</view>
</view>
<view
:class="faddishProduct && faddishProduct.length > 2 ? 'product_content product_content2' : 'product_content'">
<up-loading-icon :show="productLoading"></up-loading-icon>
<view :class="faddishProduct && faddishProduct.length > 2 ? 'product_item2' : 'product_item'"
v-for="item in faddishProduct" :key="item.id" @click="jumpInfo(item)">
<up-image :src="item.url" width="100%" height="130" bgColor="#f1f6ff00" shape="square"
radius='15'></up-image>
<view class="product_f_item">
<view class="product_f_item_name">{{ item.title }}</view>
<view class="product_f_item_price product_f_item_price_hx">优选价{{ item.adPrice }}元</view>
</view>
</view>
</view>
</view>
<!-- 积分兑换,红包抽奖 -->
<view class="min_card_warp">
<!-- 积分兑换 -->
<view class="min_card_item" @click="jumpIntegral">
<!-- <up-image src="/static/home/min_card_jfdh.png" width="60" height="14" bgColor="#f1f6ff00" ></up-image> -->
<view class="min_card_item_content">
<view class="min_card_item_title">积分兑换</view>
<view class="content_msg">
<view>好物随心兑</view>
<view class="content_msg_but">
立即抢购
<view style="margin-top: 6rpx;margin-left: 4rpx;"><up-image src="/static/common/right_y.png"
width="10" height="10" bgColor="#f1f6ff00"></up-image></view>
</view>
</view>
</view>
<up-image src="/static/home/min_card_jfdh_2.png" width="66" height="66" bgColor="#f1f6ff00"></up-image>
</view>
<!-- 红包抽奖 -->
<view class="min_card_item" @click="jumpTurntable">
<!-- <up-image src="/static/home/min_card_hbcj.png" width="60" height="14" bgColor="#f1f6ff00" ></up-image> -->
<view class="min_card_item_content">
<view class="min_card_item_title">红包抽奖</view>
<view class="content_msg">
<view>现金红包等你拿!</view>
<view class="content_msg_but">
立即抢购
<view style="margin-top: 6rpx;margin-left: 4rpx;"><up-image src="/static/common/right_y.png"
width="10" height="10" bgColor="#f1f6ff00"></up-image></view>
</view>
</view>
</view>
<up-image src="/static/home/min_card_hbcj_2.png" width="66" height="66" bgColor="#f1f6ff00"></up-image>
</view>
</view>
<!-- 好物优选 -->
<view class="product_comm yx_warp" v-if="yxProduct && yxProduct.length !== 0" @click="jumpPrdference">
<view class="product_title">
<view class="product_title_left">
<text class="product_title_z">平价专区</text>
<text class="product_title_zk">4折起</text>
</view>
<view class="product_title_f" style="color: #7632FF;">
<text style="">立即抢购</text>
<view style="margin: 6rpx 0 0 6rpx;"><up-image src="/static/common/right_y_st4.png" width="10" height="10"
bgColor="#f1f6ff00"></up-image></view>
</view>
</view>
<view class="product_tips">平价专区 抢到就是赚到!</view>
<view
:class="yxProduct && yxProduct.length > 3 ? 'product_content_yx product_content2' : 'product_content_yx'">
<up-loading-icon :show="productLoading"></up-loading-icon>
<view :class="yxProduct && yxProduct.length < 4 ? 'product_item_yx product_item_yx2' : 'product_item_yx'"
v-for="item in yxProduct" :key="item.id">
<up-image :src="item.url" width="100%" height="80" bgColor="#f1f6ff00" shape="square"
radius='10'></up-image>
<!-- <view class="product_f_item">
<view class="product_f_item_name">{{item.title}}</view>
<view class="product_f_item_price product_f_item_price_yx">优选价{{item.adPrice}}元</view>
</view> -->
</view>
</view>
</view>
<!-- 为您精选 -->
<choiceness />
</view>
</view>
<!-- 暂未开放 -->
<up-modal :show="openShow" :showConfirmButton="false">
<view class="slot-content">
<view class="close_warp" @click="openShow = false;">
<up-image src="/static/common/close.png" width="20" height="20" bgColor="#f1f6ff00"></up-image>
</view>
<view class="content_">
<view class="content_1">温馨提示</view>
<view class="content_2">暂未开放</view>
</view>
<view class="but_">
<view class="but_copy" @click="openShow = false;">确定</view>
</view>
</view>
</up-modal>
<CustomTabBar :tabIndex="0" />
<up-action-sheet :actions="languageList" :show="languageShow" cancelText="取消"
@close="languageShow = false"></up-action-sheet>
<up-overlay :show="bannerShow">
<view class="up_content" @tap.stop>
<view class="uni-banner">
<view class="banner_box">
<view class="title_">发现新版本</view>
<view class="version_">
<view class="version_item">V{{ updateApkObj.versionCode || 100 }}</view>
</view>
<view class="conter">{{ updateApkObj.content }}</view>
<view class="banner_foot" v-if="!bannerPercentageShow">
<button @click="goUpdate(updateApkObj, platformType)" class="banner_foot_button">立即更新</button>
<view @click="bannerShow = false;" class="banner_foot_button_no" v-if="!updateApkObj.isForce">暂不更新</view>
</view>
<view v-else>
<up-line-progress :percentage="bannerPercentage" activeColor="#FF7C41"></up-line-progress>
<view class="banner_loading_msg">
更新中{{ bannerPercentage }}%
</view>
</view>
</view>
</view>
</view>
</up-overlay>
</view>
</template>
<script>
import choiceness from '@/components/choiceness/choiceness.vue';
import { searchList } from '@/api/product.js';
import { getCascadeCategory, checkAppVersion, getCarouselImage } from '@/api/common.js';
import { SEARCH_TYPE, APP_PAGE_TYPE } from '@/utils/enumUtils.js'
import CustomTabBar from '@/components/custom-tab-bar.vue'; // 引入自定义组件路径可能需要根据项目结构调整
import dayjs from 'dayjs';
import { comparisonVersionHandler } from '@/utils/index.js';
export default {
components: { choiceness, CustomTabBar },
data() {
return {
swiperList: [
],
currentNum: 0,
sortList: [],
languageShow: false,// 语言选项
languageList: [
{
name: '中文',
key: "CN"
}, {
name: '英文',
key: "EN"
},
],
currentLanguage: {},
yxProduct: [],// 好物优选列表
faddishProduct: [],// 爆款专区
hotList: [
{
id: 1,
name: "中文中文中文中文中文",
url: "/static/common/product_def.png",
price: 99,
}, {
id: 2,
name: "中文中文中文中文",
url: "/static/common/product_def.png",
price: 99,
}, {
id: 3,
name: "中文中文中文中文中文",
url: "/static/common/product_def.png",
price: 99,
}, {
id: 4,
name: "中文中文中文中文中文",
url: "/static/common/product_def.png",
price: 99,
},
],// 热门
productLoading: false,
openShow: false,
platformType: null,// 当前设备信息
bannerShow: false, // 是否需要強制更新app
type: '', // 设备类型 android:2, ios:1
updateApkObj: {}, // 后台数据
bannerPercentageShow: false,// 是否显示进度条
bannerPercentage: 0,// 进度条
}
},
onShow() {
/*#ifdef APP-PLUS*/
uni.hideTabBar({
animation: false
})
/*#endif*/
// 获取设备是安卓还是ios
const appUpdate = uni.getStorageSync('platform');
const versionUpdateTime = uni.getStorageSync("versionUpdateTime");
// #ifdef APP-PLUS
console.log("上次更新时间 versionUpdateTime", dayjs(versionUpdateTime).format("YYYY-MM-DD HH:mm:ss"));
console.log("当前时间戳", dayjs().format("YYYY-MM-DD HH:mm:ss"));
const time1 = dayjs(versionUpdateTime);// 上一次更新的时间
const time2 = dayjs();
const diff = time2.diff(time1);
if (!versionUpdateTime || diff > 5 * 60 * 1000) {
this.platformType = appUpdate == 'android' ? 'ANDROID' : 'IOS';
this.checkUpdate(); // 判断是否需要更新
} else {
console.log("不需要更新...");
}
// #endif
this.getSortList();
this.querySearchList(SEARCH_TYPE.SOMETHING);// 好物专区
this.querySearchList(SEARCH_TYPE.EXPLOSIVE);// 爆单专区
this.getCarouselImage();
},
mounted() {
},
methods: {
checkUpdate() {
const self = this,
localAppVersonName = uni.getStorageSync('version'),
localAppVerson = uni.getStorageSync('versionCode');
// #ifdef APP-PLUS
plus.runtime.getProperty(plus.runtime.appid, function (widgetInfo) {
const params = {
terminal: self.platformType,
versionCode: localAppVerson,
}
checkAppVersion(params).then(res => {
if (res && res.bizcode === 100) {
const data = res.data || {};
// app大版本更新,versionName:1.0.1 versionCode:102
if (data && Object.keys(data).length !== 0 && comparisonVersionHandler(localAppVerson, data.versionCode)) {
uni.hideTabBar() // 隐藏首页底部tabbar 按钮
self.updateApkObj = data;
self.bannerShow = true; // 显示弹窗
return;
} else {
return;
}
}
});
});
// #endif
},
// 安装
goUpdate(updateApkObj, platformType) {
const self = this;
if (platformType == 'ANDROID') {
// 弹出系统等待对话框
var dtask = plus.downloader.createDownload(updateApkObj.downloadUrl, {}, function (d, status) {
// 下载完成
if (status == 200) {
plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), { force: true }, function (resp) {
// 直接重启APP
uni.setStorageSync('versionUpdateTime', dayjs().valueOf()); // 记录升级的时间
plus.runtime.restart();
}, function (error) {
console.log("error", error);
uni.showToast({
title: error.message,
mask: false,
duration: 1500
});
});
} else {
self.bannerPercentageShow = false;
uni.showToast({
title: '更新失败',
mask: false,
duration: 1500
});
}
});
try {
dtask.start(); // 开启下载的任务
let prg = 0;
this.bannerPercentageShow = true;
dtask.addEventListener('statechanged', function (task, status) {
// 给下载任务设置一个监听 并根据状态 做操作
switch (task.state) {
case 1:
break;
case 2:
break;
case 3:
prg = parseInt((parseFloat(task.downloadedSize) / parseFloat(task.totalSize)) * 100);
self.bannerPercentage = prg;
break;
case 4:
plus.nativeUI.closeWaiting();
self.bannerShow = false; // 显示弹窗
break;
}
});
} catch (err) {
console.log("更新失败-03err", err);
plus.nativeUI.closeWaiting();
uni.showToast({
title: '更新失败-03',
mask: false,
duration: 1500
});
}
} else if (platformType == 'IOS') { // ios跳转到app store
plus.runtime.openURL(updateApkObj.downloadUrl);
}
},
// 查询轮播图
async getCarouselImage() {
const params = {
pageUi: APP_PAGE_TYPE.HOME,
}
const resp = await getCarouselImage(params);
if (resp && resp.bizcode === 100) {
const data = resp.data || [];
this.swiperList = data.length !== 0 ? data.map(obj => obj.carouselImage) : [];
}
},
jumpIntegral() {
uni.navigateTo({
url: '/pages/other_package/pointsRedemption/pointsRedemption',
})
},
jumpTurntable() {
uni.navigateTo({
url: '/pages/other_package/turntable/turntable?backPath=home',
})
},
jumpPrdference() {
uni.navigateTo({
url: '/pages/login_package/preference/preference',
})
},
jumpWelcome() {
uni.navigateTo({
url: '/pages/login_package/welcome/welcome',
// url:'/pages/customized_zone/customized_zone',
})
},
jumpSearch() {
uni.navigateTo({
url: '/pages/other_package/search/search',
})
},
/**
* 查询商品列表
*/
async querySearchList(type) {
this.productLoading = true;
const params = {
type,
page: 1,
pageSize: type === SEARCH_TYPE.SOMETHING ? 4 : 3,
}
const resp = await searchList(params);
if (resp && resp.bizcode === 100) {
if (type === SEARCH_TYPE.SOMETHING) {// 好物优选
this.yxProduct = resp.data;
} else if (type === SEARCH_TYPE.EXPLOSIVE) {// 爆单专区
this.faddishProduct = resp.data;
}
}
this.productLoading = false;
},
/**
* 查询分类列表
*/
async getSortList() {
const resp = await getCascadeCategory({ parentId: 0 });
if (resp && resp.bizcode === 100) {
this.sortList = resp.data.slice(0, 10);
}
},
// 跳转到分类栏目
jumpSort(item) {
uni.setStorageSync('sortId', item.id);
uni.switchTab({// 首页
url: '/pages/sort/sort',
})
},
// 跳转到商品详情
jumpInfo(item) {
uni.navigateTo({
url: '/pages/other_package/productInfo/productInfo?id=' + item.id,
})
}
}
}
</script>
<style lang="scss" scoped>
.home_warp {
background: $app-bj;
height: calc(100vh - 140rpx); // 140rpx 是底部的导航栏高度
overflow: auto;
position: relative;
}
.home_header_warp {
// background-color: #AC2A29FF;
// background: linear-gradient(0deg, $app-bj, #AC2A29FF);
background: linear-gradient(270deg, #AF39C4 0%, #7732FF 100%);
height: 500rpx;
padding: 100rpx 30rpx 0rpx;
}
.home_content_z_warp {
position: absolute;
top: 90rpx;
.header_title_warp {
display: flex;
margin-bottom: 30rpx;
padding: 0 30rpx;
}
.header_right_warp {
display: flex;
align-items: center;
width: calc(100% - 0rpx);
}
.language_warp {
display: flex;
justify-content: space-between;
align-items: center;
width: 100rpx;
padding: 10rpx 20rpx;
background: #ffffff30;
border-radius: 24rpx;
background: linear-gradient(270deg, #ae39c5, #7932fe) 2 2;
}
.search_msg_warp {
margin-left: 12rpx;
font-weight: 500;
font-size: 28rpx;
color: #ffffffb3;
}
}
.logo_banner {
display: flex;
justify-content: space-between;
padding: 0 30rpx;
color: #FFFFFF;
.logo_banner_title {
font-weight: bold;
font-size: 38rpx;
line-height: 36rpx;
margin: 20rpx 0;
}
.logo_banner_msg {
font-size: 22rpx;
}
}
.home_sort_warp {
// position: absolute;
top: 460rpx;
padding: 30rpx 30rpx 0;
width: calc(100% - 60rpx);
.sort_warp {
background: #ffffff;
padding: 20rpx;
border-radius: 20rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.sort_item {
width: 18%;
text-align: center;
margin-bottom: 20rpx;
}
.sort_item_title {
font-weight: 500;
font-size: 22rpx;
color: #333333;
}
}
}
.home_content_warp {
padding: 0 30rpx;
.product_comm {
border-radius: 30rpx;
padding: 10rpx;
color: #FFFFFF;
margin-top: 20rpx;
}
.yx_warp {
background: linear-gradient(270deg, #FDEFFF 0%, #EDE3FF 100%);
}
.hx_warp {
background: linear-gradient(270deg, #B164FB 0%, $app-zt-color 100%);
}
.product_title {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 20rpx;
}
.product_title_yp {
font-weight: 800;
font-size: 36rpx;
color: #FFFFFF;
margin-right: 10rpx;
}
.product_title_z {
font-weight: 800;
font-size: 36rpx;
color: #333333FF;
margin-right: 10rpx;
}
.product_title_zk {
background: #b164fb45;
border-radius: 6rpx;
padding: 2rpx 20rpx;
color: $app-zt-color;
}
.product_title_left {
font-size: 20rpx;
display: flex;
align-items: center;
}
.product_title_f {
font-size: 20rpx;
color: #FFFFFF;
margin-left: 10rpx;
display: flex;
align-items: center;
}
.product_content_yx {
display: flex;
padding: 20rpx;
}
.product_content {
background-color: #FFFFFF;
padding: 20rpx;
border-radius: 24rpx;
display: flex;
align-items: center;
}
.product_content2 {
justify-content: space-between;
}
.product_item {
width: 32%;
position: relative;
margin-right: 20rpx;
}
.product_item2 {
width: 32%;
position: relative;
}
.product_item_yx {
width: 23%;
position: relative;
}
.product_item_yx2 {
margin-right: 20rpx;
}
.product_f_item {
position: absolute;
bottom: 0;
width: calc(100% - 40rpx);
height: 66rpx;
background: #F0E7FE;
border-radius: 0rpx 0rpx 12rpx 12rpx;
border: 1rpx solid #FFFFFF;
padding: 10rpx 20rpx;
font-size: 18rpx;
color: #000000;
}
.product_f_item_name {
width: 172rpx;
white-space: nowrap;
/* 防止文本换行 */
overflow: hidden;
/* 隐藏溢出的文本 */
text-overflow: ellipsis;
/* 使用省略号表示溢出的内容 */
font-weight: bold;
}
.product_f_item_price {
text-align: center;
border-radius: 10rpx;
color: #FFFFFF;
margin-top: 10rpx;
padding: 2rpx 0;
}
.product_f_item_price_yx {
background: #FFBA41;
}
.product_f_item_price_hx {
background: linear-gradient(270deg, #AF39C4 0%, #7732FF 100%);
}
.product_tips {
font-size: 24rpx;
line-height: 40rpx;
margin-left: 20rpx;
background: linear-gradient(180deg, #B039C2 0%, #8B34E9 23%, #7632FF 100%);
-webkit-background-clip: text;
color: transparent;
display: inline-block;
}
// 积分兑换,红包
.min_card_warp {
display: flex;
justify-content: space-between;
margin-top: 20rpx;
.min_card_item {
padding: 20rpx;
width: 43%;
border-radius: 30rpx;
opacity: 0.8;
border-radius: 16rpx;
border: 1rpx solid #DFDFDF;
display: flex;
justify-content: space-between;
}
.min_card_item_content {
margin-top: 10rpx;
.min_card_item_title {
font-weight: bold;
font-size: 28rpx;
color: #000000;
}
.content_msg {
font-size: 20rpx;
color: #808080;
display: grid;
margin-top: 10rpx;
}
.content_msg_but {
display: flex;
align-items: center;
margin-top: 20rpx;
}
}
}
// 热门榜
.hot_warp {
background: #FFFFFF;
border-radius: 30rpx;
padding: 20rpx;
margin-top: 20rpx;
.hot_title_warp {
display: flex;
justify-content: space-between;
align-items: center;
.title_warp {
display: flex;
align-items: center;
}
.title_ {
font-weight: 800;
font-size: 36rpx;
color: #111111;
margin-right: 10rpx;
}
.good_warp {
display: flex;
align-items: center;
}
.good__msg_warp {
background: #FFF8F3;
/* border-radius: 18rpx; */
border-top: 2rpx solid $app-zt-color;
border-right: 2rpx solid $app-zt-color;
border-bottom: 2rpx solid $app-zt-color;
font-size: 20rpx;
color: $app-zt-color;
padding: 4rpx 14rpx 4rpx 20rpx;
margin-left: -6px;
border-radius: 0rpx 18rpx 18rpx 0rpx;
}
.more_warp {
display: flex;
font-size: 24rpx;
color: #666666;
}
}
.hot_content_warp {
display: flex;
justify-content: space-between;
margin-top: 20rpx;
.hot_item {
width: 24%;
}
.hot_item_name {
font-weight: 800;
font-size: 24rpx;
color: #000000;
width: 160rpx;
white-space: nowrap;
/* 防止文本换行 */
overflow: hidden;
/* 隐藏溢出的文本 */
text-overflow: ellipsis;
/* 使用省略号表示溢出的内容 */
}
.hot_item_price {
display: flex;
justify-content: center;
font-size: 20rpx;
color: $app-zt-color;
text-align: center;
margin-top: 10rpx;
}
}
}
// 哈希商学院
.business_school_warp {
margin-top: 20rpx;
height: 160rpx;
background-image: url("https: //cex-pub.s3.ap-southeast-1.amazonaws.com/static/result.png");
background-size: 100% 100%;
background-position: center;
/* 将图片居中显示 */
display: grid;
align-items: center;
padding: 0 40rpx;
color: rgba(255, 255, 255, 0.9);
border-radius: 20rpx;
.title {
font-weight: 800;
font-size: 32rpx;
// color: #0987F8;
}
.msg {
font-size: 20rpx;
// color: #666666;
display: flex;
align-items: center;
// margin-top: 10rpx;
}
}
}
</style>