detail.vue 99 KB

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