Browse Source

feat(home): 新增走进菜大王页面及相关功能组件

- 添加走进菜大王主页面及详情页,支持图片和视频展示
- 实现视频播放和图片预览功能
- 新增相关API接口和样式文件
- 优化页面布局和交互体验
master
wei 3 days ago
parent
commit
a28b79ba47
  1. 40
      libs/api/index.js
  2. 52
      pages/home/announcement.vue
  3. 81
      pages/home/enterKing/enterKing.scss
  4. 160
      pages/home/enterKing/enterKing.vue
  5. 9
      pages/home/enterKing/enterKingInfo.scss
  6. 115
      pages/home/enterKing/enterKingInfo.vue
  7. BIN
      static/enterVegetableKingInfo/video.png

40
libs/api/index.js

@ -398,7 +398,7 @@ export function getMenuProductsApi(params = {}) {
*/ */
export function newMenusToCartApi(data = {}) { export function newMenusToCartApi(data = {}) {
return request({ return request({
errorMessage: "添加菜谱到购物车",
errorMessage: "菜谱",
method: "POST", method: "POST",
data, data,
header: { header: {
@ -407,3 +407,41 @@ export function newMenusToCartApi(data = {}) {
url: "/setmeal/addCaiPu.do", url: "/setmeal/addCaiPu.do",
}); });
} }
// //
// module.exports.getJoinEnterprise = function (postData, success) {
// request('/company/searchCompanyInfo.do', 'GET', postData, success)
// }
/**
* 获取加入企业列表
* @param {*} params
*/
export function getJoinEnterpriseApi(params = {}) {
return request({
errorMessage: "企业列表",
method: "GET",
params,
url: "/company/searchCompanyInfo.do",
});
}
// //走进菜大王列表数据
// module.exports.getNewsList = function (postData, success) {
// request('/webAboutUs/getList.do', 'get', postData, success)
// }
/**
* 获取走进菜大王列表
*/
export function getNewsListApi(params = {}) {
return request({
errorMessage: "菜大王列表",
method: "GET",
params,
url: "/webAboutUs/getList.do",
});
}
// odule.exports.addCart = function (postData, success) {
// request('/cart/add.do', 'POST', postData, success);
// };

52
pages/home/announcement.vue

@ -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>

81
pages/home/enterKing/enterKing.scss

@ -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; */
}

160
pages/home/enterKing/enterKing.vue

@ -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>

9
pages/home/enterKing/enterKingInfo.scss

@ -0,0 +1,9 @@
#video_box{
width: 100%;
height: 100%;
}
video{
width: 100%;
height: 100%;
}

115
pages/home/enterKing/enterKingInfo.vue

@ -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>

BIN
static/enterVegetableKingInfo/video.png

After

Width: 64  |  Height: 64  |  Size: 1.9 KiB

Loading…
Cancel
Save