From ab933cc99ad3f7b0b0b5ae5fdae7f46ea0c0be03 Mon Sep 17 00:00:00 2001 From: peng <peng.com> Date: 星期一, 25 八月 2025 17:53:57 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/dev_fix_sub' into dev_fix_sub --- config/api.js | 8 pages.json | 9 api/popup.js | 20 ++ api/video.js | 11 + pages/ActivityPopup/ActivityPopup.vue | 354 +++++++++++++++++++++++++++++++++++ pages/tabbar/index/home.vue | 142 ++++++++++++- pages/commodity-square/commoditySquare.vue | 4 store/index.js | 20 ++ 8 files changed, 548 insertions(+), 20 deletions(-) diff --git a/api/popup.js b/api/popup.js new file mode 100644 index 0000000..3fba0fd --- /dev/null +++ b/api/popup.js @@ -0,0 +1,20 @@ + +import { http, Method } from "@/utils/request.js"; + +import api from "@/config/api.js"; + + export function setPopupRedisTime() { + return http.request({ + url: "/lmk/popup/setPopupRedisTime", + method: Method.GET, + needToken: true, + }); +} + + export function getPopupAcitivty() { + return http.request({ + url: "/lmk/popup/getPopupActivity", + method: Method.GET, + needToken: true, + }); +} \ No newline at end of file diff --git a/api/video.js b/api/video.js index cb46c25..e316383 100644 --- a/api/video.js +++ b/api/video.js @@ -155,6 +155,17 @@ } /** + * + */ + +export function removeByIdVideoComment(params){ + return http.request({ + url:"/lmk/video-comment/" + params, + method: Method.DELETE, + needToken: true, + }) +} +/** * 鍙戝竷瑙嗛璇勮 * * @param params diff --git a/config/api.js b/config/api.js index 9db28a0..0884b85 100644 --- a/config/api.js +++ b/config/api.js @@ -9,10 +9,10 @@ buyer: "http://192.168.0.15:8888", store: "http://192.168.0.15:8889", - // im: "http://127.0.0.1:8885", - // common: "http://127.0.0.1:8890", - // buyer: "http://127.0.0.1:8888", - // store: "http://127.0.0.1:8889", + im: "http://127.0.0.1:8885", + common: "http://127.0.0.1:8890", + buyer: "http://127.0.0.1:8888", + store: "http://127.0.0.1:8889", // common: "http://192.168.0.113:8890", // buyer: "http://192.168.0.113:8888", diff --git a/pages.json b/pages.json index fd3ed7c..f985091 100644 --- a/pages.json +++ b/pages.json @@ -27,7 +27,14 @@ "navigationStyle": "custom" // 闅愯棌椤堕儴瀵艰埅鏍� } - } + }, + { + "path" : "pages/ActivityPopup/ActivityPopup", + "style" : + { + "navigationBarTitleText" : "" + } + } // { // "path": "pages/tabbar/home/index", // "style": { diff --git a/pages/ActivityPopup/ActivityPopup.vue b/pages/ActivityPopup/ActivityPopup.vue new file mode 100644 index 0000000..cdfdea5 --- /dev/null +++ b/pages/ActivityPopup/ActivityPopup.vue @@ -0,0 +1,354 @@ +<template> + <view class="activity-popup" v-if="show" @click="onMaskClick"> + <!-- 閬僵灞� --> + <view class="popup-mask" :class="{ 'mask-enter': show, 'mask-leave': !show }"></view> + + <!-- 寮圭獥鍐呭 --> + <view class="popup-content" + :class="{ 'content-enter': show, 'content-leave': !show }" + @click.stop> + + <!-- 鍏抽棴鎸夐挳 --> + <view class="close-btn" @click="onClose"> + <uni-icons type="close" size="24" color="#666"></uni-icons> + </view> + + <!-- 娲诲姩鍥剧墖 --> + <view class="activity-img"> + <image :src="activityImage" mode="widthFix" class="popup-img"></image> + </view> + + <!-- 娲诲姩淇℃伅 --> + <view class="activity-info"> + <h3 class="activity-title">{{ activityTitle }}</h3> + <p class="activity-desc">{{ activityDesc }}</p> + + <!-- 鍊掕鏃讹紙濡傛灉闇�瑕侊級 --> + <view class="countdown" v-if="showCountdown"> + <text class="countdown-text">娲诲姩鍓╀綑鏃堕棿锛�</text> + <view class="countdown-time"> + <text class="time-box">{{ days }}</text> + <text class="time-sep">:</text> + <text class="time-box">{{ hours }}</text> + <text class="time-sep">:</text> + <text class="time-box">{{ minutes }}</text> + <text class="time-sep">:</text> + <text class="time-box">{{ seconds }}</text> + </view> + </view> + + <!-- 鍙備笌鎸夐挳 --> + <button class="join-btn" @click="onJoinActivity"> + {{ joinButtonText }} + </button> + </view> + </view> + </view> +</template> + +<script> +import {getPopupAcitivty} from '@/api/popup.js' +export default { + name: 'ActivityPopup', + props: { + // 鎺у埗寮圭獥鏄剧ず/闅愯棌 + show: { + type: Boolean, + default: false + }, + // 娲诲姩鍥剧墖URL + activityImage: { + type: String, + default: '' + }, + // 娲诲姩鏍囬 + activityTitle: { + type: String, + default: '闄愭椂浼樻儬娲诲姩' + }, + // 娲诲姩鎻忚堪 + activityDesc: { + type: String, + default: '鍙備笌鏈娲诲姩锛屽嵆鍙幏寰楄秴鍊煎ぇ濂栵紝鏈轰細闅惧緱锛屼笉瑕侀敊杩囷紒' + }, + // 鍙備笌鎸夐挳鏂囨湰 + joinButtonText: { + type: String, + default: '绔嬪嵆鍙備笌' + }, + // 鏄惁鏄剧ず鍊掕鏃� + showCountdown: { + type: Boolean, + default: true + }, + // 鍊掕鏃剁粨鏉熸椂闂达紙鏃堕棿鎴筹級 + endTime: { + type: Number, + default: () => { + // 榛樿7澶╁悗缁撴潫 + return Date.now() + 7 * 24 * 60 * 60 * 1000; + } + } + }, + data() { + return { + days: '00', + hours: '00', + minutes: '00', + seconds: '00', + countdownTimer: null + }; + }, + watch: { + show(newVal) { + console.log("寮圭獥鐩戝惉鍙樺寲",newVal) + if (newVal && this.showCountdown) { + this.startCountdown(); + } else if (!newVal && this.countdownTimer) { + clearInterval(this.countdownTimer); + this.countdownTimer = null; + } + } + }, + mounted() { + console.log('缁勪欢宸叉寕杞斤紝姝ゆ椂鍙互璁块棶 props 鍜� DOM'); + console.log('褰撳墠 show 鐘舵�侊細', this.show); // 鍙互鎵撳嵃 props 涓殑 show + + }, + methods: { + onpan(){ + + }, + // 寮�濮嬪�掕鏃� + startCountdown() { + this.updateCountdown(); + if (this.countdownTimer) { + clearInterval(this.countdownTimer); + } + this.countdownTimer = setInterval(() => { + this.updateCountdown(); + }, 1000); + }, + + // 鏇存柊鍊掕鏃� + updateCountdown() { + const now = Date.now(); + const diff = this.endTime - now; + + if (diff <= 0) { + this.days = '00'; + this.hours = '00'; + this.minutes = '00'; + this.seconds = '00'; + clearInterval(this.countdownTimer); + this.countdownTimer = null; + return; + } + + // 璁$畻澶┿�佹椂銆佸垎銆佺 + const days = Math.floor(diff / (1000 * 60 * 60 * 24)); + const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((diff % (1000 * 60)) / 1000); + + // 鏍煎紡鍖栨暟瀛椾负涓や綅鏁� + this.days = days.toString().padStart(2, '0'); + this.hours = hours.toString().padStart(2, '0'); + this.minutes = minutes.toString().padStart(2, '0'); + this.seconds = seconds.toString().padStart(2, '0'); + }, + + // 鍏抽棴寮圭獥 + onClose() { + this.$emit('close'); + }, + + // 鐐瑰嚮閬僵灞傚叧闂� + onMaskClick() { + this.$emit('close'); + }, + + // 鐐瑰嚮鍙備笌娲诲姩 + onJoinActivity() { + this.$emit('join'); + // 鍙互鍦ㄨ繖閲屾坊鍔犲弬涓庢椿鍔ㄥ悗鐨勯�昏緫锛屾瘮濡傚叧闂脊绐� + // this.onClose(); + } + }, + beforeDestroy() { + if (this.countdownTimer) { + clearInterval(this.countdownTimer); + } + } +}; +</script> + +<style scoped> +.activity-popup { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + display: flex; + justify-content: center; + align-items: center; + padding: 20rpx; +} + + +/* 閬僵灞傛牱寮� */ +.popup-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + +} + +.mask-enter { + opacity: 1; +} + +.mask-leave { + opacity: 0; +} + +/* 寮圭獥鍐呭鏍峰紡 */ +.popup-content { + width: 100%; + max-width: 600rpx; + background-color: #ffffff; + border-radius: 24rpx; + box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.2); + overflow: hidden; + transform: translateY(50rpx) scale(0.9); + opacity: 0; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.content-enter { + transform: translateY(0) scale(1); + opacity: 1; +} + +.content-leave { + transform: translateY(50rpx) scale(0.9); + opacity: 0; +} + +/* 鍏抽棴鎸夐挳 */ +.close-btn { + position: absolute; + top: 20rpx; + right: 20rpx; + width: 50rpx; + height: 50rpx; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(255, 255, 255, 0.8); + border-radius: 50%; + z-index: 10; +} + +/* 娲诲姩鍥剧墖 */ +.activity-img { + position: relative; + width: 100%; /* 瀹瑰櫒瀹藉害閾烘弧寮圭獥鍐呭鍖� */ + /* 鍙�夛細娣诲姞鑳屾櫙鑹诧紝閬垮厤鍥剧墖鍔犺浇鍓嶆樉绀虹┖鐧� */ + background-color: #f5f5f5; + border-top-left-radius: 24rpx; /* 涓庡浘鐗囧渾瑙掍竴鑷达紝閬垮厤瀹瑰櫒闇茬櫧 */ + border-top-right-radius: 24rpx; +} + +.popup-img { + width: 100%; + /* 鏍稿績锛氱敤 max-height 闄愬埗鏈�澶ч珮搴︼紝涓嶉檺鍒� min-height锛堜繚鐣欐瘮渚嬶級 */ + max-height: 300rpx; /* 鍥剧墖鏈�澶ч珮搴︼紙瓒呰繃鍒欐寜姣斾緥缂╁皬锛屼繚璇佸畬鏁存樉绀猴級 */ +} + +/* 娲诲姩淇℃伅 */ +.activity-info { + padding: 30rpx; + text-align: center; +} + +.activity-title { + font-size: 32rpx; + font-weight: bold; + color: #333333; + margin-bottom: 20rpx; + line-height: 1.3; +} + +.activity-desc { + font-size: 26rpx; + color: #666666; + margin-bottom: 30rpx; + line-height: 1.5; +} + +/* 鍊掕鏃舵牱寮� */ +.countdown { + margin-bottom: 30rpx; + text-align: center; +} + +.countdown-text { + font-size: 24rpx; + color: #ff6b3b; + margin-right: 10rpx; +} + +.countdown-time { + display: inline-flex; + align-items: center; +} + +.time-box { + display: inline-block; + width: 50rpx; + height: 50rpx; + line-height: 50rpx; + background-color: #ff6b3b; + color: #ffffff; + font-size: 26rpx; + font-weight: bold; + border-radius: 8rpx; + text-align: center; +} + +.time-sep { + margin: 0 10rpx; + color: #ff6b3b; + font-size: 28rpx; + font-weight: bold; +} + +/* 鍙備笌鎸夐挳 */ +.join-btn { + width: 100%; + height: 80rpx; + line-height: 80rpx; + background-color: #ff6b3b; + color: #ffffff; + font-size: 30rpx; + border-radius: 40rpx; + border: none; + box-shadow: 0 5rpx 15rpx rgba(255, 107, 59, 0.4); + transition: all 0.2s ease; +} + +.join-btn::after { + border: none; +} + +.join-btn:active { + background-color: #e55a2a; + transform: scale(0.98); +} +</style> diff --git a/pages/commodity-square/commoditySquare.vue b/pages/commodity-square/commoditySquare.vue index 78e087b..45b66c6 100644 --- a/pages/commodity-square/commoditySquare.vue +++ b/pages/commodity-square/commoditySquare.vue @@ -77,7 +77,7 @@ <view class="settlement">鍘昏喘鐗╄溅缁撶畻</view> </view> --> </view> - <view class="squareFotter" style="width: 750rpx; display: flex;align-items: center; + <view @click="gotoCardList()" class="squareFotter" style="width: 750rpx; display: flex;align-items: center; justify-content: space-between;padding: 0 32rpx;box-sizing: border-box;"> <view style="display: flex;align-items: center;justify-content: center;"> <view class="icon" style="position: relative;"> @@ -93,7 +93,7 @@ <view style="margin-left: 10rpx;color: #e06c75;font-size: 48rpx;font-weight: bold;"> 锟{priceInfo.price}}</view> </view> - <view class="settlement" @click="gotoCardList()">鍘荤粨绠�</view> + <view class="settlement">鍘荤粨绠�</view> </view> </view> </template> diff --git a/pages/tabbar/index/home.vue b/pages/tabbar/index/home.vue index d51340e..c0fbd55 100644 --- a/pages/tabbar/index/home.vue +++ b/pages/tabbar/index/home.vue @@ -202,11 +202,13 @@ </view> <view v-else class="comment-item" v-for="(comment, index) in comments" :key="comment.id"> - <view style="display: flex;"> + <view style="display: flex;" > <image class="comment-avatar" :src="comment.userAvatar || '/static/default-avatar.png'"></image> <view class="comment-content"> - <text class="nickname">{{comment.userNickname}} <text v-if="userId===comment.userId">(鎴�)</text> </text> - <text class="content">{{comment.commentContent}}</text> + <view @click="replyClick(comment)"> + <text class="nickname">{{comment.userNickname}} <text v-if="userId===comment.userId">(鎴�)</text> </text> + <text class="content">{{comment.commentContent}}</text> + </view> <view style="position: relative;"> <text class="time">{{formatTime(comment.createTime)}}</text> <text @click="openReply(comment)" class="reply-btu time">鍥炲</text> @@ -218,7 +220,7 @@ <!-- 鍥炲鍒楄〃 --> <view class="reply-list" v-if="comment.replies && comment.replies.length > 0"> <view class="reply-item" v-for="(reply, replyIndex) in comment.replies" :key="reply.id"> - <view class="reply-content"> + <view class="reply-content" @click="replyClick(reply)"> <view style="display: flex;"> <image class="comment-reply-avatar" :src="reply.replyUserAvatar || '/static/default-avatar.png'"></image> <text class="nickname">{{reply.userNickname}}<text v-if="userId===comment.userId">(鎴�)</text></text> @@ -261,6 +263,16 @@ <custom-tabbar bgColor="#333333" selected="index" selectedTextColor="#ffffff"></custom-tabbar> + + <ActivityPopup + :show="activityPopup.show" + :activityTitle="activityPopup.title" + :activityDesc="activityPopup.desc" + :activityImage="activityPopup.image" + :endTime="activityPopup.endTime" + @close="onClosePopup" + @join="onJoinActivity" + /> </view> </template> @@ -274,8 +286,13 @@ thubmsUpComment, cancelThubmsUpComment, changeThumbsUp, - getGoodsSimilarlyVideos + getGoodsSimilarlyVideos, + removeByIdVideoComment, } from "@/api/video.js"; + +import ActivityPopup from '@/pages/ActivityPopup/ActivityPopup.vue' +import { mapState, mapMutations } from 'vuex' +import {setPopupRedisTime,getPopupAcitivty} from '@/api/popup.js' import { changeCollect } from "@/api/collect.js"; import { saveShare, saveShareClickRecord } from "@/api/share.js"; import { silentLogin } from "@/api/connect.js"; @@ -283,13 +300,15 @@ import storage from "@/utils/storage.js"; import TopBar from "@/components/TopBar.vue"; import { nextTick } from "vue"; - +import {getVideoCover } from "@/api/common.js" export default { - components: {TopBar}, + components: {TopBar,ActivityPopup}, computed: { hasPlayTime() { return this.sliderFormatTime(this.progress > 0 ? this.duration * this.progress / 100 : 0); - } + }, + // 閿欒锛氭病鏈夌敤 ... 灞曞紑锛屽鑷� activityPopup 鏄嚱鏁� + ...mapState(['activityPopup']) }, data() { return { @@ -382,6 +401,10 @@ } }, onShow() { + + this.openActivityPopup() + + if(!this.userId){ this.getUserId() } @@ -463,12 +486,104 @@ shareUser: userInfo.id } saveShare(data) - return { - title: videoInfo.title, - path: `/pages/tabbar/index/home?videoId=${videoInfo.id}&userId=${userInfo.id}`, - } - }, + // getVideoCover(videoInfo.id).then(res =>{ + // if(res.statusCode === 200){ + // imageUrl = res.data.data + // console.log(imageUrl) + // return { + // title: videoInfo.title, + // path: `/pages/tabbar/index/home?videoId=${videoInfo.id}&userId=${userInfo.id}`, + // imageUrl: imageUrl + // } + // } + + // }) + console.log(videoInfo) + return { + title: videoInfo.title, + path: `/pages/tabbar/index/home?videoId=${videoInfo.id}&userId=${userInfo.id}`, + imageUrl: videoInfo.coverUrl + } + // 淇濆瓨鍒嗕韩璁板綍 + }, methods: { + async openActivityPopup() { + await getPopupAcitivty().then(res =>{ + if(res.statusCode === 200){ + let obj = res.data.data; + if(obj.enableStatus === 'ON'){ + setPopupRedisTime().then(res =>{ + if(res.statusCode === 200){ + if(res.data.state){ + this.showActivityPopup({ + title: obj.activityName, + desc: obj.activityDes, + image: obj.activityCoverUrl, + endTime:new Date(obj.endTime).getTime() + }) + }else{ + this.hideActivityPopup() + } + + } + }); + } + + } + }) + + }, + ...mapMutations(['showActivityPopup','hideActivityPopup']), // 寮曞叆Vuex鐨勬柟娉� + onClosePopup() { + this.hideActivityPopup() + }, + onJoinActivity() { + // 澶勭悊鍙備笌娲诲姩閫昏緫 + console.log('鍏ㄥ眬锛氱敤鎴峰弬涓庢椿鍔�') + this.hideActivityPopup() + }, + replyClick(reply){ + + if(this.userId === reply.userId){ + let that = this; + uni.showModal({ + title: '鎻愮ず', + content: '浣犵‘瀹氳鍒犻櫎鍚�', + success: function (res) { + if (res.confirm) { + console.log('纭畾'); + //璋冪敤鍒犻櫎鐨勯�昏緫 + console.log(reply) + removeByIdVideoComment(reply.id).then(res =>{ + const item = { + id:reply.videoId + } + that.commentQuery.pageNumber = 1; + //閲嶆柊鏇存柊璇勮 + that.showComments(item); + }) + + } else if (res.cancel) { + console.log('鍙栨秷'); + } + } + }); + + } + console.log(reply) + }, + // 鎴彇瑙嗛褰撳墠甯� + captureVideoFrame(videoCtx) { + return new Promise((resolve) => { + videoCtx.requestFrame(() => { + wx.canvasToTempFilePath({ + canvasId: 'shareCanvas', + success: (res) => resolve(res), + fail: () => resolve({ tempFilePath: '/assets/default-cover.jpg' }) + }); + }); + }); + }, requestFullScreen(id,item){ console.log(item) @@ -813,6 +928,7 @@ this.commentQuery.pageNumber++; }) }, + // 鏄剧ず璇勮寮圭獥 async showComments(item) { this.commentForm.videoId = item.id; diff --git a/store/index.js b/store/index.js index 3458c64..f05a8df 100644 --- a/store/index.js +++ b/store/index.js @@ -15,8 +15,28 @@ userInfo: storage.getUserInfo(), uuid: storage.getUuid(), token: "", + // 娲诲姩寮圭獥鐘舵�� + activityPopup: { + show: false, + title: '', + desc: '', + image: '', + endTime: 0 + } }, mutations: { + // 鏄剧ず寮圭獥 + showActivityPopup(state, data) { + state.activityPopup = { + show: true, + ...data // 鍚堝苟浼犲叆鐨勫脊绐楁暟鎹紙鏍囬銆佹弿杩扮瓑锛� + } + console.log("Vuex 鐘舵�佹洿鏂板悗锛�", state.activityPopup); + }, + // 闅愯棌寮圭獥 + hideActivityPopup(state) { + state.activityPopup.show = false + }, login(state, userInfo) { state.userInfo = userInfo || {}; state.userName = -- Gitblit v1.8.0