detail.vue 100 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487
  1. <template>
  2. <view class="polyv_detail">
  3. <uni-nav-bar
  4. left-icon="back"
  5. :statusBar="true"
  6. fixed="true"
  7. :title="detail.courseName || '课程详情'"
  8. @clickLeft="clickLeft"
  9. ></uni-nav-bar>
  10. <view id="top">
  11. <view class="video_box" v-if="!startStatus">
  12. <image
  13. :src="$method.splitImgHost(goodsData.coverUrl)"
  14. mode="widthFix"
  15. style="width: 100%; height: 421rpx"
  16. ></image>
  17. </view>
  18. <view v-else>
  19. <my-player
  20. ref="player"
  21. :playVid="playVID"
  22. :autoplay="autoplay"
  23. :allowSeek="isAllowSeek"
  24. :playbackRate="playbackRate"
  25. :videoCurrentTime="recordObj.videoCurrentTime || 0"
  26. @playing="playing"
  27. @pause="pause"
  28. @ended="ended"
  29. @loadedmetadata="loadedmetadata"
  30. @timeupdate="timeupdate"
  31. ></my-player>
  32. </view>
  33. <view class="course_name">
  34. <view class="course_titles">
  35. <view class="video_t1" :class="{ one: !goodsData.buyNote }">{{
  36. detail.courseName
  37. }}</view>
  38. <view class="notice_wrap" v-if="goodsData.buyNote">
  39. <view class="video_t1_t" @click="studyNotice"> 学员须知 </view>
  40. </view>
  41. <view
  42. class="toggle_course"
  43. v-if="goodsTeacher.length > 1"
  44. @click="changeCourses()"
  45. >
  46. <image
  47. class="img"
  48. src="/pages3/static/imgs/toggle.png"
  49. mode="widthFix"
  50. ></image>
  51. <view class="toggle_name">切换课程</view>
  52. <!-- courseTotal -->
  53. <view class="numbers">共{{ goodsTeacher.length }}门</view>
  54. </view>
  55. </view>
  56. </view>
  57. <u-line color="#D6D6DB" />
  58. <view>
  59. <view>
  60. <u-tabs
  61. :item-width="itemWidth()"
  62. :list="list"
  63. font-size="32"
  64. bar-width="24"
  65. :current="current"
  66. @change="change"
  67. active-color="#007AFF"
  68. ></u-tabs>
  69. </view>
  70. </view>
  71. <u-line color="#D6D6DB" />
  72. </view>
  73. <view class="box" :class="{ first_ml: current == 0 }">
  74. <scroll-view class="box_in" scroll-y="true">
  75. <!--目录 -->
  76. <view v-show="current == 0">
  77. <view
  78. class="top__header"
  79. v-if="livingItem"
  80. @click="goLive(livingItem)"
  81. >
  82. <image
  83. class="img"
  84. src="/pages3/static/imgs/live.png"
  85. mode="widthFix"
  86. ></image>
  87. <view class="note">正在直播中</view>
  88. <view class="title">{{ livingItem.sectionName }}</view>
  89. </view>
  90. <view
  91. v-if="teacherList && teacherList.length > 0"
  92. class="teacher_names"
  93. >
  94. <view
  95. v-for="(tea, index) in teacherList"
  96. :key="index"
  97. class="names"
  98. :class="{ nactive: teacherIndex == index }"
  99. @click="activeFunc(tea, index)"
  100. >
  101. {{ tea.aliasName }}
  102. </view>
  103. </view>
  104. <view
  105. class="menuBox onessss"
  106. v-for="(item, index) in menuList"
  107. :key="index"
  108. >
  109. <template v-if="!$method.isEmptyObject(sectionItem)">
  110. <!--模块 -->
  111. <view v-if="item.type == 1"
  112. ><courseModule
  113. v-if="reStart"
  114. :orderGoodsId="orderGoodsId"
  115. :sectionMaxNum="goodsData.sectionMaxNum"
  116. :needOpen="sectionItem.moduleId == item.menuId"
  117. :courseId="courseId"
  118. :preItem="menuList[index - 1]"
  119. :learningOrder="orderNum"
  120. :goodsId="goodsId"
  121. :gradeId="gradeId"
  122. :isBuy="true"
  123. :menuItem="item"
  124. :levelId="item.menuId"
  125. :goodsType="1"
  126. :menuAllList="menuAllList"
  127. :sectionItem="sectionItem"
  128. ></courseModule
  129. ></view>
  130. <!--章 -->
  131. <view v-if="item.type == 2"
  132. ><courseChapter
  133. v-if="reStart"
  134. :orderGoodsId="orderGoodsId"
  135. :sectionMaxNum="goodsData.sectionMaxNum"
  136. :needOpen="
  137. !sectionItem.moduleId &&
  138. sectionItem.chapterId == item.menuId
  139. "
  140. :courseId="courseId"
  141. :preItem="menuList[index - 1]"
  142. @playEnd="sectionPlayEnd($event, index)"
  143. :learningOrder="orderNum"
  144. :goodsId="goodsId"
  145. :gradeId="gradeId"
  146. :isBuy="true"
  147. :menuItem="item"
  148. :levelId="'0-' + item.menuId"
  149. :goodsType="1"
  150. :menuAllList="menuAllList"
  151. :sectionItem="sectionItem"
  152. ></courseChapter
  153. ></view>
  154. <!--节 -->
  155. <view v-if="item.type == 3"
  156. ><courseSection
  157. ref="MoudleSection"
  158. v-if="reStart"
  159. :orderGoodsId="orderGoodsId"
  160. :sectionMaxNum="goodsData.sectionMaxNum"
  161. @playEnd="sectionPlayEnd($event, index)"
  162. :courseId="courseId"
  163. :preItem="menuList[index - 1]"
  164. :learningOrder="orderNum"
  165. :goodsId="goodsId"
  166. :gradeId="gradeId"
  167. :isBuy="true"
  168. :menuItem="item"
  169. :levelId="'0-0-' + item.menuId"
  170. :goodsType="1"
  171. :testType="3"
  172. :menuAllList="menuAllList"
  173. ></courseSection
  174. ></view>
  175. </template>
  176. <!-- @togoBack="togoBack($event)" -->
  177. </view>
  178. </view>
  179. <!--讲义 -->
  180. <view v-show="current == 1">
  181. <handouts-box
  182. :handoutsId="goodsData.handoutsId"
  183. v-if="goodsData.handoutsId"
  184. ></handouts-box>
  185. </view>
  186. <!--笔记 -->
  187. <view v-if="current == 2">
  188. <note-Box
  189. :isPlayRebuild="sectionItem.rebuild"
  190. :refPlv="refPlv"
  191. @jumpNote="jumpNote"
  192. :params="params()"
  193. ></note-Box>
  194. </view>
  195. <!--答疑 -->
  196. <view v-show="current == 3">
  197. <answer-box
  198. :userId="userInfo ? userInfo.userId : 0"
  199. :params="params(['orderGoodsId', 'goodsId', 'courseId', 'gradeId'])"
  200. ></answer-box>
  201. </view>
  202. <!--目录 -->
  203. <view v-show="current == 4">
  204. <view
  205. class="menuBox"
  206. v-for="(item, index) in reMenuList"
  207. :key="index"
  208. >
  209. <!--模块 -->
  210. <view v-if="item.type == 1"
  211. ><courseModule
  212. :orderGoodsId="orderGoodsId"
  213. :sectionMaxNum="goodsData.sectionMaxNum"
  214. :courseId="courseId"
  215. :learningOrder="orderNum"
  216. :goodsId="goodsId"
  217. :gradeId="gradeId"
  218. :isRebuild="true"
  219. :isBuy="true"
  220. :menuItem="item"
  221. :levelId="item.menuId"
  222. :goodsType="1"
  223. :menuAllList="menuAllList"
  224. :sectionItem="sectionItem"
  225. ></courseModule
  226. ></view>
  227. <!--章 -->
  228. <view v-if="item.type == 2">
  229. <courseChapter
  230. :orderGoodsId="orderGoodsId"
  231. :courseId="courseId"
  232. :learningOrder="orderNum"
  233. :sectionMaxNum="goodsData.sectionMaxNum"
  234. @playEnd="sectionPlayEnd($event, index)"
  235. :gradeId="gradeId"
  236. :goodsId="goodsId"
  237. :isRebuild="true"
  238. :isBuy="true"
  239. :menuItem="item"
  240. :levelId="'0-' + item.menuId"
  241. :goodsType="1"
  242. :menuAllList="menuAllList"
  243. ></courseChapter>
  244. </view>
  245. <!--节 -->
  246. <view v-if="item.type == 3">
  247. <courseSection
  248. :orderGoodsId="orderGoodsId"
  249. :courseId="courseId"
  250. :learningOrder="orderNum"
  251. :sectionMaxNum="goodsData.sectionMaxNum"
  252. @playEnd="sectionPlayEnd($event, index)"
  253. :gradeId="gradeId"
  254. :goodsId="goodsId"
  255. :isRebuild="true"
  256. :isBuy="true"
  257. :nextMenuItem="findMenuNextSection(index)"
  258. :menuItem="item"
  259. :levelId="'0-0-' + item.menuId"
  260. :goodsType="1"
  261. :testType="3"
  262. :menuAllList="menuAllList"
  263. ></courseSection>
  264. </view>
  265. </view>
  266. </view>
  267. </scroll-view>
  268. </view>
  269. <!-- 播放前拍照end -->
  270. <u-popup
  271. v-model="showSet"
  272. :mask-close-able="false"
  273. mode="center"
  274. border-radius="24"
  275. >
  276. <view
  277. style="
  278. align-items: center;
  279. padding: 0 40rpx;
  280. display: flex;
  281. flex-direction: column;
  282. justify-content: center;
  283. "
  284. >
  285. <view
  286. style="
  287. font-weight: bold;
  288. color: #333333;
  289. font-size: 30rpx;
  290. margin-top: 30rpx;
  291. "
  292. >温馨提示</view
  293. >
  294. <view
  295. style="
  296. width: 457rpx;
  297. color: #666666;
  298. font-size: 30rpx;
  299. margin-top: 30rpx;
  300. "
  301. >学习过程中需要拍照验证学员身份, 拍照功能需要使用您的相机。
  302. 是否授权使用?</view
  303. >
  304. <view style="margin: 40rpx 0">
  305. <button
  306. open-type="openSetting"
  307. @bindopensetting="openSetting"
  308. class="btnSet"
  309. >
  310. 去授权
  311. </button>
  312. </view>
  313. </view>
  314. </u-popup>
  315. <u-popup
  316. v-model="photoPopup"
  317. mode="bottom"
  318. border-radius="40"
  319. :mask-close-able="false"
  320. >
  321. <!-- 播放前拍照start -->
  322. <!-- :mask-close-able="false" -->
  323. <!-- style="bottom: 0; position: fixed; width: 100%; z-index: 999" -->
  324. <view v-if="photoPopup">
  325. <view class="photoBox">
  326. <view class="photoTop">
  327. <view class="sqzz" v-if="false"
  328. ><u-icon
  329. name="close"
  330. color="#333333"
  331. size="30"
  332. @click="closePhoto"
  333. ></u-icon
  334. ></view>
  335. <view class="centersq">请正视手机屏幕</view>
  336. <view class="sqzz"></view>
  337. </view>
  338. <view class="photoCenter">
  339. <view class="center_camera" v-if="photoPopup && isTaking">
  340. <!-- #ifdef MP-WEIXIN -->
  341. <camera
  342. device-position="front"
  343. flash="off"
  344. @error="error"
  345. style="width: 100%; height: 100%"
  346. >
  347. <!-- 加人脸框 -->
  348. <cover-view class="head_take">
  349. <cover-view class="headTake_up color"></cover-view>
  350. <cover-view class="headTake_minddle">
  351. <cover-view class="min_left color"></cover-view>
  352. <cover-view class="min_img"></cover-view>
  353. <cover-view class="min_right color"></cover-view>
  354. </cover-view>
  355. <cover-view class="headTake_down color"></cover-view>
  356. </cover-view>
  357. </camera>
  358. <!-- #endif -->
  359. <!-- #ifdef H5 -->
  360. <video
  361. :controls="false"
  362. id="video"
  363. width="400"
  364. height="300"
  365. class="photo_v"
  366. ></video>
  367. <view class="mask"></view>
  368. <!-- #endif -->
  369. </view>
  370. <view class="custom" v-if="!isTaking">
  371. <!-- #ifdef MP-WEIXIN -->
  372. <image :src="avatarUrl" mode=""></image>
  373. <!-- #endif -->
  374. <!-- #ifdef H5 -->
  375. <image :src="faceUrl" mode=""></image>
  376. <!-- #endif -->
  377. </view>
  378. </view>
  379. <view class="btns">
  380. <!-- <view class="btnResult" v-if="isTaking" @click="takePhoto"
  381. >拍照</view
  382. > -->
  383. <view v-if="isTaking" class="takePhoto_btn">
  384. <view style="width: 100rpx; height: 2rpx"></view>
  385. <view class="middle_btn" @click="takePhoto">
  386. <view class="square"></view>
  387. </view>
  388. <view class="rights" @click="takePhTips()">
  389. <text>拍照提示</text>
  390. <u-icon name="arrow-right" color="#FFFFFF" size="30"></u-icon>
  391. </view>
  392. </view>
  393. <view class="btnResult" v-if="!isTaking" @click="reTake">重拍</view>
  394. <view class="btnResult" v-if="!isTaking" @click="submit">确认</view>
  395. </view>
  396. </view>
  397. </view>
  398. </u-popup>
  399. <u-popup
  400. v-model="noticeShow"
  401. class="notice_modal"
  402. mode="center"
  403. border-radius="28"
  404. width="650rpx"
  405. height="622rpx"
  406. :mask-close-able="false"
  407. @close="closeNotice"
  408. >
  409. <view class="content">
  410. <view class="title">学员须知</view>
  411. <scroll-view scroll-y="true">
  412. <view
  413. class="text"
  414. v-html="
  415. goodsData.buyNote && goodsData.buyNote.replace(/\n|\r\n/g, '<br>')
  416. "
  417. >
  418. </view>
  419. </scroll-view>
  420. <view
  421. class="had_read"
  422. :class="{ gray: CountTo >= 0 }"
  423. @click="noticeConfirm()"
  424. >
  425. <text v-if="CountTo >= 0">请阅读学员须知,30s后可关闭</text>
  426. <text v-else>我已阅读学员须知</text>
  427. <text v-if="CountTo >= 0">{{ " " + CountTo + "s" }}</text>
  428. </view>
  429. </view>
  430. </u-popup>
  431. <!-- 倒计时提交 -->
  432. <u-popup
  433. v-model="noticeShow1"
  434. class="notice_modal"
  435. mode="center"
  436. border-radius="28"
  437. width="650rpx"
  438. height="262rpx"
  439. :mask-close-able="false"
  440. >
  441. <view class="content">
  442. <view class="title">提示</view>
  443. <view class="had_read">
  444. <text v-if="CountTo1 >= 0">视频学习时长不达标,请等待</text>
  445. <text v-if="CountTo1 >= 0">{{ " " + CountTo1 + "s" }}</text>
  446. </view>
  447. </view>
  448. </u-popup>
  449. <u-modal
  450. v-model="showMark"
  451. title="提示"
  452. @confirm="markConfirm"
  453. @cancel="toBack"
  454. confirm-text="复制学习网址"
  455. :show-cancel-button="true"
  456. cancel-text="关闭"
  457. >
  458. <view class="slot-content">
  459. <view>您的学习账号已经开通,请按照步骤操作,进行学习。</view>
  460. <view>1.复制学习地址:{{ markContent }}</view>
  461. <view>2.在【浏览器中】打开复制的学习网址</view>
  462. <view>3.打开学习网址后,选择【个人用户】进行登录</view>
  463. <view>(1)账号:您个人的身份证号码</view>
  464. <view>(2)密码:身份证号码,再加111111</view>
  465. </view>
  466. </u-modal>
  467. <!-- 切换课程弹窗 -->
  468. <u-popup
  469. v-model="toggleCourseShow"
  470. mode="bottom"
  471. border-radius="40"
  472. :mask-close-able="false"
  473. >
  474. <view class="popup_box">
  475. <view class="check_head">
  476. <view class="headers">
  477. <view class="grade">切换课程</view>
  478. <u-icon
  479. name="close"
  480. color="#9C9C9C"
  481. size="40"
  482. @click="closePop()"
  483. ></u-icon>
  484. </view>
  485. <view class="coruse_num">共{{ goodsTeacher.length }}门</view>
  486. <view class="menuSel">
  487. <scroll-view class="sub_sliper" scroll-x="true">
  488. <view
  489. v-for="(item, index) in subList"
  490. :key="index"
  491. style="margin-right: 50rpx; display: inline-block"
  492. >
  493. <view
  494. class="r_t1"
  495. :class="{ nactive: subIndex == index }"
  496. @click="cMenu(item, index)"
  497. >
  498. {{ item.subjectName }}
  499. </view>
  500. </view>
  501. </scroll-view>
  502. </view>
  503. </view>
  504. <view class="check_con">
  505. <scroll-view scroll-y="true" style="height: 700rpx">
  506. <view v-for="(courseItem, gTindex) in goodsTeacher" :key="gTindex">
  507. <view
  508. v-for="(item, index) in courseItem.courseList"
  509. :key="index"
  510. v-show="
  511. item.subjectId === newActiveSubjectId || !newActiveSubjectId
  512. "
  513. >
  514. <view class="course_items" v-if="item.show && item.show == 1">
  515. <view class="course_lefts">
  516. <view class="course_title">
  517. {{ item.courseName }}
  518. </view>
  519. <view
  520. v-if="courseItem.teaList && courseItem.teaList.length > 0"
  521. class="teacher_names"
  522. >
  523. <view
  524. v-for="(tea, tindex) in courseItem.teaList"
  525. :key="tindex"
  526. class="names"
  527. >{{ tea.aliasName }}</view
  528. >
  529. </view>
  530. <view class="course_pros">
  531. 学习进度
  532. <text>
  533. {{ item.stuAllNum + item.recordNum }}/{{
  534. item.secAllNum + item.examNum
  535. }}</text
  536. >
  537. </view>
  538. </view>
  539. <view
  540. class="course_rights"
  541. @click="jump(item, gTindex, 'jump')"
  542. >
  543. <view class="cicles">
  544. <u-icon
  545. name="arrow-right"
  546. color="#498AFE"
  547. size="20"
  548. ></u-icon>
  549. </view>
  550. <view class="intoStudy">进入学习</view>
  551. </view>
  552. </view>
  553. </view>
  554. </view>
  555. </scroll-view>
  556. </view>
  557. </view>
  558. </u-popup>
  559. <!-- 拍照提示 -->
  560. <popup-photo
  561. :popupPhotoShow.sync="popupPhotoShow"
  562. @takePhoto="toTakePhoto()"
  563. ></popup-photo>
  564. </view>
  565. </template>
  566. <script>
  567. import plv from "../static/polyv-sdk/index";
  568. import courseModule from "@/components/course/courseModule.vue";
  569. import courseChapter from "@/components/course/courseChapter.vue";
  570. import courseSection from "@/components/course/courseSection.vue";
  571. import handoutsBox from "@/components/course/handoutsBox.vue";
  572. import PopupPhoto from "@/components/popup/index.vue";
  573. import myCompressImage from "@/common/compressPhoto.js";
  574. import myPlayer from "../../components/myPlayer/polyvPlayer.vue";
  575. import noteBox from "../../components/course/noteBox.vue";
  576. import answerBox from "../../components/course/answerBox.vue";
  577. import { mapGetters, mapMutations } from "vuex";
  578. import { lockAction } from "../../utils/lock";
  579. export default {
  580. components: {
  581. courseModule,
  582. courseChapter,
  583. courseSection,
  584. PopupPhoto,
  585. handoutsBox,
  586. myPlayer,
  587. noteBox,
  588. answerBox,
  589. },
  590. data() {
  591. return {
  592. markContent: "http://admin.zhujianpeixun.com/",
  593. showMark: false,
  594. hasStart: false,
  595. channelItem: null,
  596. lockTimer: null,
  597. orderGoodsId: 0,
  598. noticeShow: false,
  599. enableAutoRotation: true,
  600. seekTime: "",
  601. toastTimer: null,
  602. videoToastShow: false,
  603. showSet: false,
  604. startStatus: false,
  605. detail: {},
  606. courseId: 0,
  607. menuList: [],
  608. current: 0,
  609. vid: "",
  610. goodsId: 0,
  611. goodsData: {},
  612. photoPopup: false,
  613. goodsPlayConfig: null,
  614. autoplay: false,
  615. isAllowSeek: "no",
  616. playbackRate: [1.0],
  617. timer: null,
  618. goodsPhotographConfig: null,
  619. intervalTimeList: [], // 间隔拍照时长
  620. intervalTimeIndex: 0, //当前处于哪个时间段拍照
  621. playTime: 0, //页面播放时长,不含暂停
  622. currentTime: 0,
  623. avatarUrl: "",
  624. ossAvatarUrl: "",
  625. studyDuration: 0, // 当前视频时长
  626. gradeId: 0,
  627. chapterId: 0,
  628. moduleId: 0,
  629. reMenuList: [],
  630. recordObj: {},
  631. isTaking: true, //是否正在拍照
  632. needSeek: false, //第一次播放是否需要跳转
  633. photoNum: 0,
  634. photoList: [], //拍照的时间点
  635. photoConfig: false, //是否配置好拍照次数
  636. photoIndex: 0, //当前位于拍照的区间下标 从0开始
  637. photoHistoryList: [], //已拍照历史的下标点
  638. sectionItem: {},
  639. showNotes: true,
  640. uploadLock: false, //上传图片
  641. isPlayRebuild: false, //是否正在播放重修视频needOpen
  642. isRebuild: false, //视频是否从重修目录点击
  643. clearTimer: null,
  644. livingItem: "",
  645. option: null,
  646. toggleCourseShow: false, // 切换课程弹窗
  647. courseList: [], // 课程列表
  648. reStart: false, // 是否显示模块/章/节
  649. subList: [],
  650. subIndex: 0,
  651. goodsTeacher: [],
  652. teacherList: [],
  653. teacherIndex: 0,
  654. newActiveSubjectId: "", //当前选中ID
  655. compareFaceData: 0, // 拍照匹配相似度
  656. prendreAutoCarme: false, // 是否发起授权相机
  657. studyTimer: null, // 学习记录定时器
  658. CountTo: 30, // 倒计时
  659. CountTo1: 0,
  660. handoutTipLength: 0,
  661. menuAllList: [],
  662. popupPhotoShow: false,
  663. curPlayIndex: 0, // 正在播放的节的下标
  664. faceUrl: "",
  665. erJianErZao: false,
  666. pauseTime: 0,
  667. pauseTimer: null,
  668. barTimer: null,
  669. isReach: false,
  670. noticeShow1: false,
  671. refPlv: null,
  672. };
  673. },
  674. computed: {
  675. ...mapGetters([
  676. "userInfo",
  677. "playSectionId",
  678. "playChannelId",
  679. "playVID",
  680. "config",
  681. ]),
  682. playSecIsLearn() {
  683. return this.sectionItem.learning != 1;
  684. },
  685. orderNum() {
  686. return 0;
  687. return this.goodsData.goodsLearningOrder;
  688. },
  689. list() {
  690. let list = [
  691. {
  692. name: "目录",
  693. },
  694. {
  695. name: "讲义",
  696. },
  697. {
  698. name: "笔记",
  699. },
  700. {
  701. name: "答疑",
  702. },
  703. ];
  704. if (this.reMenuList.length > 0) {
  705. list.push({ name: "重修目录" });
  706. }
  707. return list;
  708. },
  709. params: function () {
  710. return (keys = ["orderGoodsId", "goodsId", "courseId"]) => {
  711. let params = {};
  712. for (const key of keys) {
  713. params[key] = this[key];
  714. }
  715. return params;
  716. };
  717. },
  718. },
  719. watch: {
  720. showSet(n) {
  721. if (n) {
  722. if (polyvPlayerContext) {
  723. // #ifdef MP-WEIXIN
  724. polyvPlayerContext.pause();
  725. // #endif
  726. // #ifdef H5
  727. polyvPlayerContext.j2s_pauseVideo(); // 暂停播放视频
  728. // #endif
  729. }
  730. }
  731. },
  732. photoPopup(n) {
  733. if (n) {
  734. if (this.prendreAutoCarme) {
  735. this.photoPopup = false;
  736. }
  737. this.showSet && (this.photoPopup = false);
  738. }
  739. },
  740. },
  741. async onLoad(option) {
  742. if (option.isOther) {
  743. this.showMark = true;
  744. return;
  745. }
  746. this.option = option;
  747. let { skipPort, id, goodsId, orderGoodsId, gradeId, informId } = option;
  748. if (skipPort) {
  749. await this.$method.skipLogin(skipPort);
  750. }
  751. if (this.$method.isGoLogin()) {
  752. return;
  753. }
  754. this.courseId = Number(id) || "";
  755. this.goodsId = Number(goodsId);
  756. this.orderGoodsId = Number(orderGoodsId) || "";
  757. this.gradeId = gradeId;
  758. await this.isCanLearn();
  759. !this.userInfo && this.$api.refreshUserInfo();
  760. // 公众号模板消息的数据埋点
  761. informId && this.clickOfficial(informId);
  762. this.init();
  763. this.courseCourseList();
  764. },
  765. async onShow() {
  766. // this.closePhoto();
  767. },
  768. onUnload() {
  769. console.log("onUnloadonUnloadonUnloadonUnload");
  770. this.originUnload();
  771. this.clears();
  772. clearInterval(this.lockTimer);
  773. },
  774. onHide() {
  775. this.originUnload();
  776. },
  777. mounted() {},
  778. methods: {
  779. ...mapMutations(["updateChapterOpen", "updateLiveLast"]),
  780. init() {
  781. // #ifdef MP-WEIXIN
  782. this.getCameraSetting();
  783. this.isAllowSeek = "no";
  784. // #endif
  785. // #ifdef H5
  786. this.isAllowSeek = "on";
  787. // #endif
  788. // 锁
  789. lockAction();
  790. this.lockTimer = setInterval(lockAction, 10000);
  791. },
  792. // 新增微信公众号模板消息点击数据
  793. clickOfficial(informId) {
  794. this.$http({
  795. url: "/data/click",
  796. method: "post",
  797. data: { informId },
  798. });
  799. },
  800. // 点击课程目录
  801. cMenu(item, index) {
  802. this.subIndex = index;
  803. this.newActiveSubjectId = item.subjectId;
  804. },
  805. courseCourseList() {
  806. this.courseList = [];
  807. this.menuList = [];
  808. this.photoConfig = false;
  809. this.$api
  810. .courseCourseList({
  811. pageNum: 1,
  812. pageSize: 200,
  813. goodsId: this.goodsId,
  814. gradeId: this.gradeId,
  815. orderGoodsId: this.orderGoodsId,
  816. })
  817. .then((res) => {
  818. if (res.data.code == 200) {
  819. this.courseList = res.data.rows;
  820. // 科目
  821. let allItem = [{ subjectId: 0, subjectName: "所有" }];
  822. let ids = [];
  823. const newArr = [];
  824. this.courseList.forEach((item) => {
  825. if (ids.indexOf(item.subjectId) == -1) {
  826. ids.push(item.subjectId);
  827. newArr.push(item);
  828. }
  829. });
  830. this.subList = [...allItem, ...newArr];
  831. this.originOnShow();
  832. this.originMounted();
  833. }
  834. });
  835. },
  836. // 查询用户最后一次看的录播的信息
  837. getUserWatchLast() {
  838. this.$http({
  839. url: "/study/record/getUserWatchLast",
  840. method: "get",
  841. data: {
  842. orderGoodsId: this.orderGoodsId,
  843. },
  844. }).then((res) => {
  845. if (res.data.code == 200) {
  846. this.sectionItem = res.data.data || {};
  847. if (res.data.data && Object.keys(res.data.data).length) {
  848. //有最后一次看的录播的信息
  849. this.courseId = res.data.data.courseId;
  850. // console.log('查询用户最后一次看的录播的信息', res.data, this.courseId)
  851. } else {
  852. this.courseId = this.courseList[0].courseId; // 没有观看记录默认一个课程
  853. // this.toggleCourseShow = true
  854. }
  855. } else {
  856. this.courseId = this.courseList[0].courseId; // 没有观看记录默认一个课程
  857. }
  858. this.originOnShow();
  859. this.originMounted();
  860. //获取商品双师资模板
  861. this.getCourseTeacher(this.courseList);
  862. });
  863. },
  864. getCourseTeacher(rows) {
  865. this.goodsTeacher = [];
  866. //获取商品双师资模板
  867. this.$api
  868. .courseTeacherList({
  869. goodsId: this.goodsId,
  870. })
  871. .then((res1) => {
  872. if (res1.data.data && res1.data.data.length > 0) {
  873. //课程老师模板
  874. let teacherTel = res1.data.data;
  875. //商品课程
  876. let courses = rows;
  877. teacherTel.forEach((tea) => {
  878. let dataList = [];
  879. let teacherList = [];
  880. courses.forEach((item) => {
  881. let data = tea.courseList.filter(
  882. (x) => x.courseId == item.courseId
  883. );
  884. if (data && data.length > 0) {
  885. dataList.push(item);
  886. teacherList = tea.courseList;
  887. }
  888. });
  889. let result = {
  890. teaList: teacherList,
  891. courseList: dataList,
  892. };
  893. this.goodsTeacher.push(result);
  894. });
  895. if (this.goodsTeacher && this.goodsTeacher.length > 0) {
  896. let courseIds = [];
  897. this.goodsTeacher.forEach((item) => {
  898. item.courseList.forEach((course) => {
  899. courseIds.push(course.courseId);
  900. });
  901. });
  902. if (courseIds.length > 0) {
  903. courses.forEach((item) => {
  904. if (!courseIds.includes(item.courseId)) {
  905. let data = {
  906. teaList: [],
  907. courseList: [],
  908. };
  909. data.courseList.push(item);
  910. this.goodsTeacher.push(data);
  911. }
  912. });
  913. }
  914. this.goodsTeacher.forEach((item) => {
  915. if (item.courseList && item.courseList.length > 0) {
  916. item.courseList[0].show = 1;
  917. }
  918. });
  919. }
  920. } else {
  921. //没有双师资模板
  922. rows.forEach((item) => {
  923. item.show = 1;
  924. let data = {
  925. teaList: [],
  926. courseList: [],
  927. };
  928. data.courseList.push(item);
  929. this.goodsTeacher.push(data);
  930. });
  931. }
  932. // console.log(this.goodsTeacher,'this.goodsTeacher', this.courseId);
  933. this.goodsTeacher.forEach((item) => {
  934. if (item.courseList.some((x) => x.courseId == this.courseId)) {
  935. this.teacherList = item.teaList;
  936. }
  937. });
  938. });
  939. },
  940. erJianErZaoPauseTip() {
  941. if (this.playSecIsLearn && this.erJianErZao) {
  942. if (this.pauseTimer) {
  943. return;
  944. }
  945. this.pauseTime = Date.now();
  946. console.log("开启定时器");
  947. this.pauseTimer = setInterval(() => {
  948. console.log("暂停时间", Date.now() - this.pauseTime, this.pauseTime);
  949. if (Date.now() - this.pauseTime > 5 * 60 * 1000) {
  950. // 5 * 60 * 1000
  951. let text = this.photoPopup ? "拍照停留" : "暂停";
  952. this.photoPopup = false;
  953. uni.showModal({
  954. title: "提示",
  955. showCancel: false,
  956. content: `检测${text}时间过长,刷新当前页面`,
  957. cancelText: "取消",
  958. confirmText: "确定",
  959. success: (res) => {
  960. if (res.confirm) {
  961. // #ifdef H5
  962. location.reload();
  963. // #endif
  964. // #ifdef MP-WEIXIN
  965. this.courseCourseList();
  966. // #endif
  967. }
  968. },
  969. });
  970. this.clearPauseTimer();
  971. }
  972. }, 5000);
  973. }
  974. },
  975. // 原来onshow里面的内容
  976. async originOnShow() {
  977. this.courseDetail();
  978. this.getGoodsDetail();
  979. await this.studyRecordMenuAllList();
  980. // 消息过来 定位某个节
  981. if (this.option.noteSecond) {
  982. this.jumpNote({
  983. sectionType: 1,
  984. ...this.option,
  985. });
  986. return;
  987. }
  988. this.studyRecordQueryLiveLast();
  989. },
  990. // 原来的mouted内容
  991. originMounted() {
  992. uni.$on("changeSection", (oldSectionId) => {
  993. console.log(
  994. "切换课程-originMounted->playVID:",
  995. this.playVID,
  996. oldSectionId
  997. );
  998. this.studyTimer && clearInterval(this.studyTimer); // 清除定时器
  999. this.clearPauseTimer();
  1000. this.hasStart = false;
  1001. this.photoConfig = false;
  1002. this.photoIndex = 0;
  1003. //清除直播
  1004. this.$store.commit("setPlayChannelId", { playChannelId: 0 });
  1005. this.postStudyRecord(0, oldSectionId);
  1006. });
  1007. uni.$on("getSection", (item) => {
  1008. //清除直播
  1009. this.studyTimer && clearInterval(this.studyTimer);
  1010. this.hasStart = false;
  1011. this.isPlayRebuild = item.rebuild;
  1012. this.photoConfig = false;
  1013. this.photoIndex = 0;
  1014. this.sectionItem = item;
  1015. this.moduleId = item.moduleId || null;
  1016. this.chapterId = item.chapterId || null;
  1017. this.$store.commit("setPlayChannelId", { playChannelId: 0 });
  1018. //获取拍照历史
  1019. this.getPhotoLastRecord();
  1020. this.playVideo(item);
  1021. });
  1022. uni.$on("levelId", (item) => {
  1023. let arr = item.split("-");
  1024. //点击节获取的各层级ID
  1025. this.moduleId = arr[0];
  1026. this.chapterId = arr[1];
  1027. });
  1028. uni.$on("getChannel", (item) => {
  1029. //清除录播
  1030. this.studyTimer && clearInterval(this.studyTimer);
  1031. this.hasStart = false;
  1032. this.$store.commit("setPlayVID", { playVID: null });
  1033. this.moduleId = item.moduleId;
  1034. this.chapterId = item.chapterId;
  1035. this.$store.commit("setPlaySectionId", {
  1036. playSectionId: item.sectionId || item.menuId,
  1037. });
  1038. this.getPhotoLastRecord();
  1039. this.playChannel(item);
  1040. this.channelItem = item;
  1041. });
  1042. uni.$on("isRebuild", (item) => {
  1043. this.isRebuild = item;
  1044. });
  1045. this.updateChapterOpen(true);
  1046. },
  1047. clearPauseTimer() {
  1048. if (this.pauseTimer) {
  1049. this.pauseTime = 0;
  1050. clearInterval(this.pauseTimer);
  1051. this.pauseTimer = null;
  1052. }
  1053. },
  1054. clearBarTimer() {
  1055. if (this.barTimer) {
  1056. clearInterval(this.barTimer);
  1057. this.barTimer = null;
  1058. }
  1059. },
  1060. // 原来onUnload里面的内容
  1061. originUnload() {
  1062. if (this.playSectionId > 0 && this.hasStart) {
  1063. //退出提交记录
  1064. this.postStudyRecord();
  1065. }
  1066. //清除正在播放的节ID
  1067. // this.$store.commit('setPlayObj',null)
  1068. this.$store.commit("setPlaySectionId", { playSectionId: 0 });
  1069. this.$store.commit("setPlayChannelId", { playChannelId: 0 });
  1070. this.$store.commit("setPlayVID", { playVID: null });
  1071. this.closePlv();
  1072. //移除所有的事件监听器
  1073. uni.$off();
  1074. this.clearTimer && clearTimeout(this.clearTimer);
  1075. this.toastTimer && clearTimeout(this.toastTimer);
  1076. if (this.studyTimer) {
  1077. clearInterval(this.studyTimer);
  1078. this.hasStart = false;
  1079. }
  1080. this.clearPauseTimer();
  1081. this.clearBarTimer();
  1082. if (this.lockTimer) {
  1083. clearInterval(this.lockTimer);
  1084. this.$api
  1085. .lockDelLock({
  1086. action: "jxjy",
  1087. uuid: this.$method.getUuid(),
  1088. })
  1089. .then((res) => {
  1090. uni.hideLoading();
  1091. });
  1092. }
  1093. },
  1094. changeCourses() {
  1095. this.toggleCourseShow = true;
  1096. },
  1097. closePop() {
  1098. this.toggleCourseShow = false;
  1099. },
  1100. async activeFunc(item, index) {
  1101. this.teacherIndex = index;
  1102. let findResult = "";
  1103. this.goodsTeacher.forEach((citem, index) => {
  1104. citem.courseList.forEach((e, e_index) => {
  1105. if (e.courseId == item.courseId) {
  1106. findResult = e;
  1107. }
  1108. });
  1109. });
  1110. this.jump(findResult, 1);
  1111. },
  1112. // 进入学习
  1113. async jump(item, index, type) {
  1114. // console.log('item------>', index,item,this.goodsTeacher)
  1115. if (index == 0) {
  1116. await this.nextCourses(item, type);
  1117. if (item.rebuild === 0) {
  1118. //未重修
  1119. this.$navTo.togo("/pages2/learn/details", {
  1120. id: item.courseId,
  1121. gradeId: item.gradeId,
  1122. goodsId: this.goodsId,
  1123. orderGoodsId: this.orderGoodsId,
  1124. });
  1125. return;
  1126. }
  1127. this.$api.courseDetail(item.courseId).then((res) => {
  1128. if (res.data.code == 200) {
  1129. // if (res.data.data.educationName == "继续教育") {
  1130. this.$method.checkLock().then((res) => {
  1131. this.courseId = item.courseId;
  1132. this.originOnShow();
  1133. this.originMounted();
  1134. });
  1135. }
  1136. });
  1137. } else {
  1138. if (this.orderNum == 2) {
  1139. //学习顺序是从头到尾学习,没学完上一课不能学习下一课
  1140. let prevItem = this.courseList[index - 1]; //上一课
  1141. if (prevItem.stuAllNum == prevItem.secAllNum) {
  1142. await this.nextCourses(item, type);
  1143. if (item.rebuild === 0) {
  1144. //未重修
  1145. this.$navTo.togo("/pages2/learn/details", {
  1146. id: item.courseId,
  1147. gradeId: item.gradeId,
  1148. goodsId: this.goodsId,
  1149. orderGoodsId: this.orderGoodsId,
  1150. });
  1151. return;
  1152. }
  1153. this.$api.courseDetail(item.courseId).then((res) => {
  1154. if (res.data.code == 200) {
  1155. // if (res.data.data.educationName == "继续教育") {
  1156. this.$method.checkLock().then((res) => {
  1157. this.courseId = item.courseId;
  1158. this.originOnShow();
  1159. this.originMounted();
  1160. });
  1161. }
  1162. });
  1163. } else {
  1164. uni.showToast({
  1165. icon: "none",
  1166. title: "请按顺序学完上一课再学习这一课",
  1167. });
  1168. }
  1169. } else {
  1170. await this.nextCourses(item, type);
  1171. if (item.rebuild === 0) {
  1172. //未重修
  1173. this.$navTo.togo("/pages2/learn/details", {
  1174. id: item.courseId,
  1175. gradeId: item.gradeId,
  1176. goodsId: this.goodsId,
  1177. orderGoodsId: this.orderGoodsId,
  1178. });
  1179. return;
  1180. }
  1181. this.$api.courseDetail(item.courseId).then((res) => {
  1182. if (res.data.code == 200) {
  1183. // if (res.data.data.educationName == "继续教育") {
  1184. this.$method.checkLock().then((res) => {
  1185. this.courseId = item.courseId;
  1186. this.originOnShow();
  1187. this.originMounted();
  1188. });
  1189. }
  1190. });
  1191. }
  1192. }
  1193. },
  1194. async nextCourses(item, type) {
  1195. this.vid = "";
  1196. this.hasStart = true;
  1197. await this.originUnload();
  1198. if (type) {
  1199. this.teacherIndex = 0;
  1200. this.goodsTeacher.forEach((citem) => {
  1201. if (citem.courseList.some((x) => x.courseId == item.courseId)) {
  1202. this.teacherList = citem.teaList;
  1203. }
  1204. });
  1205. }
  1206. this.reStart = false;
  1207. this.courseId = item.courseId;
  1208. this.gradeId = item.gradeId;
  1209. this.toggleCourseShow = false;
  1210. },
  1211. clickLeft() {
  1212. // uni.navigateBack()
  1213. uni.switchTab({
  1214. url: "/pages/learn/index",
  1215. });
  1216. },
  1217. toBack(delta = 1) {
  1218. uni.navigateBack({
  1219. delta,
  1220. });
  1221. },
  1222. markConfirm() {
  1223. uni.setClipboardData({
  1224. data: this.markContent,
  1225. success: () => {
  1226. setTimeout(this.toBack, 1000);
  1227. },
  1228. });
  1229. },
  1230. closeNotice() {
  1231. this.$api
  1232. .baseHandoutTip({
  1233. orderGoodsId: this.orderGoodsId,
  1234. })
  1235. .then((res) => {});
  1236. },
  1237. noticeConfirm() {
  1238. if (this.CountTo < 0) {
  1239. this.noticeShow = false;
  1240. if (this.handoutTipLength == 0 && this.goodsPlayConfig.autoPlay > 0) {
  1241. this.autoplay = true;
  1242. this.refPlv.resumeVideo();
  1243. }
  1244. }
  1245. },
  1246. baseHandoutTipList() {
  1247. this.$api
  1248. .baseHandoutTipList({
  1249. orderGoodsId: this.orderGoodsId,
  1250. })
  1251. .then((res) => {
  1252. this.handoutTipLength = res.data.rows.length;
  1253. if (res.data.rows.length == 0) {
  1254. this.noticeShow = true;
  1255. if (this.CountTo == 30) {
  1256. var timer = setInterval(() => {
  1257. this.CountTo--;
  1258. if (this.CountTo < 0) {
  1259. clearInterval(timer);
  1260. }
  1261. }, 1000);
  1262. }
  1263. } else {
  1264. this.CountTo = -1;
  1265. }
  1266. });
  1267. },
  1268. /**
  1269. * 获取上次观看的直播
  1270. */
  1271. studyRecordGetLastLive() {
  1272. this.$api
  1273. .studyRecordGetLastLive({
  1274. orderGoodsId: this.orderGoodsId,
  1275. courseId: this.courseId,
  1276. })
  1277. .then((res) => {
  1278. this.updateLiveLast(res.data.data);
  1279. });
  1280. },
  1281. async initPlayVideo(sectionItem) {
  1282. this.moduleId = sectionItem.moduleId;
  1283. this.chapterId = sectionItem.chapterId;
  1284. if (sectionItem.sectionType == 1) {
  1285. //录播
  1286. await this.getPhotoLastRecord(); // 获取拍照历史
  1287. this.playVideo(sectionItem);
  1288. } else if (sectionItem.sectionType == 2) {
  1289. //直播
  1290. this.studyRecordGetLastLive();
  1291. } else if (sectionItem.sectionType == 3) {
  1292. //回放
  1293. this.playVideo(sectionItem);
  1294. } else if (sectionItem.doType == 2) {
  1295. uni.showModal({
  1296. title: "温馨提示",
  1297. content: "当前节视频已学完,是否进入考试?",
  1298. success: (res) => {
  1299. if (res.confirm) {
  1300. this.toQuestionBank(sectionItem);
  1301. }
  1302. },
  1303. });
  1304. return;
  1305. }
  1306. },
  1307. toQuestionBank(sectionItem) {
  1308. uni.navigateTo({
  1309. url:
  1310. "/pages2/class/questionBank?courseId=" +
  1311. this.courseId +
  1312. "&gradeId=" +
  1313. this.gradeId +
  1314. "&isFromVideo=1&id=" +
  1315. sectionItem.id +
  1316. "&goodsid=" +
  1317. this.goodsId +
  1318. "&moduleId=" +
  1319. (sectionItem.moduleId || 0) +
  1320. "&chapterId=" +
  1321. (sectionItem.chapterId || 0) +
  1322. "&orderGoodsId=" +
  1323. this.orderGoodsId +
  1324. "&type=" +
  1325. (sectionItem.type == 4 ? 1 : 3) +
  1326. "&learning=" +
  1327. sectionItem.studyStatus +
  1328. "&isBackVideo=" +
  1329. 1,
  1330. });
  1331. },
  1332. studyRecordQueryLiveLast() {
  1333. // /study/record/queryLiveLast
  1334. this.$api
  1335. .studyRecordQueryLiveLast({
  1336. gradeId: this.gradeId,
  1337. orderGoodsId: this.orderGoodsId,
  1338. courseId: this.courseId,
  1339. })
  1340. .then((res) => {
  1341. console.log("🚀 ~ file: detail.vue:1575 ~ .then ~ res:", res);
  1342. let { data } = res.data;
  1343. if (!data.sectionId) {
  1344. data = this.menuAllList[0];
  1345. } else {
  1346. // if (data.learning == 1 && this.orderNum == 2) {
  1347. // let next = this.menuAllList.find((e) => e.studyStatus != 1);
  1348. // next && (data = next);
  1349. // }
  1350. }
  1351. this.initPlayVideo(data);
  1352. });
  1353. },
  1354. /**
  1355. * 模块大节播放完毕,刷新列表
  1356. */
  1357. sectionPlayEnd(isRebuild, index) {
  1358. if (this.reMenuList.length > 0) {
  1359. //有重修目录
  1360. if (isRebuild.isRebuild) {
  1361. //从重修点击
  1362. this.$api
  1363. .reMenuList({
  1364. orderGoodsId: this.orderGoodsId,
  1365. courseId: this.courseId,
  1366. rebuild: 1,
  1367. gradeId: this.gradeId,
  1368. })
  1369. .then((res) => {
  1370. if (res.data.code == 200) {
  1371. if (res.data.rows.length) {
  1372. res.data.rows[index].name = res.data.rows[index].menuName;
  1373. this.$set(this.reMenuList, index, res.data.rows[index]);
  1374. for (let i = 0; i < res.data.rows.length; i++) {
  1375. let item = res.data.rows[i];
  1376. item.down = true;
  1377. item.id = item.menuId;
  1378. item.name = item.menuName;
  1379. }
  1380. this.reMenuList = [];
  1381. this.$nextTick(() => {
  1382. this.reMenuList = res.data.rows;
  1383. // console.log(this.reMenuList,'this.reMenuList1')
  1384. });
  1385. } else {
  1386. this.reMenuList = [];
  1387. }
  1388. }
  1389. });
  1390. this.$api
  1391. .reMenuList({
  1392. courseId: this.courseId,
  1393. gradeId: this.gradeId,
  1394. orderGoodsId: this.orderGoodsId,
  1395. })
  1396. .then((res) => {
  1397. if (res.data.code == 200) {
  1398. for (let i = 0; i < res.data.rows.length; i++) {
  1399. let item = res.data.rows[i];
  1400. item.down = true;
  1401. item.id = item.menuId;
  1402. item.name = item.menuName;
  1403. item.menuType = item.type;
  1404. }
  1405. this.menuList = [];
  1406. this.$nextTick(() => {
  1407. this.menuList = res.data.rows;
  1408. });
  1409. }
  1410. });
  1411. } else {
  1412. //从普通目录点击
  1413. this.$api
  1414. .reMenuList({
  1415. courseId: this.courseId,
  1416. gradeId: this.gradeId,
  1417. orderGoodsId: this.orderGoodsId,
  1418. })
  1419. .then((res) => {
  1420. if (res.data.code == 200) {
  1421. res.data.rows[index].name = res.data.rows[index].menuName;
  1422. res.data.rows[index].id = res.data.rows[index].menuId;
  1423. this.$set(this.menuList, index, res.data.rows[index]);
  1424. }
  1425. });
  1426. this.$api
  1427. .reMenuList({
  1428. orderGoodsId: this.orderGoodsId,
  1429. courseId: this.courseId,
  1430. rebuild: 1,
  1431. gradeId: this.gradeId,
  1432. })
  1433. .then((res) => {
  1434. if (res.data.code == 200) {
  1435. if (res.data.rows.length) {
  1436. // for (let i = 0; i < res.data.rows.length; i++) {
  1437. // let item = res.data.rows[i];
  1438. // item.down = true;
  1439. // item.id = item.menuId;
  1440. // item.name = item.menuName;
  1441. // }
  1442. // this.reMenuList = res.data.rows;
  1443. } else {
  1444. this.reMenuList = [];
  1445. }
  1446. }
  1447. });
  1448. }
  1449. } else {
  1450. console.log("--模块大节播放完毕,刷新列表-");
  1451. //没有重修目录
  1452. this.$api
  1453. .reMenuList({
  1454. courseId: this.courseId,
  1455. gradeId: this.gradeId,
  1456. orderGoodsId: this.orderGoodsId,
  1457. })
  1458. .then((res) => {
  1459. if (res.data.code == 200) {
  1460. res.data.rows[index].name = res.data.rows[index].menuName;
  1461. res.data.rows[index].id = res.data.rows[index].menuId;
  1462. this.$set(this.menuList, index, res.data.rows[index]);
  1463. }
  1464. });
  1465. }
  1466. },
  1467. goLive(item) {
  1468. let moduleId = item.moduleId || 0;
  1469. let chapterId = item.chapterId || 0;
  1470. let sectionId = item.sectionId || item.menuId;
  1471. let uuid = new Date().valueOf() + "";
  1472. // buyCourse 是否购买课程:1是 0否
  1473. let encode = encodeURIComponent(
  1474. this.config.hostLive +
  1475. "/pages/live/index?token=" +
  1476. uni.getStorageSync("token") +
  1477. "&userInfo=" +
  1478. JSON.stringify(this.userInfo) +
  1479. "&channelId=" +
  1480. item.liveUrl +
  1481. "&gradeId=" +
  1482. this.gradeId +
  1483. "&courseId=" +
  1484. this.courseId +
  1485. "&goodsId=" +
  1486. this.goodsId +
  1487. "&orderGoodsId=" +
  1488. this.orderGoodsId +
  1489. "&sectionId=" +
  1490. sectionId +
  1491. "&chapterId=" +
  1492. chapterId +
  1493. "&moduleId=" +
  1494. moduleId +
  1495. "&buyCourse=1" +
  1496. "&ident=" +
  1497. uuid
  1498. );
  1499. uni.navigateTo({
  1500. url: `../../pages/webview/index?url=` + encode,
  1501. });
  1502. },
  1503. studyRecordMenuAllList() {
  1504. // study/record/menuAllList
  1505. return this.$api
  1506. .studMenuAllList({
  1507. courseId: this.courseId,
  1508. gradeId: this.gradeId,
  1509. goodsId: this.goodsId,
  1510. })
  1511. .then((res) => {
  1512. let nowTime = Number(new Date().getTime() / 1000).toFixed(0);
  1513. if (res.data.data) {
  1514. this.menuAllList = res.data.data.filter(
  1515. (e) => e.doType != 1 || (e.doType == 2 && e.studyStatus == 1)
  1516. );
  1517. this.livingItem = res.data.data.find(
  1518. (item) =>
  1519. item.liveStartTime <= nowTime && item.liveEndTime > nowTime
  1520. );
  1521. }
  1522. return Promise.resolve();
  1523. });
  1524. },
  1525. async getbaseprofiletplists() {
  1526. let {
  1527. data: { code, rows },
  1528. } = await this.$api.getbaseprofiletplists({
  1529. goodsId: this.goodsId,
  1530. orderGoodsId: this.orderGoodsId,
  1531. });
  1532. if (code === 200 && rows.length && rows[0].keyValue) {
  1533. let baseRes = await this.$api.getbaseprofiletpId(this.goodsId);
  1534. if (baseRes.data.code === 200 && baseRes.data.data) {
  1535. let {
  1536. data: { code, data },
  1537. } = await this.$api.getbaseprofiletpgetInfo({
  1538. goodsId: this.goodsId,
  1539. orderGoodsId: this.orderGoodsId,
  1540. });
  1541. if (
  1542. code === 200 &&
  1543. (!data || (data.status === 3 && data.changeStatus === 1))
  1544. ) {
  1545. uni.showModal({
  1546. content: !data
  1547. ? "请前往填写资料"
  1548. : "资料审核不通过,请前往重新填写",
  1549. cancelText: "返回",
  1550. success: (resultst) => {
  1551. if (resultst.confirm) {
  1552. this.$navTo.togo("/pages2/verify/input", {
  1553. id: this.goodsId,
  1554. orderGoodsId: this.orderGoodsId,
  1555. });
  1556. }
  1557. if (resultst.cancel) {
  1558. uni.navigateBack();
  1559. }
  1560. },
  1561. });
  1562. return Promise.reject();
  1563. } else if (data.status === 1 && JSON.parse(rows[0].keyValue2)[0]) {
  1564. let {
  1565. data: { code, data },
  1566. } = await this.$api.getbaseprofileStampgetInfo({
  1567. goodsId: this.goodsId,
  1568. orderGoodsId: this.orderGoodsId,
  1569. });
  1570. if (
  1571. code === 200 &&
  1572. (!data || (data.status === 3 && data.changeStatus === 1))
  1573. ) {
  1574. uni.showModal({
  1575. content: !data
  1576. ? "请前往填写盖章资料"
  1577. : "资料盖章审核不通过,请前往重新填写",
  1578. cancelText: "返回",
  1579. success: (resultst) => {
  1580. if (resultst.confirm) {
  1581. this.$navTo.togo("/pages2/verify/input2", {
  1582. id: this.goodsId,
  1583. orderGoodsId: this.orderGoodsId,
  1584. });
  1585. }
  1586. if (resultst.cancel) {
  1587. uni.navigateBack();
  1588. }
  1589. },
  1590. });
  1591. return Promise.reject();
  1592. }
  1593. }
  1594. }
  1595. }
  1596. let detail = await this.$api.goodsDetail(this.goodsId);
  1597. if (detail.data.data.erJianErZao) {
  1598. let info = await this.$api.userConfirmInfoDetail({
  1599. orderGoodsId: this.orderGoodsId,
  1600. });
  1601. if (!info.data.data || info.data.data.pushInfo !== 1) {
  1602. uni.showModal({
  1603. showCancel: false,
  1604. title: "提示",
  1605. content: "开通信息推送不成功,无法进入学习!",
  1606. success: (resultst) => {
  1607. uni.navigateBack();
  1608. },
  1609. });
  1610. return Promise.reject();
  1611. }
  1612. }
  1613. return Promise.resolve();
  1614. },
  1615. async isCanLearn() {
  1616. await this.getbaseprofiletplists();
  1617. await this.getGradeInfo();
  1618. },
  1619. /**
  1620. * 计算tabs宽度
  1621. */
  1622. itemWidth() {
  1623. return 100 / this.list.length + "%";
  1624. },
  1625. findMenuNextSection(index) {
  1626. for (let i = index + 1; i < this.reMenuList.length; i++) {
  1627. let item = this.reMenuList[i];
  1628. if (item.type == 3) {
  1629. return item;
  1630. }
  1631. }
  1632. return {};
  1633. },
  1634. loadedmetadata(event) {
  1635. this.refPlv = this.$refs.player;
  1636. },
  1637. getPhotoLastRecord() {
  1638. if (this.erJianErZao || !this.playSecIsLearn || this.photoNum <= 0) {
  1639. return;
  1640. }
  1641. let self = this;
  1642. let data = {
  1643. sectionId: parseInt(self.playSectionId),
  1644. goodsId: parseInt(self.goodsId),
  1645. courseId: parseInt(self.courseId),
  1646. gradeId: parseInt(self.gradeId),
  1647. chapterId: parseInt(self.chapterId),
  1648. moduleId: parseInt(self.moduleId),
  1649. orderGoodsId: this.orderGoodsId,
  1650. };
  1651. // /course/photo/log/getLastInfo'
  1652. this.$api.getPhotoLastRecord(data).then((res) => {
  1653. if (res.data.code == 200) {
  1654. //清空历史数据
  1655. self.photoHistoryList = [];
  1656. this.photoIndex = 0;
  1657. self.photoList = [];
  1658. for (let i = 0; i < res.data.data.length; i++) {
  1659. //-2存储随机拍照数组
  1660. if (res.data.data[i].photoIndex == -2) {
  1661. self.photoList =
  1662. res.data.data[i].timeInterval &&
  1663. res.data.data[i].timeInterval.split(",");
  1664. } else {
  1665. self.photoHistoryList.push(res.data.data[i].photoIndex);
  1666. }
  1667. }
  1668. // console.log('7777', this.photoHistoryList, this.photoList);
  1669. }
  1670. });
  1671. },
  1672. //postTime 只提交随机时间
  1673. postCoursePhotoRecord(postTime = false) {
  1674. return new Promise((resolve, reject) => {
  1675. let currentTime = 0;
  1676. // var polyvPlayerContext = this.selectComponent("#playerVideo");
  1677. if (polyvPlayerContext) {
  1678. // #ifdef MP-WEIXIN
  1679. currentTime = polyvPlayerContext.getCurrentTime();
  1680. // #endif
  1681. // #ifdef H5
  1682. currentTime = polyvPlayerContext.j2s_getCurrentTime();
  1683. // #endif
  1684. }
  1685. let self = this;
  1686. let photoIndex = self.photoIndex;
  1687. let data = {
  1688. photo: self.ossAvatarUrl,
  1689. sectionId: parseInt(self.playSectionId),
  1690. goodsId: parseInt(self.goodsId),
  1691. courseId: parseInt(self.courseId),
  1692. photoTime: parseInt(currentTime > 0 ? currentTime : 0),
  1693. gradeId: parseInt(self.gradeId),
  1694. photoIndex: postTime ? -2 : parseInt(photoIndex), //从0算起,-2只提交随机时间
  1695. photoNum: parseInt(self.photoNum),
  1696. chapterId: parseInt(self.chapterId),
  1697. moduleId: parseInt(self.moduleId),
  1698. timeInterval: postTime ? self.photoList.join(",") : "",
  1699. orderGoodsId: this.orderGoodsId,
  1700. };
  1701. // console.log("提交接口", data);
  1702. this.$api
  1703. .coursePhotoRecord(data)
  1704. .then((res) => {
  1705. if (res.data.code == 200) {
  1706. resolve();
  1707. } else {
  1708. reject();
  1709. }
  1710. })
  1711. .catch((err) => {
  1712. reject();
  1713. });
  1714. });
  1715. },
  1716. randomNum(minNum, maxNum) {
  1717. switch (arguments.length) {
  1718. case 1:
  1719. return parseInt(Math.random() * minNum + 1, 10);
  1720. break;
  1721. case 2:
  1722. return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
  1723. break;
  1724. default:
  1725. return 0;
  1726. break;
  1727. }
  1728. },
  1729. //配置随机拍照时间
  1730. configPhoto() {
  1731. // var polyvPlayerContext = this.selectComponent("#playerVideo");
  1732. let totalVideoTime = 0;
  1733. let duration = 0;
  1734. // #ifdef MP-WEIXIN
  1735. totalVideoTime = polyvPlayerContext.getDuration();
  1736. duration = polyvPlayerContext.getCurrentTime();
  1737. // #endif
  1738. // #ifdef H5
  1739. totalVideoTime = polyvPlayerContext.j2s_getDuration();
  1740. duration = polyvPlayerContext.j2s_getCurrentTime();
  1741. // #endif
  1742. let photoNum = this.photoNum;
  1743. if (!this.photoConfig) {
  1744. this.photoConfig = true;
  1745. if (this.erJianErZao) {
  1746. this.photoList = this.randomConfig(totalVideoTime, duration);
  1747. return;
  1748. }
  1749. //没有历史拍照间隔数据
  1750. if (this.photoList.length == 0) {
  1751. if (totalVideoTime >= 900) {
  1752. //大于15分钟
  1753. if (photoNum == 1) {
  1754. //开头拍1张
  1755. this.photoList.push(0);
  1756. } else if (photoNum == 3) {
  1757. //拍3张
  1758. this.photoList.push(0); //开头拍一张
  1759. let centerTime = Math.floor(totalVideoTime / 2); //获取中间时间
  1760. let centerMinTime = centerTime - 300; //前后5分钟
  1761. let centerMaxTime = centerTime + 300;
  1762. let centerTakeTime = this.randomNum(centerMinTime, centerMaxTime);
  1763. this.photoList.push(centerTakeTime); //中间拍一张
  1764. let endMaxTime = totalVideoTime - 60;
  1765. let endMinTime = totalVideoTime - 300;
  1766. let endTakeTime = this.randomNum(endMinTime, endMaxTime);
  1767. this.photoList.push(endTakeTime); //最后拍一张
  1768. }
  1769. } else {
  1770. //小于15分钟,只拍前后各一张
  1771. if (photoNum == 1) {
  1772. //开头拍1张
  1773. this.photoList.push(0);
  1774. } else if (photoNum == 3) {
  1775. this.photoList.push(1);
  1776. let centerTime = this.randomNum(
  1777. (1 / 3) * totalVideoTime,
  1778. (2 / 3) * totalVideoTime
  1779. );
  1780. this.photoList.push(centerTime);
  1781. let endTakeTime = this.randomNum(
  1782. (2 / 3) * totalVideoTime,
  1783. totalVideoTime
  1784. );
  1785. this.photoList.push(endTakeTime);
  1786. }
  1787. }
  1788. this.postCoursePhotoRecord(true); //提交随机拍照时间数组
  1789. }
  1790. //兼容已有观看历史
  1791. for (let i = 0; i < this.photoList.length - 1; i++) {
  1792. if (
  1793. this.photoList[i] < duration &&
  1794. this.photoList[i + 1] > duration
  1795. ) {
  1796. this.photoIndex = i + 1;
  1797. break;
  1798. }
  1799. if (duration > this.photoList[this.photoList.length - 1]) {
  1800. this.photoIndex = this.photoList.length - 1; //取最后一个下标
  1801. break;
  1802. }
  1803. }
  1804. }
  1805. },
  1806. // 随机拍摄时间
  1807. randomConfig(totalVideoTime, duration) {
  1808. this.photoHistoryList = [];
  1809. let photoList = [duration];
  1810. let pre = duration;
  1811. if (totalVideoTime > 300) {
  1812. while (pre <= totalVideoTime) {
  1813. pre += this.randomNum(780, 900);
  1814. pre <= totalVideoTime && photoList.push(pre);
  1815. }
  1816. if (totalVideoTime - 300 > photoList.slice(-1)[0]) {
  1817. photoList.push(this.randomNum(totalVideoTime - 180, totalVideoTime));
  1818. }
  1819. }
  1820. return photoList;
  1821. },
  1822. closePlv() {
  1823. if (plv) {
  1824. plv.destroy();
  1825. }
  1826. },
  1827. openSetting(res) {
  1828. console.log(res, 98);
  1829. },
  1830. getCameraSetting() {
  1831. const self = this;
  1832. // 不支持h5
  1833. wx.getSetting({
  1834. success: (res) => {
  1835. if (res.authSetting["scope.camera"]) {
  1836. // 用户已经授权
  1837. self.showSet = false;
  1838. this.prendreAutoCarme = false;
  1839. } else {
  1840. this.prendreAutoCarme = true;
  1841. // 用户还没有授权,向用户发起授权请求
  1842. wx.authorize({
  1843. scope: "scope.camera",
  1844. success: () => {
  1845. // 用户同意授权
  1846. self.showSet = false;
  1847. this.prendreAutoCarme = false;
  1848. },
  1849. fail: () => {
  1850. // 用户不同意授权
  1851. self.showSet = true;
  1852. },
  1853. });
  1854. }
  1855. },
  1856. fail: (res) => {},
  1857. });
  1858. },
  1859. studyNotice() {
  1860. this.noticeShow = true;
  1861. },
  1862. //播放笔记视频
  1863. async playNoteVideo(item) {
  1864. if (this.timer) {
  1865. clearInterval(this.timer);
  1866. }
  1867. this.vid = item.recordingUrl;
  1868. // #ifdef MP-WEIXIN
  1869. if (this.vid) {
  1870. polyvPlayerContext.changeVid(this.vid);
  1871. }
  1872. // #endif
  1873. this.recordObj = { videoCurrentTime: item.noteSecond };
  1874. if (this.recordObj.videoCurrentTime) {
  1875. this.needSeek = true; //需要跳转到播放记录
  1876. }
  1877. this.startStatus = true;
  1878. },
  1879. //正常播放视频
  1880. async playVideo(item) {
  1881. this.sectionItem = item;
  1882. if (this.timer) {
  1883. clearInterval(this.timer);
  1884. }
  1885. this.recordObj = item.videoCurrentTime
  1886. ? { videoCurrentTime: item.videoCurrentTime }
  1887. : await this.getRecordLast(item);
  1888. this.$store.commit("setPlayVID", {
  1889. playVID: item.recordingUrl,
  1890. });
  1891. this.$store.commit("setPlaySectionId", {
  1892. playSectionId: item.sectionId,
  1893. });
  1894. if (this.refPlv) {
  1895. this.refPlv.changeVid({
  1896. vid: item.recordingUrl,
  1897. videoCurrentTime: this.recordObj.videoCurrentTime,
  1898. });
  1899. }
  1900. this.startStatus = true;
  1901. },
  1902. getRecordLast(sectionItem) {
  1903. let { chapterId, sectionId, courseId, moduleId } = sectionItem;
  1904. return new Promise((resolve) => {
  1905. let data = {
  1906. gradeId:
  1907. this.gradeId || this.gradeId == 0 ? Number(this.gradeId) : null,
  1908. goodsId:
  1909. this.goodsId || this.goodsId == 0 ? Number(this.goodsId) : null,
  1910. sectionId: sectionId || 0,
  1911. courseId: courseId || courseId == 0 ? Number(courseId) : null,
  1912. chapterId: chapterId || 0,
  1913. moduleId: moduleId || 0,
  1914. orderGoodsId: this.orderGoodsId,
  1915. };
  1916. this.$api.recordLast(data).then((res) => {
  1917. resolve(res.data.data);
  1918. });
  1919. });
  1920. },
  1921. jumpNote(item) {
  1922. this.$u.toast("即将跳到笔记位置");
  1923. if (this.playSectionId != item.sectionId) {
  1924. this.initPlayVideo({
  1925. sectionType: 1,
  1926. ...item,
  1927. videoCurrentTime: Number(item.noteSecond),
  1928. });
  1929. } else {
  1930. this.refPlv.seekVideo(item.noteSecond);
  1931. }
  1932. },
  1933. getGradeInfo() {
  1934. // 即刻 1 待定2 日期3
  1935. return this.$api.goodsGradeInfo(this.gradeId).then((res) => {
  1936. if (res.data.code == 200) {
  1937. let { data } = res.data;
  1938. if (
  1939. data.learningStatus == 2 ||
  1940. (data.learningStatus == 3 &&
  1941. Number(data.learningTimeStart) > Number(new Date() / 1000))
  1942. ) {
  1943. uni.showModal({
  1944. showCancel: false,
  1945. confirmText: "确定",
  1946. content:
  1947. "当前课程正在申请中,正式开班后方可进行学习,请耐心等候!",
  1948. success: function (resultst) {
  1949. uni.navigateBack();
  1950. },
  1951. });
  1952. return Promise.reject(123);
  1953. }
  1954. }
  1955. });
  1956. },
  1957. postStudyRecord(status = 0, sectionId = this.playSectionId) {
  1958. console.log(this.refPlv, "this.refPlv");
  1959. let currentTime = this.refPlv.playCurrentTime();
  1960. let PlayDuration = this.refPlv.playVideoTime();
  1961. if (currentTime < 10 && !this.ossAvatarUrl) {
  1962. return;
  1963. }
  1964. if (this.playChannelId > 0) {
  1965. currentTime = 2; //直播无法获取,无论开始结束都传2秒
  1966. }
  1967. let self = this;
  1968. let data = {
  1969. fromPlat: 1, //来源平台 1小程序 2网站
  1970. photo: self.ossAvatarUrl,
  1971. sectionId: sectionId || 0,
  1972. goodsId: parseInt(self.goodsId),
  1973. courseId: parseInt(self.courseId),
  1974. orderGoodsId: this.orderGoodsId,
  1975. studyDuration: parseInt(
  1976. PlayDuration > 0 ? PlayDuration : self.studyDuration
  1977. ),
  1978. gradeId: parseInt(self.gradeId),
  1979. chapterId: this.chapterId || 0,
  1980. moduleId: this.moduleId || 0,
  1981. videoCurrentTime: parseInt(
  1982. currentTime > 0 ? currentTime : self.studyDuration
  1983. ),
  1984. erJianErZao: this.erJianErZao,
  1985. };
  1986. if (this.ossAvatarUrl) {
  1987. data.similarity = this.compareFaceData; // 相似度
  1988. }
  1989. if (status > 0) {
  1990. data.status = status;
  1991. }
  1992. console.log(data, "记录参数");
  1993. return new Promise((resolve, reject) => {
  1994. this.$api
  1995. .studyRecord(data)
  1996. .then((res) => {
  1997. console.log(res, "记录返回");
  1998. let { code, msg } = res.data;
  1999. if (code == 200) {
  2000. if (status > 0) {
  2001. this.studyRecordMenuAllList();
  2002. let moduleId = this.moduleId || 0;
  2003. let chapterId = this.chapterId || 0;
  2004. let playNextIdisRebuild = `moduleId${moduleId}chapterId${chapterId}sectionId${sectionId}isRebuild`;
  2005. let playNextId = `moduleId${moduleId}chapterId${chapterId}sectionId${sectionId}`; //拼接对应章节唯一id
  2006. uni.$emit("playNext" + playNextIdisRebuild, {
  2007. fromRebuild: this.isRebuild,
  2008. }); //通知播放结束,不来自重修目录的点击不用弹窗学习下一节
  2009. uni.$emit("playNext" + playNextId); //通知播放结束
  2010. }
  2011. self.ossAvatarUrl = "";
  2012. } else if (code == 600) {
  2013. uni.showModal({
  2014. showCancel: false,
  2015. title: "提示",
  2016. content: msg,
  2017. success: (resultst) => {
  2018. uni.navigateBack();
  2019. },
  2020. });
  2021. } else if (code == 558) {
  2022. this.CountTo1 = msg.split(",")[1];
  2023. this.noticeShow1 = true;
  2024. var timer = setInterval(() => {
  2025. this.CountTo1--;
  2026. if (this.CountTo1 < 0) {
  2027. this.noticeShow1 = false;
  2028. clearInterval(timer);
  2029. this.postStudyRecord(1);
  2030. }
  2031. }, 1000);
  2032. reject("中断执行");
  2033. } else {
  2034. this.uploadLock = false;
  2035. uni.showToast({
  2036. icon: "none",
  2037. title: res.data.msg,
  2038. duration: 2000,
  2039. });
  2040. if (this.erJianErZao && code == 559) {
  2041. this.isReach = true;
  2042. this.openPhoto();
  2043. }
  2044. if (code == 559 || code == 588) {
  2045. reject("中断执行");
  2046. }
  2047. }
  2048. resolve();
  2049. })
  2050. .catch((err) => {
  2051. this.studyRecordMenuAllList();
  2052. });
  2053. });
  2054. },
  2055. uploadFile(options, int) {
  2056. var self = this;
  2057. return new Promise((resolve, reject) => {
  2058. var data = {
  2059. imageStatus: int,
  2060. gradeId: this.gradeId,
  2061. orderGoodsId: this.orderGoodsId,
  2062. };
  2063. self.$api.aliyunpolicy(data).then((res) => {
  2064. if (res.data.code != 200) {
  2065. self.$method.showToast("签名错误" + JSON.stringify(res.data));
  2066. return;
  2067. }
  2068. var ossToken = res.data.data.resultContent;
  2069. if (ossToken.host == null || ossToken.host == undefined) {
  2070. self.$method.showToast("上传路径报错" + JSON.stringify(res.data));
  2071. return;
  2072. }
  2073. let filePath = "";
  2074. // #ifdef H5
  2075. var localData = options; //dataUrl为base64位
  2076. let base = atob(localData.substring(localData.indexOf(",") + 1)); // base是将base64编码解码,去掉data:image/png;base64部分
  2077. let length = base.length;
  2078. let url = new Uint8Array(length);
  2079. while (length--) {
  2080. url[length] = base.charCodeAt(length);
  2081. }
  2082. filePath = new File([url], "a.jpg", {
  2083. type: "image/jpg",
  2084. });
  2085. uni.uploadFile({
  2086. url: ossToken.host,
  2087. name: "file",
  2088. file: filePath,
  2089. fileType: "image",
  2090. header: {
  2091. AuthorizationToken: "WX " + uni.getStorageSync("token"),
  2092. },
  2093. formData: {
  2094. key: ossToken.dir,
  2095. OSSAccessKeyId: ossToken.accessid,
  2096. policy: ossToken.policy,
  2097. Signature: ossToken.signature,
  2098. callback: ossToken.callback,
  2099. success_action_status: 200,
  2100. },
  2101. success: (result) => {
  2102. this.$u.toast("上传成功");
  2103. self.ossAvatarUrl = ossToken.dir;
  2104. resolve(ossToken.dir);
  2105. },
  2106. fail: (error) => {
  2107. uni.showToast({
  2108. title: "上传接口报错,请重新拍照上传" + error,
  2109. icon: "none",
  2110. });
  2111. this.openPhoto();
  2112. return;
  2113. },
  2114. });
  2115. // #endif
  2116. // #ifdef MP-WEIXIN
  2117. uni.uploadFile({
  2118. url: ossToken.host,
  2119. name: "file",
  2120. filePath: options,
  2121. fileType: "image",
  2122. header: {
  2123. AuthorizationToken: "WX " + uni.getStorageSync("token"),
  2124. },
  2125. formData: {
  2126. key: ossToken.dir,
  2127. OSSAccessKeyId: ossToken.accessid,
  2128. policy: ossToken.policy,
  2129. Signature: ossToken.signature,
  2130. callback: ossToken.callback,
  2131. success_action_status: 200,
  2132. },
  2133. success: (result) => {
  2134. // if (result.statusCode === 200) {
  2135. this.$u.toast("上传成功");
  2136. self.ossAvatarUrl = ossToken.dir;
  2137. resolve(ossToken.dir);
  2138. },
  2139. fail: (error) => {
  2140. uni.showToast({
  2141. title: "上传接口报错,请重新拍照上传" + error,
  2142. icon: "none",
  2143. });
  2144. this.openPhoto();
  2145. return;
  2146. },
  2147. });
  2148. // #endif
  2149. });
  2150. });
  2151. },
  2152. imageInfos() {
  2153. var self = this;
  2154. return new Promise(async (resolve, reject) => {
  2155. let resPath = await myCompressImage(this.avatarUrl || this.faceUrl, 50);
  2156. const waitUpload = await self.uploadFile(resPath, 0);
  2157. resolve(waitUpload);
  2158. });
  2159. },
  2160. timeEvent(playTime) {
  2161. this.configPhoto();
  2162. console.info(this.photoList, "photoList");
  2163. let photoTime = 0; //获取拍照秒数
  2164. for (let i = 0; i < this.photoList.length; i++) {
  2165. photoTime = Number(this.photoList[i]); //获取拍照秒数
  2166. if (
  2167. (this.erJianErZao && !this.photoHistoryList.length) ||
  2168. (photoTime < playTime && photoTime > playTime - 8)
  2169. ) {
  2170. //3秒区间内才触发拍照,避免拉动滚动条
  2171. if (this.photoHistoryList.indexOf(i) < 0) {
  2172. //不存在拍照历史,没有重修过,没有学过,则拍照
  2173. //启动拍照
  2174. //暂停
  2175. console.log("去拍照");
  2176. this.refPlv.playPause();
  2177. this.refPlv.exitFullScreen();
  2178. this.photoIndex = i;
  2179. if (
  2180. uni.getStorageSync(`tabkePhotoShow${this.goodsId}`) ==
  2181. this.goodsId
  2182. ) {
  2183. return this.openPhoto();
  2184. } else {
  2185. this.popupPhotoShow = true;
  2186. uni.setStorageSync(`tabkePhotoShow${this.goodsId}`, this.goodsId); // 本地缓存用来判断是否已经弹出过弹窗
  2187. }
  2188. }
  2189. }
  2190. }
  2191. },
  2192. closeToast() {
  2193. clearTimeout(this.toastTimer);
  2194. this.videoToastShow = false;
  2195. },
  2196. // 新增用户视频学习日志
  2197. studyLog() {
  2198. this.$http({
  2199. url: "/user/study/log",
  2200. method: "post",
  2201. data: {
  2202. goodsId: this.goodsId,
  2203. courseId: this.courseId,
  2204. moduleId: this.moduleId || 0,
  2205. chapterId: this.chapterId || 0,
  2206. sectionId: this.playSectionId || 0,
  2207. fromPlat: 1, //来源平台 1小程序 2PC网站
  2208. goodsType: 1, // 商品类型 1视频2题库 3补考 4前培 5虚拟赠送题库 6直播
  2209. orderGoodsId: this.orderGoodsId,
  2210. },
  2211. }).then((res) => {});
  2212. },
  2213. timeupdate(time) {
  2214. // console.log("播放中", time);
  2215. this.clearPauseTimer();
  2216. if (this.playSecIsLearn && (this.erJianErZao || this.photoNum > 0)) {
  2217. this.isReach = false;
  2218. this.timeEvent();
  2219. }
  2220. },
  2221. playing() {
  2222. console.log("playing");
  2223. if (this.noticeShow) {
  2224. this.refPlv.playPause();
  2225. return;
  2226. }
  2227. this.studyLog();
  2228. if (!this.recordObj.videoCurrentTime) {
  2229. this.postStudyRecord(0);
  2230. }
  2231. this.studyTimer && clearInterval(this.studyTimer);
  2232. this.studyTimer = setInterval(() => {
  2233. this.postStudyRecord(0);
  2234. }, 15000);
  2235. },
  2236. pause() {
  2237. this.erJianErZaoPauseTip();
  2238. clearInterval(this.timer);
  2239. clearInterval(this.studyTimer);
  2240. },
  2241. async ended() {
  2242. this.hasStart = false;
  2243. uni.showToast({
  2244. icon: "none",
  2245. title: "播放完毕",
  2246. });
  2247. clearInterval(this.timer);
  2248. clearInterval(this.studyTimer);
  2249. await this.postStudyRecord(1);
  2250. this.nextSection();
  2251. },
  2252. playerError() {},
  2253. //播放下一节
  2254. nextSection() {
  2255. console.log("播放下一节");
  2256. if (!this.menuAllList.length) {
  2257. return;
  2258. }
  2259. this.curPlayIndex = this.menuAllList.findIndex((item) => {
  2260. let i_sectionId = item.sectionId || 0;
  2261. let i_chapterId = item.chapterId || 0;
  2262. let i_moduleId = item.moduleId || 0;
  2263. return (
  2264. i_sectionId == this.playSectionId &&
  2265. i_chapterId == this.chapterId &&
  2266. i_moduleId == this.moduleId
  2267. );
  2268. });
  2269. let data = this.menuAllList[this.curPlayIndex + 1];
  2270. if (!data) {
  2271. //第二个弹窗
  2272. uni.showModal({
  2273. title: "温馨提示",
  2274. content:
  2275. "恭喜您课程学习全部完成,教务会在1-3个工作日内完成学习初审,请耐心等待。",
  2276. showCancel: !this.erJianErZao,
  2277. success: (res) => {
  2278. if (res.confirm) {
  2279. uni.switchTab({
  2280. url: "/pages/learn/index",
  2281. });
  2282. }
  2283. },
  2284. });
  2285. } else {
  2286. if (data.doType == 2) {
  2287. if (data.studyStatus == 1) {
  2288. uni.showToast({
  2289. title: "试卷已合格!",
  2290. duration: 2000,
  2291. icon: "none",
  2292. });
  2293. return;
  2294. }
  2295. uni.showModal({
  2296. title: "温馨提示",
  2297. content: "当前节视频已学完,是否进入考试?",
  2298. success: (res) => {
  2299. if (res.confirm) {
  2300. this.toQuestionBank(data);
  2301. }
  2302. },
  2303. });
  2304. return;
  2305. }
  2306. uni.showModal({
  2307. title: "温馨提示",
  2308. content: "当前节视频已学完,继续学习下一节?",
  2309. success: async (res) => {
  2310. if (res.confirm) {
  2311. this.moduleId = data.moduleId;
  2312. this.chapterId = data.chapterId;
  2313. this.sectionId = data.sectionId;
  2314. if (data.sectionType == 1) {
  2315. //录播
  2316. this.$store.commit("setPlaySectionId", {
  2317. playSectionId: data.sectionId,
  2318. });
  2319. this.$store.commit("setPlayVID", {
  2320. playVID: data.recordingUrl,
  2321. });
  2322. this.hasStart = false;
  2323. this.photoConfig = false;
  2324. this.photoIndex = 0;
  2325. this.sectionItem = data;
  2326. await this.getPhotoLastRecord(); // 获取拍照历史
  2327. this.playVideo(data);
  2328. } else if (data.sectionType == 2) {
  2329. //直播
  2330. this.studyRecordGetLastLive();
  2331. } else if (data.sectionType == 3) {
  2332. //回放
  2333. this.$store.commit("setPlaySectionId", {
  2334. playSectionId: data.sectionId,
  2335. });
  2336. this.$store.commit("setPlayVID", {
  2337. playVID: data.recordingUrl,
  2338. });
  2339. this.sectionItem = data;
  2340. this.playVideo(data);
  2341. }
  2342. let playNextId = `moduleId${data.moduleId}chapterId${data.chapterId}sectionId${data.sectionId}`;
  2343. this.$store.commit("updatePlayNextId", playNextId);
  2344. this.updateChapterOpen(true);
  2345. this.reStart = false;
  2346. this.getMenuList();
  2347. }
  2348. },
  2349. });
  2350. }
  2351. },
  2352. //拍照
  2353. openPhoto() {
  2354. if (polyvPlayerContext) {
  2355. // #ifdef MP-WEIXIN
  2356. polyvPlayerContext.exitFullScreen();
  2357. // #endif
  2358. // #ifdef H5
  2359. if (this.isFullScreen()) {
  2360. this.exitFullscreen();
  2361. }
  2362. // #endif
  2363. }
  2364. // #ifdef MP-WEIXIN
  2365. this.enableAutoRotation = false;
  2366. this.photoPopup = true;
  2367. this.isTaking = true;
  2368. uni.setKeepScreenOn({
  2369. keepScreenOn: true,
  2370. });
  2371. uni.authorize({
  2372. scope: "scope.camera",
  2373. success() {},
  2374. });
  2375. // #endif
  2376. // #ifdef H5
  2377. if (
  2378. (window.navigator.mediaDevices &&
  2379. window.navigator.mediaDevices.getUserMedia) ||
  2380. window.navigator.getUserMedia ||
  2381. window.navigator.webkitGetUserMedia ||
  2382. window.navigator.mozGetUserMedia
  2383. ) {
  2384. console.log("getUserMedia----");
  2385. // 调用用户媒体设备, 访问摄像头
  2386. this.getUserMedia(
  2387. {
  2388. video: {
  2389. width: 400,
  2390. height: 300,
  2391. facingMode: "user",
  2392. },
  2393. },
  2394. this.photographSuccess,
  2395. this.photographError
  2396. );
  2397. } else {
  2398. console.log("1111没有摄像");
  2399. this.photographError();
  2400. }
  2401. // #endif
  2402. },
  2403. /**
  2404. * 人脸匹配
  2405. */
  2406. faceRecognition() {
  2407. return new Promise((resolve) => {
  2408. // #ifdef MP-WEIXIN
  2409. let fileSystem = uni.getFileSystemManager();
  2410. fileSystem.readFile({
  2411. filePath: `${this.avatarUrl}`,
  2412. encoding: "base64",
  2413. position: 0,
  2414. success: (res) => {
  2415. let base64 = "data:image/jpg;base64," + res.data;
  2416. // console.log('base64Data人脸识别参数:', {
  2417. // imageA: base64,
  2418. // orderGoodsId: this.orderGoodsId,
  2419. // gradeId: this.gradeId,
  2420. // })
  2421. this.CompareFace(base64, resolve);
  2422. },
  2423. fail(err) {
  2424. // this.$u.toast('人脸识别错误!')
  2425. console.error(err, "err-----人脸识别错误");
  2426. },
  2427. });
  2428. // #endif
  2429. // #ifdef H5
  2430. this.CompareFace(this.faceUrl, resolve);
  2431. // #endif
  2432. });
  2433. },
  2434. CompareFace(url, resolve) {
  2435. let timer = setTimeout(() => {
  2436. uni.showToast({
  2437. icon: "none",
  2438. title: "拍照超时,请重新拍照",
  2439. duration: 2000,
  2440. success: () => {
  2441. setTimeout(() => {
  2442. uni.navigateBack();
  2443. }, 1000);
  2444. },
  2445. });
  2446. }, 10 * 1000);
  2447. this.$api
  2448. .faceCertificationCompareFace({
  2449. imageA: url,
  2450. orderGoodsId: this.orderGoodsId,
  2451. gradeId: this.gradeId,
  2452. })
  2453. .then((res) => {
  2454. clearTimeout(timer);
  2455. console.log(res, "人脸识别成功res");
  2456. resolve(res.data.data);
  2457. })
  2458. .catch((err) => {
  2459. clearTimeout(timer);
  2460. // 当前网络延迟,
  2461. console.log("人脸识别错误:", err);
  2462. uni.showModal({
  2463. content: "当前网络延迟",
  2464. showCancel: false,
  2465. success: (resultst) => {
  2466. if (resultst.confirm) {
  2467. uni.navigateBack();
  2468. }
  2469. },
  2470. });
  2471. });
  2472. },
  2473. // 确定拍照
  2474. async submit() {
  2475. if (this.uploadLock) {
  2476. return;
  2477. }
  2478. this.uploadLock = true;
  2479. let compareFaceData = await this.faceRecognition();
  2480. this.compareFaceData = compareFaceData;
  2481. if (compareFaceData >= 80) {
  2482. await this.imageInfos();
  2483. this.postCoursePhotoRecord()
  2484. .then(async (res) => {
  2485. this.photoHistoryList.push(this.photoIndex);
  2486. // console.log('拍照确定提交', this.photoHistoryList);
  2487. this.postStudyRecord(); //提交记录
  2488. if (this.erJianErZao && this.isReach) {
  2489. console.log("1校验");
  2490. await this.postStudyRecord(1);
  2491. this.photoPopup = false;
  2492. this.uploadLock = false;
  2493. this.enableAutoRotation = true;
  2494. this.nextSection();
  2495. return;
  2496. }
  2497. //恢复播放
  2498. // #ifdef MP-WEIXIN
  2499. uni.setKeepScreenOn({
  2500. keepScreenOn: false,
  2501. });
  2502. // #endif
  2503. this.photoPopup = false;
  2504. this.uploadLock = false;
  2505. this.enableAutoRotation = true;
  2506. this.refPlv.resumeVideo();
  2507. })
  2508. .catch((err) => {
  2509. console.log("拍照记录接口的err", err);
  2510. uni.showToast({
  2511. title: "上传接口报错,请重新拍照上传" + err,
  2512. icon: "none",
  2513. });
  2514. this.uploadLock = false;
  2515. this.openPhoto();
  2516. });
  2517. } else {
  2518. uni.showToast({
  2519. title: "人脸匹配不通过,请重新拍照上传",
  2520. icon: "none",
  2521. duration: 2000,
  2522. });
  2523. setTimeout(() => {
  2524. this.uploadLock = false;
  2525. this.openPhoto();
  2526. }, 2000);
  2527. }
  2528. },
  2529. reTake() {
  2530. this.isTaking = true;
  2531. // #ifdef H5
  2532. this.faceUrl = "";
  2533. this.getUserMedia(
  2534. {
  2535. video: {
  2536. width: 400,
  2537. height: 300,
  2538. facingMode: "user",
  2539. },
  2540. },
  2541. this.photographSuccess,
  2542. this.photographError
  2543. );
  2544. // #endif
  2545. },
  2546. toTakePhoto() {
  2547. this.popupPhotoShow = false;
  2548. this.openPhoto();
  2549. },
  2550. takePhTips() {
  2551. this.popupPhotoShow = true;
  2552. this.isTaking = false;
  2553. this.photoPopup = false;
  2554. this.enableAutoRotation = false;
  2555. },
  2556. //确认拍照
  2557. takePhoto() {
  2558. // #ifdef MP-WEIXIN
  2559. const ctx = uni.createCameraContext();
  2560. ctx.takePhoto({
  2561. quality: "high",
  2562. success: (res) => {
  2563. this.avatarUrl = res.tempImagePath;
  2564. console.log("开始拍照this.avatarUrl:", this.avatarUrl);
  2565. this.isTaking = false;
  2566. },
  2567. fail: (err) => {},
  2568. });
  2569. // #endif
  2570. // #ifdef H5
  2571. const canvas = document.createElement("canvas");
  2572. canvas.width = 400;
  2573. canvas.height = 400;
  2574. const context = canvas.getContext("2d");
  2575. const box = document.querySelector(".photo_v");
  2576. const video = box.querySelector("video");
  2577. context.drawImage(video, 0, 0, 400, 400);
  2578. this.faceUrl = canvas.toDataURL("image/png");
  2579. this.isTaking = false;
  2580. // #endif
  2581. },
  2582. playError(e) {
  2583. console.log(e);
  2584. },
  2585. //拍照报错
  2586. error(e) {
  2587. console.log(e.detail);
  2588. },
  2589. //关闭相机
  2590. closePhoto() {
  2591. this.photoPopup = false;
  2592. this.enableAutoRotation = true;
  2593. },
  2594. checkFinishRequiredCourse() {
  2595. return this.$api
  2596. .checkFinishRequiredCourse({
  2597. businessId: this.goodsData.businessId,
  2598. goodsId: this.goodsId,
  2599. })
  2600. .then((res) => {
  2601. if (res.data.data > 0) {
  2602. uni.showModal({
  2603. showCancel: false,
  2604. confirmText: "确定",
  2605. content: "该业务层次下有未学完的商品,无法学习新商品!",
  2606. success: function (resultst) {
  2607. uni.navigateBack();
  2608. },
  2609. });
  2610. return Promise.reject();
  2611. }
  2612. return Promise.resolve();
  2613. });
  2614. },
  2615. getGoodsDetail() {
  2616. let self = this;
  2617. this.$api.goodsDetail(this.goodsId).then(async (res) => {
  2618. this.goodsData = res.data.data;
  2619. this.option.periodWaitTime && (await this.checkFinishRequiredCourse());
  2620. this.goodsData.buyNote && this.baseHandoutTipList();
  2621. this.gradeId = this.goodsData.gradeId;
  2622. this.erJianErZao = this.goodsData.erJianErZao;
  2623. this.getMenuList();
  2624. this.getReMenuList(); //获取重修目录
  2625. if (self.goodsData.goodsPlayConfig) {
  2626. self.goodsPlayConfig = JSON.parse(self.goodsData.goodsPlayConfig);
  2627. if (self.goodsPlayConfig.autoPlay > 0) {
  2628. self.autoplay = true;
  2629. }
  2630. if (self.goodsPlayConfig.drag > 0 && !self.erJianErZao) {
  2631. // #ifdef MP-WEIXIN
  2632. self.isAllowSeek = "yes";
  2633. // #endif
  2634. // #ifdef H5
  2635. self.isAllowSeek = "off";
  2636. // #endif
  2637. }
  2638. if (self.goodsPlayConfig.speed > 0) {
  2639. self.playbackRate = [0.5, 0.8, 1.0, 1.25, 1.5, 2.0];
  2640. }
  2641. }
  2642. if (self.goodsData.goodsPhotographConfig) {
  2643. self.goodsPhotographConfig = JSON.parse(
  2644. self.goodsData.goodsPhotographConfig
  2645. );
  2646. if (self.goodsPhotographConfig.photoNum > 0) {
  2647. self.photoNum = self.goodsPhotographConfig.photoNum;
  2648. }
  2649. }
  2650. });
  2651. },
  2652. getReMenuList() {
  2653. let self = this;
  2654. this.$api
  2655. .reMenuList({
  2656. orderGoodsId: this.orderGoodsId,
  2657. courseId: this.courseId,
  2658. rebuild: 1,
  2659. gradeId: this.gradeId,
  2660. })
  2661. .then((res) => {
  2662. if (res.data.code == 200) {
  2663. for (let i = 0; i < res.data.rows.length; i++) {
  2664. let item = res.data.rows[i];
  2665. item.down = true;
  2666. item.id = item.menuId;
  2667. item.name = item.menuName;
  2668. }
  2669. self.reMenuList = res.data.rows;
  2670. this.current = 0;
  2671. if (self.reMenuList.length > 0) {
  2672. this.showNotes = false;
  2673. if (Object.keys(this.sectionItem).length) {
  2674. let playNextIdisRebuild = `moduleId${this.sectionItem.moduleId}chapterId${this.sectionItem.chapterId}sectionId${this.sectionItem.sectionId}isRebuild`;
  2675. this.$store.commit("updatePlayNextId", playNextIdisRebuild);
  2676. }
  2677. } else {
  2678. if (Object.keys(this.sectionItem).length) {
  2679. let playNextId = `moduleId${this.sectionItem.moduleId}chapterId${this.sectionItem.chapterId}sectionId${this.sectionItem.sectionId}`;
  2680. this.$store.commit("updatePlayNextId", playNextId);
  2681. }
  2682. }
  2683. }
  2684. });
  2685. },
  2686. getMenuList() {
  2687. let self = this;
  2688. this.$api
  2689. .reMenuList({
  2690. courseId: this.courseId,
  2691. gradeId: this.gradeId,
  2692. orderGoodsId: this.orderGoodsId,
  2693. })
  2694. .then((res) => {
  2695. if (res.data.code == 200) {
  2696. for (let i = 0; i < res.data.rows.length; i++) {
  2697. let item = res.data.rows[i];
  2698. item.down = true;
  2699. item.id = item.menuId;
  2700. item.name = item.menuName;
  2701. item.menuType = item.type;
  2702. }
  2703. this.menuList = res.data.rows;
  2704. this.reStart = true;
  2705. }
  2706. });
  2707. },
  2708. courseDetail() {
  2709. this.$api.courseDetail(this.courseId).then((res) => {
  2710. if (res.data.code == 200) {
  2711. this.detail = res.data.data;
  2712. }
  2713. });
  2714. },
  2715. open(item) {
  2716. item.showChildren = !item.showChildren;
  2717. },
  2718. change(index) {
  2719. this.current = index;
  2720. },
  2721. clears() {
  2722. return new Promise((resolve, reject) => {
  2723. this.vid = "";
  2724. polyvPlayerContext && polyvPlayerContext.destroy();
  2725. polyvPlayerContext = null;
  2726. resolve();
  2727. });
  2728. },
  2729. /**
  2730. * 退出全屏
  2731. */
  2732. exitFullscreen() {
  2733. try {
  2734. var de = document;
  2735. if (de.exitFullscreen) {
  2736. de.exitFullscreen();
  2737. } else if (de.mozCancelFullScreen) {
  2738. de.mozCancelFullScreen();
  2739. } else if (de.webkitCancelFullScreen) {
  2740. de.webkitCancelFullScreen();
  2741. }
  2742. } catch (err) {}
  2743. },
  2744. fullele() {
  2745. return (
  2746. document.fullscreenElement ||
  2747. document.webkitFullscreenElement ||
  2748. document.msFullscreenElement ||
  2749. document.mozFullScreenElement ||
  2750. null
  2751. );
  2752. },
  2753. //判断是否全屏
  2754. isFullScreen() {
  2755. return !!(document.webkitIsFullScreen || this.fullele());
  2756. },
  2757. getUserMedia(constraints, success, error) {
  2758. console.log("getUserMedia===", constraints, "success:", success);
  2759. if (window.navigator.mediaDevices.getUserMedia) {
  2760. // 最新的标准API
  2761. window.navigator.mediaDevices
  2762. .getUserMedia(constraints)
  2763. .then(success)
  2764. .catch(error);
  2765. } else if (window.navigator.webkitGetUserMedia) {
  2766. // webkit核心浏览器
  2767. window.navigator.webkitGetUserMedia(constraints, success, error);
  2768. } else if (window.navigator.mozGetUserMedia) {
  2769. // firfox浏览器
  2770. window.navigator.mozGetUserMedia(constraints, success, error);
  2771. } else if (window.navigator.getUserMedia) {
  2772. // 旧版API
  2773. window.navigator.getUserMedia(constraints, success, error);
  2774. }
  2775. },
  2776. photographSuccess(stream) {
  2777. console.log("有摄像头---", stream);
  2778. this.photoPopup = true;
  2779. this.isTaking = true;
  2780. this.enableAutoRotation = false;
  2781. this.$nextTick(() => {
  2782. const box = document.querySelector(".photo_v");
  2783. const video = box.querySelector("video");
  2784. video.srcObject = stream;
  2785. video.play();
  2786. });
  2787. },
  2788. photographError(err) {
  2789. console.log("没有摄像头:", err);
  2790. uni.showModal({
  2791. title: "提示",
  2792. content:
  2793. "课程学习需要开启摄像头进行拍照,经检测您的设备无摄像头可使用,请检测环境是否支持。",
  2794. cancelText: "取消",
  2795. confirmText: "确定",
  2796. success: (res) => {
  2797. if (res.confirm) {
  2798. uni.navigateBack();
  2799. } else if (res.cancel) {
  2800. }
  2801. },
  2802. });
  2803. },
  2804. },
  2805. };
  2806. </script>
  2807. <style lang="scss" scope>
  2808. @import "./css/detail.scss";
  2809. .top {
  2810. &__header {
  2811. position: relative;
  2812. width: 100%;
  2813. height: 150rpx;
  2814. padding: 24rpx 150rpx 24rpx 24rpx;
  2815. .img {
  2816. position: absolute;
  2817. left: 0;
  2818. top: 0;
  2819. width: 100%;
  2820. }
  2821. .note {
  2822. position: relative;
  2823. z-index: 10;
  2824. font-size: 24rpx;
  2825. font-family: PingFang SC;
  2826. font-weight: bold;
  2827. color: #efdbff;
  2828. }
  2829. .title {
  2830. position: relative;
  2831. z-index: 10;
  2832. font-size: 26rpx;
  2833. font-family: PingFang SC;
  2834. font-weight: bold;
  2835. color: #ffffff;
  2836. }
  2837. }
  2838. }
  2839. #top {
  2840. position: relative;
  2841. z-index: 99;
  2842. }
  2843. .polyv_detail {
  2844. display: flex;
  2845. flex-direction: column;
  2846. height: 100vh;
  2847. position: relative;
  2848. top: 0;
  2849. left: 0;
  2850. .pops {
  2851. position: absolute;
  2852. top: 0;
  2853. left: 0;
  2854. background: #ccc;
  2855. opacity: 0.5;
  2856. width: 100%;
  2857. height: 300rpx;
  2858. z-index: 9999;
  2859. }
  2860. .box {
  2861. flex: 1;
  2862. overflow: hidden;
  2863. margin: 16rpx 16rpx 100rpx 16rpx;
  2864. .box_in {
  2865. height: 100%;
  2866. }
  2867. }
  2868. .first_ml {
  2869. margin: 16rpx 16rpx 16rpx 16rpx;
  2870. }
  2871. }
  2872. .btnSet {
  2873. width: 440rpx;
  2874. height: 80rpx;
  2875. background: #007aff;
  2876. border-radius: 40rpx;
  2877. color: #ffffff;
  2878. font-size: 28rpx;
  2879. line-height: 80rpx;
  2880. }
  2881. .lecture-content {
  2882. background: #fff;
  2883. margin-top: 10rpx;
  2884. padding: 10rpx;
  2885. border-radius: 16rpx;
  2886. }
  2887. .photoBox {
  2888. width: 100%;
  2889. // background-color: #ffffff;
  2890. // border-radius: 24px 24px 0px 0px;
  2891. .photoTop {
  2892. width: 100%;
  2893. height: 74rpx;
  2894. border-radius: 20px 20px 0px 0px;
  2895. background-color: #ffffff;
  2896. display: flex;
  2897. align-items: center;
  2898. justify-content: center;
  2899. padding: 0rpx 38rpx;
  2900. .sqzz {
  2901. width: 28rpx;
  2902. height: 28rpx;
  2903. display: flex;
  2904. align-items: center;
  2905. justify-content: center;
  2906. }
  2907. .centersq {
  2908. color: #333;
  2909. font-size: 30rpx;
  2910. font-weight: 500;
  2911. }
  2912. }
  2913. .photoCenter {
  2914. width: 750rpx;
  2915. height: 75vh;
  2916. position: relative;
  2917. .center_camera {
  2918. width: 100%;
  2919. height: 75vh;
  2920. position: fixed;
  2921. .head_take {
  2922. width: 100%;
  2923. height: 75vh;
  2924. display: flex;
  2925. flex-direction: column;
  2926. }
  2927. .headTake_up {
  2928. width: 100%;
  2929. height: 100rpx;
  2930. }
  2931. .headTake_minddle {
  2932. display: flex;
  2933. .min_img {
  2934. width: 500rpx;
  2935. height: 550rpx;
  2936. }
  2937. .min_left,
  2938. .min_right {
  2939. flex: 1;
  2940. height: 550rpx;
  2941. }
  2942. }
  2943. .headTake_down {
  2944. width: 100%;
  2945. flex: 1;
  2946. }
  2947. .color {
  2948. background-color: #333;
  2949. opacity: 0.5;
  2950. }
  2951. .photo_v {
  2952. width: 100%;
  2953. height: 100%;
  2954. }
  2955. .mask {
  2956. width: 500rpx;
  2957. height: 550rpx;
  2958. position: absolute;
  2959. top: 100rpx;
  2960. left: 0;
  2961. right: 0;
  2962. bottom: 0;
  2963. margin: 0 auto;
  2964. box-shadow: 0 0 0 2000px rgba(0, 0, 0, 0.4);
  2965. }
  2966. }
  2967. .custom {
  2968. width: 750rpx;
  2969. height: 75vh;
  2970. position: absolute;
  2971. z-index: 1000;
  2972. top: 0;
  2973. left: 0;
  2974. image {
  2975. width: 100%;
  2976. height: 100%;
  2977. }
  2978. }
  2979. }
  2980. .btns {
  2981. display: flex;
  2982. .takePhoto_btn {
  2983. width: 100%;
  2984. display: flex;
  2985. align-items: center;
  2986. justify-content: space-between;
  2987. background: #a9a7a9;
  2988. padding: 40rpx 26rpx;
  2989. .middle_btn {
  2990. width: 120rpx;
  2991. height: 120rpx;
  2992. border-radius: 40rpx;
  2993. border: 4rpx solid #ffffff;
  2994. display: flex;
  2995. align-items: center;
  2996. justify-content: center;
  2997. }
  2998. .square {
  2999. width: 96rpx;
  3000. height: 96rpx;
  3001. background: #ffffff;
  3002. border-radius: 28rpx;
  3003. }
  3004. .rights {
  3005. font-size: 32rpx;
  3006. font-weight: 500;
  3007. color: #ffffff;
  3008. }
  3009. }
  3010. .btnResult {
  3011. height: 100rpx;
  3012. flex: 1;
  3013. background-color: #07c160;
  3014. text-align: center;
  3015. line-height: 100rpx;
  3016. color: #fff;
  3017. font-size: 32rpx;
  3018. font-weight: bold;
  3019. }
  3020. }
  3021. }
  3022. .tBox {
  3023. display: flex;
  3024. align-items: center;
  3025. padding-top: 10rpx;
  3026. }
  3027. .title {
  3028. font-size: 24rpx;
  3029. color: #999999;
  3030. }
  3031. .t_content1 {
  3032. color: #007aff;
  3033. margin-left: 10rpx;
  3034. }
  3035. .tag1 {
  3036. border: 2rpx solid #007aff;
  3037. border-radius: 8rpx;
  3038. font-size: 20rpx;
  3039. color: #007aff;
  3040. padding: 5rpx;
  3041. }
  3042. .b_title {
  3043. color: #333333;
  3044. font-size: 30rpx;
  3045. font-weight: bold;
  3046. }
  3047. page {
  3048. background: #eaeef1;
  3049. }
  3050. .menuBox {
  3051. width: 100%;
  3052. background: #ffffff;
  3053. border-radius: 16rpx;
  3054. padding: 0rpx 20rpx;
  3055. margin-bottom: 20rpx;
  3056. }
  3057. .btnspric {
  3058. border-top: 1rpx solid #eee;
  3059. display: flex;
  3060. align-items: center;
  3061. justify-content: space-between;
  3062. height: 108rpx;
  3063. padding-left: 43rpx;
  3064. padding-right: 32rpx;
  3065. }
  3066. .btnspric > .lefprL {
  3067. font-size: 36rpx;
  3068. color: #0c141f;
  3069. font-weight: bold;
  3070. }
  3071. .btnspric > .lefprR {
  3072. padding: 0rpx 24rpx;
  3073. height: 60rpx;
  3074. line-height: 60rpx;
  3075. text-align: center;
  3076. color: #fff;
  3077. background: #32467b;
  3078. border-radius: 24rpx;
  3079. box-shadow: 0rpx 0rpx 16rpx 4rpx rgba(145, 156, 178, 0.1);
  3080. }
  3081. .yhj,
  3082. .hdyhj {
  3083. padding: 24rpx 29rpx 24rpx 34rpx;
  3084. }
  3085. .yhj {
  3086. border-bottom: 16rpx solid #f9f9f9;
  3087. }
  3088. .yhjtit {
  3089. font-size: 30rpx;
  3090. color: #0c141f;
  3091. font-weight: 500;
  3092. margin-bottom: 14rpx;
  3093. }
  3094. .yhjList {
  3095. display: flex;
  3096. align-items: center;
  3097. justify-content: space-between;
  3098. margin-bottom: 14rpx;
  3099. }
  3100. .yhjList > .yhjLefts {
  3101. display: flex;
  3102. align-items: center;
  3103. }
  3104. .yhjLefts > .yhl {
  3105. color: #32467b;
  3106. font-size: 30rpx;
  3107. margin-right: 31rpx;
  3108. }
  3109. .yhjLefts > .yhbq {
  3110. font-size: 24rpx;
  3111. color: #ff9500;
  3112. border-radius: 18rpx;
  3113. background-color: rgba(255, 149, 0, 0.2);
  3114. border: 2rpx solid #ff9500;
  3115. height: 38rpx;
  3116. line-height: 38rpx;
  3117. padding: 0rpx 16rpx;
  3118. }
  3119. .ts {
  3120. font-size: 24rpx;
  3121. color: #999;
  3122. margin: 14rpx 0rpx;
  3123. padding-right: 29rpx;
  3124. padding-left: 34rpx;
  3125. }
  3126. .yh {
  3127. padding-top: 20rpx;
  3128. }
  3129. .yh > .yhtitle {
  3130. display: flex;
  3131. align-items: center;
  3132. justify-content: space-between;
  3133. padding-right: 29rpx;
  3134. padding-left: 34rpx;
  3135. }
  3136. .priceBxs {
  3137. display: flex;
  3138. align-items: center;
  3139. }
  3140. .priceBxs > .pricleft {
  3141. border-radius: 24rpx;
  3142. border: 1rpx solid #e91313;
  3143. background-color: rgba(233, 19, 19, 0.1);
  3144. padding: 0rpx 18rpx;
  3145. height: 49rpx;
  3146. line-height: 49rpx;
  3147. text-align: center;
  3148. font-size: 30rpx;
  3149. font-weight: 500;
  3150. color: #e91313;
  3151. margin-right: 13rpx;
  3152. }
  3153. .topBox {
  3154. padding: 32rpx 32rpx 24rpx;
  3155. border-bottom: 1rpx solid #eeeeee;
  3156. }
  3157. .topBox > .boldFonstType {
  3158. font-weight: 500;
  3159. font-size: 30rpx;
  3160. margin: 16rpx 0rpx 23rpx;
  3161. }
  3162. .topBox > .firstTopL {
  3163. display: flex;
  3164. align-items: center;
  3165. }
  3166. .topBox > .firstTopL > .imageBs {
  3167. width: 331rpx;
  3168. height: 160rpx;
  3169. border-radius: 6rpx;
  3170. overflow: hidden;
  3171. margin-right: 8rpx;
  3172. box-shadow: 0rpx 6rpx 6rpx 0rpx rgba(47, 67, 121, 0.08);
  3173. }
  3174. .topBox > .firstTopL > .imageBs > image {
  3175. width: 100%;
  3176. height: 100%;
  3177. }
  3178. .topBox > .firstTopL > .textBs {
  3179. font-size: 30rpx;
  3180. font-weight: bold;
  3181. color: #0c141f;
  3182. }
  3183. .content {
  3184. padding: 24rpx;
  3185. text-align: left;
  3186. }
  3187. .catalogBox {
  3188. display: flex;
  3189. align-items: center;
  3190. flex-wrap: nowrap;
  3191. overflow-x: auto;
  3192. padding-left: 38rpx;
  3193. max-height: 305rpx;
  3194. overflow-y: auto;
  3195. transition: all 0.4s;
  3196. }
  3197. .catalogBox > .catalogA {
  3198. min-width: 200rpx;
  3199. height: 48rpx;
  3200. line-height: 48rpx;
  3201. // text-align: center;
  3202. border: 2rpx solid transparent;
  3203. white-space: nowrap;
  3204. text-overflow: ellipsis;
  3205. overflow: hidden;
  3206. word-break: break-all;
  3207. border-radius: 10rpx;
  3208. background: rgba(22, 119, 255, 0.05);
  3209. padding-left: 19rpx;
  3210. box-sizing: border-box;
  3211. padding-right: 15rpx;
  3212. margin-right: 16rpx;
  3213. margin-bottom: 20rpx;
  3214. margin-top: 15rpx;
  3215. font-size: 24rpx;
  3216. color: #666;
  3217. }
  3218. .catalogBox > .activesq {
  3219. border-color: #1677ff;
  3220. }
  3221. .changeCatalogBox {
  3222. display: block;
  3223. }
  3224. .catalogBox::-webkit-scrollbar {
  3225. display: none; /* Chrome Safari */
  3226. }
  3227. .price_t2 {
  3228. font-size: 18rpx;
  3229. font-family: PingFang SC;
  3230. font-weight: 500;
  3231. text-decoration: line-through;
  3232. color: #999999;
  3233. }
  3234. .price_t1 {
  3235. font-size: 33rpx;
  3236. font-family: PingFang SC;
  3237. font-weight: bold;
  3238. color: #e91313;
  3239. }
  3240. .sc_t {
  3241. font-size: 22rpx;
  3242. color: #000000;
  3243. }
  3244. .sc {
  3245. width: 29rpx;
  3246. height: 29rpx;
  3247. }
  3248. .buy {
  3249. width: 138rpx;
  3250. height: 48rpx;
  3251. line-height: 48rpx;
  3252. background: #32467b;
  3253. border-radius: 10rpx;
  3254. color: #ffffff;
  3255. font-size: 28rpx;
  3256. text-align: center;
  3257. vertical-align: middle;
  3258. position: absolute;
  3259. right: 30rpx;
  3260. }
  3261. .video_body {
  3262. padding-bottom: 96rpx;
  3263. }
  3264. .footer_tab {
  3265. position: fixed;
  3266. bottom: 0;
  3267. height: 96rpx;
  3268. width: 100%;
  3269. background-color: #ffffff;
  3270. }
  3271. .tj_box {
  3272. width: 50%;
  3273. display: inline-block;
  3274. text-align: center;
  3275. margin: 10rpx 0;
  3276. }
  3277. .teacher_t {
  3278. font-size: 24rpx;
  3279. font-family: PingFang SC;
  3280. font-weight: 400;
  3281. color: #666666;
  3282. line-height: 36rpx;
  3283. margin-left: 15rpx;
  3284. }
  3285. .teacher_img {
  3286. width: 87rpx;
  3287. height: 129rpx;
  3288. }
  3289. .t2 {
  3290. font-size: 24rpx;
  3291. font-family: PingFang SC;
  3292. color: #666666;
  3293. line-height: 36rpx;
  3294. margin: 15rpx;
  3295. }
  3296. .r_t2 {
  3297. width: 201rpx;
  3298. height: 49rpx;
  3299. background: rgba(22, 119, 255, 0.05);
  3300. border: 1rpx solid #32467b;
  3301. border-radius: 16rpx;
  3302. color: #666666;
  3303. font-size: 23rpx;
  3304. text-align: center;
  3305. display: flex;
  3306. align-items: center;
  3307. padding: 5rpx;
  3308. }
  3309. .scroll_box {
  3310. width: 100%;
  3311. height: 60rpx;
  3312. background: #ffffff;
  3313. box-shadow: 0rpx 0rpx 16rpx 4rpx rgba(145, 156, 178, 0.1);
  3314. white-space: nowrap;
  3315. overflow: hidden;
  3316. margin: 15rpx 0;
  3317. }
  3318. .r_sliper {
  3319. padding: 0 20rpx;
  3320. }
  3321. .top_line {
  3322. width: 6rpx;
  3323. height: 22rpx;
  3324. background: #32467b;
  3325. margin-right: 10rpx;
  3326. }
  3327. .video_t2 {
  3328. font-size: 24rpx;
  3329. font-family: PingFang SC;
  3330. font-weight: 500;
  3331. color: #666666;
  3332. }
  3333. .video_play {
  3334. position: absolute;
  3335. width: 95rpx;
  3336. height: 95rpx;
  3337. top: 0;
  3338. left: 0;
  3339. right: 0;
  3340. bottom: 0;
  3341. margin: auto;
  3342. }
  3343. .video_box {
  3344. position: relative;
  3345. }
  3346. .rotoct {
  3347. transform: rotate(90deg);
  3348. }
  3349. .slot-content {
  3350. padding: 0 20rpx;
  3351. }
  3352. .notice_modal {
  3353. .content {
  3354. width: 100%;
  3355. height: 100%;
  3356. padding: 56rpx 56rpx 56rpx 64rpx;
  3357. .title {
  3358. color: #222;
  3359. line-height: 40rpx;
  3360. font-size: 36rpx;
  3361. text-align: center;
  3362. font-weight: bold;
  3363. margin-bottom: 24rpx;
  3364. }
  3365. .text {
  3366. height: 340rpx;
  3367. line-height: 40rpx;
  3368. text-indent: 2em;
  3369. font-size: 32rpx;
  3370. color: #222;
  3371. }
  3372. .had_read {
  3373. width: 100%;
  3374. height: 88rpx;
  3375. line-height: 88rpx;
  3376. text-align: center;
  3377. background: #3577e8;
  3378. border-radius: 240rpx;
  3379. font-size: 32rpx;
  3380. font-weight: 500;
  3381. color: #fff;
  3382. margin-top: 20rpx;
  3383. &.gray {
  3384. background: #bbbec5;
  3385. }
  3386. }
  3387. }
  3388. }
  3389. .full_mulu {
  3390. position: absolute;
  3391. top: 100rpx;
  3392. right: 20rpx;
  3393. width: 700rpx;
  3394. height: 515rpx;
  3395. color: #333;
  3396. display: flex;
  3397. align-items: center;
  3398. justify-content: space-between;
  3399. z-index: 99999;
  3400. .mulus {
  3401. width: 623rpx;
  3402. // height: 515rpx;
  3403. height: 400rpx;
  3404. overflow-y: scroll;
  3405. // overflow: scroll;
  3406. }
  3407. .mulu_box_in {
  3408. background-color: #b7b7b7;
  3409. border-radius: 16rpx;
  3410. // transition: all 0.5s;
  3411. &::after {
  3412. content: "";
  3413. width: 0;
  3414. height: 0;
  3415. position: absolute;
  3416. top: 235rpx;
  3417. right: 27px;
  3418. border-top: 16rpx solid transparent;
  3419. border-right: 16rpx solid transparent;
  3420. border-left: 16rpx solid #b7b7b7;
  3421. border-bottom: 16rpx solid transparent;
  3422. }
  3423. }
  3424. .mulu_box_out {
  3425. // visibility: hidden;
  3426. display: none;
  3427. }
  3428. .menuBox_mulu {
  3429. // width: 100%;
  3430. background: #ffffff;
  3431. border-radius: 16rpx;
  3432. padding: 0rpx 20rpx;
  3433. margin-bottom: 20rpx;
  3434. }
  3435. .ml_img {
  3436. position: absolute;
  3437. right: 0;
  3438. top: 100rpx;
  3439. }
  3440. .items {
  3441. width: 620rpx;
  3442. height: 100rpx;
  3443. border: 1rpx solid red;
  3444. }
  3445. }
  3446. </style>