Merge branch 'master' of https://e.coding.net/ctcdevteam/cma_search
This commit is contained in:
		
						commit
						eb8dfb71a3
					
				|  | @ -35,17 +35,15 @@ const install = (Vue, vm) => { | |||
| 	//获取子任务单位的详细信息
 | ||||
| 	let getSubtaskDept = (id, params)=> vm.$u.get(`/quality/inspectdept/${id}/`, params); | ||||
| 	let getInspectRecords = (params)=> vm.$u.get('/quality/inspectrecord/', params); | ||||
| 	 | ||||
| 	let getInspectRecord = (id, params)=> vm.$u.get(`/quality/inspectrecord/${id}/`, params); | ||||
| 	 | ||||
| 	let checkInspectRecord = (id, params)=> vm.$u.put(`/quality/inspectrecord/${id}/check/`, params); | ||||
| 	 | ||||
| 	let startInspectDept = (id, params)=>vm.$u.put(`/quality/inspectdept/${id}/start/`, params);//开始检查
 | ||||
| 	 | ||||
| 	let upInspectDept = (id, params)=>vm.$u.put(`/quality/inspectdept/${id}/up/`, params);//提交记录
 | ||||
| 	 | ||||
| 	let appointChecker = (params) => vm.$u.post('/quality/inspectrecord/appoint/', params);//检查指派
 | ||||
| 	let getDocument = (params={})=>vm.$u.get('/quality/document/', params);//文档
 | ||||
| 	let getVideos = (params={})=>vm.$u.get('/vod/video/', params);//点播视频
 | ||||
| 	let getDickey = (params={})=>vm.$u.get('/system/dict/', params);//查询字典
 | ||||
| 	let putMyVideoView =(id)=>vm.$u.put(`/vod/video/${id}/myview/`);//更新本人观看信息
 | ||||
| 	vm.$u.api = {getUserInfo,  | ||||
| 				getCode, | ||||
| 				codeLogin, | ||||
|  | @ -63,7 +61,10 @@ const install = (Vue, vm) => { | |||
| 				upInspectDept, | ||||
| 				appointChecker, | ||||
| 				startInspectDept, | ||||
| 				getDocument | ||||
| 				getDocument, | ||||
| 				getVideos, | ||||
| 				getDickey, | ||||
| 				putMyVideoView | ||||
| 				}; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ const install = (Vue, vm) => { | |||
| 		// }
 | ||||
| 		showLoading: true, | ||||
| 		loadingText: '请求中..', | ||||
| 		originalData: true, | ||||
| 		originalData: false, | ||||
| 		loadingTime: 800, | ||||
| 		loadingMask: true | ||||
| 	}); | ||||
|  | @ -39,7 +39,7 @@ const install = (Vue, vm) => { | |||
| 	Vue.prototype.$u.http.interceptor.response = (response) => { | ||||
| 		// 如果把originalData设置为了true,这里得到将会是服务器返回的所有的原始数据
 | ||||
| 		// 判断可能变成了res.statueCode,或者res.data.code之类的,请打印查看结果
 | ||||
| 		const res = response.data | ||||
| 		const res = response | ||||
| 		if( res.code >= 200 && res.code < 300 ) { | ||||
| 			// 如果把originalData设置为了true,这里return回什么,this.$u.post的then回调中就会得到什么
 | ||||
| 			return res;   | ||||
|  | @ -54,6 +54,9 @@ const install = (Vue, vm) => { | |||
| 				}) | ||||
| 				return false; | ||||
| 			} | ||||
| 		else if(res.code == 404){ | ||||
| 			return false | ||||
| 		} | ||||
| 		else{  | ||||
| 			uni.showToast({ | ||||
| 				title: res.msg, | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ | |||
|             "path" : "pages/inspectrecord/deptreport", | ||||
|             "style" :                                                                                     | ||||
|             { | ||||
|                 "navigationBarTitleText": "", | ||||
|                 "navigationBarTitleText": "检查任务", | ||||
|                 "enablePullDownRefresh": false | ||||
|             } | ||||
|              | ||||
|  | @ -105,7 +105,26 @@ | |||
|             "path" : "pages/document/index", | ||||
|             "style" :                                                                                     | ||||
|             { | ||||
|                 "navigationBarTitleText": "", | ||||
|                 "navigationBarTitleText": "手册资料", | ||||
|                 "enablePullDownRefresh": false | ||||
|             } | ||||
|              | ||||
|         } | ||||
|         ,{ | ||||
|             "path" : "pages/vod/index", | ||||
|             "style" :                                                                                     | ||||
|             { | ||||
|                 "navigationBarTitleText": "云点播", | ||||
|                 "enablePullDownRefresh": true, | ||||
| 				"onReachBottomDistance":100 | ||||
|             } | ||||
|              | ||||
|         } | ||||
|         ,{ | ||||
|             "path" : "pages/vod/video", | ||||
|             "style" :                                                                                     | ||||
|             { | ||||
|                 "navigationBarTitleText": "云点播", | ||||
|                 "enablePullDownRefresh": false | ||||
|             } | ||||
|              | ||||
|  | @ -128,12 +147,12 @@ | |||
| 				"selectedIconPath": "static/common/homec.png", | ||||
| 				"text": "主页" | ||||
| 			}, | ||||
| 			// { | ||||
| 			// 	"pagePath": "pages/uview/uview", | ||||
| 			// 	"iconPath": "static/uview/example/js.png", | ||||
| 			// 	"selectedIconPath": "static/uview/example/js_select.png", | ||||
| 			// 	"text": "uview" | ||||
| 			// }, | ||||
| 			{ | ||||
| 				"pagePath": "pages/vod/video", | ||||
| 				"iconPath": "static/common/play.png", | ||||
| 				"selectedIconPath": "static/common/playc.png", | ||||
| 				"text": "点播" | ||||
| 			}, | ||||
| 			{ | ||||
| 				"pagePath": "pages/my/my", | ||||
| 				"iconPath": "static/common/me.png", | ||||
|  |  | |||
|  | @ -0,0 +1,74 @@ | |||
| <template> | ||||
| 	<view> | ||||
| 		<view> | ||||
| 			<uni-search-bar @confirm="search" ></uni-search-bar> | ||||
| 		</view> | ||||
| 		<list style="width: 100%;"> | ||||
| 			<!-- 注意事项: 不能使用 index 作为 key 的唯一标识 --> | ||||
| 			<cell v-for="(item,index) in videos" :key="item.id"> | ||||
| 				<video class="video" :id="'video'+index" :src="item.mediaurl" controls object-fit="cover" | ||||
| 					:poster="item.coverurl"></video> | ||||
| 			</cell> | ||||
| 		</list> | ||||
| 		<view style="color:gray;text-align: center;margin-top:20upx">{{loadingText}}</view> | ||||
| 	</view> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| 	export default { | ||||
| 		data() { | ||||
| 			return { | ||||
| 				page: 1, | ||||
| 				loadingText: '加载中...', | ||||
| 				videos: [] | ||||
| 			} | ||||
| 		}, | ||||
| 		onLoad() { | ||||
| 			this.getVideos() | ||||
| 		}, | ||||
| 		onPullDownRefresh() { | ||||
| 			this.page = 1 | ||||
| 			this.getVideos() | ||||
| 		}, | ||||
| 		onReachBottom() { | ||||
| 			this.page = this.page + 1 | ||||
| 			this.getVideos() | ||||
| 		}, | ||||
| 		methods: { | ||||
| 			search(){ | ||||
| 				 | ||||
| 			}, | ||||
| 			getVideos() { | ||||
| 				this.loadingText = '加载中...' | ||||
| 				this.$u.api.getVideos({ | ||||
| 					page: this.page | ||||
| 				}).then(res => { | ||||
| 					uni.stopPullDownRefresh() | ||||
| 					if (this.page == 1) { | ||||
| 						if (res.data.results.length == 0) { | ||||
| 							this.loadingText = '暂无视频' | ||||
| 						} else { | ||||
| 							this.loadingText = '' | ||||
| 							this.videos = res.data.results | ||||
| 						} | ||||
| 					} else { | ||||
| 						this.loadingText = '' | ||||
| 						this.videos.concat(res.data.results) | ||||
| 					} | ||||
| 				}).catch(res => { | ||||
| 					uni.stopPullDownRefresh() | ||||
| 					if (res.code == 404) { | ||||
| 						this.loadingText = '到底了' | ||||
| 					} | ||||
| 				}) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| </script> | ||||
| 
 | ||||
| <style> | ||||
| 	.video { | ||||
| 		width: 100%; | ||||
| 		height: 380rpx; | ||||
| 	} | ||||
| </style> | ||||
|  | @ -0,0 +1,356 @@ | |||
| <template> | ||||
| 	<view> | ||||
| 		<!-- <view style="height: 80upx;"> | ||||
| 			<uni-search-bar @confirm="startSearch" v-model="search"></uni-search-bar> | ||||
| 		</view> --> | ||||
| 		<scroll-view class="nav-scroll" :enable-flex="true" scroll-with-animation :throttle="false" | ||||
| 			:scroll-left="scrollToLeft" scroll-x @scroll="handleScroll"> | ||||
| 			<view class="nav uni-nav"> | ||||
| 				<view class="nav-item" :class="swiperIndex == index ? 'nav-item-act' : ''" :key="item.title" | ||||
| 					v-for="(item, index) in list" @click="taggleNav(index)"> | ||||
| 					{{ item.title }} | ||||
| 				</view> | ||||
| 				<view class="nav-line" :style="style"></view> | ||||
| 			</view> | ||||
| 		</scroll-view> | ||||
| 		<view class="swiper"> | ||||
| 			<swiper :current="swiperIndex" :duration="300" class="swiper-1" easing-function="linear" | ||||
| 				@change="swiperChange"> | ||||
| 				<swiper-item v-for="(item, index) in list" :key="item.title"> | ||||
| 					<scroll-view :lower-threshold="80" :refresher-triggered="refreStatus" | ||||
| 						@refresherrefresh="handleRefre" :refresher-enabled="true" class="swiper-scroll" scroll-y="true" | ||||
| 						@scrolltolower="swiperScrollLower"> | ||||
| 						<view> | ||||
| 							<view class="swiper-item-list" v-for="(video,index) in item.content" :key="video.id"> | ||||
| 								<video class="video" :src="video.mediaurl" controls object-fit="cover" | ||||
| 									:id="'video'+video.id" :poster="video.coverurl" @play="doPlay($event, index)" | ||||
| 									@pause="doPlay($event, index)" @ended="doPlay($event, index)"> | ||||
| 									<view class='video-slot' v-if="video.showTitle" :title="video.name"> | ||||
| 										<span style="margin-left:6px">{{video.name}}</span> | ||||
| 									</view> | ||||
| 								</video> | ||||
| 								<view style="color:darkblue;margin-left:4upx"> | ||||
| 								<text>{{video.name}}</text> | ||||
| 								<text style="float:right;color:gray;margin-right: 8upx;">{{video.viewsp}}人观看</text> | ||||
| 								</view> | ||||
| 							</view> | ||||
| 						</view> | ||||
| 						<view style="color:gray;text-align: center;margin-top:20upx;">{{loadingText}}</view> | ||||
| 					</scroll-view> | ||||
| 				</swiper-item> | ||||
| 			</swiper> | ||||
| 		</view> | ||||
| 	</view> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| 	export default { | ||||
| 		data() { | ||||
| 			return { | ||||
| 				playingVideoStr: null, | ||||
| 				swiperIndex: 0, //当前的swiperindex | ||||
| 				navItemWidth: '', //选中下划线的宽度 | ||||
| 				navItemLeft: 0, //选中下划线的显示位置 | ||||
| 				scrollToLeft: 0, //scrollview需要滚动的距离 | ||||
| 				navInfos: [], //所有navitem的节点信息 | ||||
| 				parentLeft: 0, //nav盒子的节点信息 | ||||
| 				componentWidth: 0, //nav盒子的宽度 | ||||
| 				list: [{ | ||||
| 					id: 0, | ||||
| 					title: '全部', | ||||
| 					page: 1, | ||||
| 					content: [] | ||||
| 				}], | ||||
| 				refreStatus: false, | ||||
| 				loadingText: "加载中", | ||||
| 				search:"" | ||||
| 			}; | ||||
| 		}, | ||||
| 		computed: { | ||||
| 			style() { | ||||
| 				return `width:${this.navItemWidth}px; left:${this.navItemLeft}px`; | ||||
| 			} | ||||
| 		}, | ||||
| 		mounted() { | ||||
| 			// this.init(); | ||||
| 		}, | ||||
| 		onLoad() { | ||||
| 			this.$u.api.getDickey({ | ||||
| 				pageoff: true, | ||||
| 				type__code: 'data_video' | ||||
| 			}).then(res => { | ||||
| 				let list = [{ | ||||
| 					id: 0, | ||||
| 					title: '全部', | ||||
| 					page: 1, | ||||
| 					content: [] | ||||
| 				}] | ||||
| 				for (var i = 0; i < res.data.length; i++) { | ||||
| 					let data = res.data[i] | ||||
| 					list.push({ | ||||
| 						id: data.id, | ||||
| 						title: data.name, | ||||
| 						page: 1, | ||||
| 						content: [] | ||||
| 					}) | ||||
| 				} | ||||
| 				this.list = list | ||||
| 				this.$nextTick(function() { | ||||
| 					this.init() | ||||
| 					this.getVideos() | ||||
| 				}); | ||||
| 			}) | ||||
| 		}, | ||||
| 		methods: { | ||||
| 			doPlay(e, index) { | ||||
| 				if (e.type == 'play') { | ||||
| 					var playingVideoStr = e.target.id | ||||
| 					this.list[this.swiperIndex].content[index].showTitle = false | ||||
| 					this.$u.api.putMyVideoView(this.list[this.swiperIndex].content[index].id).then(res=>{}) | ||||
| 					//暂停其他视频播放 | ||||
| 					if(this.playingVideoStr==null){ | ||||
| 						this.playingVideoStr = playingVideoStr | ||||
| 					} | ||||
| 					else if (playingVideoStr != this.playingVideoStr) { | ||||
| 						var videoContextPrev = uni.createVideoContext(this.playingVideoStr) | ||||
| 						videoContextPrev.pause() | ||||
| 						this.playingVideoStr = playingVideoStr | ||||
| 					} | ||||
| 				} else { | ||||
| 					this.list[this.swiperIndex].content[index].showTitle = true | ||||
| 				} | ||||
| 			}, | ||||
| 			// 获取dom信息 | ||||
| 			init() { | ||||
| 				const query = uni.createSelectorQuery().in(this); | ||||
| 				query.select('.uni-nav').fields({ | ||||
| 					rect: true, | ||||
| 					size: true | ||||
| 				}, res => { | ||||
| 					this.parentLeft = res.left; | ||||
| 					this.componentWidth = res.width; | ||||
| 					console.log('res==>', res); | ||||
| 				}); | ||||
| 				query.selectAll('.nav-item').fields({ | ||||
| 					rect: true, | ||||
| 					size: true | ||||
| 				}, data => { | ||||
| 					data.forEach((item, index) => { | ||||
| 						if (index == 0) { | ||||
| 							this.navItemWidth = item.width; | ||||
| 							this.navItemLeft = item.left; | ||||
| 						} | ||||
| 						this.navInfos.push({ | ||||
| 							width: item.width, | ||||
| 							left: item.left | ||||
| 						}); | ||||
| 					}); | ||||
| 				}); | ||||
| 				query.exec(); | ||||
| 			}, | ||||
| 			// 点击导航切换swiper | ||||
| 			taggleNav(val) { | ||||
| 				this.swiperIndex = val; | ||||
| 				if (this.list[val].content.length == 0) { | ||||
| 					this.getVideos() | ||||
| 				} | ||||
| 			}, | ||||
| 			// 滚动tabs以及移动下划线 | ||||
| 			scrollDom() { | ||||
| 				let info = this.navInfos[this.swiperIndex]; | ||||
| 				let offsetLeft = info.left - this.parentLeft; | ||||
| 				let scrollLeft = offsetLeft - (this.componentWidth - info.width) / 2; | ||||
| 				this.scrollToLeft = scrollLeft < 0 ? 0 : scrollLeft; | ||||
| 				this.navItemLeft = this.navInfos[this.swiperIndex].left; | ||||
| 				setTimeout(() => { | ||||
| 					this.navItemWidth = info.width; | ||||
| 				}, 50); | ||||
| 			}, | ||||
| 			// swiper的index变动 | ||||
| 			swiperChange(e) { | ||||
| 				this.swiperIndex = e.detail.current; | ||||
| 				this.scrollDom(); | ||||
| 				this.$emit('currentIndex', this.swiperIndex); | ||||
| 				if (this.list[e.detail.current].content.length == 0) { | ||||
| 					this.getVideos() | ||||
| 				} | ||||
| 			}, | ||||
| 			// tabs-scrollview触底 | ||||
| 			handleScroll(e) { | ||||
| 				this.scrollDom(); | ||||
| 			}, | ||||
| 			// swiper-ScrollLower触底 | ||||
| 			swiperScrollLower() { | ||||
| 				// uni.showToast({ | ||||
| 				// 	icon: 'none', | ||||
| 				// 	title: `此时为${this.list[this.swiperIndex].title}触底` | ||||
| 				// }); | ||||
| 				// setTimeout(() => { | ||||
| 				// 	this.getData(); | ||||
| 				// }, 500); | ||||
| 				this.list[this.swiperIndex].page = this.list[this.swiperIndex].page + 1 | ||||
| 				this.getVideos() | ||||
| 			}, | ||||
| 			getVideos() { | ||||
| 				let swiperIndex = this.swiperIndex | ||||
| 				let currentData = this.list[swiperIndex] | ||||
| 				var params = { | ||||
| 					page: currentData.page | ||||
| 				} | ||||
| 				if (currentData.id == 0) {} else { | ||||
| 					params.category = currentData.id | ||||
| 				} | ||||
| 				this.$u.api.getVideos(params).then(res => { | ||||
| 					this.refreStatus = false | ||||
| 					let results = res.data.results | ||||
| 					for (var i = 0; i < results.length; i++) { | ||||
| 						results[i].showTitle = true | ||||
| 					} | ||||
| 					if (currentData.page == 1) { | ||||
| 						if (results == 0) { | ||||
| 							this.loadingText = '暂无视频' | ||||
| 						} else { | ||||
| 							this.loadingText = '' | ||||
| 							this.list[swiperIndex].content = results | ||||
| 						} | ||||
| 					} else { | ||||
| 						this.loadingText = '' | ||||
| 						this.list[swiperIndex].content.concat(results) | ||||
| 					} | ||||
| 
 | ||||
| 				}).catch(res => { | ||||
| 					this.refreStatus = false | ||||
| 					if (res.code == 404) { | ||||
| 						this.loadingText = '到底了' | ||||
| 					} | ||||
| 				}) | ||||
| 
 | ||||
| 
 | ||||
| 			}, | ||||
| 			// 生成列表数据 | ||||
| 			getData() { | ||||
| 				uni.showLoading({ | ||||
| 					title: '加载中' | ||||
| 				}); | ||||
| 				setTimeout(() => { | ||||
| 					for (let index = 0; index < 10; index++) { | ||||
| 						let arr = this.list[this.swiperIndex].content; | ||||
| 						this.$set(arr, arr.length, Math.random() + '-' + index + this.list[this.swiperIndex] | ||||
| 							.title); | ||||
| 					} | ||||
| 					uni.hideLoading(); | ||||
| 				}, 1000); | ||||
| 				console.log(this.list[this.swiperIndex]); | ||||
| 			}, | ||||
| 			// 下拉事件 | ||||
| 			handleRefre() { | ||||
| 				this.refreStatus = true; | ||||
| 				// uni.showLoading({ | ||||
| 				// 	title: '下拉加载中' | ||||
| 				// }); | ||||
| 				this.list[this.swiperIndex].page = 1 | ||||
| 				this.getVideos() | ||||
| 				// setTimeout(() => { | ||||
| 				// 	this.list[this.swiperIndex].content = []; | ||||
| 				// 	for (var i = 0; i < 5; i++) { | ||||
| 				// 		this.list[this.swiperIndex].content.push([this.list[this.swiperIndex].title + '下拉-' + i]); | ||||
| 				// 	} | ||||
| 				// 	uni.hideLoading(); | ||||
| 				// }, 1000); | ||||
| 				// setTimeout(() => { | ||||
| 				// 	this.refreStatus = false; | ||||
| 				// }, 1000); | ||||
| 			}, | ||||
| 			startSearch(e){ | ||||
| 				console.log(e) | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| 	.nav-item { | ||||
| 		display: inline-block; | ||||
| 		margin: 0 16upx; | ||||
| 		text-align: center; | ||||
| 		transition: color 0.3s ease; | ||||
| 	} | ||||
| 
 | ||||
| 	.nav { | ||||
| 		white-space: nowrap; | ||||
| 		position: relative; | ||||
| 		height: 80upx; | ||||
| 		padding: 20upx 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* #ifndef APP-NVUE */ | ||||
| 	::-webkit-scrollbar { | ||||
| 		display: none; | ||||
| 	} | ||||
| 
 | ||||
| 	/* #endif */ | ||||
| 
 | ||||
| 	/* #ifdef H5 */ | ||||
| 	// 通过样式穿透,隐藏H5下,scroll-view下的滚动条 | ||||
| 	scroll-view ::v-deep ::-webkit-scrollbar { | ||||
| 		display: none; | ||||
| 	} | ||||
| 
 | ||||
| 	/* #endif */ | ||||
| 
 | ||||
| 	.nav-item-act { | ||||
| 		color: pink; | ||||
| 		font-weight: bolder; | ||||
| 	} | ||||
| 
 | ||||
| 	.nav-line { | ||||
| 		position: absolute; | ||||
| 		bottom: 0; | ||||
| 		height: 10upx; | ||||
| 		border-radius: 10upx; | ||||
| 		background-color: pink; | ||||
| 		transition: left 0.3s ease; | ||||
| 	} | ||||
| 
 | ||||
| 	swiper { | ||||
| 		height: calc(100vh - 80upx); | ||||
| 	} | ||||
| 
 | ||||
| 	// swiper-item { | ||||
| 	// 	text-align: center; | ||||
| 	// 	color: #000; | ||||
| 	// 	position: relative; | ||||
| 	// 	background-color: skyblue; | ||||
| 	// 	color: #fff; | ||||
| 	// } | ||||
| 
 | ||||
| 	.swiper-item { | ||||
| 		overflow-y: scroll; | ||||
| 	} | ||||
| 
 | ||||
| 	.swiper-item-list { | ||||
| 		margin-top:4upx; | ||||
| 		// height: 400upx; | ||||
| 		border-bottom: 4upx solid pink; | ||||
| 		// line-height: 400upx; | ||||
| 	} | ||||
| 
 | ||||
| 	.swiper-scroll { | ||||
| 		height: 100%; | ||||
| 	} | ||||
| 
 | ||||
| 	.video { | ||||
| 		width: 100%; | ||||
| 		height: 380rpx; | ||||
| 	} | ||||
| 
 | ||||
| 	.video-slot { | ||||
| 		width: 100%; | ||||
| 		height: 40px; | ||||
| 		line-height: 40px; | ||||
| 		font-size: 16px; | ||||
| 		color: white; | ||||
| 		background-color: black; | ||||
| 		opacity: 0.3; | ||||
| 	} | ||||
| </style> | ||||
|  | @ -34,7 +34,7 @@ const store = new Vuex.Store({ | |||
| 		vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {}, | ||||
| 		vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '', | ||||
| 		// vuex_host: 'http://127.0.0.1:8000',
 | ||||
| 		// vuex_api: 'http://127.0.0.1:8000/api',
 | ||||
| 		//vuex_api: 'http://47.95.0.242:9101/api',
 | ||||
| 		// vuex_apifile: 'http://127.0.0.1:8000/api/file/',
 | ||||
| 		 | ||||
| 		vuex_host: 'https://testsearch.ctc.ac.cn', | ||||
|  |  | |||
|  | @ -0,0 +1,18 @@ | |||
| ## 1.0.9(2021-05-12) | ||||
| - 新增 项目示例地址 | ||||
| ## 1.0.8(2021-04-21) | ||||
| - 优化 添加依赖 uni-icons, 导入后自动下载依赖 | ||||
| ## 1.0.7(2021-04-15) | ||||
| - uni-ui 新增 uni-search-bar 的 focus 事件 | ||||
| 
 | ||||
| ## 1.0.6(2021-02-05) | ||||
| - 优化 组件引用关系,通过uni_modules引用组件 | ||||
| 
 | ||||
| ## 1.0.5(2021-02-05) | ||||
| - 调整为uni_modules目录规范 | ||||
| - 新增 支持双向绑定 | ||||
| - 更改 input 事件的返回值,e={value:Number} --> e=value | ||||
| - 新增 支持图标插槽 | ||||
| - 新增 支持 clear、blur 事件 | ||||
| - 新增 支持 focus 属性 | ||||
| - 去掉组件背景色 | ||||
|  | @ -0,0 +1,254 @@ | |||
| <template> | ||||
| 	<view class="uni-searchbar"> | ||||
| 		<view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box" @click="searchClick"> | ||||
| 			<view class="uni-searchbar__box-icon-search"> | ||||
| 				<slot name="searchIcon"> | ||||
| 					<uni-icons color="#999999" size="18" type="search" /> | ||||
| 				</slot> | ||||
| 			</view> | ||||
| 			<input v-if="show || searchVal" :focus="showSync" :placeholder="placeholder" :maxlength="maxlength" class="uni-searchbar__box-search-input" | ||||
| 			 confirm-type="search" type="text" v-model="searchVal" @confirm="confirm" @blur="blur" @focus="emitFocus" /> | ||||
| 			<text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text> | ||||
| 			<view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='')" class="uni-searchbar__box-icon-clear" | ||||
| 			 @click="clear"> | ||||
| 				<slot name="clearIcon"> | ||||
| 					<uni-icons color="#c0c4cc" size="15" type="clear" /> | ||||
| 				</slot> | ||||
| 			</view> | ||||
| 		</view> | ||||
| 		<text @click="cancel" class="uni-searchbar__cancel" v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelText}}</text> | ||||
| 	</view> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| 
 | ||||
| 	/** | ||||
| 	 * SearchBar 搜索栏 | ||||
| 	 * @description 评分组件 | ||||
| 	 * @tutorial https://ext.dcloud.net.cn/plugin?id=866 | ||||
| 	 * @property {Number} radius 搜索栏圆角 | ||||
| 	 * @property {Number} maxlength 输入最大长度 | ||||
| 	 * @property {String} placeholder 搜索栏Placeholder | ||||
| 	 * @property {String} clearButton = [always|auto|none] 是否显示清除按钮 | ||||
| 	 * 	@value always 一直显示 | ||||
| 	 * 	@value auto 输入框不为空时显示 | ||||
| 	 * 	@value none 一直不显示 | ||||
| 	 * @property {String} cancelButton = [always|auto|none] 是否显示取消按钮 | ||||
| 	 * 	@value always 一直显示 | ||||
| 	 * 	@value auto 输入框不为空时显示 | ||||
| 	 * 	@value none 一直不显示 | ||||
| 	 * @property {String} cancelText 取消按钮的文字 | ||||
| 	 * @property {String} bgColor 输入框背景颜色 | ||||
| 	 * @property {Boolean} focus 是否自动聚焦 | ||||
| 	 * @event {Function} confirm uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value,e={value:Number} | ||||
| 	 * @event {Function} input uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value,e=value | ||||
| 	 * @event {Function} cancel 点击取消按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number} | ||||
| 	 * @event {Function} clear 点击清除按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number} | ||||
| 	 * @event {Function} blur input失去焦点时触发事件,返回参数为uniSearchBar的value,e={value:Number} | ||||
| 	 */ | ||||
| 
 | ||||
| 	export default { | ||||
| 		name: "UniSearchBar", | ||||
| 		props: { | ||||
| 			placeholder: { | ||||
| 				type: String, | ||||
| 				default: "请输入搜索内容" | ||||
| 			}, | ||||
| 			radius: { | ||||
| 				type: [Number, String], | ||||
| 				default: 5 | ||||
| 			}, | ||||
| 			clearButton: { | ||||
| 				type: String, | ||||
| 				default: "auto" | ||||
| 			}, | ||||
| 			cancelButton: { | ||||
| 				type: String, | ||||
| 				default: "auto" | ||||
| 			}, | ||||
| 			cancelText: { | ||||
| 				type: String, | ||||
| 				default: '取消' | ||||
| 			}, | ||||
| 			bgColor: { | ||||
| 				type: String, | ||||
| 				default: "#F8F8F8" | ||||
| 			}, | ||||
| 			maxlength: { | ||||
| 				type: [Number, String], | ||||
| 				default: 100 | ||||
| 			}, | ||||
| 			value: { | ||||
| 				type: [Number, String], | ||||
| 				default: "" | ||||
| 			}, | ||||
| 			focus: { | ||||
| 				type: Boolean, | ||||
| 				default: false | ||||
| 			} | ||||
| 		}, | ||||
| 		data() { | ||||
| 			return { | ||||
| 				show: false, | ||||
| 				showSync: false, | ||||
| 				searchVal: '' | ||||
| 			} | ||||
| 		}, | ||||
| 		watch: { | ||||
| 			value: { | ||||
| 				immediate: true, | ||||
| 				handler(newVal) { | ||||
| 					this.searchVal = newVal | ||||
| 					if (newVal) { | ||||
| 						this.show = true | ||||
| 					} | ||||
| 				} | ||||
| 			}, | ||||
| 			focus: { | ||||
| 				immediate: true, | ||||
| 				handler(newVal) { | ||||
| 					if (newVal) { | ||||
| 						this.show = true; | ||||
| 						this.$nextTick(() => { | ||||
| 							this.showSync = true | ||||
| 						}) | ||||
| 					} | ||||
| 				} | ||||
| 			}, | ||||
| 			searchVal(newVal, oldVal) { | ||||
| 				this.$emit("input", newVal) | ||||
| 			} | ||||
| 		}, | ||||
| 		methods: { | ||||
| 			searchClick() { | ||||
| 				if (this.show) { | ||||
| 					return | ||||
| 				} | ||||
| 				this.show = true; | ||||
| 				this.$nextTick(() => { | ||||
| 					this.showSync = true | ||||
| 				}) | ||||
| 			}, | ||||
| 			clear() { | ||||
| 				this.$emit("clear", { | ||||
| 					value: this.searchVal | ||||
| 				}) | ||||
| 				this.searchVal = "" | ||||
| 			}, | ||||
| 			cancel() { | ||||
| 				this.$emit("cancel", { | ||||
| 					value: this.searchVal | ||||
| 				}); | ||||
| 				this.searchVal = "" | ||||
| 				this.show = false | ||||
| 				this.showSync = false | ||||
| 				// #ifndef APP-PLUS | ||||
| 				uni.hideKeyboard() | ||||
| 				// #endif | ||||
| 				// #ifdef APP-PLUS | ||||
| 				plus.key.hideSoftKeybord() | ||||
| 				// #endif | ||||
| 			}, | ||||
| 			confirm() { | ||||
| 				// #ifndef APP-PLUS | ||||
| 				uni.hideKeyboard(); | ||||
| 				// #endif | ||||
| 				// #ifdef APP-PLUS | ||||
| 				plus.key.hideSoftKeybord() | ||||
| 				// #endif | ||||
| 				this.$emit("confirm", { | ||||
| 					value: this.searchVal | ||||
| 				}) | ||||
| 			}, | ||||
| 			blur() { | ||||
| 				// #ifndef APP-PLUS | ||||
| 				uni.hideKeyboard(); | ||||
| 				// #endif | ||||
| 				// #ifdef APP-PLUS | ||||
| 				plus.key.hideSoftKeybord() | ||||
| 				// #endif | ||||
| 				this.$emit("blur", { | ||||
| 					value: this.searchVal | ||||
| 				}) | ||||
| 			}, | ||||
| 			emitFocus(e) { | ||||
| 				this.$emit("focus", e.detail) | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| 	$uni-searchbar-height: 36px; | ||||
| 
 | ||||
| 	.uni-searchbar { | ||||
| 		/* #ifndef APP-NVUE */ | ||||
| 		display: flex; | ||||
| 		/* #endif */ | ||||
| 		flex-direction: row; | ||||
| 		position: relative; | ||||
| 		padding: $uni-spacing-col-base; | ||||
| 		// background-color: $uni-bg-color; | ||||
| 	} | ||||
| 
 | ||||
| 	.uni-searchbar__box { | ||||
| 		/* #ifndef APP-NVUE */ | ||||
| 		display: flex; | ||||
| 		box-sizing: border-box; | ||||
| 		/* #endif */ | ||||
| 		overflow: hidden; | ||||
| 		position: relative; | ||||
| 		flex: 1; | ||||
| 		justify-content: center; | ||||
| 		flex-direction: row; | ||||
| 		align-items: center; | ||||
| 		height: $uni-searchbar-height; | ||||
| 		padding: 5px 8px 5px 0px; | ||||
| 		border-width: 0.5px; | ||||
| 		border-style: solid; | ||||
| 		border-color: $uni-border-color; | ||||
| 	} | ||||
| 
 | ||||
| 	.uni-searchbar__box-icon-search { | ||||
| 		/* #ifndef APP-NVUE */ | ||||
| 		display: flex; | ||||
| 		/* #endif */ | ||||
| 		flex-direction: row; | ||||
| 		// width: 32px; | ||||
| 		padding: 0 8px; | ||||
| 		justify-content: center; | ||||
| 		align-items: center; | ||||
| 		color: $uni-text-color-placeholder; | ||||
| 	} | ||||
| 
 | ||||
| 	.uni-searchbar__box-search-input { | ||||
| 		flex: 1; | ||||
| 		font-size: $uni-font-size-base; | ||||
| 		color: $uni-text-color; | ||||
| 	} | ||||
| 
 | ||||
| 	.uni-searchbar__box-icon-clear { | ||||
| 		align-items: center; | ||||
| 		line-height: 24px; | ||||
| 		padding-left: 8px; | ||||
| 		/* #ifdef H5 */ | ||||
| 		cursor: pointer; | ||||
| 		/* #endif */ | ||||
| 	} | ||||
| 
 | ||||
| 	.uni-searchbar__text-placeholder { | ||||
| 		font-size: $uni-font-size-base; | ||||
| 		color: $uni-text-color-placeholder; | ||||
| 		margin-left: 5px; | ||||
| 	} | ||||
| 
 | ||||
| 	.uni-searchbar__cancel { | ||||
| 		padding-left: 10px; | ||||
| 		line-height: $uni-searchbar-height; | ||||
| 		font-size: 14px; | ||||
| 		color: $uni-text-color; | ||||
| 		/* #ifdef H5 */ | ||||
| 		cursor: pointer; | ||||
| 		/* #endif */ | ||||
| 	} | ||||
| </style> | ||||
|  | @ -0,0 +1,84 @@ | |||
| { | ||||
|   "id": "uni-search-bar", | ||||
|   "displayName": "uni-search-bar 搜索栏", | ||||
|   "version": "1.0.9", | ||||
|   "description": "搜索栏组件,通常用于搜索商品、文章等", | ||||
|   "keywords": [ | ||||
|     "uni-ui", | ||||
|     "uniui", | ||||
|     "搜索框", | ||||
|     "搜索栏" | ||||
| ], | ||||
|   "repository": "https://github.com/dcloudio/uni-ui", | ||||
|   "engines": { | ||||
|     "HBuilderX": "" | ||||
|   }, | ||||
|   "directories": { | ||||
|     "example": "../../temps/example_temps" | ||||
|   }, | ||||
|   "dcloudext": { | ||||
|     "category": [ | ||||
|       "前端组件", | ||||
|       "通用组件" | ||||
|     ], | ||||
|     "sale": { | ||||
|       "regular": { | ||||
|         "price": "0.00" | ||||
|       }, | ||||
|       "sourcecode": { | ||||
|         "price": "0.00" | ||||
|       } | ||||
|     }, | ||||
|     "contact": { | ||||
|       "qq": "" | ||||
|     }, | ||||
|     "declaration": { | ||||
|       "ads": "无", | ||||
|       "data": "无", | ||||
|       "permissions": "无" | ||||
|     }, | ||||
|     "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" | ||||
|   }, | ||||
|   "uni_modules": { | ||||
|     "dependencies": [ | ||||
| 			"uni-icons" | ||||
| 		], | ||||
|     "encrypt": [], | ||||
|     "platforms": { | ||||
|       "cloud": { | ||||
|         "tcb": "y", | ||||
|         "aliyun": "y" | ||||
|       }, | ||||
|       "client": { | ||||
|         "App": { | ||||
|           "app-vue": "y", | ||||
|           "app-nvue": "y" | ||||
|         }, | ||||
|         "H5-mobile": { | ||||
|           "Safari": "y", | ||||
|           "Android Browser": "y", | ||||
|           "微信浏览器(Android)": "y", | ||||
|           "QQ浏览器(Android)": "y" | ||||
|         }, | ||||
|         "H5-pc": { | ||||
|           "Chrome": "y", | ||||
|           "IE": "y", | ||||
|           "Edge": "y", | ||||
|           "Firefox": "y", | ||||
|           "Safari": "y" | ||||
|         }, | ||||
|         "小程序": { | ||||
|           "微信": "y", | ||||
|           "阿里": "y", | ||||
|           "百度": "y", | ||||
|           "字节跳动": "y", | ||||
|           "QQ": "y" | ||||
|         }, | ||||
|         "快应用": { | ||||
|           "华为": "u", | ||||
|           "联盟": "u" | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,86 @@ | |||
| 
 | ||||
| 
 | ||||
| ## SearchBar 搜索栏 | ||||
| 
 | ||||
| > **组件名:uni-search-bar** | ||||
| > 代码块: `uSearchBar` | ||||
| 
 | ||||
| 
 | ||||
| 评分组件 | ||||
| 
 | ||||
| ### 安装方式 | ||||
| 
 | ||||
| 本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 | ||||
| 
 | ||||
| 如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) | ||||
| 
 | ||||
| ### 基本用法 | ||||
| 
 | ||||
| 在 ``template`` 中使用组件 | ||||
| 
 | ||||
| ```html | ||||
| <!-- 基本用法 --> | ||||
| <uni-search-bar @confirm="search" @input="input" ></uni-search-bar> | ||||
| 
 | ||||
| <!-- v-model 用法 --> | ||||
| <uni-search-bar @confirm="search" :focus="true" v-model="searchValue" @blur="blur" @focus="focus" @input="input" @cancel="cancel" @change="change" @clear="clear"> | ||||
| 
 | ||||
| <!-- 自定义Placeholder --> | ||||
| <uni-search-bar placeholder="自定placeholder" @confirm="search"></uni-search-bar> | ||||
| 
 | ||||
| <!-- 设置圆角 --> | ||||
| <uni-search-bar :radius="100" @confirm="search"></uni-search-bar> | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## API | ||||
| ### SearchBar Props | ||||
| 
 | ||||
| |属性名			|类型	|默认值	|说明																					| | ||||
| |:-:			|:-:	|:-:	|:-:																					| | ||||
| |value/v-model	|StringNumber	|	|搜索栏绑定值																		| | ||||
| |placeholder	|String	|搜索	|搜索栏Placeholder																		| | ||||
| |radius			|Number	|10		|搜索栏圆角,单位px																	| | ||||
| |clearButton	|String	|auto	|是否显示清除按钮,可选值`always`-一直显示、`auto`-输入框不为空时显示、`none`-一直不显示	| | ||||
| |cancelButton	|String	|auto	|是否显示取消按钮,可选值`always`-一直显示、`auto`-输入框不为空时显示、`none`-一直不显示	| | ||||
| |cancelText		|String	|取消	|取消按钮的文字																			| | ||||
| |bgColor		|String	|#F8F8F8|输入框背景颜色																			| | ||||
| |maxlength		|Number	|100	|输入最大长度																			| | ||||
| |focus		|Boolean	|false	|																	| | ||||
| 
 | ||||
| 
 | ||||
| ### SearchBar Events | ||||
| 
 | ||||
| |事件称名	|说明																|返回参数			| | ||||
| |:-:		|:-:																|:-:				| | ||||
| |@confirm	|uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value	|e={value:Number}	| | ||||
| |@input		|uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value|e=value	| | ||||
| |@cancel		|点击取消按钮时触发事件,返回参数为uniSearchBar的value				|e={value:Number}	| | ||||
| |@clear		|点击清除按钮时触发事件,返回参数为uniSearchBar的value				|e={value:Number}	| | ||||
| |@focus			|input 获取焦点时触发事件,返回参数为uniSearchBar的value				|e={value:Number}	| | ||||
| |@blur			|input 失去焦点时触发事件,返回参数为uniSearchBar的value				|e={value:Number}	| | ||||
| 
 | ||||
| ### 替换 icon 的 slot 插槽 | ||||
| 
 | ||||
| |插槽称名	|说明																| | ||||
| |:-:		|:-:																| | ||||
| |searchIcon	|替换组件的搜索图标| | ||||
| |clearIcon	|替换组件的清除图标| | ||||
| 
 | ||||
| ```html | ||||
| <!-- 替换组件的搜索图标 --> | ||||
| <uni-search-bar placeholder="自定义searchIcon" @confirm="search" @cancel="cancel" cancel-text="cancel"> | ||||
| 	<uni-icons slot="searchIcon" color="#999999" size="18" type="home" /> | ||||
| </uni-search-bar> | ||||
| 
 | ||||
| <!-- 替换组件的清除图标 --> | ||||
| <uni-search-bar placeholder="自定义clearIcon" @confirm="search" @cancel="cancel" cancel-text="cancel"> | ||||
| 	<view slot="clearIcon" style="color: #999999" >X</view> | ||||
| </uni-search-bar> | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## 组件示例 | ||||
| 
 | ||||
| 点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/search-bar/search-bar](https://hellouniapp.dcloud.net.cn/pages/extUI/search-bar/search-bar) | ||||
|  | @ -0,0 +1,28 @@ | |||
| # Generated by Django 3.0.5 on 2021-07-06 02:05 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('vod', '0002_video_fileid'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.RenameField( | ||||
|             model_name='viewrecord', | ||||
|             old_name='num', | ||||
|             new_name='views', | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='video', | ||||
|             name='viewsp', | ||||
|             field=models.IntegerField(default=0, verbose_name='观看人数'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='viewrecord', | ||||
|             name='current', | ||||
|             field=models.IntegerField(default=0, verbose_name='当前观看进度(秒)'), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -13,6 +13,7 @@ class Video(CommonAModel): | |||
|     coverurl = models.CharField(verbose_name='封面地址', max_length=200) | ||||
|     duration = models.IntegerField(verbose_name='时长(秒)', default=0) | ||||
|     views = models.IntegerField(verbose_name='观看次数', default=0) | ||||
|     viewsp = models.IntegerField(verbose_name='观看人数', default=0) | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = '点播视频' | ||||
|  | @ -25,8 +26,8 @@ class ViewRecord(BaseModel): | |||
| 
 | ||||
|     # 观看记录 | ||||
|     user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='观看人', related_name='viewrecord_user') | ||||
|     num = models.IntegerField(verbose_name='观看次数', default=0) | ||||
|     current = models.IntegerField(verbose_name='当前观看进度', default=0) | ||||
|     views = models.IntegerField(verbose_name='观看次数', default=0) | ||||
|     current = models.IntegerField(verbose_name='当前观看进度(秒)', default=0) | ||||
|     video = models.ForeignKey(Video, verbose_name='点播视频', on_delete=models.CASCADE) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| from datetime import timedelta | ||||
| from time import timezone | ||||
| from rest_framework.mixins import ListModelMixin | ||||
| from apps.vod.serializers import VRecordSerializer, VRecordUpdateSerializer, VideoSerializer | ||||
| from apps.vod.models import Video, ViewRecord | ||||
|  | @ -11,6 +13,7 @@ from apps.system.mixins import CreateUpdateModelAMixin | |||
| from rest_framework.decorators import action, permission_classes | ||||
| from rest_framework.permissions import IsAuthenticated | ||||
| from rest_framework.status import HTTP_400_BAD_REQUEST | ||||
| from django.utils import timezone | ||||
| # Create your views here. | ||||
| 
 | ||||
| class ClassView(APIView): | ||||
|  | @ -85,16 +88,19 @@ class MyViewRecordAPIView(APIView): | |||
|     def put(self, request, id, format=None): | ||||
|         """ | ||||
|         更新该视频本人的观看信息 | ||||
|         params: {current:int} | ||||
|         """ | ||||
|         try: | ||||
|             video = Video.objects.get(pk=id) | ||||
|         except: | ||||
|             return Response('视频不存在', status=HTTP_400_BAD_REQUEST) | ||||
|         record = ViewRecord.objects.get_or_create(video=video, user=request.user, defaults={'video':video, 'user':request.user}) | ||||
|         serializer = VRecordUpdateSerializer(record, data=request.data) | ||||
|         serializer.is_valid(raise_exception=True) | ||||
|         serializer.save() | ||||
|         return Response(serializer.data) | ||||
|         record, _ = ViewRecord.objects.get_or_create(video=video, user=request.user, defaults={'video':video, 'user':request.user}) | ||||
|         if request.data.get('current', None): | ||||
|             record.current = request.data.get('current') | ||||
|         if timezone.now() > record.update_time + timedelta(hours=6) or record.create_time == record.update_time: | ||||
|             record.views = record.views + 1 | ||||
|         record.save() | ||||
|         return Response() | ||||
| 
 | ||||
| class SignatureAPIView(APIView): | ||||
|     perms_map={'get':'video_create'} | ||||
|  |  | |||
|  | @ -70,4 +70,4 @@ def getSignature(procedure=None): | |||
|     Sha1 = Hmac.digest() | ||||
|     Signature = bytes(Sha1) + bytes(Original, 'utf-8') | ||||
|     Signature2 = base64.b64encode(Signature) | ||||
|     return str(Signature2) | ||||
|     return str(Signature2, 'UTF-8') | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue