living.vue 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677
  1. <template>
  2. <view class="container">
  3. <!-- <view class="popup-video " v-if="!autoplay">
  4. <view class="fs36 bold" v-if="livedata.status==1">——直播还未开始——</view>
  5. <view class="fs36 bold" v-if="livedata.status==3">——直播已经结束——</view>
  6. <view class="fs28 mtb20">了解更多,点击下方联系老师</view>
  7. <view class="more" @click="showadd=!showadd">联系老师</view>
  8. </view> -->
  9. <!-- <image :src="livedata.liveImgUrl"
  10. :class="livedata.status!=2?'background-images':'background-image'"></image> -->
  11. <view class="blackbg"></view>
  12. <view class="content">
  13. <!-- 页面内容 -->
  14. <view style=" position: fixed;top: 0;z-index: 5;" class="content-top">
  15. <view class="u-flex-y-center">
  16. <image @click="goBack" style="width: 60rpx;height: 64rpx;margin-right: 26rpx;"
  17. src="@/static/images/live/return.png"></image>
  18. <view class=" align-center"
  19. style="padding: 6rpx 4rpx;height: 64rpx;background: rgba(0,0,0,0.5);border-radius: 32rpx;">
  20. <u-avatar :src="livedata.liveImgUrl" size="32"></u-avatar>
  21. <view class="colorf" style="margin-left: 8rpx;">
  22. <view>{{livedata.liveName?livedata.liveName:"芳华未来"}}</view>
  23. <view style="font-size: 16rpx;">
  24. {{ liveViewData.follow || liveViewData.follow === 0 ? liveViewData.follow : 0 }}位粉丝
  25. </view>
  26. </view>
  27. <view v-if="isFollow" @click="onFollow" class="follow-btn ml20">关注</view>
  28. <view v-else @click="onFollow" class="follow-btn ml20">已关注</view>
  29. </view>
  30. </view>
  31. <view class="u-flex-end align-center">
  32. <image class="w52 h52 mr4" v-for="(item,index) in filteredViewers" :key="index"
  33. style="border-radius: 26rpx;" :src="item.avatar"></image>
  34. <view class="sum">{{liveViewData.online}}</view>
  35. </view>
  36. </view>
  37. <!-- 右边的 -->
  38. <view class="side-group">
  39. <view class="side-item">
  40. <image @click="onLike()" src="/static/images/live/like.png"></image>
  41. <view>{{liveViewData.like}}</view>
  42. <!-- <view>{{liveData likeName}}</view> -->
  43. </view>
  44. <view class="side-item" @click="goStore()">
  45. <image src="/static/images/live/shop.png"></image>
  46. <view>店铺</view>
  47. </view>
  48. <view class="side-item">
  49. <image src="/static/images/live/share.png"></image>
  50. <view>分享</view>
  51. </view>
  52. </view>
  53. <view class="shop-prompt u-flex-y-center">
  54. <image class="w32 h32 mr8" src="/static/images/live/shopping.png"></image>
  55. <text> {{orderUser.userName ? maskString(orderUser.userName) : ''}} 等 {{orderUser.count || 0}}
  56. 人正在去购买</text>
  57. </view>
  58. <!-- <view class="videolist " style="margin: auto 0">
  59. <view class="vedio" :style="{height:isScreen?'100vh':''}">
  60. <video id="myVideo" class="videotop" :src="livingUrl" :autoplay="autoplay" :controls='false'
  61. vslide-gesture-in-fullscreen='true' :show-center-play-btn="false"></video>
  62. </view>
  63. </view> -->
  64. <!-- object-fit:fill; -->
  65. <view class="videolist " style="margin: auto 0">
  66. <view class="vedio" :style="{height:isScreen?'100vh':''}">
  67. <!-- 修改video组件以支持HLS -->
  68. <video id="myVideo" class="videotop" :src="livingUrl" :autoplay="autoplay" :controls='false' object-fit='contain'
  69. :custom-cache="false" :enable-progress-gesture="false" vslide-gesture-in-fullscreen='true'
  70. :show-center-play-btn="false" :http-cache="false" @error="videoError" >
  71. </video>
  72. </view>
  73. </view>
  74. <view class="pb40 mt90" style="position: fixed;bottom: 0;">
  75. <view class="w100 h300 mt20">
  76. <scroll-view enable-flex scroll-y="true" class="talk p20 scrolly flex-1 column"
  77. style="width: calc(100% - 40rpx);height: calc(100% - 40rpx);"
  78. :scroll-into-view="scrollIntoView">
  79. <view>
  80. <view class="list justify-start" v-for="(item,index) in talklist" :key="item.index"
  81. :id="`list_${index}`" v-show="item.cmd=='announcement'">
  82. <view class="talk-list ml16 justify-start">
  83. <view class="fs24">
  84. <text class='fs24 colorf'> {{item.msg}}直播间{{messageContent}}</text>
  85. </view>
  86. </view>
  87. </view>
  88. </view>
  89. <!-- 弹幕 -->
  90. <!-- <u-list class="chat-list" height="184" @scrolltolower="scrollchat">
  91. <u-list-item class="chat-item" v-for="(item,index) in chatList" :key="index">
  92. <view class="chat-lable u-flex-y-center mr8" v-if="item.lable">
  93. <image class="w24 h24 mr8" src="@/static/images/live/diamond.png"></image>
  94. <text>{{item.lable}}</text>
  95. </view>
  96. <text style="color: #FFDA73;white-space: nowrap;" class=" mr8">{{item.name}}:</text>
  97. <text style="flex: 1;min-width: 0;word-break: break-word;">{{item.txt}}</text>
  98. </u-list-item>
  99. </u-list> -->
  100. <view class="list justify-start" v-for="(item,index) in talklist" :key="item.index"
  101. :id="`list_${index}`" v-show="item.cmd=='sendMsg'">
  102. <view class="talk-list ml16 justify-start">
  103. <view class="fs24">
  104. <!-- <text style="color: #3fc69b;transform: scale(0.8);display: inline-block; "v-if="item.userId==userinfo.userId&&item.cmd=='sendMsg'">我</text> -->
  105. <!-- <text style="color: #c84e1e;transform: scale(0.8);display: inline-block;" v-if="item.userType==1">[ 管理员 ]</text> -->
  106. <text style="color: #FFDA73;">{{item.nickName}}:</text>
  107. <text class='fs24 colorf'>{{item.msg}}</text>
  108. </view>
  109. </view>
  110. </view>
  111. <!-- <view class="list justify-start" v-for="(item,index) in talklist" :key="item.index"
  112. :id="`list_${index}`" v-show="item.cmd=='sendMsg'">
  113. <view class="talk-list ml16 justify-start">
  114. <view class="fs24">
  115. <text style="color: #3fc69b;transform: scale(0.8);display: inline-block; "
  116. v-if="item.userId==userinfo.userId&&item.cmd=='sendMsg'">我</text>
  117. <text style="color: #c84e1e;transform: scale(0.8);display: inline-block;" v-if="item.userType==1">
  118. [ 管理员 ]</text>
  119. <text style="color: #FFDA73;">{{item.nickName}}:</text>
  120. <text class='fs24 colorf'>{{item.msg}}</text>
  121. </view>
  122. </view>
  123. </view> -->
  124. <view v-if="showWelcomeMessage" class="welcome-message">
  125. <view class="list justify-start" v-for="(item,index) in talklist" :key="item.index"
  126. :id="`list_${index}`" v-show="item.cmd=='entry'||item.cmd=='out'">
  127. <view class="talk-list ml16 justify-start">
  128. <view class="fs24">
  129. <text style="color: #ff89d6;">{{item.nickName}} </text>
  130. <text class='fs24 colorf'> {{item.msg}}直播间{{messageContent}}</text>
  131. </view>
  132. </view>
  133. </view>
  134. </view>
  135. </scroll-view>
  136. </view>
  137. <view class="justify-between p24">
  138. <view class="u-flex-y-center"
  139. style="background:rgba(255,255,255,0.2);padding:18rpx 14rpx 18rpx 32rpx;width: 526rpx;box-sizing:border-box;border-radius:36rpx;">
  140. <u-input :placeholder="placeholderText" border="none" customStyle='font-size:24rpx;'
  141. v-model="value" shape='circle' color='#fff' placeholderStyle='color:#e7e7e7' class="ml20"
  142. @keydown.enter="sendMsg" @confirm="sendMsg">
  143. </u-input>
  144. <!-- <image @click="sendMsg" class="w44 h44" src="@/static/images/live/like.png"></image> -->
  145. </view>
  146. <!-- :disabled='talkdisabled' ></u-input> -->
  147. <!-- <view @click="sendMsg" class="colorf center ml10 fs24">发送</view> -->
  148. <view class="justify-between mr30 align-center">
  149. <!-- <view class="icon-bg ml20" @click="answerbtn=!answerbtn">
  150. <image src="/static/images/redbag.png" class="w40 h40"></image>
  151. </view> -->
  152. <view class="icon-bg ml20" @click="shopping=!shopping">
  153. <image src="/static/images/shopping.png" class="w48 h48"></image>
  154. </view>
  155. <view class="icon-bg ml20" @click="showziliao=!showziliao">
  156. <image src="/static/images/more-icon.png" class="w48 h48"></image>
  157. </view>
  158. <!-- <view class="icon-bg ml20" :class="{ 'zoom-button-active': isZoom }"
  159. @touchstart="handleTouchStart" @touchend="handleTouchEnd">
  160. <image src="/static/images/dianzan.png" class="w40 h40"></image>
  161. </view> -->
  162. </view>
  163. </view>
  164. </view>
  165. </view>
  166. <!-- <u-popup :show="showadd" @close="close" @open="open" round='20rpx' bgColor='#fffee1'>
  167. <view class="addchat p20">
  168. <view class="u-flex-row-reverse u-flex">
  169. <u-icon name="close" size="18" @click="showadd=!showadd"></u-icon>
  170. </view>
  171. <view class="column align-center">
  172. <view class="fs36" style="color: #ff5c03;">扫码添加助教老师</view>
  173. <view class="fs28 color6">扫码添加助教老师</view>
  174. <view class="p10 mt40" style="border: #ff5c03 solid 2rpx;">
  175. <image :src="codeimg" class="wh180" @touchstart="longPress" @touchend="cancelLongPress">
  176. </image>
  177. </view>
  178. <view class="color6 mt20">长按识别二维码</view>
  179. </view>
  180. </view>
  181. </u-popup> -->
  182. <u-popup :show="showziliao" @close="closes" round='20' bgColor='#fffee1'>
  183. <view class="addchat p20 bgf" style="border-radius: 20rpx;">
  184. <view class="u-flex-row-reverse u-flex">
  185. <u-icon name="close" size="18" @click="showziliao=!showziliao"></u-icon>
  186. </view>
  187. <view class="column align-center h400">
  188. <view class="fs36 " style="color: #ff5c03;">资料</view>
  189. <view v-html="livedata.liveDesc"></view>
  190. </view>
  191. </view>
  192. </u-popup>
  193. <!-- 抽奖 -->
  194. <!-- <u-popup :show="answerbtn" @close="closeanswer" round='40rpx' bgColor='#fff'>
  195. <view class=" p20 bgf" style="border-radius: 40rpx;height: fit-content;">
  196. <view class="u-flex-row-reverse u-flex">
  197. <u-icon name="close" size="18" @click="answerbtn=!answerbtn"></u-icon>
  198. </view>
  199. <view class="column align-center h400">
  200. <view class="fs36 " style="color: #000000;font-weight: bold;">答题获取红包/积分奖励</view>
  201. <view class="answerpop" @click="noredanswer">
  202. <view class="color6 w350 fs24">
  203. 边玩边学,解锁你的知识巅峰!
  204. </view>
  205. <view class="answera">答题挑战</view>
  206. </view>
  207. <view class="answerpop">
  208. <view class="color6 fs24" v-if='redanswertips&&redanswertips.length>0'>
  209. 🔥 <text style="color: #ff5c03;" class="fs30 bold">{{redanswertips[1].probability}}</text>
  210. %用户首抽得
  211. <text style="color: #ff5c03;" class="fs40 bold">{{redanswertips[1].maxAmount}}</text>元
  212. </view>
  213. <view v-else class="color6 w350 fs24">
  214. 随机奖励
  215. </view>
  216. <view class="answera" @click="redbagAnswer">
  217. <image src="/static/images/baganswer.png"></image>
  218. <view> 获得红包</view>
  219. </view>
  220. </view>
  221. </view>
  222. </view>
  223. </u-popup> -->
  224. <!-- <u-popup :show="showAnswer" @close="closest" round='40' bgColor='#fffee1' mode="center">
  225. <view class="answerbox p20 bgf">
  226. <view class="u-flex-row-reverse u-flex">
  227. <u-icon name="close" size="18" @click="closest"></u-icon>
  228. </view>
  229. <view class="column align-center ">
  230. <view v-if="answerlist.type==1" style="width: 100%;">
  231. <view class="mb40" style="text-align: center;">
  232. <text class="color9 fs24">(单选)</text>{{answerlist.title}}
  233. </view>
  234. <view v-for="(item,index) in answerlist.content" :key="index"
  235. :class=" checkboxValue[0]== item.label?'answeract itemanswer':'itemanswer' "
  236. @click="handleCheckboxSelect(item.label)">{{item.label}}. {{item.content}}</view>
  237. </view>
  238. <view v-if="answerlist.type==2" style="width: 100%;">
  239. <view class="mb40 " style="text-align: center;">
  240. <text class="color9 fs24">(多选)</text>{{answerlist.title}}
  241. </view>
  242. <view v-for="(item,index) in answerlist.content" :key="index"
  243. :class=" checkboxValue.includes(item.label)?'answeract itemanswer':'itemanswer' "
  244. @click="handleCheckboxSelect(item.label)">{{item.label}}. {{item.content}}</view>
  245. <view class=" submitbtn" @click="submitAnswers">确认</view>
  246. </view>
  247. <view class="fs24 mtb20 " style="color: #717171;">
  248. {{answerfrist+1}}/{{Answerlistall}}
  249. </view>
  250. </view>
  251. </view>
  252. </u-popup> -->
  253. <!-- <u-popup :show="showAnswerred" @close="closestred" round='40' bgColor='#fffee1' mode="center">
  254. <view class="answerbox p20 bgf">
  255. <view class="u-flex-row-reverse u-flex">
  256. <u-icon name="close" size="18" @click="closestred"></u-icon>
  257. </view>
  258. <view class="column align-center ">
  259. <view v-if="answerlist.type==1" style="width: 100%;">
  260. <view class="mb40" style="text-align: center;">
  261. <text class="color9 fs24">(单选)</text>{{answerlist.title}}
  262. </view>
  263. <view v-for="(item,index) in answerlist.content" :key="index"
  264. :class=" checkboxValue[0]== item.label?'answeract itemanswer':'itemanswer' "
  265. @click="handleCheckboxSelect(item.label)">{{item.label}}. {{item.content}}</view>
  266. </view>
  267. <view v-if="answerlist.type==2" style="width: 100%;">
  268. <view class="mb40 " style="text-align: center;">
  269. <text class="color9 fs24">(多选)</text>{{answerlist.title}}
  270. </view>
  271. <view v-for="(item,index) in answerlist.content" :key="index"
  272. :class=" checkboxValue.includes(item.label)?'answeract itemanswer':'itemanswer' "
  273. @click="handleCheckboxSelect(item.label)">{{item.label}}. {{item.content}}</view>
  274. <view class=" submitbtn" @click="submitAnswers">确认</view>
  275. </view>
  276. <view class="fs24 mtb20 " style="color: #717171;">
  277. {{answerfrist+1}}/{{Answerlistall}}
  278. </view>
  279. </view>
  280. </view>
  281. </u-popup> -->
  282. <!-- 小黄车弹窗 -->
  283. <u-popup :show="shopping" @close="closeshop" @open="open" round='20rpx' bgColor='#f3f5f9'>
  284. <view class="shoppop">
  285. <view class="shoppop-top">
  286. <u-avatar :src="livedata.liveImgUrl" size="36" class="ml16"></u-avatar>
  287. <view class="search-input u-flex-y-center">
  288. <image style="width: 24rpx;height: 24rpx;margin-right: 16rpx;" src="@/static/images/search.png">
  289. </image>
  290. <input placeholder="搜索商品或序号" />
  291. </view>
  292. <view class="t-c search-top" style="margin-right: 48rpx;" @click="onCollect">
  293. <image style="width: 32rpx;height: 32rpx;" src="@/static/images/collect.png"></image>
  294. <view>收藏</view>
  295. </view>
  296. <view class="t-c search-top" @click="goOrderList">
  297. <image style="width: 32rpx;height: 32rpx;" src="@/static/images/order.png"></image>
  298. <view>订单</view>
  299. </view>
  300. </view>
  301. <scroll-view enable-flex scroll-y class="shop-list" :style="{ height: boxHeight + 'px' }">
  302. <view class="list-item " v-for="(item,index) in products" :key="index">
  303. <view class="goods-img">
  304. <image :src="item.imgUrl" mode="widthFix"></image>
  305. <view class="goods-label">{{index+1}}</view>
  306. </view>
  307. <view class="goods-right">
  308. <view class="goods-title">{{item.productName}}</view>
  309. <view class="goods-details">{{item.productIntroduce}}</view>
  310. <view class="goods-people">{{item.sales}} 人已购</view>
  311. <view class="goods-shop">
  312. <text class="nummber"><text style="font-size: 20rpx;font-weight: 600;">¥</text><text
  313. style="font-size: 36rpx;font-weight: bold;">{{Math.trunc(item.price)}}</text>.{{getPureDecimal(item.price)?getPureDecimal(item.price):'00'}}/日</text>
  314. <view class="btn-group u-flex-y-center">
  315. <view class="collect-btn">
  316. <image @click="onCollect(item)" style="width: 32rpx;height: 32rpx;"
  317. src="/static/images/collect.png">
  318. </image>
  319. </view>
  320. <view v-if="item.status==1" class="shop-btn" @click="goShop(item.productId)">去购买
  321. </view>
  322. <view v-else-if="item.status==0" @click="goShop(item.productId)" class="shop-btn">
  323. 已下架</view>
  324. </view>
  325. </view>
  326. </view>
  327. </view>
  328. </scroll-view>
  329. </view>
  330. </u-popup>
  331. </view>
  332. </template>
  333. <script>
  334. import Hls from 'hls.js';
  335. import CryptoJS from 'crypto-js'
  336. import {
  337. liveDataLike, // 点赞
  338. collectStore, // 收藏/取消收藏
  339. follow, // 关注/取消关注
  340. getRecentLiveViewers, //获取直播间用户(展示在线用户)
  341. // 小黄车
  342. liveStore, //店铺展示,
  343. // liveGoodsDetail, //商品详情,
  344. liveOrderUser, //正在购买
  345. getLiveInfo, //获取直播间信息接口
  346. getLiveViewData //直播间点赞、关注、在线人数数据
  347. } from '@/api/live'
  348. import {
  349. liveOrderList, // 订单列表
  350. } from '@/api/order'
  351. import parse from '../../uni_modules/uview-plus/libs/config/props/parse';
  352. import {
  353. LiveWS
  354. } from '@/utils/liveWS.js'
  355. import {
  356. getlive,
  357. gettextlist,
  358. getAnswerlist,
  359. submitAnswer
  360. } from '@/api/home'
  361. // var wsUrl = "ws://192.168.10.166:17114/app/webSocket";
  362. // var wsUrl = "ws://192.168.10.166:7114/app/webSocket"; //余红奇
  363. var wsUrl = "ws://live.test.ylrztop.com/prod-api/app/webSocket"; //余红奇
  364. // var wsUrl = "ws://nd383294.natappfree.cc/app/webSocket"; //余红奇
  365. // var wsUrl = "ws://v56c9b8e.natappfree.cc/app/webSocket"; //余红奇
  366. // var wsUrl = "ws://192.168.10.170:7114/app/webSocket"; //陈果
  367. // var wsUrl = "ws://live.ylrzcloud.com/socket/app/webSocket";
  368. var pingpangTimes = null;
  369. var initTimes = null;
  370. var isSocketOpen = false;
  371. var socket = null;
  372. export default {
  373. data() {
  374. return {
  375. boxHeight: 300, //小黄车高度
  376. isFollow: true,
  377. liveViewData: {},
  378. liveViewers: [], //观众
  379. likeName: 0,
  380. hlsPlayer: null, // HLS播放器实例,
  381. livingUrl: "",
  382. products: {},
  383. store: {},
  384. orderUser: {}, //正在购买
  385. userType: 0,
  386. timestamp: '',
  387. liveId: null,
  388. // userId: uni.getStorageSync("userInfo.userId"),
  389. livedata: {},
  390. codeimg: '',
  391. placeholderText: '说点什么...',
  392. isZoom: false, //点赞按钮控制是否放大
  393. userinfo: '', //用户信息
  394. // path: 'http://192.168.10.166/dev-api', //余红奇
  395. // path: 'http://v56c9b8e.natappfree.cc', //余红奇
  396. path: 'live.test.ylrztop.com/prod-api', //余红奇
  397. // path: 'http://192.168.10.170/dev-api', //陈果
  398. value: '',
  399. talkdisabled: false, //输入框是否禁用
  400. autoplay: false, //视频自动播放
  401. showadd: false,
  402. talklist: [],
  403. scrollIntoView: '',
  404. bufferRate: 0, //视频缓冲时间
  405. playDuration: 0, //视频播放时间
  406. videoContext: '',
  407. thistime: uni.$u.timeFormat(new Date(), 'yyyy-mm-dd hh:MM:ss'),
  408. upDown: true, //是否视频显示隐藏
  409. isLongPress: false, // 是否长按
  410. timeout: null, // 计时器
  411. showWelcomeMessage: false,
  412. isSubmit: false,
  413. messageContent: "",
  414. showziliao: false,
  415. isScreen: true,
  416. showAnswer: false, //展示答题
  417. Answerlistall: {}, //所有题目
  418. answerlist: {}, //当前题目
  419. answerfrist: 0, //当前选择
  420. checkboxValue: [], //多选数据
  421. checkboxFormValue: "", //多选数据
  422. allAnswerLists: [], // 新增:存储所有题目列表
  423. showAnswerred: false, //展示红包答题
  424. answerbtn: false, //答题按钮弹窗
  425. redallAnswerLists: [], //储存所有红包答题列表
  426. redanswerAll: [], //红包当前题目
  427. redanswerList: [], //红包答题列表
  428. redanswertips: [], //红包答题提示
  429. shopping: false, //小黄车弹窗
  430. scrollTop: 0, //弹幕
  431. old: {
  432. scrollTop: 0
  433. },
  434. liveData: {}, //直播间点赞、关注、在线人数数据
  435. // shopList: [{
  436. // title: '史士昊老师四神汤健脾消食疗法',
  437. // details: '看它来喘口气,小小震撼,',
  438. // people: '45708 '
  439. // },{
  440. // title: '史士昊老师四神汤健脾消食疗法',
  441. // details: '看它来喘口气,小小震撼,',
  442. // people: '45708 '
  443. // }],
  444. // chatList: [{
  445. // lable: '达人',
  446. // name: '锅巴',
  447. // txt: '中医调节身体确实'
  448. // },
  449. // {
  450. // lable: '',
  451. // name: '从芯开始',
  452. // txt: '来了'
  453. // }
  454. // {
  455. // lable: '',
  456. // name: '北京的帅小伙:',
  457. // txt: '来了来了,上茶'
  458. // },
  459. // {
  460. // lable: '',
  461. // name: '萍萍',
  462. // txt: '来了'
  463. // }
  464. // ]
  465. };
  466. },
  467. onLoad(options) {
  468. if (options.liveId) {
  469. this.liveId = options.liveId;
  470. // this.liveId = decodeURIComponent(options.liveId);
  471. console.log("接收到的liveId:", this.liveId);
  472. }
  473. },
  474. computed: {
  475. filteredViewers() {
  476. // 只返回前3项(索引0、1、2)
  477. return this.liveViewers.slice(0, 3);
  478. }
  479. },
  480. // computed: {
  481. // userId() {
  482. // return this.$store.state.user.userId
  483. // }
  484. // },
  485. mounted() {
  486. // this.onLike()
  487. this.getliveViewData() ////直播间点赞、关注、在线人数数据
  488. this.intervalId = setInterval(() => {
  489. this.getliveViewData();
  490. }, 60 * 1000);
  491. // this.getLiveinformation() // 获取直播间信息接口
  492. this.getliveOrder() //正在购买
  493. this.getliveStore() // 获取小黄车 店铺展示
  494. // this.getliveGoods() // 获取小黄车 商品详情
  495. this.getliveUser() // 获取直播间用户
  496. this.initTime()
  497. // this.initWebSocket()
  498. this.initSocket()
  499. var that = this;
  500. uni.$on('initSocket', () => {
  501. that.initSocket()
  502. })
  503. uni.$on('sendMsg', (item) => {
  504. that.sendMsg(item)
  505. })
  506. uni.$on('closeWebSocket', () => {
  507. that.closeWebSocket()
  508. })
  509. this.getEWechatSdk();
  510. this.getliving() //hls
  511. this.gettalklist()
  512. // this.getAnswerlists()
  513. this.userinfo = JSON.parse(uni.getStorageSync("userInfo"))
  514. },
  515. onReady: function(res) {
  516. this.videoContext = uni.createVideoContext('myVideo')
  517. // console.log(this.videoContext)
  518. },
  519. onUnload() {
  520. // 销毁HLS播放器
  521. if (this.hlsPlayer) {
  522. this.hlsPlayer.destroy();
  523. this.hlsPlayer = null;
  524. }
  525. },
  526. methods: {
  527. goStore() {
  528. uni.navigateTo({
  529. url: '/pages_shop/store?liveId=' + this.liveId
  530. })
  531. // uni.navigateTo({
  532. // url: "/pages_shop/store"
  533. // })
  534. },
  535. // 去订单列表
  536. goOrderList() {
  537. uni.navigateTo({
  538. url: "/pages_shop/order"
  539. })
  540. },
  541. // 初始化HLS播放器
  542. initHlsPlayer() {
  543. if (Hls.isSupported() && this.livingUrl) {
  544. const video = document.getElementById('myVideo');
  545. if (video) {
  546. this.hlsPlayer = new Hls();
  547. this.hlsPlayer.loadSource(this.livingUrl);
  548. this.hlsPlayer.attachMedia(video);
  549. this.hlsPlayer.on(Hls.Events.MANIFEST_PARSED, () => {
  550. video.play();
  551. });
  552. }
  553. }
  554. },
  555. // 视频错误处理
  556. videoError(e) {
  557. console.error('视频播放错误:', e.detail.errMsg);
  558. // 尝试重新加载或切换到备用流
  559. if (this.livingUrl) {
  560. setTimeout(() => {
  561. this.videoContext.play();
  562. }, 2000);
  563. }
  564. },
  565. getliving() {
  566. const param = {
  567. id: this.liveId
  568. }
  569. getlive(param).then(res => {
  570. if (res.code == 200) {
  571. this.livedata = res.data
  572. // this.codeimg = res.data.qwQrCode
  573. this.livingUrl = res.data.livingUrl; // 确保设置livingUrl
  574. // 检查是否是HLS流
  575. if (this.livingUrl && this.livingUrl.indexOf('.m3u8') > -1) {
  576. // 在H5平台初始化HLS播放器
  577. // #ifdef H5
  578. this.initHlsPlayer();
  579. // #endif
  580. // 其他平台(App、小程序)原生支持HLS
  581. this.$nextTick(() => {
  582. if (this.videoContext) {
  583. this.videoContext.play();
  584. }
  585. });
  586. } else {
  587. // 非HLS流正常播放
  588. if (this.livedata.liveType == 1) {
  589. this.autoplay = true
  590. this.livingUrl=res.videoUrl
  591. this.videoContext.seek(this.livedata.nowDuration)
  592. } else if(this.livedata.liveType == 2) {
  593. this.autoplay = true
  594. this.getLiveinformation()
  595. // this.livingUrl=res.livingUrl
  596. } else {
  597. this.autoplay = false
  598. this.placeholderText = "直播开始才能发言讨论"
  599. this.talkdisabled = true
  600. }
  601. }
  602. } else {
  603. uni.showToast({
  604. title: res.msg,
  605. icon: 'none',
  606. duration: 2000
  607. });
  608. }
  609. })
  610. },
  611. maskString(str, maskChar = '*') {
  612. // 新增:如果str是undefined或null,直接返回空字符串
  613. if (!str) return '';
  614. // 确保str是字符串(如果是数字等类型,先转为字符串)
  615. const strVal = String(str);
  616. return strVal.split('').map((char, index) => (index === 0 ? char : maskChar)).join('');
  617. },
  618. getPureDecimal(num, precision = 6) {
  619. const decimalPart = Math.abs(num).toFixed(precision).split('.')[1];
  620. return decimalPart?.replace(/0+$/, '') || ''; // 移除末尾多余的0
  621. },
  622. // 返回上一个页面并关闭WebSocket
  623. goBack() {
  624. uni.navigateBack();
  625. closeWebSocket();
  626. },
  627. // // 收藏商品
  628. // collectProducts(){
  629. // },
  630. //直播间点赞、关注、在线人数数据
  631. getliveViewData() {
  632. getLiveViewData(this.liveId).then(res => {
  633. if (res.code == 200) {
  634. // console.log("直播间点赞、关注、在线人数数据>>>>", res)
  635. this.liveViewData = res
  636. } else {
  637. uni.showToast({
  638. title: res.msg,
  639. icon: 'none'
  640. });
  641. }
  642. },
  643. rej => {}
  644. );
  645. },
  646. //正在购买
  647. getliveOrder() {
  648. liveOrderUser(this.liveId).then(res => {
  649. if (res.code == 200) {
  650. console.log("正在购买>>>>", res)
  651. this.orderUser = res
  652. } else {
  653. uni.showToast({
  654. title: res.msg,
  655. icon: 'none'
  656. });
  657. }
  658. },
  659. rej => {}
  660. );
  661. },
  662. //小黄车 店铺展示
  663. getliveStore() {
  664. let data = {
  665. pageSize: 10,
  666. page: 1
  667. }
  668. liveStore(this.liveId, data).then(res => {
  669. if (res.code == 200) {
  670. console.log("小黄车 店铺展示>>>>", res)
  671. this.products = res.data
  672. // this.store = res.store
  673. } else {
  674. uni.showToast({
  675. title: res.msg,
  676. icon: 'none'
  677. });
  678. }
  679. },
  680. rej => {}
  681. );
  682. },
  683. // 获取直播间信息接口
  684. getLiveinformation() {
  685. getLiveInfo(this.liveId).then(res => {
  686. if (res.code == 200) {
  687. console.log("获取直播间信息接口>>>>", res)
  688. this.livingUrl = res.livingUrl
  689. } else {
  690. uni.showToast({
  691. title: res.msg,
  692. icon: 'none'
  693. });
  694. }
  695. },
  696. rej => {}
  697. );
  698. },
  699. // 获取直播间用户
  700. getliveUser() {
  701. getRecentLiveViewers(this.liveId).then(res => {
  702. if (res.code == 200) {
  703. console.log("获取直播间用户>>>>", res)
  704. this.liveViewers = res.recentLiveViewers
  705. } else {
  706. uni.showToast({
  707. title: res.msg,
  708. icon: 'none'
  709. });
  710. }
  711. },
  712. rej => {}
  713. );
  714. },
  715. // 点赞
  716. onLike() {
  717. liveDataLike(this.liveId).then(res => {
  718. if (res.code == 200) {
  719. if (
  720. typeof res.msg === 'number' || (typeof res.msg === 'string' && /^\d+$/.test(res.msg
  721. .trim()))
  722. ) {
  723. this.liveData++
  724. } else {
  725. uni.showToast({
  726. title: res.msg,
  727. icon: 'none'
  728. });
  729. }
  730. } else {
  731. uni.showToast({
  732. title: res.msg,
  733. icon: 'none'
  734. });
  735. }
  736. },
  737. rej => {}
  738. );
  739. },
  740. // 去购买,跳商品详情
  741. goShop(item) {
  742. console.log("去购买,跳商品详情", item)
  743. uni.navigateTo({
  744. url: '/pages_shop/goods?productId=' + item + '&liveId=' + this.liveId
  745. })
  746. },
  747. // 收藏
  748. onCollect(item) {
  749. console.log("item>>>", item.productId)
  750. uni.setStorageSync("storeId", storeId);
  751. let data = {
  752. liveId: this.liveId,
  753. productId: item.productId,
  754. storeId: this.store.storeId
  755. }
  756. collectStore(data).then(res => {
  757. if (res.code == 200) {
  758. console.log("收藏lcollectStore>>>>", res)
  759. } else {
  760. uni.showToast({
  761. title: res.msg,
  762. icon: 'none'
  763. });
  764. }
  765. },
  766. rej => {}
  767. );
  768. },
  769. // 关注
  770. onFollow() {
  771. follow(this.liveId).then(res => {
  772. this.isFollow = !this.isFollow
  773. uni.showToast({
  774. title: res.msg,
  775. icon: 'none'
  776. });
  777. },
  778. rej => {}
  779. );
  780. },
  781. initTime() {
  782. const now = new Date();
  783. this.timestamp = now.getTime(); // 例如:'2023-04-01 12:00:00'
  784. // 或者使用其他格式化方法,例如:
  785. // this.currentTime = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
  786. },
  787. // initWebSocket() {
  788. // const liveWS = new LiveWS('ws://your-server.com', 123, 456);
  789. // // 从 URL 中解析 timestamp
  790. // const urlParams = new URL(liveWS.url).searchParams;
  791. // this.timestamp = urlParams.get('timestamp');
  792. // // console.log('Timestamp:', timestamp);
  793. // },
  794. // 弹幕滚动
  795. lowerChat: function(e) {
  796. console.log(e)
  797. },
  798. scroll: function(e) {
  799. console.log(e)
  800. this.old.scrollTop = e.detail.scrollTop
  801. },
  802. loadmore() {
  803. // for (let i = 0; i < 30; i++) {
  804. // this.indexList.push({
  805. // url: this.shopList[uni.$u.random(0, this.shopList.length - 1)],
  806. // });
  807. // }
  808. },
  809. // 弹幕
  810. scrollchat() {
  811. // this.loadmore();
  812. },
  813. noredanswer() {
  814. if (this.Answerlistall > 0) {
  815. this.showAnswer = !this.this.showAnswer
  816. } else {
  817. uni.showToast({
  818. title: '暂无题目',
  819. icon: 'none',
  820. });
  821. }
  822. },
  823. redbagAnswer() {
  824. this.showAnswerred = !this.showAnswerred
  825. this.answerbtn = !this.answerbtn
  826. },
  827. submitAnswers() {
  828. if (this.isSubmit) return;
  829. this.isSubmit = true;
  830. const data = {
  831. questionId: this.answerlist.id,
  832. answer: this.checkboxFormValue
  833. }
  834. submitAnswer(data).then(res => {
  835. if (res.code == 200) {
  836. uni.showToast({
  837. title: res.msg,
  838. icon: 'none',
  839. });
  840. }
  841. // 本地切换下一题
  842. if (this.answerfrist < this.Answerlistall - 1) {
  843. this.answerfrist++;
  844. this.answerlist = this.allAnswerLists[this.answerfrist];
  845. this.answerlist.content = JSON.parse(this.answerlist.content);
  846. } else {
  847. uni.showToast({
  848. title: '已是最后一题',
  849. icon: 'none'
  850. });
  851. this.showAnswer = false; // 自动关闭弹窗
  852. }
  853. this.checkboxValue = []
  854. this.checkboxFormValue = "";
  855. uni.showToast({
  856. title: res.msg,
  857. icon: 'none'
  858. });
  859. }).finally(e => {
  860. this.isSubmit = false;
  861. })
  862. },
  863. handleCheckboxSelect(value) {
  864. const index = this.checkboxValue.indexOf(value)
  865. console.log(value)
  866. if (this.answerlist.type == 1) {
  867. this.checkboxValue = [value]
  868. this.checkboxFormValue = this.checkboxValue.join(',')
  869. // setTimeout(() => {
  870. // uni.showToast({
  871. // title: '准备下一题',
  872. // icon: 'none',
  873. // duration: 2000
  874. // });
  875. // }, 1000);
  876. this.submitAnswers()
  877. console.log(this.checkboxValue)
  878. } else if (this.answerlist.type == 2) {
  879. if (index > -1) {
  880. this.checkboxValue.splice(index, 1)
  881. this.checkboxFormValue = this.checkboxValue.join(',')
  882. } else {
  883. this.checkboxValue.push(value)
  884. this.checkboxFormValue = this.checkboxValue.join(',')
  885. }
  886. console.log(this.checkboxFormValue)
  887. }
  888. },
  889. getAnswerlists() {
  890. console.log(123)
  891. const data = {
  892. liveId: this.liveId
  893. }
  894. getAnswerlist(data).then(res => {
  895. if (res.code == 200) {
  896. if (res.data.length > 0) {
  897. this.allAnswerLists = res.data; // 存储所有题目
  898. this.Answerlistall = res.data.length;
  899. if (this.allAnswerLists.length > 0) {
  900. this.answerlist = this.allAnswerLists[0];
  901. this.answerlist.content = JSON.parse(this.allAnswerLists[0].content);
  902. }
  903. this.showAnswer = true
  904. } else {
  905. this.showAnswer = false
  906. }
  907. }
  908. })
  909. },
  910. gettalklist() {
  911. const param = {
  912. id: this.liveId
  913. }
  914. gettextlist(param).then(res => {
  915. if (res.code == 200) {
  916. this.talklist = res.data
  917. // console.log(res.data);
  918. this.$nextTick(() => {
  919. this.scrollIntoView = `list_${this.talklist.length-1}`
  920. })
  921. }
  922. })
  923. },
  924. open() {
  925. },
  926. close() {
  927. this.showadd = !this.showadd
  928. },
  929. closes() {
  930. this.showziliao = !this.showziliao
  931. },
  932. closest() {
  933. this.showAnswer = !this.showAnswer
  934. },
  935. closestred() {
  936. this.showAnswerred = !this.showAnswerred
  937. },
  938. closeanswer() {
  939. this.answerbtn = !this.answerbtn
  940. },
  941. // 关闭小黄车
  942. closeshop() {
  943. this.shopping = !this.shopping
  944. },
  945. longPress() {
  946. this.timeout = setTimeout(() => {
  947. this.isLongPress = true;
  948. // 执行保存图片的操作
  949. uni.saveImageToPhotosAlbum({
  950. filePath: this.livedata.qwQrCode, // 图片的本地路径或网络路径
  951. success: () => {
  952. uni.showToast({
  953. title: '保存成功'
  954. });
  955. },
  956. fail: () => {
  957. uni.showToast({
  958. title: '',
  959. icon: 'none'
  960. });
  961. }
  962. });
  963. }, 500); // 设置长按的阈值时间,这里是500毫秒
  964. },
  965. cancelLongPress() {
  966. clearTimeout(this.timeout);
  967. this.isLongPress = false;
  968. },
  969. // 触摸开始
  970. handleTouchStart() {
  971. this.isZoom = true; // 触发放大效果
  972. },
  973. // 触摸结束
  974. handleTouchEnd() {
  975. this.isZoom = false; // 恢复原状
  976. },
  977. // getliving() {
  978. // const param = {
  979. // id: this.liveId
  980. // }
  981. // getlive(param).then(res => {
  982. // if (res.code == 200) {
  983. // this.livedata = res.data
  984. // this.codeimg = res.data.qwQrCode
  985. // if (this.livedata.status == 1) {
  986. // this.autoplay = true
  987. // this.videoContext.seek(this.livedata.nowDuration)
  988. // // console.log(this.autoplay)
  989. // } else {
  990. // this.autoplay = false
  991. // this.placeholderText = "直播开始才能发言讨论"
  992. // this.talkdisabled = true
  993. // }
  994. // console.log(this.autoplay)
  995. // } else {
  996. // uni.showToast({
  997. // title: res.msg,
  998. // icon: 'none',
  999. // duration: 2000
  1000. // });
  1001. // }
  1002. // })
  1003. // },
  1004. getEWechatSdk() {
  1005. // 只在H5平台执行
  1006. // #ifdef H5
  1007. let eWechatSdk = '';
  1008. if (/(Android)/i.test(navigator.userAgent)) {
  1009. eWechatSdk = 'jWeixin';
  1010. } else if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
  1011. eWechatSdk = 'wx';
  1012. } else {
  1013. eWechatSdk = 'jWeixin';
  1014. }
  1015. uni.setStorageSync("wxSdk", eWechatSdk);
  1016. // #endif
  1017. },
  1018. closeWebSocket() {
  1019. if (socket != null) {
  1020. uni.closeSocket();
  1021. }
  1022. clearInterval(pingpangTimes)
  1023. },
  1024. reConnect() {
  1025. var that = this;
  1026. try {
  1027. uni.closeSocket();
  1028. } catch (e) {
  1029. }
  1030. setTimeout(function() {
  1031. that.initSocket();
  1032. }, 10000);
  1033. },
  1034. initSocket() {
  1035. this.userinfo = JSON.parse(uni.getStorageSync("userInfo"))
  1036. // console.log("liveId", this.liveId);
  1037. // console.log("userId", this.userinfo.userId);
  1038. // console.log("userType", this.userType);
  1039. // console.log("timestamp", this.timestamp);
  1040. let signature = CryptoJS.HmacSHA256(
  1041. CryptoJS.enc.Utf8.parse(this.liveId.toString() + this.userinfo.userId + this.userType + this
  1042. .timestamp),
  1043. CryptoJS.enc.Utf8.parse(this.timestamp)).toString(CryptoJS.enc.Hex)
  1044. var that = this;
  1045. // console.log("initSocket")
  1046. //创建一个socket连接
  1047. socket = uni.connectSocket({
  1048. // url: wsUrl+"?userId=40486&liveId=2",
  1049. // url: wsUrl + "?userId=" + this.userid + "&liveId=" +
  1050. // this.liveId+"&AppToken="+'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0IiwiaWF0IjoxNzQwNzIxMDQ1LCJleHAiOjE3NDEzMjU4NDV9.PgS83JTMSJgVFD6vGAhUsEPbS6Az4yMyX8wVug61TZNTB3092CtvANo-AB9ZG4NdSBLgLrf4litM3vvTk-FK0g',
  1051. //
  1052. // url: wsUrl + "?userId=" + this.userId + "&liveId=" + this.liveId + "&AppToken=" + uni
  1053. // .getStorageSync('AppToken'),
  1054. url: wsUrl + "?userId=" + this.userinfo.userId + "&liveId=" + this.liveId + "&userType=" + this
  1055. .userType +
  1056. "&timestamp=" + this.timestamp + "&signature=" + signature,
  1057. multiple: true,
  1058. success: res => {
  1059. //先确保清除了之前的心跳定时器
  1060. clearInterval(pingpangTimes)
  1061. uni.onSocketMessage((res) => {
  1062. if (res.data.code == 500) {
  1063. uni.showToast({
  1064. title: res.data.msg,
  1065. icon: 'none',
  1066. duration: 2000
  1067. });
  1068. }
  1069. const redata = JSON.parse(res.data);
  1070. console.log("WebSocket拿到的东西", redata)
  1071. this.talklist.push(redata.data)
  1072. this.$nextTick(() => {
  1073. this.scrollIntoView = `list_${this.talklist.length-1}`
  1074. })
  1075. if (redata.cmd == 'deleteId') {
  1076. uni.$emit('deleteId');
  1077. } else if (redata.cmd == 'init') {
  1078. uni.$emit('init', redata.data);
  1079. } else if (redata.cmd == 'reload') {
  1080. uni.$emit('reload');
  1081. } else if (redata.data.cmd == 'sendRedPacketQuestion') {
  1082. const list = JSON.parse(redata.data.data)
  1083. this.redanswerAll = [...this.redanswerAll, ...list]
  1084. if (this.redanswerAll[1].randomAmount !== null) {
  1085. this.redanswertips = JSON.parse(this.redanswerAll[0].randomAmount)
  1086. }
  1087. console.log(this.redanswertips)
  1088. console.log(this.redanswerAll)
  1089. } else if (redata.data.cmd == 'entry') {
  1090. this.showWelcomeMessage = true
  1091. // setTimeout(() => {
  1092. // this.showWelcomeMessage = false;
  1093. // }, 1000);
  1094. uni.$emit('entry', redata.data);
  1095. // console.log(redata.data)/
  1096. }
  1097. })
  1098. },
  1099. error: res => {
  1100. uni.$emit('websocket', 0);
  1101. console.log(res)
  1102. },
  1103. })
  1104. //监听socket打开
  1105. uni.onSocketOpen(() => {
  1106. isSocketOpen = true
  1107. console.log('WebSocket连接已打开!!');
  1108. // uni.$emit('websocket',1);
  1109. uni.showToast({
  1110. title: "插件已打开",
  1111. icon: 'none',
  1112. });
  1113. })
  1114. //监听socket关闭
  1115. uni.onSocketClose(() => {
  1116. isSocketOpen = false
  1117. clearInterval(pingpangTimes)
  1118. console.log('WebSocket连接已关闭!');
  1119. // uni.$emit('websocket',0);
  1120. uni.showToast({
  1121. title: "插件离线",
  1122. icon: 'none',
  1123. });
  1124. //重连
  1125. that.reConnect()
  1126. })
  1127. //监听socket错误
  1128. uni.onSocketError(() => {
  1129. isSocketOpen = false
  1130. clearInterval(pingpangTimes)
  1131. console.log('WebSocket连接打开失败');
  1132. // uni.$emit('websocket',0);
  1133. uni.showToast({
  1134. title: "插件离线",
  1135. icon: 'none',
  1136. });
  1137. uni.showModal({
  1138. content: '聊天连接失败是否重新尝试连接',
  1139. success() {
  1140. that.reConnect()
  1141. }
  1142. })
  1143. })
  1144. },
  1145. sendMsg() {
  1146. // this.userinfo = JSON.parse(uni.getStorageSync("userInfo"))
  1147. if (isSocketOpen) {
  1148. const data = {
  1149. liveId: this.liveId,
  1150. userId: this.userinfo.userId,
  1151. userType: 0,
  1152. cmd: "sendMsg",
  1153. msg: this.value,
  1154. nickName: this.userinfo.nickName,
  1155. avatar: this.userinfo.avatar
  1156. }
  1157. if (this.value == "") {
  1158. uni.showToast({
  1159. title: "不能发送空消息",
  1160. icon: 'none',
  1161. });
  1162. } else {
  1163. socket.send({
  1164. data: JSON.stringify(data),
  1165. success: () => {
  1166. // this.gettalklist()
  1167. console.log("发送成功")
  1168. this.value = ''
  1169. },
  1170. fail: () => {
  1171. console.log("发送失败")
  1172. }
  1173. })
  1174. }
  1175. }
  1176. },
  1177. },
  1178. };
  1179. </script>
  1180. <style scoped lang="scss">
  1181. // 抽奖
  1182. // .answerpop {
  1183. // background: linear-gradient(to right, #fff7f8, #fee1e2);
  1184. // margin-top: 30rpx;
  1185. // padding: 10rpx 20rpx;
  1186. // width: calc(100% - 40rpx);
  1187. // border-radius: 20rpx;
  1188. // display: flex;
  1189. // align-items: center;
  1190. // justify-content: space-between;
  1191. // box-shadow: 2px 2px 4px 0 rgba(255, 124, 126, 0.1);
  1192. // .answera {
  1193. // display: flex;
  1194. // justify-content: center;
  1195. // background-color: #fff;
  1196. // padding: 20rpx 0;
  1197. // width: 35%;
  1198. // border-radius: 40rpx;
  1199. // align-items: center;
  1200. // margin: 10rpx 0;
  1201. // box-shadow: 2px 2px 4px 0 rgba(72, 72, 72, 0.1);
  1202. // image {
  1203. // width: 40rpx;
  1204. // height: 40rpx;
  1205. // margin-right: 10rpx;
  1206. // }
  1207. // }
  1208. // }
  1209. // .submitbtn {
  1210. // width: 260rpx;
  1211. // margin: 0 auto;
  1212. // text-align: center;
  1213. // border-radius: 80rpx;
  1214. // padding: 20rpx 0;
  1215. // color: #fff;
  1216. // background-color: #ff5c03;
  1217. // }
  1218. // .itemanswer {
  1219. // padding: 20rpx 20rpx;
  1220. // text-align: center;
  1221. // border-radius: 80rpx;
  1222. // border: 2rpx solid #dddddd;
  1223. // margin: 12rpx 0;
  1224. // color: #555;
  1225. // width: calc(100% - 40rpx);
  1226. // }
  1227. // .answeract {
  1228. // background-color: rgba(0, 202, 166, 1);
  1229. // color: #fff;
  1230. // }
  1231. // .answerbox {
  1232. // width: 600rpx;
  1233. // border-radius: 20rpx;
  1234. // }
  1235. // .welcome-message {
  1236. // position: fixed;
  1237. // width: 100%;
  1238. // bottom: 120rpx;
  1239. // left: 50%;
  1240. // transform: translateX(-50%);
  1241. // color: white;
  1242. // padding: 10px 20px;
  1243. // border-radius: 20px;
  1244. // animation: fadeOut 1s ease 1s forwards;
  1245. // z-index: 1000;
  1246. // }
  1247. // @keyframes fadeOut {
  1248. // from {
  1249. // opacity: 1;
  1250. // }
  1251. // to {
  1252. // opacity: 0;
  1253. // }
  1254. // }
  1255. // .container {
  1256. // position: relative;
  1257. // width: 100%;
  1258. // height: 100vh;
  1259. // overflow: hidden;
  1260. // }
  1261. // .talktext {
  1262. // border-radius: 8rpx;
  1263. // background-color: rgba(255, 255, 255, 0.1);
  1264. // view {
  1265. // width: 100%;
  1266. // }
  1267. // }
  1268. // .talk-list {
  1269. // border-radius: 30rpx;
  1270. // background-color: rgba(255, 255, 255, 0.1);
  1271. // padding: 10rpx 30rpx;
  1272. // }
  1273. // .zoom-button-active {
  1274. // transform: scale(1.5);
  1275. // }
  1276. // .background-image {
  1277. // position: absolute;
  1278. // top: 0;
  1279. // left: -40rpx;
  1280. // width: 110%;
  1281. // height: 110%;
  1282. // object-fit: cover;
  1283. // filter: blur(20px);
  1284. // z-index: 0;
  1285. // }
  1286. // .background-images {
  1287. // position: absolute;
  1288. // top: 0;
  1289. // left: -40rpx;
  1290. // width: 110%;
  1291. // height: 110%;
  1292. // object-fit: cover;
  1293. // filter: blur(20px);
  1294. // z-index: 6;
  1295. // }
  1296. // .blackbg {
  1297. // position: absolute;
  1298. // top: 0;
  1299. // left: 0;
  1300. // width: 100%;
  1301. // height: 100%;
  1302. // background: rgba(0, 0, 0, 0.7);
  1303. // object-fit: cover;
  1304. // filter: blur(10px);
  1305. // z-index: 1;
  1306. // }
  1307. .content {
  1308. position: relative;
  1309. z-index: 2;
  1310. height: 100%;
  1311. width: 100%;
  1312. top: 0;
  1313. left: 0;
  1314. display: flex;
  1315. flex-direction: column;
  1316. justify-content: space-between;
  1317. .content-top {
  1318. width: 100%;
  1319. margin-top: 150rpx;
  1320. display: flex;
  1321. align-items: center;
  1322. justify-content: space-between;
  1323. padding: 0 24rpx;
  1324. box-sizing: border-box;
  1325. .sum {
  1326. width: 80rpx;
  1327. height: 52rpx;
  1328. background: rgba(0, 0, 0, 0.5);
  1329. border-radius: 26rpx 26rpx 26rpx 26rpx;
  1330. font-size: 24rpx;
  1331. color: #FFFFFF;
  1332. text-align: center;
  1333. line-height: 52rpx;
  1334. }
  1335. }
  1336. .follow-btn {
  1337. padding: 8rpx 16rpx;
  1338. background: linear-gradient(270deg, #FF5C03 0%, #FFAC64 100%);
  1339. border-radius: 26rpx;
  1340. font-weight: 500;
  1341. font-size: 26rpx;
  1342. color: #FFFFFF;
  1343. }
  1344. }
  1345. .videolist {
  1346. position: relative;
  1347. }
  1348. .vedio {
  1349. // height: 500rpx;
  1350. height: 100vh;
  1351. /* 占屏幕高度的80% */
  1352. width: 100%;
  1353. background-color: rgba(0, 0, 0, 0.6);
  1354. }
  1355. .videotop {
  1356. width: 100%;
  1357. height: 100%;
  1358. }
  1359. .popup-video {
  1360. position: absolute;
  1361. top: 30%;
  1362. height: 500rpx;
  1363. display: flex;
  1364. flex-direction: column;
  1365. align-items: center;
  1366. justify-content: center;
  1367. width: 100%;
  1368. color: #fff;
  1369. z-index: 9;
  1370. .more {
  1371. background-color: #3280fe;
  1372. border-radius: 80rpx;
  1373. width: 280rpx;
  1374. text-align: center;
  1375. height: 60rpx;
  1376. line-height: 60rpx;
  1377. }
  1378. }
  1379. .icon-bg {
  1380. background-color: rgba(255, 255, 255, 0.2);
  1381. border-radius: 50%;
  1382. width: 72rpx;
  1383. height: 72rpx;
  1384. display: flex;
  1385. justify-content: center;
  1386. align-items: center;
  1387. transition: transform 0.2s ease;
  1388. }
  1389. .list {
  1390. width: 80%;
  1391. margin-bottom: 20rpx;
  1392. animation: xxxawdawd .2s;
  1393. }
  1394. @keyframes xxxawdawd {
  1395. from {
  1396. margin-top: 0rpx;
  1397. opacity: 0;
  1398. }
  1399. to {
  1400. margin-top: 20rpx;
  1401. opacity: 1;
  1402. }
  1403. }
  1404. .shop-prompt {
  1405. position: absolute;
  1406. bottom: 600rpx;
  1407. left: 24rpx;
  1408. padding: 6rpx 20rpx;
  1409. background: rgba(230, 154, 34, 0.7);
  1410. border-radius: 24rpx;
  1411. z-index: 9;
  1412. font-weight: 500;
  1413. font-size: 26rpx;
  1414. color: #FFFFFF;
  1415. }
  1416. .side-group {
  1417. position: absolute;
  1418. top: 30%;
  1419. right: 50rpx;
  1420. z-index: 9;
  1421. display: flex;
  1422. flex-direction: column;
  1423. align-items: center;
  1424. .side-item {
  1425. font-weight: 500;
  1426. font-size: 24rpx;
  1427. color: #FFFFFF;
  1428. margin-bottom: 32rpx;
  1429. text-align: center;
  1430. image {
  1431. width: 72rpx;
  1432. height: 72rpx;
  1433. }
  1434. }
  1435. }
  1436. .shoppop {
  1437. padding: 22rpx 16rpx;
  1438. .shoppop-top {
  1439. display: flex;
  1440. justify-content: space-between;
  1441. align-items: center;
  1442. padding: 0 16rpx 22rpx;
  1443. .search-input {
  1444. width: 414rpx;
  1445. height: 76rpx;
  1446. background: #FFFFFF;
  1447. border-radius: 36rpx;
  1448. margin-left: 20rpx;
  1449. padding: 0 32rpx;
  1450. box-sizing: border-box;
  1451. font-size: 24rpx;
  1452. margin-right: 24rpx;
  1453. }
  1454. .search-top {
  1455. font-size: 18rpx;
  1456. color: #222222;
  1457. }
  1458. }
  1459. .shop-list {
  1460. overflow: hidden;
  1461. .list-item {
  1462. display: flex;
  1463. align-items: center;
  1464. padding: 20rpx 16rpx;
  1465. background: #FFFFFF;
  1466. border-radius: 16rpx;
  1467. margin-bottom: 16rpx;
  1468. .goods-img {
  1469. width: 200rpx;
  1470. height: 200rpx;
  1471. border-radius: 16rpx;
  1472. overflow: hidden;
  1473. position: relative;
  1474. margin-right: 24rpx;
  1475. image {
  1476. width: 100%;
  1477. height: 100%;
  1478. }
  1479. .goods-label {
  1480. position: absolute;
  1481. top: 0;
  1482. width: 64rpx;
  1483. height: 40rpx;
  1484. background: rgba(0, 0, 0, 0.5);
  1485. border-radius: 16rpx 0rpx 16rpx 0rpx;
  1486. text-align: center;
  1487. font-weight: 500;
  1488. font-size: 28rpx;
  1489. color: #FFFFFF;
  1490. }
  1491. }
  1492. .goods-right {
  1493. flex: 1;
  1494. .goods-title {
  1495. font-weight: 500;
  1496. font-size: 28rpx;
  1497. color: #000000;
  1498. }
  1499. .goods-details {
  1500. font-size: 24rpx;
  1501. color: #999999;
  1502. margin: 10rpx 0 20rpx;
  1503. }
  1504. .goods-people {
  1505. font-size: 22rpx;
  1506. color: #E69A22;
  1507. height: 56rpx;
  1508. }
  1509. .goods-shop {
  1510. display: flex;
  1511. justify-content: space-between;
  1512. .nummber {
  1513. color: #FF5C03;
  1514. font-size: 22rpx;
  1515. font-weight: 500;
  1516. }
  1517. .btn-group {
  1518. text-align: center;
  1519. line-height: 56rpx;
  1520. .collect-btn {
  1521. width: 72rpx;
  1522. background: #F5F7FA;
  1523. border-radius: 8rpx 0rpx 0rpx 8rpx;
  1524. }
  1525. .shop-btn {
  1526. width: 152rpx;
  1527. background: linear-gradient(270deg, #FF5C03 0%, #FFAC64 100%);
  1528. border-radius: 0rpx 8rpx 8rpx 0rpx;
  1529. font-weight: 500;
  1530. font-size: 26rpx;
  1531. color: #FFFFFF;
  1532. }
  1533. }
  1534. }
  1535. }
  1536. }
  1537. }
  1538. }
  1539. :deep(.u-list-item) {
  1540. width: 100%;
  1541. display: flex;
  1542. align-items: center;
  1543. }
  1544. </style>