Browse Source
feat(home): 新增走进菜大王页面及相关功能组件
feat(home): 新增走进菜大王页面及相关功能组件
- 添加走进菜大王主页面及详情页,支持图片和视频展示 - 实现视频播放和图片预览功能 - 新增相关API接口和样式文件 - 优化页面布局和交互体验master
7 changed files with 456 additions and 1 deletions
-
40libs/api/index.js
-
52pages/home/announcement.vue
-
81pages/home/enterKing/enterKing.scss
-
160pages/home/enterKing/enterKing.vue
-
9pages/home/enterKing/enterKingInfo.scss
-
115pages/home/enterKing/enterKingInfo.vue
-
BINstatic/enterVegetableKingInfo/video.png
@ -0,0 +1,52 @@ |
|||
<script setup> |
|||
import { onLoad } from "@dcloudio/uni-app"; |
|||
import { ref } from "vue"; |
|||
import navv from "@/components/nav/nav.vue"; |
|||
import topTitle from "@/components/topTitle/topTitle.vue"; |
|||
import { getNoticesApi } from "@/libs/api"; |
|||
|
|||
const notices = ref([]); |
|||
|
|||
async function getList() { |
|||
const res = await getNoticesApi(); |
|||
if (res.code !== "0") { |
|||
return; |
|||
} |
|||
notices.value = res.data; |
|||
} |
|||
|
|||
onLoad(() => { |
|||
getList(); |
|||
}); |
|||
</script> |
|||
|
|||
<template> |
|||
<navv> |
|||
<template #default="{ screen, status, menu }"> |
|||
<topTitle title="通知公告" /> |
|||
|
|||
<view |
|||
:style="{ |
|||
borderTop: 'solid 1px #F0f0f0', |
|||
width: '100%', |
|||
height: `${screen - status - (menu || 0)}px`, |
|||
overflowY: 'auto', |
|||
}" |
|||
> |
|||
<view v-for="(item, index) in notices" :key="index" class="notice"> |
|||
<rich-text :nodes="item" /> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
</navv> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped> |
|||
.notice{ |
|||
padding: 30rpx 30rpx; |
|||
border-bottom: solid 20rpx #f0f0f0; |
|||
line-height: 48rpx; |
|||
font-size: 32rpx; |
|||
/* background: #ffffff; */ |
|||
} |
|||
</style> |
|||
@ -0,0 +1,81 @@ |
|||
.grid-item{ |
|||
width: 33.33333333333%; |
|||
/* height: 63.5vw; */ |
|||
height: calc(100% /3); |
|||
float: left; |
|||
margin-bottom: 10rpx; |
|||
} |
|||
|
|||
.grid-item .box{ |
|||
position: relative; |
|||
} |
|||
|
|||
.grid-item .text-box{ |
|||
position: absolute; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
width: 100%; |
|||
background-image: linear-gradient(#00000000, rgba(0, 0, 0, 0.842), rgba(0, 0, 0, 0.842)); |
|||
padding: 30rpx 10rpx 20rpx 10rpx; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.grid-item .text-box .text{ |
|||
font-size: 26rpx; |
|||
color: #fff; |
|||
text-align: center; |
|||
} |
|||
|
|||
.play_btn{ |
|||
position:absolute; |
|||
top: 50%; |
|||
margin-top: -20px; |
|||
left: 50%; |
|||
margin-left: -20px; |
|||
width: 40px; |
|||
height: 40px; |
|||
} |
|||
.play_btn image{ |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
.title{ |
|||
/* background: #fff; */ |
|||
padding: 30rpx 15rpx; |
|||
/* background: #f1f1f1; */ |
|||
font-size: 40rpx; |
|||
color: #151515; |
|||
/* margin-bottom: 30rpx; */ |
|||
display: flex; |
|||
align-items: center; |
|||
/* border-bottom: 1px solid #f1f1f1; */ |
|||
} |
|||
|
|||
.title image{ |
|||
width: 50rpx; |
|||
height: 30rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.title text{ |
|||
position: relative; |
|||
padding-left: 20rpx; |
|||
} |
|||
|
|||
.title text::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
top: 50%; |
|||
left: 0%; |
|||
width: 6rpx; |
|||
height: 50%; |
|||
border-radius: 14rpx; |
|||
background-color: #05B359; |
|||
transform: translateY(-50%); |
|||
} |
|||
|
|||
page{ |
|||
/* background: #f5f5f5; */ |
|||
} |
|||
@ -0,0 +1,160 @@ |
|||
<script setup> |
|||
import { onLoad } from "@dcloudio/uni-app"; |
|||
import { ref } from "vue"; |
|||
import navv from "@/components/nav/nav.vue"; |
|||
import topTitle from "@/components/topTitle/topTitle.vue"; |
|||
import { getNewsListApi } from "@/libs/api"; |
|||
|
|||
const lists = ref([]); |
|||
const currentPage = ref(1); |
|||
const finished = ref(false); |
|||
const images = ref([]);// 图片 |
|||
const videos = ref([]);// 视频 |
|||
|
|||
async function loadList() { |
|||
if (finished.value) { |
|||
return; |
|||
} |
|||
const res = await getNewsListApi({ |
|||
current: currentPage.value, |
|||
size: 21, |
|||
title: "", |
|||
}); |
|||
if (res.code !== "0") { |
|||
return; |
|||
} |
|||
|
|||
res.data.forEach((each) => { |
|||
if (each.fileType == 2 && each.content.includes(",")) { |
|||
each.content = each.content.split(","); |
|||
} |
|||
if (each.fileType == 1) { |
|||
videos.value.push(each); |
|||
} |
|||
else { |
|||
images.value.push(each); |
|||
} |
|||
}); |
|||
|
|||
lists.value = [...lists.value, ...res.data]; |
|||
|
|||
if (lists.value.length === res.total) { |
|||
finished.value = true; |
|||
} |
|||
else { |
|||
currentPage.value++; |
|||
} |
|||
} |
|||
|
|||
function gotoInfoPage(item) { |
|||
if (item.fileType == 1) { |
|||
// 收集所有视频内容,当前项排第一,其余按遍历顺序追加 |
|||
item.content = [ |
|||
item.content, |
|||
...lists.value |
|||
.filter(data => data.fileType == 1 && data.content !== item.content) |
|||
.map(data => data.content), |
|||
]; |
|||
} |
|||
uni.navigateTo({ |
|||
url: `./enterKingInfo?data=${JSON.stringify(item)}`, |
|||
}); |
|||
} |
|||
|
|||
onLoad(() => { |
|||
loadList(); |
|||
}); |
|||
</script> |
|||
|
|||
<template> |
|||
<navv> |
|||
<template #default="{ content, screen, status, menu }"> |
|||
<topTitle title="走进菜大王" /> |
|||
|
|||
<scroll-view |
|||
:scroll-y="true" |
|||
:style="{ |
|||
width: '100%', |
|||
height: `${screen - status - (menu || 0)}px`, |
|||
overflowY: 'auto', |
|||
}" |
|||
@scrolltolower="loadList" |
|||
> |
|||
<view class="title"> |
|||
<text>厂家合作</text> |
|||
</view> |
|||
|
|||
<view style="overflow: hidden;padding: 0 20rpx;"> |
|||
<view |
|||
v-for="(item, index) in images" |
|||
:key="index" |
|||
class="grid-item" |
|||
:style="{ height: `calc(${content / 3.1}px - 10rpx)` }" |
|||
@tap="() => gotoInfoPage(item)" |
|||
> |
|||
<view style="margin-right: 10rpx;height: 100%;" class="box"> |
|||
<view v-if="item.fileType == 2" style="background: #333333;height: 100%;"> |
|||
<image style="width: 100%; height:100%" mode="aspectFill" :src="item.content[0]" /> |
|||
</view> |
|||
|
|||
<view |
|||
v-if="item.fileType == 1" |
|||
style="position:relative;width:100%;height: 100%;background: #333333;" |
|||
> |
|||
<image style="width: 100%; height:100%" mode="aspectFit" :src="item.imageUrl" /> |
|||
<view class="play_btn"> |
|||
<image src="/static/enterVegetableKingInfo/video.png" /> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="text-box"> |
|||
<view class="text"> |
|||
{{ item.title }} |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="title" style="margin-top: 30rpx;"> |
|||
<text>菜大王视频</text> |
|||
</view> |
|||
|
|||
<view style="overflow: hidden;padding: 0 20rpx;"> |
|||
<view |
|||
v-for="(item, index) in videos" |
|||
:key="index" |
|||
class="grid-item" |
|||
:data-item="item" |
|||
:style="{ height: `${content / 3.1}px` }" |
|||
@tap="() => gotoInfoPage(item)" |
|||
> |
|||
<view style="margin-right: 10rpx;height: 100%;" class="box"> |
|||
<view v-if="item.fileType == 2" style="background: #333333;height: 100%;"> |
|||
<image style="width: 100%; height:100%" mode="aspectFit" :src="item.content[0]" /> |
|||
</view> |
|||
<view |
|||
v-if="item.fileType == 1" |
|||
style="position:relative;width:100%;height: 100%;background: #333333;" |
|||
> |
|||
<image style="width: 100%; height:100%" mode="aspectFill" :src="item.imageUrl" /> |
|||
<view class="play_btn"> |
|||
<image src="/static/enterVegetableKingInfo/video.png" /> |
|||
</view> |
|||
</view> |
|||
<view class="text-box"> |
|||
<view class="text"> |
|||
{{ item.title }} |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</scroll-view> |
|||
</template> |
|||
</navv> |
|||
</template> |
|||
|
|||
<style scoped lang="scss"> |
|||
@import "./enterKing.scss"; |
|||
</style> |
|||
@ -0,0 +1,9 @@ |
|||
#video_box{ |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
video{ |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
@ -0,0 +1,115 @@ |
|||
<script setup> |
|||
import { onLoad } from "@dcloudio/uni-app"; |
|||
import { ref } from "vue"; |
|||
import navv from "@/components/nav/nav.vue"; |
|||
import topTitle from "@/components/topTitle/topTitle.vue"; |
|||
|
|||
const type = ref(""); |
|||
const result = ref([]); |
|||
const videoIndex = ref(0); // 视频滑块index |
|||
|
|||
onLoad((options) => { |
|||
try { |
|||
const data = JSON.parse(options.data); |
|||
result.value = data.content; |
|||
type.value = data.fileType; |
|||
const videoContext = uni.createVideoContext(`myvideo${videoIndex.value}`); |
|||
videoContext.play(); |
|||
console.log(type.value, result.value); |
|||
} |
|||
catch (err) { |
|||
console.error(err); |
|||
} |
|||
}); |
|||
|
|||
function swiperchange(e) { |
|||
videoIndex.value = e.detail.current; |
|||
for (let index = 0; index < this.data.result.length; index++) { |
|||
if (e.detail.current == index) { |
|||
const videoContext = uni.createVideoContext(`myvideo${index}`); |
|||
videoContext.play(); |
|||
} |
|||
else { |
|||
const videoContexta = uni.createVideoContext(`myvideo${index}`); |
|||
videoContexta.pause(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function preview(index) { |
|||
// const index = e.currentTarget.dataset.index; |
|||
uni.previewImage({ |
|||
current: result.value[index], // 当前显示图片的http链接 |
|||
urls: result.value, // 需要预览的图片http链接列表 |
|||
}); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<navv> |
|||
<template #default="{ screen, status, menu }"> |
|||
<topTitle title="菜大王" /> |
|||
|
|||
<view |
|||
:style="{ |
|||
height: `${screen - status - (menu || 0)}px`, |
|||
overflowY: 'auto', |
|||
}" |
|||
> |
|||
<swiper |
|||
v-if="type == 2" |
|||
:style="{ |
|||
height: '100%', |
|||
// height: 'calc(100% - 40rpx)', |
|||
background: '#000000', |
|||
paddingBottom: '40rpx', |
|||
}" |
|||
:indicator-dots="true" |
|||
indicator-color="rgba(255, 255, 255, .8)" |
|||
autoplay |
|||
interval="3000" |
|||
duration="200" |
|||
> |
|||
<block |
|||
v-for="(item, index) in result" |
|||
:key="index" |
|||
> |
|||
<swiper-item |
|||
@tap="() => preview(index)" |
|||
> |
|||
<image style="width: 100%; height:100%" mode="aspectFit" :src="item" /> |
|||
</swiper-item> |
|||
</block> |
|||
</swiper> |
|||
|
|||
<swiper |
|||
v-if="type == 1" |
|||
:style="{ |
|||
height: 'calc(100% - 40rpx)', |
|||
background: '#000000', |
|||
paddingBottom: '40rpx', |
|||
}" |
|||
vertical |
|||
circular |
|||
@change="(e) => swiperchange(e)" |
|||
> |
|||
<block |
|||
v-for="(item, index) in result" |
|||
:key="index" |
|||
> |
|||
<swiper-item> |
|||
<video :id="`myvideo${index}`" :src="item" loop /> |
|||
</swiper-item> |
|||
</block> |
|||
</swiper> |
|||
</view> |
|||
</template> |
|||
</navv> |
|||
|
|||
<!-- <video id="video_box" autoplay |
|||
wx:if="{{type==1}}" src="{{result}}"></video> --> |
|||
</template> |
|||
|
|||
<style scoped lang="scss"> |
|||
@import "./enterKingInfo.scss"; |
|||
</style> |
|||
|
After Width: 64 | Height: 64 | Size: 1.9 KiB |
Write
Preview
Loading…
Cancel
Save
Reference in new issue