liujiaxin 2 settimane fa
parent
commit
37e00b1d48

+ 9 - 0
pages.json

@@ -816,6 +816,15 @@
 						
 					}
 
+				},{
+					"path": "live/complaint",
+					"style": {
+						"navigationBarTitleText": "我的反馈",
+						"navigationBarTextStyle": "black",
+						"app-plus": {
+							"bounce": "none"
+						}
+					}
 				},
 
 				{

+ 28 - 7
pages_course/living.vue

@@ -28,6 +28,11 @@
 					</view>
 				</view>
 
+				<!-- <view class="complaint-box" @click="navgetTo('/pages_shopping/live/complaint')">
+					<image class="image w32 h32 mr10"  src="/static/images/complaint.png" mode="widthFix" />
+					<view class="fs26">投诉</view>
+				</view> -->
+
 				<!-- 右边的side -->
 				<view class="side-group" :class="{ 
 								'top2': (!isShowRed && !(isShowLottery && countdown)),
@@ -38,14 +43,14 @@
 							<image class="image" style="width: 72rpx;" src="/static/images/redbag.png"
 								mode="widthFix" />
 						</button>
-						<view style="font-size: 30rpx;">领红包</view>
+						<view class="fs30">领红包</view>
 					</view>
 
 					<view class="side-item" @click="onLottery()" v-if="isShowLottery && countdown">
 						<button class="button button-reset">
 							<image class="image" src="/static/images/lottery.png" mode="widthFix" />
 						</button>
-						<view style="font-size: 30rpx;">抽奖</view>
+						<view class="fs30">抽奖</view>
 					</view>
 
 					<view class="side-item" @click="onLike">
@@ -320,14 +325,14 @@
 					<image class="bg" src="/static/images/red_bg.png"></image>
 					<view class="winning_content">
 						<view class="title">我的中奖记录</view>
-						<view class="row mb40">
+						<view class="row mb40" fs34>
 							<view class="start">时间</view>
 							<view class="center">状态</view>
 							<view class="end ">奖品</view>
 						</view>
 						<scroll-view enable-flex scroll-y v-if="prizeAll" style="height: 500rpx">
-							<view class="row fs28 mb20" v-for="(item, index) in prizeAll" :key="index">
-								<view class="start">{{ item.createTime }}</view>
+							<view class="row mb20 fs34 " v-for="(item, index) in prizeAll" :key="index">
+								<view class="start fs30">{{ item.createTime }}</view>
 								<view class="center button" v-if="item.orderStatus=='-9'||!item.orderStatus"
 									@click="navgetTo('/pages_shopping/live/confirmCreateOrder?type=win&productId='+item.productId+'&liveId='+liveId+'&recordId='+item.id),winning=false">
 									<text>填地址</text>
@@ -2193,6 +2198,7 @@
 			},
 			// 录播时间点
 			onVideoMetaLoaded(e) {
+				console.log("录播时间点",e)
 				this.videoProgressKey = `videoProgress_${this.liveId}`;
 				this.setVideoProgress();
 			},
@@ -2206,8 +2212,11 @@
 					// 录播:计算当前时间与开始时间的差值,对视频总时长取模
 					const diff = this.getTimeDifferenceInSeconds(this.liveItem.startTime);
 					if (diff > this.liveItem.duration) {
-						const storedProgress = uni.getStorageSync(this.videoProgressKey);
+						console.log("开始断点续播了")
+						const storedProgress = uni.getStorageSync(this.videoProgressKey) || 0;
+						console.log("开始断点续播了storedProgress", storedProgress)
 						currentTime = storedProgress >= this.liveItem.duration ? 0 : storedProgress || 0;
+						console.log("开始断点续播了currentTime", currentTime)
 					} else {
 						currentTime = diff % this.liveItem.duration;
 					}
@@ -2249,7 +2258,6 @@
 				if (Math.floor(this.videoCurrentTime) % 10 === 0) {
 					this.saveVideoProgress();
 				}
-				// this.setVideoProgress();
 			},
 
 			// 视频暂停
@@ -4036,6 +4044,19 @@
 			}
 		}
 
+		.complaint-box {
+			position: absolute;
+			top: 15%;
+			right: 24rpx;
+			display: flex;
+			align-items: center;
+			background-color: rgba(77, 77, 77, 0.5);
+			padding: 16rpx 26rpx;
+			color: #fff;
+			border-radius: 28rpx;
+			z-index: 999;
+		}
+
 		// 减少重绘
 		.side-group,
 		.content-top {

+ 489 - 0
pages_shopping/live/complaint.vue

@@ -0,0 +1,489 @@
+<template>
+	<view>
+		<view class="header-nav" :style="{height: `calc(88rpx + ${statusBarHeight}px)`,paddingTop: statusBarHeight + 'px'}">
+			<view class="arrow-left" :style="{top: statusBarHeight + 'px'}" @click="goBack">返回</view>
+			<view class="header-title" :style="{height:menuButtonH+'px',lineHeight:menuButtonH+'px'}">投诉反馈</view>
+		</view>
+		<view class="container" :style="{paddingTop: `calc(88rpx + ${statusBarHeight}px)`}">
+			<view class="formbox" v-if="isLastChild==1">
+				<view class="formbox-title">{{ text }}</view>
+				<view class="form">
+					<u-form labelPosition="top" labelWidth='auto' :model="formdata" :rules="rules" ref="uForm" errorType="toast">
+						<u-form-item label=" " prop="complaintContent">
+							<u--textarea v-model="formdata.complaintContent" border="none" :clearable="true" placeholder="请填写反馈内容" count maxlength='200'></u--textarea>
+						</u-form-item>
+						<view class="box">
+							<u-form-item label="图片(最多9张)">
+								<view class="imgitem">
+									<u-upload
+										:fileList="fileList1"
+										@afterRead="afterRead"
+										@delete="deletePic"
+										name="1"
+										:maxCount="9"
+									></u-upload>
+								</view>
+							</u-form-item>
+						</view>
+					</u-form>
+				</view>
+				<view class="footer-btn">
+					<button class="submit-btn" @click="submit">提交</button>
+					<!-- <button class="submit-btn back-btn" @click="goBack">返回</button> -->
+				</view>
+			</view>
+			<view class="container" v-else>
+				<view class="list-item title">请选择反馈类型</view>
+				<view class="list-item" v-for="(item, index) in feedbackItems" :key="index"
+					@click="handleClick(item,index)">
+					<view>{{ item.complaintTypeName }}</view>
+					<uni-icons type="right" size="20" color="rgba(0,0,0,.3)" v-if="isLastChild==0"></uni-icons>
+				</view>
+				<view class="list-item" v-if="pageIndex!=0&&isLastChild==0" @click="goBack">
+					返回上一层
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapGetters } from 'vuex';
+	import{ getTypeTree, complaintRecord,loginByMp } from "@/api/course.js"
+	export default {
+		data() {
+			return {
+				statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
+				menuButtonH: 45,
+				pageIndex: 0,
+				list: [],
+				feedbackItems: [],
+				userId: '',
+				courseId: '',
+				videoId: '',
+				formdata: {
+					complaintContent: ""
+				},
+				rules: {
+					complaintContent:[{
+						required: true,
+						message: '投诉反馈内容不能为空',
+						trigger: ["change", "blur"]
+					}]
+				},
+				text: '',
+				templateId: 0,
+				user: {},
+				isLastChild: 0,
+				isLogin: false,
+				fileList1: [],
+				projectCode:'',
+				code:''
+			};
+		},
+		computed: {
+			...mapGetters(['coureLogin']),
+		},
+		watch: {
+		    coureLogin: {
+		      immediate: true,          // 页面一进入就检查一次
+		      handler(val) {
+		        if (val == 2) {
+					console.log("AppToken失效,请重新登录")
+					this.isLogin = false
+					this.goLogin()
+		        }
+		      }
+		    }
+		},
+		onLoad(option) {
+			this.userId = option.userId || ''
+			this.courseId = option.courseId || ''
+			this.videoId = option.videoId || ''
+			this.projectCode = option.projectCode || ''
+			uni.$on('usercode',(data)=>{
+				if(data) {
+					this.code=data.code
+					this.goLogin(data)
+				}
+			})
+			this.utils.getDomain({projectCode:this.projectCode}).then(res=>{
+				if(res.code == 200) {
+					uni.setStorageSync('addressUrl',res.addressUrl)
+					this.utils.isLoginCourseAuto().then(
+						res => {
+							if(res){
+								this.isLogin = true
+								this.getMenuButton()
+								this.getList()
+							} else{
+								this.isLogin = false
+								this.goLogin()
+							}
+						},
+						rej => {}
+					);
+				}
+			})
+		},
+		onUnload() {
+			uni.$off('usercode')
+		},
+		methods: {
+			getMenuButton(){
+				const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
+				this.menuButtonH = menuButtonInfo.height
+			},
+			goBack() {
+				// 返回上一层逻辑
+				if (this.pageIndex == 0) {
+					uni.navigateBack();
+				} else {
+					this.pageIndex--;
+					this.formdata = {
+						complaintContent: ""
+					}
+					if (this.isLastChild == 1) {
+						this.isLastChild = 0
+					} else {
+						if (this.pageIndex == 0) {
+							this.feedbackItems = this.list
+							this.templateId = 0
+						} else {
+							const list = this.findGrandparentOrAllData(this.list, this.templateId)
+							this.feedbackItems = list.childrenType
+							this.templateId = list.complaintTypeId
+						}
+					}
+				
+				}
+			},
+			findGrandparentOrAllData(data, targetId) {
+				// 递归函数,用于查找目标节点的父级节点
+				function findParent(node, targetId) {
+					if (!node || !node.childrenType) return null;
+			
+					for (let child of node.childrenType) {
+						if (child.complaintTypeId === targetId) {
+							return node; // 找到目标节点的父级节点
+						}
+			
+						const result = findParent(child, targetId); // 递归查找子节点
+						if (result) return result;
+					}
+			
+					return null;
+				}
+			
+				// 遍历顶层节点,查找目标节点的父级和祖父级节点
+				for (let root of data) {
+					if (root.complaintTypeId === targetId) {
+						return data; // 如果目标节点是顶层节点,返回所有数据
+					}
+			
+					const parent = findParent(root, targetId); // 查找目标节点的父级节点
+					if (parent) {
+						const grandparent = findParent(root, parent.complaintTypeId); // 查找父级节点的父级节点
+						return grandparent || data; // 如果找到祖父节点返回祖父节点,否则返回所有数据
+					}
+				}
+			
+				return data; // 如果没有找到目标节点,返回所有数据
+			},
+			handleClick(item,index) {
+				if (this.isLastChild == 1) return
+				if (this.pageIndex >= 0) {
+					this.pageIndex++
+					let children = this.feedbackItems[index].childrenType || [];
+					this.templateId = this.feedbackItems[index].complaintTypeId
+					this.formdata = {
+						complaintContent: ""
+					}
+					this.text = this.feedbackItems[index].complaintTypeName
+					if (children.length > 0) {
+						this.isLastChild = 0
+						this.feedbackItems = children
+						this.templateId = this.feedbackItems[0].complaintTypeId
+					} else {
+						this.isLastChild = 1
+						this.formdata = {
+							complaintContent: ""
+						}
+						setTimeout(() => {
+							this.$refs.uForm.setRules(this.rules)
+						}, 200)
+					}
+				}
+			},
+			getList(){
+				getTypeTree().then(res=>{
+					if(res.code == 200) {
+						this.list = res.data
+						this.pageIndex = 0
+						this.feedbackItems = this.list
+					}
+				})
+			},
+			submit() {
+				if(this.fileList1.some(item=>item.status == 'uploading')) {
+					uni.showToast({
+						title: '等待图片上传中',
+						icon: 'none'
+					})
+					return
+				}
+				var images=[];
+				this.fileList1.forEach(function(element) {
+					images.push(element.url)
+				});
+				this.$refs.uForm.validate().then(res => {
+					if (res) {
+						const param = {
+							userId: this.userId,
+							complaintTypeId: this.templateId,
+							complaintContent: this.formdata.complaintContent,
+							courseId: this.courseId,
+							videoId: this.videoId,
+							complaintUrl: images.toString()
+						}
+						complaintRecord(param).then(res=>{
+							uni.showModal({
+								title: '',
+								content: '我们已收到您的反馈,谢谢',
+								showCancel: false,
+								success: function (res) {
+									if (res.confirm) {
+										uni.navigateBack()
+									} else if (res.cancel) {
+										uni.navigateBack()
+									}
+								}
+							});
+						})
+					}
+				})
+			},
+			deletePic(event) {
+				this[`fileList${event.name}`].splice(event.index, 1)
+			},
+			async afterRead(event) {
+				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
+				let lists = [].concat(event.file)
+				let fileListLen = this[`fileList${event.name}`].length
+				lists.map((item) => {
+					this[`fileList${event.name}`].push({
+						...item,
+						status: 'uploading',
+						message: '上传中'
+					})
+				})
+				for (let i = 0; i < lists.length; i++) {
+					const result = await this.uploadFilePromise(lists[i].url)
+					let item = this[`fileList${event.name}`][fileListLen]
+					this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
+						status: 'success',
+						message: '',
+						url: result
+					}))
+					fileListLen++
+				}
+			},
+			uploadFilePromise(url) {
+				const projectCode = uni.getStorageSync('projectCode')
+				return new Promise((resolve, reject) => {
+					let a = uni.uploadFile({
+						url: uni.getStorageSync('addressUrl_'+projectCode)+ '/app/common/uploadOSS', // 仅为示例,非真实的接口地址
+						filePath: url,
+						name: 'file',
+						success: (res) => {
+							setTimeout(() => {
+								console.log(JSON.parse(res.data).url)
+								resolve(JSON.parse(res.data).url)
+							}, 1000)
+						}
+					});
+				})
+			},
+			goLogin(data) {
+				if(!this.projectCode){
+					uni.showToast({
+						title: '链接有误',
+						icon: 'none'
+					});
+					return
+				} 
+				this.loginFsUserWx(data)
+				return
+				this.utils.getProvider().then(provider=>{
+					console.log('当前的环境商',provider)
+					if (!provider) {
+					  reject()
+					}
+					uni.login({
+						provider: provider,
+						success: async loginRes => {
+							console.log(loginRes)
+							uni.getUserInfo({
+							   provider: provider,
+							   success: (infoRes)=> {
+								    uni.showToast({
+										title: '处理中...',
+										icon: 'loading'
+								    });
+									loginByMp({code: loginRes.code,encryptedData:infoRes.encryptedData,iv:infoRes.iv,appId:getApp().globalData.appId}).then(res=>{
+										 uni.hideLoading();
+										 if (res.code == 200) {
+											 this.$store.commit('setCoureLogin', 1);
+											uni.setStorageSync(this.utils.TOKEN_KEYAuto, res.token);
+											uni.setStorageSync('auto_userInfo', JSON.stringify(res.user));
+											this.userId = res.user.userId || ''
+											this.isLogin = true
+											this.getMenuButton()
+											this.getList()
+										 } else {
+											uni.showToast({
+												title: res.msg,
+												icon: 'none'
+											});
+										 }
+									 }).catch(err=>{
+										uni.hideLoading();
+										uni.showToast({
+											icon:'none',
+											title: "登录失败,请重新登录",
+										});
+									});
+							   }
+							});
+						}
+					})
+				}).catch(err => {})
+			},
+			// H5授权绑定关系
+			async loginFsUserWx(data){
+				if(data){
+					let token = uni.getStorageSync('TOKEN_WEXIN');
+					let user = uni.getStorageSync('userInfo')
+					
+					uni.setStorageSync(this.utils.TOKEN_KEYAuto, token);
+					uni.setStorageSync('auto_userInfo', JSON.stringify(user));
+					this.userId = user.userId || ''
+					this.isLogin = true
+					this.getMenuButton()
+					this.getList()
+				}else{
+					uni.setStorageSync('H5course',{
+						companyId: this.urlOption.companyId,
+						companyUserId:this.urlOption.companyUserId,
+						type: 1, //1自动,其他手动
+					})
+					uni.showLoading({ title: '加载中' });
+										
+					try {
+					  await this.utils.getDomain({ projectCode: this.projectCode}); // code 换成你的业务标识
+					  await this.utils.getConfigKey();
+					  uni.navigateTo({
+					  	url:'/pages_course/webview?H5course='+uni.getStorageSync('H5course')
+					  })
+					} catch (err) {
+					  console.error('初始化失败', err);
+					  uni.showToast({ title: '请求失败', icon: 'none' });
+					} finally {
+					  uni.hideLoading();
+					}
+				}
+			}
+		}
+	};
+</script>
+
+<style scoped lang="scss">
+	.container {
+		background-color: #fff;
+	}
+	.formbox-title {
+		padding-bottom: 30rpx;
+		border-bottom: 1px solid #f4f4f4;
+	}
+	.formbox {
+		border-top: 1px solid #f4f4f4;
+		padding: 30rpx;
+	}
+	.box {
+		padding-bottom: 24rpx;
+		border-top: 1px solid #f4f4f4;
+		.imgitem {
+			padding-top: 20rpx;
+		}
+	}
+	.footer-btn {
+		margin-top: 50rpx;
+	}
+	.submit-btn {
+		width: 50%;
+		height: 88rpx;
+		line-height: 88rpx;
+		text-align: center;
+		font-size: 30rpx;
+		font-family: PingFang SC;
+		color: #FFFFFF;
+		background: rgb(0,178,106);
+		border-radius: 16rpx;
+		border: 1rpx solid ;
+		margin-bottom: 30rpx;
+		&::after {
+			border: none;
+		}
+	}
+	.back-btn {
+		color: #bbb;
+		background: transparent;
+		border-radius: 16rpx;
+		border: 1rpx solid #999;
+	}
+	.header-nav {
+		height: 88rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		overflow: hidden;
+		background-color: #fff;
+		box-sizing: border-box;
+		width: 100%;
+		position: fixed;
+		top: 0;
+		left: 0;
+		.header-title {
+			flex: 1;
+			text-align: center;
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+			font-family: PingFang SC,PingFang SC;
+			font-weight: 500;
+			font-size: 15px;
+			color: #000;
+			box-sizing: border-box;
+		}
+	}
+	.arrow-left {
+		position: absolute;
+		left: 24rpx;
+		height: 88rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		overflow: hidden;
+	}
+	.list-item {
+		background-color: #fff;
+		padding: 24rpx;
+		border-bottom: 1rpx solid #f4f4f4;
+		font-size: 15px;
+		color: #333;
+	}
+
+	.title {
+		background-color: #f4f4f4;
+	}
+</style>

+ 1 - 1
pages_shopping/live/confirmCreateOrder.vue

@@ -345,7 +345,7 @@
 			        userAddress: this.address.province + ' ' + this.address.city + ' ' + this.address.district + ' ' + this.address.detail,
 			        cartId: "5",
 			        productId: this.productId,
-			        totalNum: this.totalNum,
+			        totalNum: 1,
 			        couponUserId: this.couponUserId,
 					recordId:this.recordId
 			    }

BIN
static/images/complaint.png