living-app1.nvue 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. <template>
  2. <view class="es">
  3. <view :style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;' ">
  4. <list loadmoreoffset="100" @scroll="scrolls" :show-scrollbar="false" :style="'height: '+ (boxStyle.height) +'px;padding-top:'+statusBarHeight+'px' " ref="listBox" :pagingEnabled="true" :scrollable="true">
  5. <refresh @pullingdown='onpullingdown' @refresh="onrefresh" :display=" refreshing ? 'show' : 'hide' " class="refresh x-c ">
  6. <loading-indicator style="width: 22px;height: 22px;color:#fff;"></loading-indicator>
  7. <text class="es-fs-32 es-ml-8 es-c-white">{{refreshText}}</text>
  8. </refresh>
  9. <cell v-for="(item,i) in dataList" :key="i">
  10. <view :style="'width: '+ windowWidth +'px;height:'+ (videoStyle.height)+'px' " :ref="'item'+i" style="position: relative;">
  11. <view v-if="(k-i)<=1" style="position: relative;" >
  12. <view class="root" >
  13. <video :id="item.id" :loop="true" :src="item.src" :poster="item.cover"
  14. @play="playIngs(i)" :enable-progress-gesture="false" :page-gesture="false"
  15. :controls="false" :show-loading="false" :initial-time="0"
  16. :show-fullscreen-btn="false" :show-center-play-btn="false" :style="videoStyle"
  17. :object-fit="object_fit" @timeupdate="timeupdate($event,i)"
  18. @fullscreenchange="onFullscreenChange" @waiting="onWaiting()" @progress="onProgress()"
  19. @ended="endedPlayNext()" @canplay="onVideoCanPlay" @canplaythrough="onVideoCanPlayThrough"
  20. @loadeddata="onLoadeddata" @loadedmetadata="onLoadedMetadata" @error="onError"
  21. >
  22. </video>
  23. </view>
  24. <view class="videoHover" @click="tapVideoHover(item.state,$event)"
  25. @touchstart="touchstartHover" :style="boxStyle">
  26. <image v-if="item.state=='pause' && item.isShowPlayIcon" class="playState" src="/static/image/course/play.png"></image>
  27. </view>
  28. <view class="right es-c-white">
  29. <view class="item1 es es-ac es-pc es-mt-33">
  30. <view class="es-icon-100 es-br">
  31. <image class="es-icon-100" style="border-radius: 50rpx;" :src="item.headImg"></image>
  32. </view>
  33. </view>
  34. <view class="item1 es es-ver es-ac es-pc es-mt-33" @tap="doLike(item,i)">
  35. <view class="es-icon-84">
  36. <image class="es-icon-84" :src="item.like==1?'/static/images/other/video/zan1_on.png':'/static/images/other/video/zan1.png'"></image>
  37. </view>
  38. <view><text class="es-c-white es-fs-22 es-fw-500">{{item.likeNum}}</text></view>
  39. </view>
  40. <view class="item1 es es-ver es-ac es-pc es-mt-33" @tap="openComment(item)">
  41. <view class="es-icon-84">
  42. <image class="es-icon-84" src="/static/images/other/video/comment1.png"></image>
  43. </view>
  44. <view><text class="es-c-white es-fs-22 es-fw-500">{{item.smsNum}}</text></view>
  45. </view>
  46. <view class="item1 es es-ver es-ac es-pc es-mt-33" @tap="doFavorite(item,i)">
  47. <view class="es-icon-84">
  48. <image class="es-icon-84" :src="item.favorite==1?'/static/images/other/video/fav1_on.png':'/static/images/other/video/fav1.png'" ></image>
  49. </view>
  50. <view><text class="es-c-white es-fs-22 es-fw-500">{{item.favoriteNum}}</text></view>
  51. </view>
  52. <view class="item1 es es-ver es-ac es-pc es-mt-33" @tap="openShare(item)">
  53. <view class="es-icon-84">
  54. <image class="es-icon-70" src="/static/images/other/video/share1.png"></image>
  55. </view>
  56. <view><text class="es-c-white es-fs-22 es-fw-500">{{item.shares}}</text></view>
  57. </view>
  58. <view class="item1 es es-ac es-pc es-mt-33">
  59. <view class="es-br ">
  60. <text class="es-c-white es-fs-34">{{item.uploadType}}</text>
  61. </view>
  62. </view>
  63. </view>
  64. <view class="left" v-if="item.isShowGoods && item.productId!=null" >
  65. <view class="es-w-40 es-h-40" @tap="closePro(item,i)" style="position: absolute;right:0rpx;top:74rpx;z-index:999">
  66. <image class="es-w-40 es-h-40" src="../../../static/images/close40.png"></image>
  67. </view>
  68. <view class="es-h-74 es es-ac">
  69. <view class="es-f1 es es-ac" id="w">
  70. <view class="bg" style="width: 320rpx;" >
  71. <image src="@/static/images/other/video/bg.png" style="height: 74rpx;width: 100%;" ></image>
  72. </view>
  73. <view class="es-w-30"></view>
  74. </view>
  75. </view>
  76. <view class="goods" @tap="goToPro(item)">
  77. <view class="icon" style="width: 290rpx;height: 290rpx;">
  78. <image :src="item.imgUrl" style="width: 290rpx;height: 290rpx;" class="es-br-10"></image>
  79. </view>
  80. <view class="es-omit es-mt-19" style="width: 290rpx;"><text class="es-fw es-fs-30">{{item.packageName}}</text></view>
  81. </view>
  82. </view>
  83. <view class="bottom">
  84. <text class="txtTitle" :class="showExpand?'ellipsis':''" :style="defTitStyle" :id="'txtTitle'+i" :ref="'txtTitle'+i">{{item.title}}</text>
  85. <text v-if="showExpand" class="expandBtn" @tap="clickExpand">{{ titIsExpand?'收起':'展开' }}</text>
  86. </view>
  87. </view>
  88. </view>
  89. </cell>
  90. </list>
  91. </view>
  92. <view v-if="isShowTab" :style="'width: '+ windowWidth +'px; '" class="tabbar1">
  93. <n-tabs style="background: transparent;" v-model="tabIndex" :tabs="mtabs" :height="88" @change="tabChange" :tab-width="134"></n-tabs>
  94. </view>
  95. <view class="redpacked x-c es-br-ban" v-if="!iserr && !showGuide" @click.stop="tapRedpacked">
  96. <gb-progress class="es x-c es-br-ban" :radius="43" :startPosDegree="0" originalColor="#222222"
  97. processColor="#FF5C03" innerbgColor="#222222" :process="process" :barWidth="5">
  98. <image class="es-w-50 es-h-50" src="@/static/images/ad/redpacked.png" mode="widthFix" ></image>
  99. </gb-progress>
  100. </view>
  101. <!-- 新手指引 -->
  102. <view class="guide" :style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;'" v-if="showGuide" @touchmove.stop.prevent>
  103. <view class="guide-box" style="width: 100%; height:100%; left: 0px; top: 0px;box-shadow: rgb(33 33 33 / 80%) 0px 0px 0px 0px, rgb(33 33 33 / 50%) 0px 0px 0px 5000px;" >
  104. <view class="tips" id="guidetips" :style="'width: '+ windowWidth +'px; height: '+ boxStyle.height +'px;' " style="top: 0px; left: 0px;" @click="nextGuide">
  105. <view class="liveguide" >
  106. <image class="phone_icon" src="@/static/images/guide/phone_icon.png" mode="aspectFill"></image>
  107. <image class="hand_icon" :class="{origin: !goSwipe, target: goSwipe}" src="@/static/images/guide/hand_icon.png" mode="aspectFill"></image>
  108. <text class="liveguide-tip">上滑查看更多视频</text>
  109. </view>
  110. </view>
  111. </view>
  112. <!-- 遮罩层,防止点击 -->
  113. <view class="v-model" @click="nextGuide"></view>
  114. </view>
  115. <!-- 分享弹窗 -->
  116. <u-popup :show="showShare" @close="showShare = false" >
  117. <share-box :shareItem="shareItem" @closeShare='showShare = false' ></share-box>
  118. </u-popup>
  119. </view>
  120. </template>
  121. <script>
  122. import { getVideoList,doFavorite,doLike } from '@/api/shortvideo'
  123. import { addIntegral } from '@/api/integral'
  124. import { isLogin } from '@/utils/common'
  125. import { showLoginPage } from '@/utils/login'
  126. import shareBox from "@/components/share-box/share-boxN.vue"
  127. // #ifdef APP-PLUS
  128. const dom = weex.requireModule('dom');
  129. // #endif
  130. export default {
  131. components: {
  132. shareBox
  133. },
  134. data() {
  135. return {
  136. step: {
  137. name: 'liveguide',
  138. guideList: [{
  139. el: '',
  140. tips: '上滑查看更多视频',
  141. next: '',
  142. }]
  143. },
  144. dataList: [], //用于数据循环的列表????
  145. wHeight: 0, //获取的屏幕高度????
  146. boxStyle: { //视频父视图样式????
  147. 'height': 0,
  148. 'width': 0,
  149. },
  150. videoStyle: { //视频,图片封面样式????
  151. 'height': 0,
  152. 'width': 0,
  153. 'marginTop':0
  154. },
  155. Heights: 0,
  156. k: 0, //默认为0????
  157. playIngIds: [], //正在播放的视频id列队,列队用于处理滑动过快导致的跳频问题????
  158. ready: false, //可忽略
  159. isDragging: false, //false代表停止滑动????
  160. refreshing: false, //用于下拉刷新????
  161. windowWidth: 0, //获取屏幕宽度????
  162. windowHeight: 0,
  163. dex: [0, 0], //用于判断是上滑还是下滑,第一个存旧值,第二个存新值【目前在1.0.7已经废弃】
  164. currents: 0, //用于左右滑动,0代表视频界面,1代表右滑界面????
  165. platform: '', //用于获取操作系统:ios、android????
  166. playIng: false, //用于视频初始化时是否播放,默认不播放????
  167. videoTime: '', //视频总时长,这个主要用来截取时间数值??
  168. videoTimes: '', //视频时长,用这个来获取时间值,例如:00:30这个时间值??
  169. changeTime: '', //显示滑动进度条时变化的时间??
  170. isShowimage: false, //是否显示封面【1.0.4已废弃,但是意思需要记住】
  171. currenttimes: 0, //当前时间??
  172. isShowProgressBarTime: false, //是否拖动进度条,如果拖动(true)则显示进度条时间,否则不显示(false)【1.0.4已废弃,但是意思需要记住】
  173. ProgressBarOpacity: 0.7, //进度条不拖动时的默认值,就是透明的??
  174. dotWidth: 0, //播放的小圆点,默认没有??
  175. deleteHeight: 0, //测试高度????
  176. statusBarHeight:0,
  177. percent: 0, //百分小数??
  178. currentPosition: 0, //滑块当前位置??//2.0已弃用,现已用于后端参数
  179. currentPositions: 0, //滑块当前位置的副本??//2.0已弃用,现已用于后端参数
  180. newTime: 0, //跟手滑动后的最新时间??
  181. timeNumber: 0, //????
  182. ProgressBarBottom: 20, //进度条离底部的距离??
  183. object_fit: 'contain', //视频样式默认包含???? contain :包含 fill:填充 cover:覆盖
  184. mode: 'aspectFit', //图片封面样式????
  185. timeout: "", //??用来阻止 setTimeout()方法
  186. voice: "", //??用来阻止 setTimeout()方法
  187. oldVideo: "",
  188. isAutoplay: false, //是否开启自动播放(默认不开启)
  189. autoplayText: "开启自动播放",
  190. timers: "",
  191. leftTimers:"",
  192. // 引入评论 - 参数
  193. heightNum: 1.18,
  194. // 双击点赞参数
  195. touchNum: 0,
  196. aixinLeft: 0,
  197. aixinTop: 0,
  198. isShowAixin: false,
  199. Rotate: 0,
  200. isShowTab:true,
  201. isShow1: false, //控制渲染变量1
  202. isShow2: false, //控制渲染变量2 : 专门控制 uni-popup
  203. showPlay: false, //转轮显示控制
  204. rotates: 0, //转轮旋转角度
  205. rotateTime: "", //转轮递归事件控制
  206. xrotats: "",
  207. player: "",
  208. top:0,
  209. w:0,
  210. showLeft:true,
  211. keyword:"",
  212. pageNum:1,
  213. pageSize:10,
  214. isLastPage:false,
  215. refreshText: '↓ 下拉刷新',
  216. tabIndex: 0, // tab下标
  217. current: 0,
  218. mtabs: [
  219. {id: "tab00",name: '推荐'},{id: "tab01",name: '热点'},{id: "tab02",name: '直播'},{id: "tab03",name: '健康'}
  220. ],
  221. specVisible: false,
  222. esComment:null,
  223. showExpand:false,
  224. titIsExpand:false,
  225. lines:2,
  226. lineCount:0,
  227. titOpacity:0,
  228. defTitStyle:{'opacity':0},
  229. showShare:false,
  230. shareItem:{ imageUrl:"",title:"",path:""},
  231. viewVideoNum:0,
  232. //圆环倒计时
  233. iserr:false,
  234. interval:null,
  235. process:0,
  236. processDatas:[],
  237. isCounting:true,
  238. isPostBack:true,
  239. countItem:{"process":0,"isLoad":false},
  240. doLikeDisabled:false,
  241. doFavDisabled:false,
  242. showGuide:true,
  243. goSwipe: false,
  244. countNum:false,
  245. guideTimer:null
  246. }
  247. },
  248. created: function() {
  249. // setTimeout(e => {
  250. // uni.createSelectorQuery().select('#w').boundingClientRect(r2 => {
  251. // this.w = r2.width;
  252. // }).exec();
  253. // }, 50)
  254. },
  255. onLoad(options) {
  256. const systemInfo = uni.getSystemInfoSync();
  257. this.statusBarHeight=systemInfo.statusBarHeight;
  258. this.windowWidth = systemInfo.screenWidth //获取屏幕宽度
  259. this.boxStyle.width = this.windowWidth + 'px' //给宽度加px
  260. let tabBarHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
  261. this.wHeight=systemInfo.windowHeight; //获取屏幕高度
  262. this.boxStyle.height = this.wHeight - this.deleteHeight; //改变视频高度
  263. this.videoStyle.width=this.boxStyle.width;
  264. this.videoStyle.height=this.boxStyle.height - this.statusBarHeight;
  265. this.getData();
  266. uni.getSystemInfo({success: (res) => {
  267. this.top = res.safeArea.top;
  268. }
  269. });
  270. let that=this;
  271. uni.$on('refreshVideoComment', (data) => {
  272. let item=that.dataList[that.k];
  273. item.smsNum=data.smsNum;
  274. that.dataList[that.k]=item;
  275. that.$forceUpdate(); // 如果你需要强制刷新,可以调用 $forceUpdate()
  276. });
  277. const guide = uni.getStorageSync(this.step.name);
  278. console.log("qxj guide:"+guide);
  279. if (!guide) {
  280. this.showGuide = true;
  281. } else {
  282. this.showGuide = false;
  283. }
  284. this.guideTimer=setInterval(() => {
  285. if(this.countNum%2==0){
  286. this.goSwipe=true;
  287. }
  288. else{
  289. this.goSwipe=false;
  290. }
  291. this.countNum++;
  292. }, 900)
  293. },
  294. onShow(){
  295. const systemInfo = uni.getSystemInfoSync();
  296. if(this.dataList.length !== 0){
  297. this.dataList[this.k].state = 'play';
  298. uni.createVideoContext(this.dataList[this.k].id,this).play();
  299. }
  300. },
  301. onHide(){
  302. this.dataList[this.k].state = 'pause';//界面隐藏也要停止播放视频
  303. uni.createVideoContext(this.dataList[this.k].id,this).pause();//暂停以后继续播放
  304. //this.showToast('回到后台');
  305. },
  306. destroyed() {
  307. uni.$off("refreshVideoComment");
  308. },
  309. watch:{
  310. k(k,old_k){//监听 k 值的变化,可以控制视频的播放与暂停
  311. //console.log(k)
  312. // 清理定时器
  313. //this.dataList[old_k].state = 'stop'//如果是被滑走的视频,就停止播放
  314. this.dataList[old_k].playIng = false//如果视频暂停,就加载封面
  315. this.dataList[old_k].isplay = true
  316. console.log("qxj 旧视频暂停");
  317. uni.createVideoContext(this.dataList[old_k].id,this).seek(0);
  318. uni.createVideoContext(this.dataList[old_k].id,this).play();
  319. clearTimeout(this.oldVideo)
  320. this.oldVideo = setTimeout(()=>{
  321. //uni.createVideoContext(this.dataList[old_k].id,this).seek(0)
  322. uni.createVideoContext(this.dataList[old_k].id,this).pause()
  323. console.log('预留第' + (old_k + 1) + '个视频:' + this.dataList[old_k].id)
  324. },10);
  325. // clearTimeout(this.timeout)
  326. // this.timeout = setTimeout(()=>{
  327. // uni.createVideoContext(this.dataList[k+1].id,this).seek(0);
  328. // uni.createVideoContext(this.dataList[k+1].id,this).pause();
  329. // console.log('预加载第' + (k+1) + '个视频:' + this.dataList[k+1].id)
  330. // },50);
  331. // 2.0版本已经去掉了下面这一句,视频不用暂停,只需要把声音禁止就行
  332. // uni.createVideoContext(this.dataList[old_k].id + '' + old_k,this).stop()//如果视频暂停,那么旧视频停止,这里的this.dataList[old_k].id + '' + old_k,后面加 old_k 是为了每一个视频的 id 值不同,这样就可以大程度的避免串音问题
  333. this.dataList[k].state = 'play'
  334. console.log('已经暂停 --> 第' + (old_k + 1) + '个视频~')//提示
  335. clearTimeout(this.player);
  336. this.player = setTimeout(()=>{
  337. uni.createVideoContext(this.dataList[k].id,this).play();
  338. },0);
  339. if(k == (this.dataList.length-1)) {
  340. (async ()=>{
  341. console.log("qxj wath isLastPage:"+this.isLastPage);
  342. var p = k;
  343. if(this.isLastPage){
  344. this.pageNum=1;
  345. await this.getData();
  346. //var p = k;
  347. }else{
  348. this.pageNum++;
  349. await this.getData();
  350. }
  351. console.log("qxj after getData listCount:"+this.dataList.length);
  352. this.dataList[p].isplay = true
  353. setTimeout(()=>{
  354. uni.createVideoContext(this.dataList[p].id,this).play()
  355. clearTimeout(this.timeout)
  356. this.timeout = setTimeout(()=>{
  357. uni.createVideoContext(this.dataList[p].id,this).seek(0)
  358. uni.createVideoContext(this.dataList[p].id,this).pause()
  359. console.log('预加载第' + (p + 1) + '个视频:' + this.dataList[p].id)
  360. },1000)
  361. },20)
  362. })();
  363. }
  364. //【此处处理进度条卡住的问题】
  365. if(uni.getSystemInfoSync().platform !== 'ios'){
  366. setTimeout(()=>{
  367. uni.createVideoContext(this.dataList[k].id,this).pause()
  368. uni.createVideoContext(this.dataList[k].id,this).play()
  369. },100)
  370. }
  371. this.xrotats = setTimeout(()=>{
  372. this.showPlay = true;
  373. },200)
  374. }
  375. },
  376. methods: {
  377. onpullingdown(e) {
  378. if (this.refreshing) return;
  379. if (Math.abs(e.pullingDistance) > Math.abs(e.viewHeight)) {
  380. this.refreshText = '释放更新'
  381. this.isShowTab=false;
  382. } else {
  383. this.refreshText = '下拉更新'
  384. this.isShowTab=true;
  385. }
  386. },
  387. onrefresh(e) {
  388. console.log('onRefreshing...');
  389. this.refreshing = true;
  390. this.isShowTab=false;
  391. this.pageNum=1;
  392. this.getData();
  393. if (this.refreshing) return;
  394. },
  395. getData:function(){
  396. // userList.forEach(e=>{
  397. // e.id = 'A'+e.id+''+parseInt(Math.random()*1000);
  398. // this.dataList.push(e);
  399. // });
  400. // if(this.isLastPage){
  401. // return;
  402. // }
  403. let that=this;
  404. const params={"keyword":this.keyword};
  405. getVideoList(params,this.pageNum,this.pageSize).then(res => {
  406. this.refreshing = false;
  407. this.isShowTab=true;
  408. if(res.code==200){
  409. const datas=res.data.list;
  410. this.isLastPage=res.data.isLastPage;
  411. datas.forEach(e=>{
  412. e.videoId=e.id;
  413. e.id = 'A'+e.id+''+parseInt(Math.random()*1000);
  414. e.src=e.src.replace("obs.shouzhujue.com","obs.jy.cc");
  415. this.dataList.push(e);
  416. });
  417. if(this.pageNum==1){
  418. setTimeout(e=>{
  419. this.tapVideoHover("reset");
  420. this.checkTextLines(0);
  421. },100)
  422. this.leftTimers=setTimeout(e=>{
  423. this.dataList[0].isShowGoods=true;
  424. },3000);
  425. }
  426. if(this.isPostBack){
  427. this.isPostBack=false;
  428. this.getBrowse();
  429. }
  430. }else{
  431. this.refreshing = false;
  432. this.isShowTab=true;
  433. }
  434. },
  435. rej => {}
  436. ).catch(()=>{
  437. //联网失败, 结束加载
  438. this.refreshing = false;
  439. this.isShowTab=true;
  440. });
  441. },
  442. touchstart(event) {
  443. this.dataList[this.k].isShowimage = true //刚触摸的时候就要显示预览视频图片了
  444. this.dataList[this.k].isShowProgressBarTime = true //显示时间线
  445. this.ProgressBarOpacity = 1 //让滑块显示起来更明显一点
  446. this.dotWidth = 10 //让点显示起来更明显一点
  447. },
  448. touchend() { //当手松开后,跳到最新时间
  449. console.log('touchEnd');
  450. uni.createVideoContext(this.dataList[this.k].id, this).seek(this.newTime)
  451. if (this.dataList[this.k].state == 'pause') {
  452. this.dataList[this.k].state = 'play'
  453. uni.createVideoContext(this.dataList[this.k].id, this).play();
  454. console.log('touchEnd 播放数据',this.k,this.dataList[this.k].id);
  455. }
  456. this.dataList[this.k].isShowProgressBarTime = false //触摸结束后,隐藏时间线
  457. this.dataList[this.k].isShowimage = false //触摸结束后,隐藏时间预览
  458. this.ProgressBarOpacity = 0.5 //隐藏起来进度条,不那么明显了
  459. this.dotWidth = 0 //隐藏起来进度条,不那么明显了
  460. },
  461. touchmove(event) { //当手移动滑块时,计算位置、百分小数、新的时间
  462. var msg = []
  463. if (this.videoTime !== '') {
  464. msg = this.videoTime.split(':')
  465. }
  466. var timeNumber = Number(msg[0]) * 60 + Number(msg[1])
  467. this.currentPositions = event.changedTouches[0].screenX
  468. this.percent = this.currentPositions / this.windowWidth
  469. this.newTime = this.percent * timeNumber
  470. this.currenttimes = parseInt(this.newTime)
  471. let theTime = this.newTime
  472. let middle = 0; // 分
  473. if (theTime > 60) {
  474. middle = parseInt(theTime / 60);
  475. theTime = parseInt(theTime % 60);
  476. }
  477. this.changeTime = `${Math.round(middle)>9?Math.round(middle):'0'+Math.round(middle)}:${Math.round(theTime)>9?Math.round(theTime):'0'+Math.round(theTime)}`
  478. },
  479. tapVideoHover(state,event){
  480. console.log('kkkk=>',this.k);
  481. this.dataList[this.k].isShowimage = false
  482. this.dataList[this.k].isShowProgressBarTime = false
  483. this.ProgressBarOpacity = 0.5
  484. this.dotWidth = 0
  485. console.log('state--',state);
  486. // 1.启用双击点赞 --- start
  487. if(state=='play'||state=='continue'){
  488. this.dataList[this.k].state = 'pause';
  489. }
  490. else if(state=='reset'){
  491. this.dataList[this.k].state = 'reset';
  492. }
  493. else{
  494. this.dataList[this.k].state = 'continue';
  495. }
  496. this.dataList[this.k].isShowPlayIcon = true;
  497. //console.log('xxx',this.dataList[this.k].state);
  498. if(this.dataList[this.k].state == 'continue'){
  499. //console.log('播放数据',this.dataList[this.k].id);
  500. uni.createVideoContext(this.dataList[this.k].id,this).play();//暂停以后继续播放
  501. }
  502. if(this.dataList[this.k].state == 'pause'){
  503. uni.createVideoContext(this.dataList[this.k].id,this).pause();//暂停以后继续播放
  504. }
  505. if(this.dataList[this.k].state == 'reset'){
  506. uni.createVideoContext(this.dataList[this.k].id,this).seek(0);
  507. uni.createVideoContext(this.dataList[this.k].id,this).play();//暂停以后继续播放
  508. this.dataList[this.k].state = 'continue';
  509. }
  510. },
  511. scrolls (event) {
  512. this.isDragging = event.isDragging;
  513. if (!event.isDragging) {//isDragging:判断用户是不是在滑动,滑动:true,停止滑动:false。我们要用户停止滑动时才给 k 赋值,这样就可以避免很多麻烦
  514. var i = Math.round(Math.abs(event.contentOffset.y) / (this.wHeight - this.deleteHeight - this.statusBarHeight + 1))//先用绝对值取出滑动的距离,然后除以屏幕高度,取一个整,就知道你现在滑动到哪一个视频了
  515. //console.log("qxj k:"+this.k+" i:"+i);
  516. if(i !== this.k){//这里加判断是因为这个方法会执行很多次,会造成重复请求,所以这里写一个限制
  517. let num = 0;
  518. clearTimeout(this.timers);
  519. this.timers = setTimeout(()=>{
  520. this.k = i;//判断了用户没有滑动,确认了用户的确是在看这个视频,然后就赋值啦
  521. this.dataList[this.k].state = 'play';
  522. //console.log('正在播放 --> 第' + (this.k + 1) + '个视频~');
  523. this.checkTextLines(i);
  524. this.getBrowse();
  525. },num);
  526. if(!isLogin()){
  527. if(this.viewVideoNum%2==0){
  528. showLoginPage();
  529. }
  530. this.viewVideoNum++;
  531. }
  532. clearTimeout(this.leftTimers);
  533. this.leftTimers=setTimeout(e=>{
  534. this.dataList[this.k].isShowGoods=true;
  535. },3000);
  536. }
  537. }
  538. },
  539. handleDoLike(item,index){
  540. if (this.doLikeDisabled) return;
  541. this.doLikeDisabled = true;
  542. this.doLike(item, i);
  543. setTimeout(() => {
  544. this.doLikeDisabled = false;
  545. }, 1000); // 1秒后重新启用方法
  546. },
  547. doLike(item,index){
  548. if(!isLogin()){
  549. showLoginPage();
  550. return;
  551. }
  552. doLike(item.videoId).then(res => {
  553. if(res.code==200){
  554. if(item.like==0){
  555. item.like=1;
  556. item.likeNum+=1;
  557. }else{
  558. item.like=0;
  559. item.likeNum-=1;
  560. }
  561. this.dataList[index]=item;
  562. this.$forceUpdate(); // 如果你需要强制刷新,可以调用 $forceUpdate()
  563. }else{
  564. this.showToast(res.msg);
  565. }
  566. },
  567. rej => {}
  568. );
  569. },
  570. doFavorite(item,index){
  571. if(!isLogin()){
  572. showLoginPage();
  573. return;
  574. }
  575. doFavorite(item.videoId).then(res => {
  576. if(res.code==200){
  577. if(item.favorite==0){
  578. item.favorite=1;
  579. item.favoriteNum+=1;
  580. }else{
  581. item.favorite=0;
  582. item.favoriteNum-=1;
  583. }
  584. this.dataList[index]=item;
  585. this.$forceUpdate(); // 如果你需要强制刷新,可以调用 $forceUpdate()
  586. }
  587. else{
  588. this.showToast(res.msg);
  589. }
  590. },
  591. rej => {}
  592. );
  593. },
  594. addIntegral(){
  595. if(!isLogin()){
  596. return;
  597. }
  598. addIntegral(2).then(res => {
  599. if(res.code==200){
  600. uni.showToast({icon:'none',title:res.msg,duration:3000,position:'bottom'});
  601. }
  602. },
  603. rej => {}
  604. );
  605. },
  606. tabChange (index) {
  607. this.tabIndex=index;
  608. },
  609. playIngs:function(){
  610. },
  611. openComment(item){
  612. const subNVue = uni.getSubNVueById('videoComment');
  613. subNVue.show('slide-in-bottom', 250);
  614. uni.$emit('videoComment', {
  615. videoId: item.videoId,
  616. smsNum:item.smsNum
  617. });
  618. },
  619. closePro(item,index){
  620. item.isShowGoods=false;
  621. this.dataList[index]=item;
  622. this.$forceUpdate();
  623. },
  624. goToPro(item){ //跳转疗法页面
  625. uni.navigateTo({
  626. url: "/pages/store/packageDetails?packageId="+item.productId
  627. });
  628. },
  629. click:function(){
  630. console.log('click');
  631. },
  632. onClickItem(e) {
  633. if (this.tabIndex !== e.currentIndex) {
  634. this.tabIndex = e.currentIndex
  635. }
  636. },
  637. getRichText(content) {
  638. content = new HTMLParser(content.trim())
  639. return content
  640. },
  641. checkTextLines(index) {
  642. var system = uni.getSystemInfoSync();
  643. let textWidth=system.screenWidth-uni.upx2px(150+20);
  644. let fontSize=uni.upx2px(30);
  645. let screenWidth=system.screenWidth;
  646. let that=this;
  647. let txtTitle=this.$refs["txtTitle"+index];
  648. this.defTitStyle={'opacity':0}
  649. this.showExpand=false;
  650. uni.createSelectorQuery().select("#txtTitle"+index).boundingClientRect(rect => {
  651. console.log("qxj checkTextLines height:"+rect.height);
  652. setTimeout(e=>{
  653. this.defTitStyle={'opacity':1};
  654. this.showExpand=rect.height>40;
  655. },50);
  656. }).exec();
  657. },
  658. linechange(event){
  659. console.log(event)
  660. const lineCount = event.detail.lineCount //行数
  661. this.lineCount = lineCount
  662. if(lineCount>3){ //如果大于3行,显示展开阅读
  663. this.showExpand = true
  664. }
  665. },
  666. clickExpand(){
  667. this.titIsExpand=!this.titIsExpand;
  668. this.defTitStyle={'opacity':1,'lines':this.titIsExpand?1000:2};
  669. },
  670. openShare(item){
  671. console.log("qxj openShare");
  672. this.shareItem.title=item.title;
  673. this.shareItem.imageUrl=item.cover;
  674. this.shareItem.compressImage = 1
  675. this.shareItem.summary="";
  676. let cdn=uni.getStorageSync('requestPath');
  677. this.shareItem.url=cdn+"/h5/pages/course/video/living-applet?videoId="+item.videoId;
  678. this.showShare=true;
  679. },
  680. getBrowse() { // 倒计时
  681. this.countItem=this.processDatas[this.k];
  682. if(this.countItem==null){
  683. this.countItem={"process":0,"isLoad":false};
  684. this.process=0;
  685. }
  686. this.process=this.countItem.isLoad?100:0;
  687. if(this.interval==null){
  688. this.interval = setInterval(() => {
  689. if(this.showGuide){
  690. return;
  691. }
  692. if (this.process < 100) {
  693. if (this.isCounting) {
  694. this.process = this.process + 1;
  695. this.countItem.process=this.process;
  696. if(this.processDatas[this.k]!=undefined){
  697. this.processDatas.splice(this.k,1,this.countItem);
  698. }else{
  699. this.processDatas.push(this.countItem);
  700. }
  701. }
  702. }
  703. else {
  704. if(!this.countItem.isLoad){
  705. this.addIntegral();
  706. //uni.showToast({title: "获取芳华币",icon: 'none',position:'bottom'});
  707. }
  708. clearInterval(this.interval);
  709. this.interval=null;
  710. this.countItem.isLoad=true;
  711. if(this.processDatas[this.k]!=undefined){
  712. this.processDatas.splice(this.k,1,this.countItem);
  713. }else{
  714. this.processDatas.push(this.countItem);
  715. }
  716. //this.isCounting=true;
  717. // // 页面返回后停止,往下执行
  718. // if (this.isCounting) {
  719. // this.process = 0
  720. // this.getBrowse();
  721. // }
  722. }
  723. }, 100);
  724. }
  725. },
  726. onProgress() {
  727. //console.log("------qxj onProgress");
  728. },
  729. timeupdate(){
  730. //console.log("------qxj onTimeupdate");
  731. },
  732. onLoadeddata() {
  733. console.log('------qxj 视频缓冲完成');
  734. },
  735. onVideoCanPlay() {
  736. console.log('------qxj 视频可以开始播放,但可能需要缓冲');
  737. },
  738. onVideoCanPlayThrough() {
  739. console.log('------qxj 视频可以无暂停地播放');
  740. },
  741. onLoadedMetadata(e) {
  742. //console.log("------qxj onLoadedMetadata");
  743. },
  744. endedPlayNext(){
  745. //console.log("------qxj endedPlayNext");
  746. },
  747. onWaiting(){
  748. ////console.log("------qxj onWaiting");
  749. //this.tapVideoHover("");
  750. },
  751. onError(){
  752. console.log("------qxj onError 当前视频播放出错");
  753. uni.showToast({title: "当前视频播放出错",icon: 'none',position:'bottom'});
  754. },
  755. showToast(title){
  756. uni.showToast({icon:'none',title: title ,duration:3000});
  757. },
  758. tapRedpacked(){
  759. },
  760. nextGuide(){
  761. console.log("qxj nextGuide");
  762. clearInterval(this.guideTimer);
  763. this.guideTimer=null;
  764. this.showGuide = false;
  765. uni.setStorageSync(this.step.name, 'true');
  766. }
  767. }
  768. }
  769. </script>
  770. <style scoped lang="scss">
  771. .container {
  772. background-color: #000000;
  773. }
  774. .item {
  775. /* width : 750rpx; */
  776. background-color: #000000;
  777. position: relative;
  778. }
  779. .videoHover {
  780. position: absolute;
  781. top: 0;
  782. left: 0;
  783. flex: 1;
  784. background-color: rgba(0, 0, 0, 0.1);
  785. justify-content: center;
  786. align-items: center;
  787. /* border-style: dashed;
  788. border-color: #DD524D;
  789. border-width: 1px; */
  790. }
  791. .playState {
  792. width: 80rpx;
  793. height: 80rpx;
  794. opacity: 0.9;
  795. }
  796. .userInfo {
  797. position: absolute;
  798. bottom: 80px;
  799. right: 10px;
  800. flex-direction: column;
  801. }
  802. .userAvatar {
  803. border-radius: 500%;
  804. margin-bottom: 15px;
  805. border-style: solid;
  806. border-width: 2px;
  807. border-color: #ffffff;
  808. }
  809. .userAvatar {
  810. width: 100rpx;
  811. height: 100rpx;
  812. }
  813. .likeIco,
  814. .shareIco,
  815. .commentIco {
  816. width: 60rpx;
  817. height: 60rpx;
  818. margin-top: 15px;
  819. }
  820. .likeNum,
  821. .commentNum,
  822. .shareTex {
  823. color: #ffffff;
  824. font-size: 30rpx;
  825. text-align: center;
  826. margin: 5px;
  827. }
  828. .likeNumActive {
  829. color: red;
  830. }
  831. .content {
  832. width: 610rpx;
  833. z-index: 99;
  834. position: absolute;
  835. bottom: 30px;
  836. /* background-color: #007AFF; */
  837. /* justify-content: center; */
  838. padding: 15rpx;
  839. flex-direction: column;
  840. justify-content: flex-start;
  841. color: #ffffff;
  842. }
  843. .userName {
  844. font-size: 30rpx;
  845. color: #ffffff;
  846. margin-top: 80upx;
  847. }
  848. .words {
  849. margin-top: 10rpx;
  850. font-size: 30rpx;
  851. color: #ffffff;
  852. }
  853. .root {
  854. background-color: #000000;
  855. /* background-color: #00ffff; */
  856. }
  857. .person {
  858. position: absolute;
  859. right: 0;
  860. height: 88rpx;
  861. }
  862. .person .num {
  863. background-color: rgba(255, 100, 3, 1);
  864. height: 58rpx;
  865. border-radius: 100rpx 0 0 100rpx;
  866. padding: 0 20rpx;
  867. }
  868. .right,.left {
  869. position: absolute;
  870. bottom: 180rpx;
  871. padding-bottom: env(safe-area-inset-bottom);
  872. }
  873. .right {
  874. right: 30rpx;
  875. bottom: 100rpx;
  876. }
  877. .right .item1 {
  878. width: 100rpx;
  879. }
  880. .right image {
  881. width: 100%;
  882. height: 100%;
  883. }
  884. .left {left: 20rpx;}
  885. .goods .icon,.goods .icon image {
  886. width: 290rpx;
  887. height: 290rpx;
  888. }
  889. .bg {
  890. /* background-image: url(/static/images/other/video/bg.png); */
  891. position: absolute;
  892. left: 0;
  893. top: 0;
  894. width: 100%;
  895. height: 74rpx;
  896. }
  897. .goods {
  898. width: 330rpx;
  899. background-color: rgba(255, 255, 255, 0.4);
  900. padding: 20rpx;
  901. border-radius: 20rpx;
  902. margin-top: 20rpx;
  903. }
  904. .tabbar1{
  905. position: absolute;
  906. top:44px;
  907. z-index: 999;
  908. height:44px;
  909. /* background-color:rgba(0,0,0,0.2) ; */
  910. }
  911. .border1{
  912. border-width: 1px;border-color: green;border-style: solid;
  913. }
  914. .border2{
  915. border-width: 1px;border-color: yellow;border-style: solid;
  916. }
  917. .refresh {
  918. display: flex;
  919. flex-direction: row;
  920. justify-content: center;
  921. height: 50px;
  922. }
  923. .bottom {
  924. position: absolute;
  925. left: 0;
  926. bottom: 60rpx;
  927. right: 150rpx;
  928. padding-bottom: env(safe-area-inset-bottom);
  929. }
  930. .txtTitle{
  931. line-height: 20px;
  932. /* 超出两行显示省略号,如果是text标签需要设置为1 */
  933. color: #fff;
  934. font-weight: 500;
  935. font-size: 30rpx;
  936. margin-left:20rpx;
  937. }
  938. .ellipsis{
  939. lines:2;
  940. /* 确保文本不会自动换行 */
  941. /* white-space: nowrap; */
  942. /* 设置文本溢出时显示省略号 */
  943. text-overflow: ellipsis;
  944. /* 限制显示的行数为2 */
  945. overflow: hidden;
  946. white-space: nowrap; /* 不换行 */
  947. padding-right: 20px; /* 设置右边距为20px,实现末尾缩进 */
  948. box-sizing: border-box; /* 包含padding在内的总宽度 */
  949. }
  950. .expandBtn{
  951. position: absolute;
  952. right: 0rpx;
  953. bottom: 0rpx;
  954. font-weight: 600;
  955. color: #fff;
  956. font-size: 30rpx;
  957. /* background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 50%); */
  958. }
  959. .redpacked{
  960. position: fixed;
  961. width: 86rpx;
  962. height: 86rpx;
  963. top: 200rpx;
  964. z-index: 999;
  965. left: 30rpx;
  966. background-color: rgba(0, 0, 0, 0.4);
  967. }
  968. .guide {
  969. left: 0;
  970. top: 0;
  971. position: absolute;
  972. z-index: 10001;
  973. .guide-box {
  974. position: absolute;
  975. z-index: 10001;
  976. background-color: rgba(0, 0, 0, 0.6);
  977. // transition: all 0.2s;
  978. .arrow {
  979. width: 28rpx;
  980. height: 28rpx;
  981. background: #fff;
  982. position: absolute;
  983. top: 0;
  984. left: 48rpx;
  985. z-index: 10000;
  986. transform: rotate(45deg);
  987. }
  988. .guide-step-tips {
  989. width: 424rpx;
  990. padding: 0 24rpx 24rpx 24rpx;
  991. box-sizing: border-box;
  992. border-radius: 12rpx;
  993. background-color: #fff;
  994. font-family: PingFang SC, PingFang SC;
  995. font-weight: 400;
  996. font-size: 26rpx;
  997. color: #757575;
  998. position: relative;
  999. }
  1000. .tips {
  1001. position: absolute;
  1002. top: 0;
  1003. left: 0;
  1004. z-index: 10001;
  1005. .text {}
  1006. .tool-btn {
  1007. margin-top: 20rpx;
  1008. display: flex;
  1009. flex-direction: row;
  1010. align-items: center;
  1011. justify-content:space-between;
  1012. font-weight: 400;
  1013. font-size: 26rpx;
  1014. color: #757575;
  1015. .next {
  1016. width: 128rpx;
  1017. height: 68rpx;
  1018. line-height: 68rpx;
  1019. text-align: center;
  1020. background: #FF5C03;
  1021. border-radius: 8rpx 8rpx 8rpx 8rpx;
  1022. font-family: PingFang SC, PingFang SC;
  1023. font-weight: 400;
  1024. font-size: 26rpx;
  1025. color: #FFFFFF;
  1026. }
  1027. }
  1028. }
  1029. }
  1030. }
  1031. .liveguide {
  1032. display: flex;
  1033. flex-direction: column;
  1034. align-items: center;
  1035. justify-content: center;
  1036. flex: 1;
  1037. .phone_icon {
  1038. width: 144rpx;
  1039. height: 262rpx;
  1040. }
  1041. }
  1042. .hand_icon {
  1043. height: 177rpx;
  1044. width: 177rpx;
  1045. margin-top: -100rpx;
  1046. margin-left: 118rpx;
  1047. margin-bottom: 20rpx;
  1048. // animation: moveUpDown 1.8s ease-in-out infinite; /* 使用简写属性 */
  1049. // animation-name: moveUpDown;
  1050. // animation-duration: 1.8s;
  1051. // animation-timing-function: ease-in-out;
  1052. // animation-iteration-count: infinite;
  1053. // /* 以下是其他可选属性,默认值已设置 */
  1054. // animation-delay: 0s; /* 默认值 */
  1055. // animation-direction: normal; /* 默认值 */
  1056. // animation-fill-mode: none; /* 默认值 */
  1057. // animation-play-state: running; /* 默认值 */
  1058. }
  1059. .target {
  1060. transform: translateY(20px);
  1061. transition:transform .9s ;
  1062. }
  1063. .origin {
  1064. transform: translateY(0px);
  1065. transition-property:transform;
  1066. transition-duration: .9s;
  1067. }
  1068. .liveguide-tip {
  1069. font-family: PingFang SC, PingFang SC;
  1070. font-weight: 600;
  1071. font-size: 36rpx;
  1072. color: #ffffff !important;
  1073. }
  1074. </style>