living-app-searchInfo.nvue 33 KB

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