Feat:寻看点和抽奖
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<view style="min-height:100vh;background: #FFFFFF" v-if="ready">
|
||||
<view style="padding: 20rpx 32rpx">
|
||||
<u-input v-model="keyword" :customStyle="{'border':'none','background': '#F6F6F6'}"
|
||||
placeholder="输入城市名、拼音或字母查询" shape="circle" @confirm="onSearch" @change="onChange">
|
||||
<template v-slot:suffix>
|
||||
<u-icon name="search" color="#FD5749" size="32rpx" @click="onSearch"/>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
|
||||
<view style="margin: 32rpx" v-if="searchList.length">
|
||||
<view class="flex flex-wrap">
|
||||
<view class="n-tag jc-center ai-center" v-for="(item,index) in searchList" :key="index"
|
||||
@click="navToWatch(item['name'])">{{ item['name'] }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template v-else>
|
||||
<view style="margin: 32rpx" v-if="cityName">
|
||||
<view style="margin-bottom: 16rpx">当前定位</view>
|
||||
<view class="n-tag jc-center ai-center" @click="navToWatch(cityName)">
|
||||
<u-icon name="map" color="#333333" size="36rpx"/>
|
||||
{{ cityName }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="margin: 32rpx" v-if="watchCity.length">
|
||||
<view style="margin-bottom: 16rpx">历史访问</view>
|
||||
<view class="flex flex-wrap">
|
||||
<view class="n-tag jc-center ai-center" v-for="(item,index) in watchCity" :key="index"
|
||||
@click="navToWatch(item)">{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-index-list :index-list="indexList" inactiveColor="#666666" activeColor="#FD5749">
|
||||
<template v-for="(item, index) in itemArr">
|
||||
<u-index-item>
|
||||
<u-index-anchor :text="indexList[index].toUpperCase()" color="#333333" size="32rpx" bgColor="#FFFFFF"/>
|
||||
<view class="list-cell" v-for="(cell, cIndex) in item" :key="cIndex" @click="navToWatch(cell['name'])">
|
||||
{{ cell['name'] }}
|
||||
</view>
|
||||
</u-index-item>
|
||||
</template>
|
||||
</u-index-list>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from '@vue/composition-api'
|
||||
import {getCurAddress, getLocation} from "@/utils/common";
|
||||
import {getVideoCity} from "@/api/video";
|
||||
|
||||
const watchCity = ref(uni.getStorageSync('watchCity') || [])
|
||||
|
||||
onMounted(() => {
|
||||
getMapData()
|
||||
fetchList()
|
||||
})
|
||||
|
||||
const ready = ref(false)
|
||||
const cityName = ref('')
|
||||
const keyword = ref('')
|
||||
|
||||
const onSearch = () => {
|
||||
const name = keyword.value.trim()
|
||||
if (name.length > 0) {
|
||||
navToWatch(name)
|
||||
}
|
||||
}
|
||||
|
||||
const raw = ref()
|
||||
const searchList = ref([])
|
||||
const onChange = (value) => {
|
||||
searchList.value = []
|
||||
if (value.trim().length === 0) return
|
||||
searchList.value = raw.value.filter(city => {
|
||||
if (city['name'].indexOf(value) > -1) return city
|
||||
})
|
||||
}
|
||||
|
||||
const handleHistory = (name) => {
|
||||
for (let i = 0; i < watchCity.value.length; i++) {
|
||||
if (name === watchCity.value[i]) return
|
||||
}
|
||||
if (watchCity.value.length === 4) {
|
||||
watchCity.value.pop()
|
||||
}
|
||||
watchCity.value.unshift(name)
|
||||
uni.setStorageSync('watchCity', watchCity.value)
|
||||
}
|
||||
|
||||
const getMapData = async () => {
|
||||
const map = await getLocation();
|
||||
if (map.length > 1) {
|
||||
const {latitude, longitude} = map[1];
|
||||
const address = await getCurAddress(latitude, longitude);
|
||||
cityName.value = address[1].data.result['ad_info']['city']
|
||||
}
|
||||
}
|
||||
|
||||
const indexList = ref(["A", "B", "C"])
|
||||
const itemArr = ref([
|
||||
['列表A1', '列表A2', '列表A3'],
|
||||
['列表B1', '列表B2', '列表B3'],
|
||||
['列表C1', '列表C2', '列表C3']
|
||||
])
|
||||
|
||||
const fetchList = async () => {
|
||||
const res = await getVideoCity()
|
||||
if (res.success) {
|
||||
raw.value = res.data
|
||||
const groupedByName = res.data.reduce((accumulator, current) => {
|
||||
const groupKey = current['firstLetter'].toUpperCase()
|
||||
if (!accumulator[groupKey]) {
|
||||
accumulator[groupKey] = []
|
||||
}
|
||||
accumulator[groupKey].push(current)
|
||||
return accumulator
|
||||
}, {})
|
||||
|
||||
indexList.value = Object.keys(groupedByName)
|
||||
itemArr.value = Object.values(groupedByName)
|
||||
}
|
||||
ready.value = true
|
||||
}
|
||||
|
||||
const navToWatch = (name) => {
|
||||
handleHistory(name)
|
||||
uni.redirectTo({url: '/pkg-video/views/watch?name=' + name})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
/deep/ .u-index-item {
|
||||
.u-border-bottom {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.list-cell {
|
||||
margin: 0 30rpx;
|
||||
padding: 16rpx 0;
|
||||
border-bottom: 1rpx solid #DCDCDC;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.n-tag {
|
||||
display: inline-flex;
|
||||
height: 60rpx;
|
||||
box-sizing: border-box;
|
||||
margin: 0 32rpx 16rpx 0;
|
||||
padding: 0 20rpx;
|
||||
border: 2px solid #B5B5B5;
|
||||
border-radius: 8rpx;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<view class="pkg-lottery-log" v-if="ready">
|
||||
<image style="width: 734rpx;height: 1418rpx" :src="webUrl+'/20240125215943273915.png'" mode="scaleToFill"/>
|
||||
|
||||
<view class="th flex">
|
||||
<view>日期</view>
|
||||
<view style="margin-left: 168rpx;">抽奖结果</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="list-box" scroll-y @scrolltolower="onBottom">
|
||||
<view class="item flex jc-between ai-center" v-for="(item,index) in list" :key="index">
|
||||
<view class="flex ai-center">
|
||||
<view style="width: 288rpx;color:#BD2323;font-size: 28rpx">{{ item['drawTime'] }}</view>
|
||||
<view class="more-t">{{ item['prizeName'] }}</view>
|
||||
</view>
|
||||
|
||||
<image class="flex-0" style="width: 111rpx;height: 64rpx" :src="webUrl+'/20240124232010456109.png'"
|
||||
mode="scaleToFill" v-if="item['isHit']===1 && item['status']===1" @click="takeItem(item)"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from '@vue/composition-api'
|
||||
import {onShow} from '@dcloudio/uni-app'
|
||||
import {VUE_APP_RESOURCES_URL as webUrl} from '../../config/index'
|
||||
import {getLogs, takePrize} from "@/api/lottery";
|
||||
|
||||
const ready = ref(false)
|
||||
|
||||
onShow(() => {
|
||||
list.value = []
|
||||
fetchList()
|
||||
})
|
||||
|
||||
const page = ref(1)
|
||||
const list = ref([])
|
||||
const fetchList = async () => {
|
||||
const res = await getLogs(page.value, 20)
|
||||
if (res.success) {
|
||||
res.data['records']?.forEach(item => list.value.push(item))
|
||||
ready.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const onBottom = () => {
|
||||
page.value++
|
||||
fetchList()
|
||||
}
|
||||
|
||||
const takeItem = async (item) => {
|
||||
if (item['prizeType'] === 1 && item['status'] === 1) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/OrderSubmission/index?lotteryRecordId=' + item['id']
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const res = await takePrize(item.id)
|
||||
if (res.success) {
|
||||
item['status'] = 2
|
||||
uni.showModal({
|
||||
title: '领取成功',
|
||||
content: '您的奖品已经领取成功,请前往我的订单查看奖品发货信息',
|
||||
cancelText: '下次再说',
|
||||
confirmText: '查看订单',
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
console.log('用户点击确定');
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/MyOrder/index'
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
console.log('用户点击取消');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.pkg-lottery-log {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
padding: 32rpx 8rpx 24rpx;
|
||||
background-color: #BD2323
|
||||
}
|
||||
|
||||
.th {
|
||||
position: absolute;
|
||||
left: 160rpx;
|
||||
top: 136rpx;
|
||||
}
|
||||
|
||||
.list-box {
|
||||
position: absolute;
|
||||
left: 42rpx;
|
||||
top: 200rpx;
|
||||
width: 672rpx;
|
||||
height: 1150rpx;
|
||||
|
||||
.item {
|
||||
width: 672rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 16rpx 6rpx 16rpx 32rpx;
|
||||
border-radius: 24rpx;
|
||||
background: #FFFBEE;
|
||||
|
||||
.more-t {
|
||||
width: 204rpx;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,341 @@
|
||||
<template>
|
||||
<view class="pkg-video-lottery" v-if="ready">
|
||||
<image style="width: 100vw;height: auto" :src="lotteryDetail.diceConfig['diceBackgroundImage']" mode="widthFix"/>
|
||||
<image class="btn-rules" :src="webUrl+'/20240124205433052863.png'" mode="scaleToFill" @click="openRulesModel"/>
|
||||
<image class="btn-log" :src="webUrl+'/20240124205425974838.png'" mode="scaleToFill" @click="navToLog"/>
|
||||
|
||||
<view class="dialog-mask" v-if="showDialog">
|
||||
<view class="dialog-rules flex jc-center" :style="{'backgroundImage':`url(${webUrl}/20240124210831292142.png)`}"
|
||||
v-if="showRules">
|
||||
<rich-text style="width: 546rpx;height:590rpx;overflow: scroll;" :nodes="lotteryDetail.diceConfig['ruleText']"/>
|
||||
<image class="btn-know" :src="webUrl+'/20240124210742446577.png'" mode="scaleToFill" @click="closeRulesModel"/>
|
||||
</view>
|
||||
|
||||
<view class="dialog-result" :style="{'backgroundImage':`url(${webUrl}/20240124210703446407.png)`}"
|
||||
v-if="showResult">
|
||||
<view class="btn-close" @click="onlyClose"/>
|
||||
<view class="img-box flex flex-col ai-center" v-if="diceResult['prizeImage']">
|
||||
<image style="width: 240rpx;height: 240rpx" :src="diceResult['prizeImage']" mode="scaleToFill"/>
|
||||
<image style="width: 80rpx;height: 80rpx;margin-top: 40rpx;" :src="diceResult['diceImage']"
|
||||
mode="scaleToFill"/>
|
||||
<view class="one-t bold" style="width:300rpx;margin-top: 40rpx;color:#F7E7B2">
|
||||
获得{{ diceResult['prizeName'] }}一份
|
||||
</view>
|
||||
</view>
|
||||
<image class="btn-result" style="width: 240rpx;height: 68rpx" :src="webUrl+'/20240125205521152611.png'"
|
||||
mode="scaleToFill" @click="closeResultModel"/>
|
||||
</view>
|
||||
|
||||
<view class="dialog-take flex jc-center" :style="{'backgroundImage':`url(${webUrl}/20240124210904824337.png)`}"
|
||||
v-if="showTake">
|
||||
<view class="btn-box flex">
|
||||
<image style="width: 220rpx;height: 66rpx" :src="webUrl+'/20240124210952306625.png'" mode="scaleToFill"
|
||||
@click="navToCoupons"/>
|
||||
<image style="width: 220rpx;height: 66rpx;margin-left: 16rpx;" :src="webUrl+'/20240124210928974187.png'"
|
||||
mode="scaleToFill" @click="closeTakeModel"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="dice-box">
|
||||
<image style="width: 200rpx;height: 200rpx" :src="diceImg" mode="scaleToFill"/>
|
||||
</view>
|
||||
<view class="btn-submit" @click="onSubmit"/>
|
||||
<view class="today-limit">{{ lotteryDetail.todayLimit }}</view>
|
||||
|
||||
<scroll-view class="prize-list flex" scroll-x="true" enable-flex="true">
|
||||
<view class="item flex flex-0 jc-center ai-center"
|
||||
:style="{'backgroundImage':`url(${webUrl}/20240122212856857899.png)`}"
|
||||
v-for="(item,index) in lotteryDetail.prizeList" :key="index">
|
||||
<image style="width: 120rpx;height: 120rpx" :src="item['prizeImage']" mode="scaleToFill"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="hit-box flex" @click="navToCoupons">
|
||||
<view class="img-first flex jc-center ai-center"
|
||||
:style="{'backgroundImage':`url(${webUrl}/20240122212841745175.png)`}"
|
||||
v-if="lotteryDetail.todayHitPrizeList.length">
|
||||
<image style="width: 128rpx;height: 128rpx" :src="lotteryDetail.todayHitPrizeList['0']['prizeImage']"
|
||||
mode="scaleToFill"/>
|
||||
</view>
|
||||
<image style="width:242rpx;height: 184rpx" :src="webUrl+'/20240122212850627682.png'" mode="scaleToFill"/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from '@vue/composition-api'
|
||||
import {VUE_APP_RESOURCES_URL as webUrl} from '../../config/index'
|
||||
import {getDetail, getPrize, takePrize} from "@/api/lottery";
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
const showDialog = ref(false)
|
||||
const showRules = ref(false)
|
||||
const showResult = ref(false)
|
||||
const showTake = ref(false)
|
||||
|
||||
const ready = ref(false)
|
||||
const lotteryDetail = ref({
|
||||
diceConfig: {},
|
||||
prizeList: [],
|
||||
todayHitPrizeList: [],
|
||||
todayLimit: 0
|
||||
})
|
||||
|
||||
const navToLog = () => {
|
||||
uni.navigateTo({url: './lottery-log'})
|
||||
}
|
||||
|
||||
|
||||
const openRulesModel = () => {
|
||||
showDialog.value = true
|
||||
showRules.value = true
|
||||
}
|
||||
const closeRulesModel = () => {
|
||||
showDialog.value = false
|
||||
showRules.value = false
|
||||
}
|
||||
|
||||
const init = async () => {
|
||||
const res = await getDetail()
|
||||
if (res.success) {
|
||||
lotteryDetail.value = res.data
|
||||
diceImg.value = lotteryDetail.value.diceConfig['diceDefaultImage']
|
||||
ready.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const diceIndex = ref(0)
|
||||
const diceImg = ref('')
|
||||
const onSubmit = async () => {
|
||||
const res = await getPrize()
|
||||
if (res.success) diceResult.value = res.data
|
||||
|
||||
diceIndex.value = lotteryDetail.value.diceConfig['diceValues'].findIndex(item => item['diceValue'] === diceResult.value.diceValue)
|
||||
diceImg.value = lotteryDetail.value.diceConfig['diceValues'][diceIndex.value]['diceValueGif']
|
||||
setTimeout(() => {
|
||||
diceImg.value = lotteryDetail.value.diceConfig['diceValues'][diceIndex.value]['diceValueImage']
|
||||
setTimeout(() => {
|
||||
init()
|
||||
showDialog.value = true
|
||||
showResult.value = true
|
||||
}, 1000)
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
const diceResult = ref({
|
||||
prizeName: '',
|
||||
prizeImage: '',
|
||||
diceImage: '',
|
||||
diceValue: 0
|
||||
})
|
||||
|
||||
const navToCoupons = () => {
|
||||
uni.navigateTo({url: '/pkg_user/views/myCoupons'})
|
||||
}
|
||||
|
||||
const onlyClose = () => {
|
||||
showResult.value = false
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
const closeResultModel = async () => {
|
||||
if (diceResult.value['prizeType'] === 4) {
|
||||
showResult.value = false
|
||||
showDialog.value = false
|
||||
return
|
||||
}
|
||||
if (diceResult.value['prizeType'] === 1) {
|
||||
showResult.value = false
|
||||
showDialog.value = false
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/OrderSubmission/index?lotteryRecordId=' + diceResult.value['id']
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const res = await takePrize(diceResult.value.id)
|
||||
if (res.success) {
|
||||
showResult.value = false
|
||||
showTake.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const closeTakeModel = () => {
|
||||
showTake.value = false
|
||||
showDialog.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
image {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.pkg-video-lottery {
|
||||
position: relative;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btn-rules {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 168rpx;
|
||||
width: 74rpx;
|
||||
height: 170rpx
|
||||
}
|
||||
|
||||
.btn-log {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 342rpx;
|
||||
width: 72rpx;
|
||||
height: 216rpx;
|
||||
}
|
||||
|
||||
.dialog-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(51, 51, 51, .6);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.dialog-rules {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 606rpx;
|
||||
height: 760rpx;
|
||||
box-sizing: border-box;
|
||||
padding: 40rpx 40rpx 120rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 606rpx 724rpx;
|
||||
z-index: 20;
|
||||
|
||||
.btn-know {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
width: 292rpx;
|
||||
height: 98rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-result {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 476rpx;
|
||||
height: 856rpx;
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 476rpx 856rpx;
|
||||
z-index: 20;
|
||||
|
||||
.btn-close {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.img-box {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 345rpx;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.btn-result {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translate(-50%, 45%);
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-take {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 520rpx;
|
||||
height: 428rpx;
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 520rpx 428rpx;
|
||||
z-index: 20;
|
||||
|
||||
.btn-box {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 26rpx;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.dice-box {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 450rpx;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 694rpx;
|
||||
transform: translate(-50%, 0);
|
||||
width: 280rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.today-limit {
|
||||
position: absolute;
|
||||
left: 48.5%;
|
||||
top: 788rpx;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.prize-list {
|
||||
position: absolute;
|
||||
left: 124rpx;
|
||||
top: 888rpx;
|
||||
width: 576rpx;
|
||||
height: 164rpx;
|
||||
|
||||
.item {
|
||||
width: 164rpx;
|
||||
height: 164rpx;
|
||||
background-size: 164rpx 164rpx;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.hit-box {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 1176rpx;
|
||||
transform: translate(-50%, 0);
|
||||
height: 184rpx;
|
||||
|
||||
.img-first {
|
||||
width: 175rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 24rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 175rpx 185rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,360 @@
|
||||
<template>
|
||||
<view class="pkg-video-watch" v-if="ready">
|
||||
|
||||
<cover-view class="fixed-header flex ai-start">
|
||||
<cover-view class="bold">推荐</cover-view>
|
||||
<cover-view class="flex ai-center" style="margin-left: 100rpx" @click="navToCity">
|
||||
<cover-view>{{ cityName }}</cover-view>
|
||||
<cover-image style="width: 48rpx;height: 48rpx" :src="webUrl+'/20240113230523321737.png'" mode="scaleToFill"/>
|
||||
</cover-view>
|
||||
</cover-view>
|
||||
|
||||
<swiper style="height:100%" vertical @change="onChange">
|
||||
<swiper-item v-for="(item,index) in list" :key="index">
|
||||
<view class="item">
|
||||
<video :id="`video-${index}`" :src="item['video']" loop :controls="false" :show-center-play-btn="false"/>
|
||||
|
||||
<view class="btn-play flex jc-center ai-center" @click="controlVideo">
|
||||
<image style="width:57rpx;height:65rpx" :src="webUrl+'/20240123093125710999.png'" mode="scaleToFill"
|
||||
v-if="showPlay"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="fixed-footer flex jc-between ai-end"
|
||||
:style="{'bottom':systemInfo['safeAreaInsets']['bottom']+'px'}" v-if="!showDialog">
|
||||
<view class="flex ai-center">
|
||||
<cover-image style="width: 80rpx;height: 80rpx;border-radius: 50%;z-index: 10" :src="item['hotelLogo']"
|
||||
@click="navToStore(item['hotelId'])"/>
|
||||
<cover-view class="more-t">{{ item['hotelName'] }}</cover-view>
|
||||
</view>
|
||||
|
||||
<cover-view class="flex ai-center">
|
||||
<cover-view class="flex flex-col ai-center" style="width:78rpx;margin-right: 16rpx;"
|
||||
@click="changeLike(item)">
|
||||
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230547221591.png'"
|
||||
v-if="item['hasLike']"/>
|
||||
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230552152511.png'" v-else/>
|
||||
<cover-view class="one-t tc">{{ item['likeCount'] }}</cover-view>
|
||||
</cover-view>
|
||||
<cover-view class="flex flex-col ai-center" style="width:78rpx;margin-right: 16rpx;"
|
||||
@click="changeFav(item)">
|
||||
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230535491918.png'"
|
||||
v-if="item['hasFavorite']"/>
|
||||
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230541207016.png'" v-else/>
|
||||
<cover-view class="one-t tc">{{ item['favoriteCount'] }}</cover-view>
|
||||
</cover-view>
|
||||
<cover-view class="flex flex-col ai-center" style="width:78rpx" @click="showDialog=true">
|
||||
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230529202260.png'"/>
|
||||
<cover-view class="one-t tc">{{ item['replyCount'] }}</cover-view>
|
||||
</cover-view>
|
||||
</cover-view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<u-popup :show="showDialog" :round="10" mode="bottom" overlay overlayOpacity="0"
|
||||
closeOnClickOverlay
|
||||
@close="dialogClose" @open="dialogOpen">
|
||||
<view style="z-index: 100">
|
||||
<cover-view class="tc" style="padding: 20rpx 0 40rpx;font-size: 28rpx">{{
|
||||
list[current]['replyCount']
|
||||
}}条评论
|
||||
</cover-view>
|
||||
<scroll-view style="max-height: 740rpx" scroll-y @scrolltolower="fetchReply">
|
||||
<view class="flex" style="margin: 0 30rpx 30rpx" v-for="(item,index) in replyList" :key="index">
|
||||
<cover-image class="flex-0" style="width: 64rpx;height: 64rpx;margin-right: 18rpx;border-radius: 50%"
|
||||
:src="item['userAvatar']"/>
|
||||
<cover-view>
|
||||
<cover-view style="color:#999999;font-size: 28rpx">{{ item['userNickname'] }}</cover-view>
|
||||
<cover-view class="more-t" style="font-size: 32rpx;line-height: 48rpx">{{ item['comment'] }}</cover-view>
|
||||
<cover-view style="color:#999999;font-size: 28rpx">{{ item['time'] }}</cover-view>
|
||||
</cover-view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="flex jc-between ai-center" style="padding: 20rpx;border-top:2rpx solid #DCDCDC;">
|
||||
<u-input :customStyle="{'border':'none','background': '#F6F6F6'}" v-model="comment"
|
||||
placeholder="请输入评论..." maxlength="200" shape="circle"/>
|
||||
<cover-view class="btn-submit flex jc-center ai-center" @click="onSubmit">发布</cover-view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from '@vue/composition-api'
|
||||
import {onLoad, onShow} from '@dcloudio/uni-app'
|
||||
import {VUE_APP_RESOURCES_URL as webUrl} from '../../config/index'
|
||||
import {getReplyList, likeVideo, randomList, removeFavoriteVideo, removeLikeVideo, submitReply} from "@/api/video";
|
||||
import {addVideo} from "@/api/favorite";
|
||||
import {getCurAddress, getLocation} from "@/utils/common";
|
||||
|
||||
const systemInfo = ref()
|
||||
|
||||
onLoad((options) => {
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
systemInfo.value = res
|
||||
}
|
||||
})
|
||||
|
||||
videoId.value = options.videoId || ''
|
||||
const name = options.name
|
||||
if (name) {
|
||||
cityName.value = name
|
||||
fetchList()
|
||||
} else {
|
||||
getMapData()
|
||||
}
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
ready.value = false
|
||||
setTimeout(() => {
|
||||
if (cityName.value) fetchList()
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
const ready = ref(false)
|
||||
const cityName = ref('')
|
||||
const videoId = ref('')
|
||||
|
||||
const navToCity = () => {
|
||||
uni.redirectTo({url: '/pkg-video/views/city'})
|
||||
}
|
||||
|
||||
const navToHome = () => {
|
||||
uni.switchTab({url: '/pages/home/index'})
|
||||
}
|
||||
|
||||
const navToStore = (id) => {
|
||||
console.log(typeof id, id)
|
||||
uni.navigateTo({url: '/pagesInn/inn/innHome?id=' + id})
|
||||
}
|
||||
|
||||
const getMapData = async () => {
|
||||
const map = await getLocation();
|
||||
if (map.length > 1) {
|
||||
const {latitude, longitude} = map[1];
|
||||
const address = await getCurAddress(latitude, longitude);
|
||||
cityName.value = address[1].data.result['ad_info']['city']
|
||||
}
|
||||
|
||||
await fetchList()
|
||||
}
|
||||
|
||||
const list = ref([])
|
||||
const fetchList = async () => {
|
||||
let param
|
||||
if (videoId.value) {
|
||||
param = {
|
||||
videoId: videoId.value,
|
||||
limit: 2
|
||||
}
|
||||
} else {
|
||||
param = {
|
||||
cityName: cityName.value,
|
||||
limit: 2
|
||||
}
|
||||
}
|
||||
const res = await randomList(param)
|
||||
if (res.success) {
|
||||
res.data?.forEach(item => list.value.push(item))
|
||||
if (!ready.value && list.value.length === 0) {
|
||||
uni.showModal({
|
||||
title: '',
|
||||
content: '当前城市还没有视频,可以先看看其他城市的喔~',
|
||||
cancelText: '返回',
|
||||
cancelColor: '#3A87FC',
|
||||
confirmText: '选择城市',
|
||||
confirmColor: '#3A87FC',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
navToCity()
|
||||
} else if (res.cancel) {
|
||||
navToHome()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
ready.value = true
|
||||
if (list.value.length > 0) handleVideoPlay()
|
||||
}
|
||||
}
|
||||
|
||||
const changeLike = async (item) => {
|
||||
const videoId = item['id']
|
||||
if (item['hasLike']) {
|
||||
const res = await removeLikeVideo(videoId)
|
||||
if (res.success) {
|
||||
item['hasLike'] = false
|
||||
item['likeCount'] = res.data['likeCount']
|
||||
}
|
||||
} else {
|
||||
const res = await likeVideo(videoId)
|
||||
if (res.success) {
|
||||
item['hasLike'] = true
|
||||
item['likeCount'] = res.data['likeCount']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const changeFav = async (item) => {
|
||||
const videoId = item['id']
|
||||
if (item['hasFavorite']) {
|
||||
const res = await removeFavoriteVideo(videoId)
|
||||
if (res.success) {
|
||||
item['hasFavorite'] = false
|
||||
item['favoriteCount'] = res.data['favoriteCount']
|
||||
}
|
||||
} else {
|
||||
const res = await addVideo(videoId)
|
||||
if (res.success) {
|
||||
item['hasFavorite'] = true
|
||||
item['favoriteCount'] = res.data['favoriteCount']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const current = ref(0)
|
||||
const onChange = (event) => {
|
||||
current.value = event.detail.current
|
||||
if (current.value + 2 >= list.value.length) fetchList()
|
||||
handleVideoPlay()
|
||||
}
|
||||
|
||||
const showPlay = ref(false)
|
||||
const currentContext = ref()
|
||||
const handleVideoPlay = () => {
|
||||
for (let i = 0; i < list.value.length; i++) {
|
||||
let id = `video-${i}`
|
||||
let videoContext = uni.createVideoContext(id)
|
||||
videoContext.pause()
|
||||
if (current.value === i) videoContext.play()
|
||||
}
|
||||
}
|
||||
const controlVideo = () => {
|
||||
let id = `video-${current.value}`
|
||||
currentContext.value = uni.createVideoContext(id)
|
||||
if (showPlay.value) {
|
||||
currentContext.value.play()
|
||||
} else {
|
||||
currentContext.value.pause()
|
||||
}
|
||||
showPlay.value = !showPlay.value
|
||||
}
|
||||
|
||||
const showDialog = ref(false)
|
||||
const dialogClose = () => {
|
||||
showDialog.value = false
|
||||
}
|
||||
const dialogOpen = () => {
|
||||
comment.value = ''
|
||||
page.value = 1
|
||||
replyList.value = []
|
||||
fetchReply()
|
||||
}
|
||||
const comment = ref('')
|
||||
const page = ref(1)
|
||||
|
||||
const replyList = ref([])
|
||||
const fetchReply = async () => {
|
||||
const id = list.value[current.value]['id']
|
||||
const res = await getReplyList(id, page.value)
|
||||
if (res.success && res.data['records']?.length > 0) {
|
||||
res.data['records']?.forEach(item => {
|
||||
item.time = uni.$u.timeFrom(Date.parse(item.createTime))
|
||||
replyList.value.push(item)
|
||||
})
|
||||
page.value++
|
||||
}
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (comment.value.trim().length === 0) return
|
||||
const videoId = list.value[current.value]['id']
|
||||
const res = await submitReply(videoId, comment.value)
|
||||
if (res.success) {
|
||||
uni.showToast({
|
||||
title: '评论已发布',
|
||||
icon: 'none',
|
||||
success() {
|
||||
list.value[current.value]['replyCount']++
|
||||
showDialog.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.pkg-video-watch {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
background: #000000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fixed-header {
|
||||
position: absolute;
|
||||
left: 200rpx;
|
||||
top: 32rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 44rpx;
|
||||
z-index: 10;
|
||||
|
||||
.bold {
|
||||
border-bottom: 10rpx solid #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.fixed-footer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
padding: 20rpx 32rpx;
|
||||
z-index: 10;
|
||||
|
||||
.more-t {
|
||||
width: 216rpx;
|
||||
margin-left: 10rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 36rpx;
|
||||
line-height: 52rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.one-t {
|
||||
width: 100%;
|
||||
margin-top: 8rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
width: 120rpx;
|
||||
height: 64rpx;
|
||||
margin-left: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #FD5749;
|
||||
color: #FFFFFF;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.btn-play {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
width: 100vw;
|
||||
height: 50vh;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user