This commit is contained in:
shilixia 2021-07-08 11:10:23 +08:00
commit eb8dfb71a3
16 changed files with 4727 additions and 25 deletions

View File

@ -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
};
}

View File

@ -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,

View File

@ -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",

View File

@ -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>

View File

@ -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>

View File

@ -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',

View File

@ -0,0 +1,18 @@
## 1.0.92021-05-12
- 新增 项目示例地址
## 1.0.82021-04-21
- 优化 添加依赖 uni-icons, 导入后自动下载依赖
## 1.0.72021-04-15
- uni-ui 新增 uni-search-bar 的 focus 事件
## 1.0.62021-02-05
- 优化 组件引用关系通过uni_modules引用组件
## 1.0.52021-02-05
- 调整为uni_modules目录规范
- 新增 支持双向绑定
- 更改 input 事件的返回值e={value:Number} --> e=value
- 新增 支持图标插槽
- 新增 支持 clear、blur 事件
- 新增 支持 focus 属性
- 去掉组件背景色

View File

@ -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的valuee={value:Number}
* @event {Function} input uniSearchBar value 改变时触发事件返回参数为uniSearchBar的valuee=value
* @event {Function} cancel 点击取消按钮时触发事件返回参数为uniSearchBar的valuee={value:Number}
* @event {Function} clear 点击清除按钮时触发事件返回参数为uniSearchBar的valuee={value:Number}
* @event {Function} blur input失去焦点时触发事件返回参数为uniSearchBar的valuee={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>

View File

@ -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"
}
}
}
}
}

View File

@ -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)

View File

@ -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='当前观看进度(秒)'),
),
]

View File

@ -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)

View File

@ -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'}

View File

@ -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')

3772
server/nohup.out Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.