Tang 3 tahun lalu
induk
melakukan
b4dfd55e25

+ 2 - 0
common/api.js

@@ -14,6 +14,7 @@ import systemPlan from './httpList/systemPlan.js'
 import myStudent from './httpList/myStudent.js'
 import order from './httpList/order.js'
 import informUser from './httpList/informUser.js'
+import study from './httpList/study.js'
 export default {
 	...login,
 	...polyvVideo,
@@ -31,4 +32,5 @@ export default {
 	...myStudent,
 	...order,
 	...informUser,
+	...study,
 }

+ 7 - 1
common/httpList/goods.js

@@ -10,13 +10,19 @@ export default {
 			noToken: true
 		})
 	},
-	goodsDetail(data) {
+	commonGoodsDetail(data) {
 		return myRequest({
 			url: '/app/common/goods/'+ data,
 			method: 'get',
 			noToken: true
 		})
 	},
+	goodsDetail(data) {
+		return myRequest({
+			url: '/goods/'+ data,
+			method: 'get'
+		})
+	},
 	goodsCourseList(data) {
 		return myRequest({
 			url: '/app/common/goods/course/list/'+ data,

+ 13 - 0
common/httpList/study.js

@@ -0,0 +1,13 @@
+import {
+	myRequest
+} from '../request.js'
+export default {
+	studyRecord(data) {
+		return myRequest({
+			url: '/study/record',
+			method: 'post',
+			data: data
+		})
+	}
+	
+}

+ 9 - 1
components/course/courseChapter.vue

@@ -7,7 +7,7 @@
 		</view>
 		<view v-if="!down">
 			<view v-for="(itemM,indexM) in list" >
-				<courseSection :isBuy="isBuy" :menuItem="itemM"></courseSection>
+				<courseSection :isBuy="isBuy" :isRebuild="isRebuild" :menuItem="itemM" :levelId="levelId+'-'+itemM.sectionId"></courseSection>
 				<u-line v-if="indexM<list.length-1"></u-line>
 			</view>
 		</view>
@@ -27,6 +27,14 @@ export default {
 		isBuy: {
 			type: Boolean,
 			default: false
+		},
+		levelId: {
+			type: String,
+			default: ""
+		},
+		isRebuild: {
+			type: Boolean,
+			default: false
 		}
 	},
 	components: {

+ 9 - 1
components/course/courseModule.vue

@@ -7,7 +7,7 @@
 		</view>
 		<view v-if="!down">
 			<view v-for="(itemM,indexM) in list" >
-				<courseChapter :isBuy="isBuy"  :menuItem="itemM"></courseChapter>
+				<courseChapter :isBuy="isBuy" :isRebuild="isRebuild"  :menuItem="itemM" :levelId="levelId+'-'+itemM.chapterId"></courseChapter>
 				<u-line v-if="indexM<list.length-1"></u-line>
 			</view>
 		</view>
@@ -26,6 +26,14 @@ export default {
 		isBuy: {
 			type: Boolean,
 			default: false
+		},
+		levelId: {
+			type: String,
+			default: ""
+		},
+		isRebuild: {
+			type: Boolean,
+			default: false
 		}
 	},
 	components: {

+ 9 - 0
components/course/courseSection.vue

@@ -41,6 +41,14 @@ export default {
 		isBuy: {
 			type: Boolean,
 			default: false
+		},
+		levelId: {
+			type: String,
+			default: ""
+		},
+		isRebuild: {
+			type: Boolean,
+			default: false
 		}
 	},
 	data() {
@@ -81,6 +89,7 @@ export default {
 			this.$store.commit('setPlaySectionId', {playSectionId  :this.newId});
 	//		return
 			eventHub.$emit('getSection', this.menuItem)
+			eventHub.$emit('levelId', this.levelId)
 			
 		}
 	},

+ 9 - 19
pages/wd/index.vue

@@ -30,15 +30,6 @@
 						今天有 <text style="color: #007AFF;margin: 0 5rpx;">3</text> 个学习任务
 					</view>
 				</navigator>
-				<navigator url="/pages2/learn/my_learn" class="menu_box">
-					<view style="display: flex;align-items: center;">
-						<image src="/static/icon/my_icon2.png" class="my_icon"></image>
-						<view>我的学时</view>
-					</view>
-					<view>
-						累计<text style="color: #007AFF;margin: 0 5rpx;">3</text> 学时未通过
-					</view>
-				</navigator>
 				<view class="two_menu">
 					<navigator url="/pages2/wd/class" class="small_menu">
 						<image src="/static/icon/my_icon3.png" class="my_icon"></image>
@@ -49,16 +40,15 @@
 						<view>我的题库通</view>
 					</navigator>
 				</view>
-				<view class="two_menu">
-					<navigator class="small_menu">
-						<image src="/static/icon/my_icon5.png" class="my_icon"></image>
-						<view>我的证书</view>
-					</navigator>
-					<navigator class="small_menu">
-						<image src="/static/icon/my_icon6.png" class="my_icon"></image>
-						<view>我的发票</view>
-					</navigator>
-				</view>
+				<navigator url="/pages2/learn/my_learn" class="menu_box">
+					<view style="display: flex;align-items: center;">
+						<image src="/static/icon/my_icon2.png" class="my_icon"></image>
+						<view>我的学时</view>
+					</view>
+					<view>
+						累计<text style="color: #007AFF;margin: 0 5rpx;">3</text> 学时未通过
+					</view>
+				</navigator>
 				<navigator url="/pages2/exam/index"  class="menu_box">
 					<view style="display: flex;align-items: center;">
 						<image src="/static/icon/my_icon7.png" class="my_icon"></image>

+ 4 - 4
pages2/bank/detail.vue

@@ -5,7 +5,7 @@
 				<image :src="$method.splitImgHost(goodsData.coverUrl, true)" style="width: 100%;"></image>
 				<view style="padding:20rpx">
 					<view style="display: flex;margin-top: 13rpx;">
-						<view class="yearTag">{{goodsData.createTime | formatDate}}</view>
+						<view class="yearTag">{{goodsData.year}}</view>
 						<view class="titleTag">{{goodsData.goodsName}}</view>
 					</view>
 					<view style="display: flex;justify-content: space-between;margin-top: 13rpx;">
@@ -93,7 +93,7 @@
 			</view>
 		</view>
 		<view class="bottomBox">
-			<view class="priceTag">¥ 999.00</view>
+			<view class="priceTag">¥ {{goodsData.standPrice}}</view>
 			<view style="display: flex;color: #FFFFFF;align-items: center;">
 				<view class="btn1" @click="addCart">加购物车</view>
 				<view class="btn2" @click="buy">立即购买</view>
@@ -144,7 +144,7 @@ export default {
 	},
 	methods: {
 		getDetail(){
-			this.$api.goodsDetail(this.id).then(res => {
+			this.$api.commonGoodsDetail(this.id).then(res => {
 				console.log(res)
 				this.goodsData = res.data.data;
 				 
@@ -189,7 +189,7 @@ export default {
 			if(this.$method.isGoLogin()){
 				return
 			}
-			this.$navTo.togo('/pages2/order/confirm_list');
+			this.$navTo.togo('/pages2/order/confirm_list?id='+this.id);
 		},
 		addCart(){
 			if(this.$method.isGoLogin()){

+ 1 - 1
pages2/bank/question_detail.vue

@@ -135,7 +135,7 @@ export default {
 	},
 	methods: {
 		getDetail(){
-			this.$api.goodsDetail(this.id).then(res => {
+			this.$api.commonGoodsDetail(this.id).then(res => {
 				console.log(res)
 				this.goodsData = res.data.data;
 				 

+ 278 - 41
pages2/class/detail.vue

@@ -13,6 +13,10 @@
 					:vid="vid"
 					:showSettingBtn="true"
 					:enablePlayGesture="true"
+					@statechange="onStateChange"
+					:autoplay="autoplay"
+					:isAllowSeek="isAllowSeek"
+					:playbackRate="playbackRate"
 				></polyv-player>
 			</view>
 			<view>
@@ -29,9 +33,9 @@
 				</u-row>
 			</view>
 			<u-line color="#D6D6DB" />
-			<view>
-				<view style="width: 240px;margin: 0 auto;">
-					<u-tabs :list="list" item-width="150" font-size="24" bar-width="80" :current="current" @change="change" active-color="#007AFF"></u-tabs>
+			<view style="display: flex;justify-content: center;">
+				<view style="width: 280px;">
+					<u-tabs :list="list"  font-size="24" bar-width="80" :current="current" @change="change" active-color="#007AFF"></u-tabs>
 				</view>
 			</view>
 			<u-line color="#D6D6DB" />
@@ -39,17 +43,28 @@
 		<view class="box">
 			<!--目录 -->
 			<view v-show="current == 0">
+				<view class="menuBox" v-for="(item, index) in reMenuList">
+					<!--模块 -->
+					<view v-if="item.type == 1"><courseModule :isRebuild="true" :isBuy="true" :menuItem="item" :levelId="item.menuId"></courseModule></view>
+					<!--章 -->
+					<view v-if="item.type == 2"><courseChapter :isRebuild="true" :isBuy="true" :menuItem="item" :levelId="'0-'+item.menuId"></courseChapter></view>
+					<!--节 -->
+					<view v-if="item.type == 3"><courseSection :isRebuild="true" :isBuy="true" :menuItem="item" :levelId="'0-0-'+item.menuId"></courseSection></view>
+				</view>
+			</view>
+			<!--目录 -->
+			<view v-show="current == 1">
 				<view class="menuBox" v-for="(item, index) in menuList">
 					<!--模块 -->
-					<view v-if="item.type == 1"><courseModule :isBuy="true" :menuItem="item"></courseModule></view>
+					<view v-if="item.type == 1"><courseModule :isBuy="true" :menuItem="item" :levelId="item.menuId"></courseModule></view>
 					<!--章 -->
-					<view v-if="item.type == 2"><courseChapter :isBuy="true" :menuItem="item"></courseChapter></view>
+					<view v-if="item.type == 2"><courseChapter :isBuy="true" :menuItem="item" :levelId="'0-'+item.menuId"></courseChapter></view>
 					<!--节 -->
-					<view v-if="item.type == 3"><courseSection :isBuy="true" :menuItem="item"></courseSection></view>
+					<view v-if="item.type == 3"><courseSection :isBuy="true" :menuItem="item" :levelId="'0-0-'+item.menuId"></courseSection></view>
 				</view>
 			</view>
 			<!--笔记 -->
-			<view v-show="current == 1">
+			<view v-show="current == 2">
 				<view class="inputBottom">
 					<view style="width: 10%;"><image src="/static/icon/note3.png" style="width: 39rpx;height: 39rpx;margin:0 29rpx;"></image></view>
 					<view style="width: 73%;height: 88rpx;margin-bottom: 15rpx;">
@@ -77,7 +92,7 @@
 				</view>
 			</view>
 			<!--答疑 -->
-			<view v-show="current == 2">
+			<view v-show="current == 3">
 				<view class="inputBottom">
 					<view style="width: 73%;height: 88rpx;margin-bottom: 15rpx;margin-left: 10% ;">
 						<u-input height="78" fixed="true" placeholder="您可以在这里输入答疑内容" type="textarea" :custom-style="inputStyle" v-model="value" />
@@ -98,10 +113,10 @@
 			</view>
 		</view>
 		<!-- 播放前拍照start -->
-		<u-popup v-model="photoPopup" mode="bottom" border-radius="32">
+		<u-popup v-model="photoPopup" mode="bottom" border-radius="32" :mask-close-able="false">
 					<view class="photoBox">
 						<view class="photoTop">
-							<view class="sqzz">
+							<view class="sqzz" v-if="true">
 								<u-icon name="close" color="#333333" size="30" @click="closePhoto"></u-icon>
 							</view>
 							<view class="centersq">
@@ -114,7 +129,7 @@
 						<view class="photoCenter">
 							<camera device-position="front" flash="off" @error="error" style="width: 100%; height: 100%" v-if="photoPopup"></camera>
 							<view class="custom">
-								<image src="@/static/zhezhao@2x.png" mode=""></image>
+								<image src="@/pages2/static/zhezhao.png" mode=""></image>
 							</view>
 						</view>
 						<view class="btnResult" @click="takePhoto">
@@ -152,6 +167,9 @@ export default {
 			},
 			playbackRate: [0.5, 0.8, 1.0],
 			list: [
+				{
+					name: '重修目录'
+				},
 				{
 					name: '目录'
 				},
@@ -163,61 +181,243 @@ export default {
 				}
 			],
 			menuList: [
-				{
-					list: [
-						{
-							showChildren: false,
-							children: [1, 2, 3]
-						},
-						{
-							showChildren: false,
-							children: [1]
-						},
-						{
-							showChildren: false,
-							children: [1, 2]
-						}
-					],
-					type: 1
-				},
-				{
-					type: 2,
-					showChildren: false,
-					list: [{}, {}, {}]
-				},
-				{
-					type: 3,
-					list: [{}, {}]
-				}
 			],
-			current: 0,
+			current: 1,
 			vid:'',
 			goodsId:0,
 			goodsData:{},
 			photoPopup:false,
+			goodsPlayConfig:null,
+			autoplay:false,
+			isAllowSeek:'no',
+			playbackRate: [1.0],
+			timer:null,
+			goodsPhotographConfig:null,
+			intervalTimeList:[],// 间隔拍照时长
+			intervalTimeIndex:0 ,//当前处于哪个时间段拍照
+			playTime:0 ,//页面播放时长,不含暂停
+			currentTime:0,
+			avatarUrl:'',
+			ossAvatarUrl:'',
+			studyDuration:0, // 当前视频时长
+			gradeId:0,
+			chapterId:0,
+			moduleId:0,
+			reMenuList: [
+			],
+			
 		};
 	},
 	onUnload() {},
-	computed: { ...mapGetters(['userInfo']) },
+	computed: { ...mapGetters(['userInfo','playSectionId']) },
 	onLoad(option) {
 		this.courseId = option.id;
 		this.goodsId = uni.getStorageSync('courseGoodsId');
 		this.courseDetail();
 		this.getMenuList();
 		this.getGoodsDetail()
+		
 	},
 	onShow() {},
+	onUnload() {
+		if(this.playSectionId>0){
+			//退出提交记录
+			this.ossAvatarUrl = ""
+			this.postStudyRecord()
+			//清除正在播放的节ID
+			this.$store.commit('setPlaySectionId', {playSectionId  :0});
+		}
+		
+	},
 	mounted() {
 		eventHub.$on('getSection', item => {
-			this.vid = item.recordingUrl
+			if(this.timer){
+				clearInterval(this.timer);
+			}
+			 if(this.vid){
+				 //切换视频
+				 var polyvPlayerContext = this.selectComponent('#playerVideo');
+				 polyvPlayerContext.changeVid(item.recordingUrl)
+			 }else{
+				 this.vid = item.recordingUrl
+			 }
 			this.startStatus = true
+			this.startTime = 0
+		});
+		eventHub.$on('levelId', item => {
+			let arr = item.split('-')
+			//点击节获取的各层级ID
+			this.moduleId = arr[0]
+			this.chapterId = arr[1]
+			console.log(item,99)
 		});
 	},
 	methods: {
+		postStudyRecord(status=0) {
+			let self = this;
+			let data = {
+				photo:self.ossAvatarUrl,
+				sectionId:parseInt(self.playSectionId),
+				goodsId:parseInt(self.goodsId),
+				courseId:parseInt(self.courseId),
+				studyDuration:parseInt(self.studyDuration),
+				gradeId:parseInt(self.gradeId),
+				chapterId:parseInt(self.chapterId),
+				moduleId:parseInt(self.moduleId)
+			}
+			if(status>0){
+				data.status = status
+			}
+			console.log("提交接口",data)
+			this.$api.studyRecord(data).then(res => {
+				console.log(res)
+			});
+		},
+		uploadFile(options, int) {
+			var self = this;
+			return new Promise((resolve, reject) => {
+				var data = {
+					imageStatus: int
+				};
+				self.$api.aliyunpolicy(data).then(res => {
+
+					if(res.data.code!=200){
+						self.$method.showToast('签名错误'+JSON.stringify(res.data))
+						return
+					}
+					var ossToken = res.data.data.resultContent;
+					if(ossToken.host==null||ossToken.host==undefined){
+						self.$method.showToast('上传路径报错'+JSON.stringify(res.data))
+						return
+					}
+					uni.uploadFile({
+						url: ossToken.host,
+						name: 'file',
+						filePath: options,
+						fileType: 'image',
+						header: {
+							AuthorizationToken: 'WX ' + uni.getStorageSync('token')
+						},
+						formData: {
+							key: ossToken.dir,
+							OSSAccessKeyId: ossToken.accessid,
+							policy: ossToken.policy,
+							Signature: ossToken.signature,
+							callback: ossToken.callback,
+							success_action_status: 200
+						},
+						success: result => {
+							if (result.statusCode === 200) {
+								self.ossAvatarUrl = ossToken.dir;
+								resolve();
+							} else {
+								uni.showToast({
+									title: '上传失败',
+									icon: 'none'
+								});
+								return;
+							}
+						},
+						fail: error => {
+							uni.showToast({
+								title: '上传接口报错'+error,
+								icon: 'none'
+							});
+							return;
+						}
+					});
+				});
+			});
+		},
+		imageInfos(){
+			var self = this
+			return new Promise((resolve, reject) => {
+				uni.getImageInfo({
+					src: self.avatarUrl,
+					success: async res => {
+						let canvasWidth = res.width; //图片原始长宽
+						let canvasHeight = res.height;
+						if (canvasWidth > 1000 || canvasHeight > 1000) {
+							uni.compressImage({
+								src: self.avatarUrl,
+								quality: 75,
+								width: '50%',
+								height: '50%',
+								success: async rest => {
+									const waitUpload = await self.uploadFile(rest.tempFilePath, 0);
+									resolve()
+								} 
+							});
+						} else {
+							console.log('无需压缩');
+							const waitUpload = await self.uploadFile(self.avatarUrl, 0);
+							resolve()
+						}
+					}
+				});
+			});
+		},
+		timeEvent() {
+			let self = this
+		        var polyvPlayerContext = this.selectComponent('#playerVideo');
+				if (polyvPlayerContext != null) {
+					let PlayCurrentTime = polyvPlayerContext.getCurrentTime();
+					this.studyDuration = PlayCurrentTime
+					if(this.currentTime<PlayCurrentTime){
+						this.playTime+=(PlayCurrentTime-this.currentTime)
+						this.currentTime = PlayCurrentTime
+					}else{
+						this.currentTime = PlayCurrentTime
+					}
+					//判断是否需要拍照
+					if(this.intervalTimeList.length>this.intervalTimeIndex){
+						let photoTime = Number(this.intervalTimeList[this.intervalTimeIndex]) * 60 //获取拍照秒数
+						if(photoTime<this.playTime){
+							//启动拍照
+							//暂停
+							polyvPlayerContext.exitFullScreen()
+							polyvPlayerContext.pause()
+							this.openPhoto();
+							this.intervalTimeIndex++
+						}
+					}
+				
+				}
+		},
+		onStateChange(newstate, oldstate) {
+			if (newstate.detail.newstate == 'playing') {
+				//开始播放
+				if(this.timer){
+					clearInterval(this.timer);
+				}
+				this.timer = setInterval(this.timeEvent, 1500);//定时器
+			}
+			if (newstate.detail.newstate == 'pause') {
+				//暂停提交记录
+				/* this.ossAvatarUrl = ""
+				this.postStudyRecord() */
+			}
+			if (newstate.detail.newstate == 'ended') {
+				this.ossAvatarUrl = ""
+				this.postStudyRecord(1)
+			}
+			
+			
+		},
 		//拍照
 		openPhoto(){
 			this.photoPopup = true
 		},
+		async submit(){
+			const waitYS = await this.imageInfos();
+			this.postStudyRecord()//提交记录
+			//恢复播放
+			var polyvPlayerContext = this.selectComponent('#playerVideo');
+			if (polyvPlayerContext != null) {
+				polyvPlayerContext.play();
+			}
+			console.log(this.ossAvatarUrl,"拍照完成456")
+		},
 		//确认拍照
 		takePhoto() {
 			var self = this
@@ -226,6 +426,9 @@ export default {
 				quality: 'high',
 				success: res => {
 					console.log(res.tempImagePath)
+					self.avatarUrl = res.tempImagePath
+					self.submit()
+					
 					self.photoPopup = false
 				},
 				fail: err => {
@@ -245,12 +448,45 @@ export default {
 			let self = this
 			this.$api.goodsDetail(this.goodsId).then(res => {
 				self.goodsData = res.data.data;
-				 
+				self.gradeId = self.goodsData.gradeId
+				self.getReMenuList() //获取重修目录
+				if(self.goodsData.goodsPlayConfig){
+					self.goodsPlayConfig = JSON.parse(self.goodsData.goodsPlayConfig);
+					if(self.goodsPlayConfig.autoPlay>0){
+						self.autoplay = true
+					}
+					if(self.goodsPlayConfig.drag>0){
+						self.isAllowSeek = "yes"
+					}
+					if(self.goodsPlayConfig.speed>0){
+						self.playbackRate = [0.5,0.8,1.0,1.25,1.5,2.0]
+					}
+				}
+				if(self.goodsData.goodsPhotographConfig){
+					self.goodsPhotographConfig = JSON.parse(self.goodsData.goodsPhotographConfig);
+					if(self.goodsPhotographConfig.intervalTime){
+						self.intervalTimeList = self.goodsPhotographConfig.intervalTime.split(',')
+					}
+				}
 			})
 		},
 		startVideo() {
 			this.startStatus = true;
 		},
+		getReMenuList() {
+			let self = this;
+			this.$api.menuList({ courseId: this.courseId,rebuild:1,gradeId:this.gradeId }).then(res => {
+				if (res.data.code == 200) {
+					for (let i = 0; i < res.data.rows.length; i++) {
+						let item = res.data.rows[i];
+						item.down = true;
+						item.id = item.menuId;
+						item.name = item.menuName;
+					}
+					self.reMenuList = res.data.rows;
+				}
+			});
+		},
 		getMenuList() {
 			let self = this;
 			this.$api.menuList({ courseId: this.courseId }).then(res => {
@@ -270,6 +506,7 @@ export default {
 			this.$api.courseDetail(this.courseId).then(res => {
 				if (res.data.code == 200) {
 					self.detail = res.data.data;
+					self.gradeId = self.detail.gradeId
 				}
 			});
 		},

+ 3 - 5
pages2/course/detail.vue

@@ -61,6 +61,7 @@
 								<courseChapter v-if="itemM.type==2" :isBuy="false" :menuItem="itemM"></courseChapter>
 								<courseSection v-if="itemM.type==3" :isBuy="false" :menuItem="itemM"></courseSection>
 								<u-line></u-line>
+								
 							</view>
 						</view>
 					</view>
@@ -135,7 +136,6 @@ export default {
 					if(itemChild.auditionMinute>0){
 						this.listenSecond = itemChild.auditionMinute *60 //试听秒数
 					}
-					
 				}
 			}
 			
@@ -166,7 +166,7 @@ export default {
 				if(this.timer){
 					clearInterval(this.timer);
 				}
-				this.timer = setInterval(this.timeEvent, 2000);//定时器
+				this.timer = setInterval(this.timeEvent, 1500);//定时器
 			}
 			
 		},
@@ -191,9 +191,7 @@ export default {
 								self.closePlay()
 							}
 						});
-						
 					}
-					
 				}
 		},
 		openCourse(item){
@@ -253,7 +251,7 @@ export default {
 		getDetail() {
 			let self = this
 			let sectionIdList = []
-			this.$api.goodsDetail(this.id).then(res => {
+			this.$api.commonGoodsDetail(this.id).then(res => {
 				if(res.data.code==200){
 					if(res.data.data.mobileDetailHtml){
 						res.data.data.mobileDetailHtml = res.data.data.mobileDetailHtml.replace(/<img/gi,'<img style="max-width:100%;"')

+ 1 - 1
pages2/order/confirm_list.vue

@@ -299,7 +299,7 @@ export default {
 		},
 		getDetail() {
 			let self = this
-			this.$api.goodsDetail(this.id).then(res => {
+			this.$api.commonGoodsDetail(this.id).then(res => {
 				if(res.data.code==200){
 					self.detail = res.data.data
 					self.getExamine(self.detail.projectId)

+ 0 - 0
static/zhezhao@2x.png → pages2/static/zhezhao.png