countdown.vue 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383
  1. <template>
  2. <div class="countdown">
  3. <div class="c_timeBox" v-if="showType == 0">
  4. <div class="c_tb_top">
  5. <div class="c_time">
  6. <div class="c_t_item" v-if="type == 0">
  7. <div
  8. class="c_t_i_card"
  9. v-if="!showCountDownInput1"
  10. @click="changeShowInput1(true)"
  11. >
  12. <div>
  13. <span class="c_t_i_btnTop" v-if="!isCountdown"
  14. ><el-button class="c_t_i_btn" @click.stop="addTime(600)"
  15. >+</el-button
  16. ></span
  17. >
  18. <div>{{ countdownTimeShow.m1 }}</div>
  19. <span class="c_t_i_btnBottom" v-if="!isCountdown"
  20. ><el-button class="c_t_i_btn" @click.stop="reduceTime(600)"
  21. >-</el-button
  22. ></span
  23. >
  24. </div>
  25. <div>
  26. <span class="c_t_i_btnTop" v-if="!isCountdown"
  27. ><el-button class="c_t_i_btn" @click.stop="addTime(60)"
  28. >+</el-button
  29. ></span
  30. >
  31. <div>{{ countdownTimeShow.m2 }}</div>
  32. <span class="c_t_i_btnBottom" v-if="!isCountdown"
  33. ><el-button class="c_t_i_btn" @click.stop="reduceTime(60)"
  34. >-</el-button
  35. ></span
  36. >
  37. </div>
  38. <span>{{ lang.ssMinute }}</span>
  39. </div>
  40. <div class="c_t_i_card" v-else v-click-outside="handleBlur1">
  41. <div class="c_t_i_c_inputBox">
  42. <el-input
  43. v-model.number="countDownInputValue1"
  44. ref="countDownInput1Ref"
  45. :min="0"
  46. :max="60"
  47. @keyup.enter.native="changeShowInput1(false)"
  48. ></el-input>
  49. </div>
  50. <span>{{ lang.ssMinute }}</span>
  51. </div>
  52. <div
  53. class="c_t_i_card"
  54. v-if="!showCountDownInput2"
  55. @click="changeShowInput2(true)"
  56. >
  57. <div>
  58. <span class="c_t_i_btnTop" v-if="!isCountdown"
  59. ><el-button class="c_t_i_btn" @click.stop="addTime(10)"
  60. >+</el-button
  61. ></span
  62. >
  63. <div>{{ countdownTimeShow.s1 }}</div>
  64. <span class="c_t_i_btnBottom" v-if="!isCountdown"
  65. ><el-button class="c_t_i_btn" @click.stop="reduceTime(10)"
  66. >-</el-button
  67. ></span
  68. >
  69. </div>
  70. <div>
  71. <span class="c_t_i_btnTop" v-if="!isCountdown"
  72. ><el-button class="c_t_i_btn" @click.stop="addTime(1)"
  73. >+</el-button
  74. ></span
  75. >
  76. <div>{{ countdownTimeShow.s2 }}</div>
  77. <span class="c_t_i_btnBottom" v-if="!isCountdown"
  78. ><el-button class="c_t_i_btn" @click.stop="reduceTime(1)"
  79. >-</el-button
  80. ></span
  81. >
  82. </div>
  83. <span>{{ lang.ssSecond }}</span>
  84. </div>
  85. <div class="c_t_i_card" v-else v-click-outside="handleBlur2">
  86. <div class="c_t_i_c_inputBox">
  87. <el-input
  88. v-model.number="countDownInputValue2"
  89. :min="0"
  90. :max="60"
  91. ref="countDownInput2Ref"
  92. @keyup.enter.native="changeShowInput2(false)"
  93. ></el-input>
  94. </div>
  95. <span>{{ lang.ssSecond }}</span>
  96. </div>
  97. </div>
  98. <div class="c_t_item" v-if="type == 1">
  99. <div class="c_t_i_card">
  100. <div>
  101. <div>{{ keepTimeShow.m1 }}</div>
  102. </div>
  103. <div>
  104. <div>{{ keepTimeShow.m2 }}</div>
  105. </div>
  106. <span>{{ lang.ssMinute }}</span>
  107. </div>
  108. <div class="c_t_i_card">
  109. <div>
  110. <div>{{ keepTimeShow.s1 }}</div>
  111. </div>
  112. <div>
  113. <div>{{ keepTimeShow.s2 }}</div>
  114. </div>
  115. <span>{{ lang.ssSecond }}</span>
  116. </div>
  117. </div>
  118. </div>
  119. <div class="c_choiceTime" v-if="type == 0">
  120. <div class="c_title">
  121. <span>{{ lang.ssQuickSettings }}</span>
  122. </div>
  123. <div class="c_ct_box">
  124. <span @click="setCountdownTime(30)">{{ lang.ss30Seconds }}</span>
  125. <span @click="setCountdownTime(60)">{{ lang.ss1Minute }}</span>
  126. <span @click="setCountdownTime(120)">{{ lang.ss2Minutes }}</span>
  127. <span @click="setCountdownTime(180)">{{ lang.ss3Minutes }}</span>
  128. <span @click="setCountdownTime(300)">{{ lang.ss5Minutes }}</span>
  129. <span @click="setCountdownTime(360)">{{ lang.ss6Minutes }}</span>
  130. <span @click="setCountdownTime(480)">{{ lang.ss8Minutes }}</span>
  131. <span @click="setCountdownTime(600)">{{ lang.ss10Minutes }}</span>
  132. </div>
  133. </div>
  134. <div class="c_behaviorTag">
  135. <div class="c_title">
  136. <span>{{ lang.ssBehaviorTags }}</span>
  137. <div class="c_t_btnArea">
  138. <span
  139. @click="changeBehaviorTagType(0)"
  140. :class="[behaviorTagType == 0 ? 'c_t_ba_active' : '']"
  141. >{{ lang.ssCommon }}</span
  142. >
  143. <span
  144. @click="changeBehaviorTagType(1)"
  145. :class="[behaviorTagType == 1 ? 'c_t_ba_active' : '']"
  146. >{{ lang.ssMore }}</span
  147. >
  148. <!-- <el-button-group>
  149. <el-button
  150. size="mini"
  151. :disabled="isCountdown || isKeepTime"
  152. :type="behaviorTagType == 0 ? 'primary' : 'info'"
  153. @click.stop="changeBehaviorTagType(0)"
  154. >
  155. 常用
  156. </el-button>
  157. <el-button
  158. size="mini"
  159. :disabled="isCountdown || isKeepTime"
  160. :type="behaviorTagType == 1 ? 'primary' : 'info'"
  161. @click.stop="changeBehaviorTagType(1)"
  162. >
  163. 更多
  164. </el-button>
  165. </el-button-group> -->
  166. </div>
  167. </div>
  168. <div
  169. class="c_bt_box"
  170. v-loading="behaviorTagMoreLoading && behaviorTagType == 1"
  171. >
  172. <template v-if="behaviorTagType == 1">
  173. <span
  174. :class="[choiceBehavior.includes(item) ? 'c_bt_b_active' : '']"
  175. v-for="(item, index) in behaviorTagMore"
  176. @click="choiceBehaviorTag(item)"
  177. :key="behaviorTagType + '-' + index"
  178. >{{ item }}</span
  179. >
  180. </template>
  181. <template v-if="behaviorTagType == 0">
  182. <span
  183. :class="[choiceBehavior.includes(item) ? 'c_bt_b_active' : '']"
  184. v-for="(item, index) in behaviorTagCommon"
  185. @click="choiceBehaviorTag(item)"
  186. :key="behaviorTagType + '-' + index"
  187. >{{ item }}</span
  188. >
  189. </template>
  190. </div>
  191. </div>
  192. <div class="c_btnArea">
  193. <span>
  194. <div class="c_b_musicListArea">
  195. <el-tooltip
  196. effect="light"
  197. placement="top"
  198. :content="showSourceList ? lang.ssHideMusicList : lang.ssShowMusicList"
  199. >
  200. <span @click.stop="()=>showSourceList = !showSourceList">
  201. <svg
  202. :style="
  203. `transform: rotate(${showSourceList ? '0deg' : '180deg'})`
  204. "
  205. t="1728975847364"
  206. class="icon"
  207. viewBox="0 0 1024 1024"
  208. version="1.1"
  209. xmlns="http://www.w3.org/2000/svg"
  210. p-id="4250"
  211. width="100%"
  212. height="100%"
  213. >
  214. <path
  215. d="M814.795 320.301c9.571 0 12.392 6.018 6.264 13.372l-297.761 357.392c-6.128 7.355-16.154 7.355-22.281 0l-297.761-357.392c-6.128-7.355-3.309-13.372 6.264-13.372l605.275 0z"
  216. p-id="4251"
  217. ></path>
  218. </svg>
  219. </span>
  220. </el-tooltip>
  221. <div v-if="showSourceList" v-click-outside="()=>showSourceList = false">
  222. <div :class="[sourceUrl==item.url?'c_b_musicListArea_active':'']" v-for="(item,index) in sourceUrlList" :key="index" @click="changeSourceUrl(item.url)">
  223. <span>{{item.name}}</span>
  224. </div>
  225. </div>
  226. </div>
  227. <el-tooltip
  228. class="item"
  229. effect="light"
  230. :content="sourceActive ? lang.ssTurnOffMusic : lang.ssTurnOnMusic"
  231. placement="top"
  232. >
  233. <svg
  234. width="24"
  235. height="24"
  236. viewBox="0 0 24 24"
  237. fill="none"
  238. @click="music()"
  239. xmlns="http://www.w3.org/2000/svg"
  240. >
  241. <path
  242. fill-rule="evenodd"
  243. clip-rule="evenodd"
  244. d="M12.0001 3.18362C7.13095 3.18362 3.18374 7.13083 3.18374 11.9999C3.18374 16.4071 6.41825 20.0602 10.6428 20.7125C11.0848 20.7808 11.5381 20.8163 12.0001 20.8163C12.4058 20.8163 12.7348 21.1452 12.7348 21.551C12.7348 21.9567 12.4058 22.2857 12.0001 22.2857C11.4627 22.2857 10.9345 22.2444 10.4186 22.1647C5.48856 21.4035 1.71436 17.1431 1.71436 11.9999C1.71436 6.3193 6.31943 1.71423 12.0001 1.71423C16.5776 1.71423 20.4549 4.70396 21.7896 8.83532C22.1119 9.83321 22.2858 10.897 22.2858 11.9999C22.2858 12.4057 21.9569 12.7346 21.5511 12.7346C21.1453 12.7346 20.8164 12.4057 20.8164 11.9999C20.8164 11.0522 20.6671 10.1407 20.3913 9.28702C19.2469 5.74447 15.9216 3.18362 12.0001 3.18362Z"
  245. :fill="sourceActive ? '#E11E1E' : 'black'"
  246. fill-opacity="0.9"
  247. />
  248. <path
  249. fill-rule="evenodd"
  250. clip-rule="evenodd"
  251. d="M22.0162 13.8835C22.1871 14.0192 22.2856 14.2186 22.2856 14.4285V20.1428C22.2856 20.3322 22.2053 20.5139 22.0625 20.6479L21.3005 21.3622C21.003 21.6411 20.5206 21.6411 20.2231 21.3622C19.9255 21.0832 19.9255 20.631 20.2231 20.352L20.7618 19.8469V15.2717L17.7142 15.7479V20.8571C17.7142 21.0465 17.6339 21.2282 17.491 21.3622L16.7291 22.0765C16.4316 22.3554 15.9492 22.3554 15.6516 22.0765C15.3541 21.7975 15.3541 21.3452 15.6516 21.0663L16.1904 20.5612V15.1428C16.1904 14.7936 16.4596 14.4956 16.827 14.4382L21.3984 13.724C21.6194 13.6894 21.8453 13.7478 22.0162 13.8835Z"
  252. :fill="sourceActive ? '#E11E1E' : '#3681FC'"
  253. />
  254. <path
  255. d="M14.5713 12C14.5713 13.4202 13.4201 14.5714 11.9999 14.5714C10.5797 14.5714 9.42847 13.4202 9.42847 12C9.42847 10.5799 10.5797 9.42859 11.9999 9.42859C13.4201 9.42859 14.5713 10.5799 14.5713 12Z"
  256. :fill="sourceActive ? '#E11E1E' : 'black'"
  257. fill-opacity="0.9"
  258. />
  259. </svg>
  260. </el-tooltip>
  261. </span>
  262. <div class="c_ba_startArea">
  263. <div
  264. :class="[
  265. !canStartCountdownTime
  266. ? 'c_ba_startType0'
  267. : !isCountdown
  268. ? 'c_ba_startType'
  269. : 'c_ba_startType2'
  270. ]"
  271. v-if="type == 0"
  272. style=""
  273. @click="countdownTimeFn()"
  274. >
  275. <svg
  276. v-if="!isCountdown"
  277. t="1721117381559"
  278. viewBox="0 0 1024 1024"
  279. version="1.1"
  280. xmlns="http://www.w3.org/2000/svg"
  281. p-id="12941"
  282. width="64"
  283. height="64"
  284. >
  285. <path
  286. d="M161.2 839.9v-654c0-56.1 60.7-91.1 109.3-63.1l566.3 327c48.6 28 48.6 98.1 0 126.2L270.4 903c-48.5 28-109.2-7.1-109.2-63.1z"
  287. p-id="12942"
  288. ></path>
  289. </svg>
  290. <svg
  291. v-else
  292. t="1721198913879"
  293. class="icon"
  294. viewBox="0 0 1024 1024"
  295. version="1.1"
  296. xmlns="http://www.w3.org/2000/svg"
  297. p-id="4266"
  298. width="64"
  299. height="64"
  300. >
  301. <path
  302. d="M426.666667 138.666667v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334H266.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h106.666666a53.393333 53.393333 0 0 1 53.333334 53.333334z m330.666666-53.333334H650.666667a53.393333 53.393333 0 0 0-53.333334 53.333334v746.666666a53.393333 53.393333 0 0 0 53.333334 53.333334h106.666666a53.393333 53.393333 0 0 0 53.333334-53.333334V138.666667a53.393333 53.393333 0 0 0-53.333334-53.333334z"
  303. p-id="4267"
  304. ></path>
  305. </svg>
  306. <!-- <svg v-else t="1721117616634" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13970" width="64" height="64"><path d="M128 128m53.333333 0l661.333334 0q53.333333 0 53.333333 53.333333l0 661.333334q0 53.333333-53.333333 53.333333l-661.333334 0q-53.333333 0-53.333333-53.333333l0-661.333334q0-53.333333 53.333333-53.333333Z" p-id="13971"></path></svg> -->
  307. </div>
  308. <div
  309. :class="[!isKeepTime ? 'c_ba_startType' : 'c_ba_startType2']"
  310. v-if="type == 1"
  311. @click="keepTimeFn()"
  312. >
  313. <svg
  314. v-if="!isKeepTime"
  315. t="1721117381559"
  316. viewBox="0 0 1024 1024"
  317. version="1.1"
  318. xmlns="http://www.w3.org/2000/svg"
  319. p-id="12941"
  320. width="64"
  321. height="64"
  322. >
  323. <path
  324. d="M161.2 839.9v-654c0-56.1 60.7-91.1 109.3-63.1l566.3 327c48.6 28 48.6 98.1 0 126.2L270.4 903c-48.5 28-109.2-7.1-109.2-63.1z"
  325. p-id="12942"
  326. ></path>
  327. </svg>
  328. <svg
  329. v-else
  330. t="1721198913879"
  331. class="icon"
  332. viewBox="0 0 1024 1024"
  333. version="1.1"
  334. xmlns="http://www.w3.org/2000/svg"
  335. p-id="4266"
  336. width="64"
  337. height="64"
  338. >
  339. <path
  340. d="M426.666667 138.666667v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334H266.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h106.666666a53.393333 53.393333 0 0 1 53.333334 53.333334z m330.666666-53.333334H650.666667a53.393333 53.393333 0 0 0-53.333334 53.333334v746.666666a53.393333 53.393333 0 0 0 53.333334 53.333334h106.666666a53.393333 53.393333 0 0 0 53.333334-53.333334V138.666667a53.393333 53.393333 0 0 0-53.333334-53.333334z"
  341. p-id="4267"
  342. ></path>
  343. </svg>
  344. </div>
  345. </div>
  346. <span @click="reset()">
  347. <el-tooltip
  348. class="item"
  349. effect="light"
  350. :content="lang.ssResetTimer"
  351. placement="top"
  352. >
  353. <svg
  354. width="24"
  355. height="24"
  356. viewBox="0 0 24 24"
  357. fill="none"
  358. xmlns="http://www.w3.org/2000/svg"
  359. >
  360. <path
  361. fill-rule="evenodd"
  362. clip-rule="evenodd"
  363. d="M2.25 19.5C2.25 19.0858 2.58579 18.75 3 18.75H22.5C22.9142 18.75 23.25 19.0858 23.25 19.5C23.25 19.9142 22.9142 20.25 22.5 20.25H3C2.58579 20.25 2.25 19.9142 2.25 19.5Z"
  364. fill="black"
  365. />
  366. <path d="M3 8.25L3.75 14.25L8.25 10.5L3 8.25Z" fill="black" />
  367. <path
  368. fill-rule="evenodd"
  369. clip-rule="evenodd"
  370. d="M6.88061 9.09714C8.37158 7.62191 10.4445 6.75 12.75 6.75C17.3064 6.75 21 10.4437 21 15C21 15.4142 21.3358 15.75 21.75 15.75C22.1643 15.75 22.5 15.4142 22.5 15C22.5 9.61522 18.1348 5.25 12.75 5.25C9.83406 5.25 7.20333 6.45088 5.41113 8.46737L3.29545 7.56065C3.04847 7.4548 2.76374 7.48917 2.54904 7.65074C2.33433 7.81231 2.22247 8.0764 2.2558 8.34303L3.0058 14.343C3.03982 14.6151 3.21963 14.847 3.47471 14.9477C3.7298 15.0483 4.01948 15.0017 4.23015 14.8262L8.73015 11.0762C8.93061 10.9091 9.02983 10.6499 8.99215 10.3917C8.95447 10.1335 8.78529 9.91343 8.54545 9.81065L6.88061 9.09714ZM4.48437 9.70214L3.9064 9.45443L4.03677 10.4974C4.17389 10.2236 4.32334 9.95829 4.48437 9.70214ZM4.91452 12.3033C5.14843 11.5796 5.47638 10.9088 5.884 10.302L6.82973 10.7073L4.91452 12.3033Z"
  371. fill="black"
  372. />
  373. </svg>
  374. </el-tooltip>
  375. </span>
  376. </div>
  377. <div class="ActivityMemo">
  378. <span @click="changeShowType(1)">
  379. {{ lang.ssTeachingActivityMemo }}
  380. <svg
  381. width="16"
  382. height="16"
  383. viewBox="0 0 16 16"
  384. fill="none"
  385. xmlns="http://www.w3.org/2000/svg"
  386. >
  387. <path
  388. fill-rule="evenodd"
  389. clip-rule="evenodd"
  390. d="M3.66782 3.1263C3.87421 2.94284 4.19025 2.96143 4.37371 3.16782L8.37371 7.66782C8.5421 7.85727 8.5421 8.14274 8.37371 8.33219L4.37371 12.8322C4.19025 13.0386 3.87421 13.0572 3.66782 12.8737C3.46143 12.6903 3.44284 12.3742 3.6263 12.1678L7.33103 8.00001L3.6263 3.83219C3.44284 3.6258 3.46143 3.30976 3.66782 3.1263Z"
  391. fill="black"
  392. />
  393. <path
  394. fill-rule="evenodd"
  395. clip-rule="evenodd"
  396. d="M7.66782 3.1263C7.87421 2.94284 8.19025 2.96143 8.37371 3.16782L12.3737 7.66782C12.5421 7.85727 12.5421 8.14274 12.3737 8.33219L8.37371 12.8322C8.19025 13.0386 7.87421 13.0572 7.66782 12.8737C7.46143 12.6903 7.44284 12.3742 7.6263 12.1678L11.331 8.00001L7.6263 3.83219C7.44284 3.6258 7.46143 3.30976 7.66782 3.1263Z"
  397. fill="black"
  398. />
  399. </svg>
  400. </span>
  401. </div>
  402. </div>
  403. <div class="c_changeType">
  404. <div class="c_ct_btn" @click="changeType(0)">
  405. <div>{{ lang.ssCountdown }}</div>
  406. <span v-if="type == 0"></span>
  407. <svg
  408. width="21"
  409. height="6"
  410. viewBox="0 0 21 6"
  411. fill="none"
  412. xmlns="http://www.w3.org/2000/svg"
  413. v-if="type == 0"
  414. >
  415. <path
  416. fill-rule="evenodd"
  417. clip-rule="evenodd"
  418. d="M1.05713 0.470583C1.80179 -0.155333 3.01121 -0.157081 3.75845 0.466679C5.4879 1.91035 7.86809 2.8 10.5 2.8C13.1319 2.8 15.5121 1.91035 17.2416 0.466679C17.9888 -0.157081 19.1982 -0.155333 19.9429 0.470583C20.6875 1.0965 20.6854 2.10956 19.9382 2.73332C17.5219 4.75032 14.1834 6 10.5 6C6.81664 6 3.47806 4.75032 1.06179 2.73332C0.314559 2.10956 0.312473 1.0965 1.05713 0.470583Z"
  419. fill="url(#paint0_linear_269_7318)"
  420. />
  421. <defs>
  422. <linearGradient
  423. id="paint0_linear_269_7318"
  424. x1="0.5"
  425. y1="6"
  426. x2="20.5"
  427. y2="6"
  428. gradientUnits="userSpaceOnUse"
  429. >
  430. <stop stop-color="#3673E8" />
  431. <stop offset="1" stop-color="#AD88FD" />
  432. </linearGradient>
  433. </defs>
  434. </svg>
  435. </div>
  436. <span></span>
  437. <div class="c_ct_btn" @click="changeType(1)">
  438. <div>{{ lang.ssTimer }}</div>
  439. <span v-if="type == 1"></span>
  440. <svg
  441. width="21"
  442. height="6"
  443. viewBox="0 0 21 6"
  444. fill="none"
  445. xmlns="http://www.w3.org/2000/svg"
  446. v-if="type == 1"
  447. >
  448. <path
  449. fill-rule="evenodd"
  450. clip-rule="evenodd"
  451. d="M1.05713 0.470583C1.80179 -0.155333 3.01121 -0.157081 3.75845 0.466679C5.4879 1.91035 7.86809 2.8 10.5 2.8C13.1319 2.8 15.5121 1.91035 17.2416 0.466679C17.9888 -0.157081 19.1982 -0.155333 19.9429 0.470583C20.6875 1.0965 20.6854 2.10956 19.9382 2.73332C17.5219 4.75032 14.1834 6 10.5 6C6.81664 6 3.47806 4.75032 1.06179 2.73332C0.314559 2.10956 0.312473 1.0965 1.05713 0.470583Z"
  452. fill="url(#paint0_linear_269_7318)"
  453. />
  454. <defs>
  455. <linearGradient
  456. id="paint0_linear_269_7318"
  457. x1="0.5"
  458. y1="6"
  459. x2="20.5"
  460. y2="6"
  461. gradientUnits="userSpaceOnUse"
  462. >
  463. <stop stop-color="#3673E8" />
  464. <stop offset="1" stop-color="#AD88FD" />
  465. </linearGradient>
  466. </defs>
  467. </svg>
  468. </div>
  469. <!-- <el-button-group>
  470. <el-button
  471. :type="isCountdown ? 'danger' : type == 0 ? 'primary' : ''"
  472. @click.stop="changeType(0)"
  473. :disabled="isCountdown || isKeepTime"
  474. >
  475. 倒计时
  476. </el-button>
  477. <el-button
  478. :type="isKeepTime ? 'danger' : type == 1 ? 'primary' : ''"
  479. @click.stop="changeType(1)"
  480. :disabled="isCountdown || isKeepTime"
  481. >
  482. 计时器
  483. </el-button>
  484. </el-button-group> -->
  485. </div>
  486. </div>
  487. <div class="c_behavior" v-if="showType == 1">
  488. <div class="behaviorBack">
  489. <span @click="changeShowType(0)">
  490. <svg
  491. width="16"
  492. height="16"
  493. viewBox="0 0 16 16"
  494. fill="none"
  495. xmlns="http://www.w3.org/2000/svg"
  496. >
  497. <path
  498. fill-rule="evenodd"
  499. clip-rule="evenodd"
  500. d="M3.66782 3.1263C3.87421 2.94284 4.19025 2.96143 4.37371 3.16782L8.37371 7.66782C8.5421 7.85727 8.5421 8.14274 8.37371 8.33219L4.37371 12.8322C4.19025 13.0386 3.87421 13.0572 3.66782 12.8737C3.46143 12.6903 3.44284 12.3742 3.6263 12.1678L7.33103 8.00001L3.6263 3.83219C3.44284 3.6258 3.46143 3.30976 3.66782 3.1263Z"
  501. fill="black"
  502. />
  503. <path
  504. fill-rule="evenodd"
  505. clip-rule="evenodd"
  506. d="M7.66782 3.1263C7.87421 2.94284 8.19025 2.96143 8.37371 3.16782L12.3737 7.66782C12.5421 7.85727 12.5421 8.14274 12.3737 8.33219L8.37371 12.8322C8.19025 13.0386 7.87421 13.0572 7.66782 12.8737C7.46143 12.6903 7.44284 12.3742 7.6263 12.1678L11.331 8.00001L7.6263 3.83219C7.44284 3.6258 7.46143 3.30976 7.66782 3.1263Z"
  507. fill="black"
  508. /></svg
  509. >{{ lang.ssReturn }}</span
  510. >
  511. </div>
  512. <div class="c_b_btnArea">
  513. <el-button-group>
  514. <el-button
  515. :type="showBtnType == 0 ? 'primary' : ''"
  516. size="small"
  517. @click="showBtnType = 0"
  518. >{{ lang.ssAllEvents }}</el-button
  519. >
  520. <el-button
  521. :type="showBtnType == 1 ? 'primary' : ''"
  522. size="small"
  523. @click="showBtnType = 1"
  524. >{{ lang.ssTimingEvents }}</el-button
  525. >
  526. </el-button-group>
  527. <span
  528. @click="derive(showMemorandumList)"
  529. v-loading="exportLoading"
  530. >
  531. <el-tooltip class="item" effect="dark" :content="lang.ssExport" placement="top">
  532. <svg
  533. t="1724319590942"
  534. class="icon"
  535. viewBox="0 0 1024 1024"
  536. version="1.1"
  537. xmlns="http://www.w3.org/2000/svg"
  538. p-id="8252"
  539. width="200"
  540. height="200"
  541. >
  542. <path
  543. d="M608.888 94c4.528 0 8.844 1.919 11.877 5.28l241.113 267.153a16 16 0 0 1 4.122 10.72V566a8 8 0 0 1-8 8h-64a8 8 0 0 1-8-8V443H576c-17.673 0-32-14.327-32-32V174H242v675h233a8 8 0 0 1 8 8v64a8 8 0 0 1-8 8H194c-17.673 0-32-14.327-32-32V126c0-17.673 14.327-32 32-32h414.888z m153.49 277L616 208.912V371h146.378z"
  544. fill="#000000"
  545. p-id="8253"
  546. ></path>
  547. <path
  548. d="M670.089 647.914l77.198 77.197H535.312a8 8 0 0 0-8 8v64a8 8 0 0 0 8 8h213.753l-78.976 78.976a8 8 0 0 0 0 11.314l45.255 45.255a8 8 0 0 0 11.314 0l152.027-152.028c12.497-12.497 12.497-32.758 0-45.255L726.658 591.345a8 8 0 0 0-11.314 0L670.089 636.6a8 8 0 0 0 0 11.314z"
  549. fill="#000000"
  550. p-id="8254"
  551. ></path>
  552. </svg>
  553. </el-tooltip>
  554. </span>
  555. <!-- <el-button style="margin-left: 20px;" type="warning" @click.stop="derive">导出</el-button> -->
  556. </div>
  557. <div class="c_step" ref="stepRef" v-loading="memorandumLoading">
  558. <el-timeline>
  559. <el-timeline-item
  560. v-for="(item, index) in showMemorandumList"
  561. :class="item.color"
  562. :key="index"
  563. :timestamp="item.time"
  564. size="large"
  565. >
  566. <span v-html="item.textList.join(',')"></span>
  567. <div class="c_s_time" v-if="item.timeDiff">
  568. <div>
  569. <span v-if="item.timeDiff.h !== null"
  570. >{{ item.timeDiff.h }}{{ lang.ssHourUnit }}</span
  571. >
  572. <span v-if="item.timeDiff.m !== null"
  573. >{{ item.timeDiff.m }}{{ lang.ssMinute }}</span
  574. >
  575. <span v-if="item.timeDiff.s !== null"
  576. >{{ item.timeDiff.s }}{{ lang.ssSecond }}</span
  577. >
  578. </div>
  579. </div>
  580. </el-timeline-item>
  581. </el-timeline>
  582. </div>
  583. </div>
  584. <mini-audio
  585. v-show="false"
  586. ref="audioRef"
  587. :loop="true"
  588. :audio-source="sourceUrl"
  589. ></mini-audio>
  590. <mini-audio
  591. v-show="false"
  592. ref="endSourceUrlRef"
  593. :loop="false"
  594. :audio-source="endSourceUrl"
  595. ></mini-audio>
  596. </div>
  597. </template>
  598. <script>
  599. import { v4 as uuidv4 } from "uuid";
  600. // 自定义指令,用于处理点击外部区域的事件
  601. const clickOutside = {
  602. bind(el, binding) {
  603. // 在元素上绑定一个点击事件监听器
  604. el.clickOutsideEvent = function(event) {
  605. // 检查点击事件是否发生在元素的内部
  606. if (!(el === event.target || el.contains(event.target))) {
  607. // 如果点击事件发生在元素的外部,则触发指令绑定的方法,将点击的event数据传过去
  608. binding.value(event);
  609. }
  610. };
  611. // 在文档上添加点击事件监听器
  612. document.addEventListener("click", el.clickOutsideEvent);
  613. },
  614. unbind(el) {
  615. // 在元素上解除点击事件监听器
  616. document.removeEventListener("click", el.clickOutsideEvent);
  617. }
  618. };
  619. export default {
  620. props: {
  621. courseDetail: {
  622. type: Object,
  623. default: () => {}
  624. },
  625. fileId: {
  626. type: Array,
  627. default: () => []
  628. }
  629. },
  630. directives: {
  631. "click-outside": clickOutside // 注册自定义指令
  632. },
  633. data() {
  634. return {
  635. userid: this.$route.query.userid,
  636. courseId: this.$route.query.courseId,
  637. tcid2: this.$route.query.tcid,
  638. showType: 0,
  639. sourceUrl:
  640. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%80%92%E8%AE%A1%E6%97%B6%E9%9F%B3%E4%B9%901721355956636.mp3",
  641. endSourceUrl:
  642. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%80%92%E6%95%B010%E7%A7%92%E5%8F%A0%E5%8A%A0%E9%9F%B3%E6%95%881721638403882.MP3",
  643. sourceUrlList: [
  644. {
  645. name: this.lang.ssMusic1,
  646. url:
  647. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%80%92%E8%AE%A1%E6%97%B6%E9%9F%B3%E4%B9%901721355956636.mp3"
  648. },
  649. {
  650. name: this.lang.ssMusic2,
  651. url:
  652. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2F%E9%9F%B3%E4%B9%9021728975233277.mp3"
  653. },
  654. {
  655. name: this.lang.ssMusic3,
  656. url:
  657. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2F%E9%9F%B3%E4%B9%9031728975268412.mp3"
  658. },
  659. {
  660. name: this.lang.ssMusic4,
  661. url:
  662. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2F%E9%9F%B3%E4%B9%9041728975432067.mp3"
  663. },
  664. {
  665. name: this.lang.ssMusic5,
  666. url:
  667. "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2F%E9%9F%B3%E4%B9%9051728975447857.mp3"
  668. }
  669. ],
  670. showSourceList: false,
  671. sourceActive: false,
  672. type: 0, //0:倒计时 1:计时器
  673. isCountdown: false,
  674. showCountDownInput1: false,
  675. countDownInputValue1: 0,
  676. showCountDownInput2: false,
  677. countDownInputValue2: 0,
  678. isKeepTime: false,
  679. countdownTime: 0,
  680. countdownTimeDefault: 0,
  681. countdownTimeTimer: null,
  682. keepTime: 0,
  683. keepTimeTimer: null,
  684. startCountdownTime: 0,
  685. behaviorTagType: 0, //0:常用 1:更多
  686. behaviorTagMore: [], //更多
  687. behaviorTagMoreLoading: false,
  688. behaviorTagCommon: [
  689. this.lang.ssGroupDiscussion,
  690. this.lang.ssGroupReport,
  691. this.lang.ssHandsOnExperiment,
  692. this.lang.ssClassroomGame,
  693. this.lang.ssIndependentLearning,
  694. this.lang.ssWorkDisplay,
  695. this.lang.ssStudentSpeech,
  696. this.lang.ssStudentShare,
  697. this.lang.ssClassPractice,
  698. this.lang.ssQuickQAndA,
  699. this.lang.ssReadingMaterials,
  700. this.lang.ssObservationRecord
  701. ],
  702. //常用
  703. choiceBehavior: [],
  704. memorandumList: [],
  705. memorandumLoading: false,
  706. showBtnType: 1, //0:所有事件 1:计时事件
  707. exportLoading: false
  708. };
  709. },
  710. computed: {
  711. canStartCountdownTime() {
  712. let _result = false;
  713. if (this.countdownTime > 0) {
  714. _result = true;
  715. }
  716. return _result;
  717. },
  718. countdownTimeShow() {
  719. let _result = {
  720. m1: 0,
  721. m2: 0,
  722. s1: 0,
  723. s2: 0
  724. };
  725. if (this.countdownTime <= 0) return _result;
  726. let minutes = Math.floor(this.countdownTime / 60);
  727. let seconds = this.countdownTime % 60;
  728. if (minutes > 9) {
  729. _result.m1 = Math.floor(minutes / 10);
  730. _result.m2 = minutes % 10;
  731. } else {
  732. _result.m1 = 0;
  733. _result.m2 = minutes;
  734. }
  735. if (seconds > 9) {
  736. _result.s1 = Math.floor(seconds / 10);
  737. _result.s2 = seconds % 10;
  738. } else {
  739. _result.s1 = 0;
  740. _result.s2 = seconds;
  741. }
  742. return _result;
  743. },
  744. keepTimeShow() {
  745. let _result = {
  746. m1: 0,
  747. m2: 0,
  748. s1: 0,
  749. s2: 0
  750. };
  751. if (this.keepTime <= 0) return _result;
  752. let minutes = Math.floor(this.keepTime / 60);
  753. let seconds = this.keepTime % 60;
  754. if (minutes > 9) {
  755. _result.m1 = Math.floor(minutes / 10);
  756. _result.m2 = minutes % 10;
  757. } else {
  758. _result.m1 = 0;
  759. _result.m2 = minutes;
  760. }
  761. if (seconds > 9) {
  762. _result.s1 = Math.floor(seconds / 10);
  763. _result.s2 = seconds % 10;
  764. } else {
  765. _result.s1 = 0;
  766. _result.s2 = seconds;
  767. }
  768. return _result;
  769. },
  770. showMemorandumList() {
  771. let _result = [];
  772. let _time1 = ""; //_interval1之内的时间
  773. let _time2 = ""; //_interval2之内的时间
  774. let _type = "blue"; //要展示的颜色
  775. let _interval1 = 300; //行为间隔 s
  776. let _interval2 = 10; //行为间隔 s
  777. let _previousBehavior = "";
  778. let _resultTemplate = [];
  779. let _topic = "";
  780. let _list = JSON.parse(JSON.stringify(this.memorandumList));
  781. if (this.showBtnType == 1) {
  782. _list = _list.filter(i => i.text.indexOf("计时") !== -1);
  783. }
  784. _list.forEach((item, index) => {
  785. if (index == 0) {
  786. _time1 = item.time;
  787. _time2 = item.time;
  788. _type = "blue";
  789. return _result.push({
  790. textList: [item.text],
  791. time: item.time,
  792. color: _type
  793. });
  794. }
  795. if (this.isMoreThanSeconds(item.time, _time1, _interval1)) {
  796. //切换颜色
  797. _type = _type == "blue" ? "green" : "blue";
  798. _time1 = item.time;
  799. }
  800. //针对查看学生的作业情况
  801. if (_result[_result.length - 1].textList.length) {
  802. if (
  803. _result[_result.length - 1].textList[
  804. _result[_result.length - 1].textList.length - 1
  805. ].indexOf("的作业") === -1 &&
  806. item.text.indexOf("的作业") !== -1
  807. ) {
  808. return _result.push({
  809. textList: [item.text],
  810. time: item.time,
  811. color: _type
  812. });
  813. } else if (
  814. _result[_result.length - 1].textList[
  815. _result[_result.length - 1].textList.length - 1
  816. ].indexOf("的作业") !== -1 &&
  817. item.text.indexOf("的作业") !== -1
  818. ) {
  819. return _result[_result.length - 1].textList.push(item.text);
  820. } else if (
  821. _result[_result.length - 1].textList[
  822. _result[_result.length - 1].textList.length - 1
  823. ].indexOf("的作业") !== -1 &&
  824. item.text.indexOf("的作业") == -1
  825. ) {
  826. return _result.push({
  827. textList: [item.text],
  828. time: item.time,
  829. color: _type
  830. });
  831. }
  832. }
  833. //针对任务面板做题的操作情况
  834. if (
  835. item.text.match(/<span class=['"]variable['"]>第(.*?)题<\/span>/g) !=
  836. null
  837. ) {
  838. let _match = item.text.match(
  839. /<span class=['"]variable['"]>(.*?)<\/span>/
  840. );
  841. let _matchTopic = _match[1];
  842. if (
  843. _result[_result.length - 1].textList[
  844. _result[_result.length - 1].textList.length - 1
  845. ].match(/<span class=['"]variable['"]>第(.*?)题<\/span>/g) == null
  846. ) {
  847. _topic = _matchTopic;
  848. return _result.push({
  849. textList: [item.text],
  850. time: item.time,
  851. color: _type
  852. });
  853. } else {
  854. if (_topic == _matchTopic) {
  855. //同一题
  856. return _result[_result.length - 1].textList.push(item.text);
  857. } else {
  858. _topic = _matchTopic;
  859. return _result.push({
  860. textList: [item.text],
  861. time: item.time,
  862. color: _type
  863. });
  864. }
  865. }
  866. } else if (
  867. _result[_result.length - 1].textList[
  868. _result[_result.length - 1].textList.length - 1
  869. ].match(/<span class=['"]variable['"]>第(.*?)题<\/span>/g)
  870. ) {
  871. return _result.push({
  872. textList: [item.text],
  873. time: item.time,
  874. color: _type
  875. });
  876. }
  877. if (this.isMoreThanSeconds(item.time, _time2, _interval2)) {
  878. _time2 = item.time;
  879. //十秒过了
  880. _result.push({
  881. textList: [item.text],
  882. time: item.time,
  883. color: _type
  884. });
  885. } else {
  886. _result[_result.length - 1].textList.push(`${item.text}`);
  887. }
  888. });
  889. _result.forEach(i => {
  890. if (i.textList.every(ei => ei.indexOf("的作业") !== -1)) {
  891. let _useSet = new Set();
  892. i.textList.forEach(i2 => {
  893. let _userMatch = i2.match(
  894. /<span class=['"]variable['"]>(.*?)<\/span>的作业/
  895. );
  896. if (_userMatch) {
  897. _useSet.add(_userMatch[1]);
  898. }
  899. });
  900. if (Array.from(_useSet).length > 1) {
  901. i.textList = this.lookWork(i.textList);
  902. } else {
  903. i.textList = this.lookWork2(i.textList);
  904. }
  905. } else if (
  906. i.textList.every(ei =>
  907. ei.match(/<span class=['"]variable['"]>第(.*?)题<\/span>/g)
  908. )
  909. ) {
  910. i.textList = this.lookTask(i.textList);
  911. }
  912. });
  913. _result.forEach((item, index) => {
  914. if (index !== _result.length - 1) {
  915. item.timeDiff = this.getTimeDifferences(
  916. item.time,
  917. _result[index + 1].time
  918. );
  919. } else {
  920. item.timeDiff = null;
  921. }
  922. });
  923. return _result;
  924. }
  925. },
  926. watch: {
  927. countdownTime(newValue) {
  928. if (this.isCountdown && this.countdownTimeTimer && newValue == 0) {
  929. this.countdownTimeFinish();
  930. } else if (!this.isCountdown && !this.countdownTimeTimer) {
  931. this.countdownTimeDefault = newValue;
  932. }
  933. if (this.$refs.audioRef.playing && this.sourceActive && newValue == 10) {
  934. this.$refs.audioRef.stop();
  935. this.$refs.endSourceUrlRef.play();
  936. // this.$refs.audioRef.setVolume(newValue / 10);
  937. }
  938. },
  939. countDownInputValue1(newValue) {
  940. if (newValue > 60) {
  941. this.countDownInputValue1 = 60;
  942. } else if (newValue < 0) {
  943. this.countDownInputValue1 = 0;
  944. }
  945. },
  946. countDownInputValue2(newValue) {
  947. if (newValue > 60) {
  948. this.countDownInputValue2 = 60;
  949. } else if (newValue < 0) {
  950. this.countDownInputValue2 = 0;
  951. }
  952. }
  953. },
  954. methods: {
  955. derive(_data) {
  956. if (this.exportLoading) return this.$message.info(this.lang.ssPleaseWaitDots);
  957. this.exportLoading = true;
  958. let _array = [];
  959. _data.forEach((item, index) => {
  960. let json = {};
  961. json[this.lang.ssTime] = item.time;
  962. json[this.lang.ssEvent] = item.textList
  963. .map(i => i.replace(/<[^>]+>/g, ""))
  964. .join(",");
  965. json[this.lang.ssTimeDifference] =
  966. index == 0
  967. ? ""
  968. : `${
  969. _data[index - 1].timeDiff.h
  970. ? _data[index - 1].timeDiff.h + this.lang.ssHourUnit
  971. : ""
  972. }${
  973. _data[index - 1].timeDiff.m
  974. ? _data[index - 1].timeDiff.m + this.lang.ssMinute
  975. : ""
  976. }${
  977. _data[index - 1].timeDiff.s
  978. ? _data[index - 1].timeDiff.s + this.lang.ssSecond
  979. : ""
  980. }`;
  981. _array.push(json);
  982. });
  983. let XLSX = require("xlsx");
  984. const workbook = XLSX.utils.book_new(); //创建一个新的工作簿对象
  985. let ws = XLSX.utils.json_to_sheet(_array); //将json对象数组转化成工作表
  986. ws["!cols"] = [
  987. //设置每一列的宽度
  988. { wch: 25 },
  989. { wch: 50 },
  990. { wch: 25 }
  991. ];
  992. XLSX.utils.book_append_sheet(workbook, ws, "sheet1"); //把sheet添加到workbook里,第三个参数是sheet名
  993. XLSX.writeFile(workbook, this.lang.ssEventExportFileName);
  994. this.exportLoading = false;
  995. this.$message.success(this.lang.ssExportSuccess);
  996. },
  997. lookWork(data) {
  998. const taskTypes = {
  999. [this.lang.ssViewHomework]: new Set(),
  1000. [this.lang.ssPerformLike]: new Set(),
  1001. [this.lang.ssPerformComment]: new Set(),
  1002. [this.lang.ssPerformRating]: new Set()
  1003. };
  1004. let _result = [];
  1005. const viewRegex = new RegExp(`${this.lang.ssViewHomework}<span class=['"]variable['"]>(.*?)<\/span>${this.lang.ssHomeworkOf}`, 'g');
  1006. const likeRegex = new RegExp(`${this.lang.ssPerformActionOn}<span class=['"]variable['"]>(.*?)<\/span>${this.lang.ssHomeworkOf}${this.lang.ssPerformLike}<span class=['"]btn['"]>${this.lang.ssLikeL}<\/span>`, 'g');
  1007. const commentRegex = new RegExp(`${this.lang.ssPerformActionOn}<span class=['"]variable['"]>(.*?)<\/span>${this.lang.ssHomeworkOf}${this.lang.ssPerformComment}<span class=['"]btn['"]>${this.lang.ssComment}<\/span>`, 'g');
  1008. const markRegex = new RegExp(`${this.lang.ssPerformActionOn}<span class=['"]variable['"]>(.*?)<\/span>${this.lang.ssHomeworkOf}${this.lang.ssPerformRating}<span class=['"]btn['"]>${this.lang.ssMarkScore}<\/span>`, 'g');
  1009. data.forEach(str => {
  1010. if (viewRegex.test(str)) {
  1011. this.extractText(str, viewRegex).forEach(item =>
  1012. taskTypes[this.lang.ssViewHomework].add(item)
  1013. );
  1014. } else if (likeRegex.test(str)) {
  1015. this.extractText(str, likeRegex).forEach(item =>
  1016. taskTypes[this.lang.ssPerformLike].add(item)
  1017. );
  1018. } else if (commentRegex.test(str)) {
  1019. this.extractText(str, commentRegex).forEach(item =>
  1020. taskTypes[this.lang.ssPerformComment].add(item)
  1021. );
  1022. } else if (markRegex.test(str)) {
  1023. this.extractText(str, markRegex).forEach(item =>
  1024. taskTypes[this.lang.ssPerformRating].add(item)
  1025. );
  1026. }
  1027. });
  1028. if (Array.from(taskTypes[this.lang.ssViewHomework]).length > 0) {
  1029. _result.push(
  1030. `${this.lang.ssViewHomework}<span class='variable'>${Array.from(taskTypes[this.lang.ssViewHomework]).join(
  1031. ","
  1032. )}</span>${this.lang.ssHomeworkOf}`
  1033. );
  1034. }
  1035. if (Array.from(taskTypes[this.lang.ssPerformLike]).length > 0) {
  1036. _result.push(
  1037. `${this.lang.ssPerformActionOn}<span class='variable'>${Array.from(taskTypes[this.lang.ssPerformLike]).join(
  1038. ","
  1039. )}</span>${this.lang.ssHomeworkOf}${this.lang.ssPerformLike}<span class="btn">${this.lang.ssLikeL}</span>`
  1040. );
  1041. }
  1042. if (Array.from(taskTypes[this.lang.ssPerformComment]).length > 0) {
  1043. _result.push(
  1044. `${this.lang.ssPerformActionOn}<span class='variable'>${Array.from(taskTypes[this.lang.ssPerformComment]).join(
  1045. ","
  1046. )}</span>${this.lang.ssHomeworkOf}${this.lang.ssPerformComment}<span class="btn">${this.lang.ssComment}</span>`
  1047. );
  1048. }
  1049. if (Array.from(taskTypes[this.lang.ssPerformRating]).length > 0) {
  1050. _result.push(
  1051. `${this.lang.ssPerformActionOn}<span class='variable'>${Array.from(taskTypes[this.lang.ssPerformRating]).join(
  1052. ","
  1053. )}</span>${this.lang.ssHomeworkOf}${this.lang.ssPerformRating}<span class="btn">${this.lang.ssMarkScore}</span>`
  1054. );
  1055. }
  1056. return _result;
  1057. },
  1058. lookWork2(data) {
  1059. // 用于存储结果
  1060. let result = [];
  1061. // 用于跟踪 variable 和对应的 btn 操作
  1062. let map = new Map();
  1063. data.forEach(item => {
  1064. // 提取 variable
  1065. let variableMatch = item.match(
  1066. /<span class=["']variable["']>(.*?)<\/span>/
  1067. );
  1068. // 提取 btn
  1069. let btnMatch = item.match(/<span class=["']btn["']>(.*?)<\/span>/);
  1070. if (variableMatch) {
  1071. let variable = variableMatch[1];
  1072. if (btnMatch) {
  1073. let btn = btnMatch[1];
  1074. if (!map.has(variable)) {
  1075. map.set(variable, []);
  1076. }
  1077. // 存储 btn 操作
  1078. map.get(variable).push(btn);
  1079. } else {
  1080. // 如果没有 btn 操作,直接推入结果
  1081. result.push(item);
  1082. }
  1083. }
  1084. });
  1085. // 构建结果数组
  1086. map.forEach((btns, variable) => {
  1087. // 构建新的字符串
  1088. let newString = `${this.lang.ssPerformActionOn}<span class="variable">${variable}</span>${this.lang.ssHomeworkOf}<span class="btn">${btns.join(
  1089. ","
  1090. )}</span>`;
  1091. result.push(newString);
  1092. });
  1093. return Array.from(new Set(result));
  1094. },
  1095. lookTask(data) {
  1096. // 创建一个对象来存储 variable 和对应的操作
  1097. let map = {};
  1098. let arr = Array.from(new Set(data));
  1099. arr.forEach(item => {
  1100. // 提取 variable 和操作部分
  1101. let variableMatch = item.match(
  1102. /<span class=["']variable["']>(.*?)<\/span>/
  1103. );
  1104. let operationMatch = item.match(/<\/span>(.*?)$/);
  1105. if (variableMatch && operationMatch) {
  1106. let variable = variableMatch[1];
  1107. let operation = operationMatch[1];
  1108. if (!map[variable]) {
  1109. map[variable] = [];
  1110. }
  1111. // 将操作部分去掉前面的 "的" 字符串,并添加到 map 中
  1112. map[variable].push(operation.replace(/^的/, ""));
  1113. }
  1114. });
  1115. // 构建结果数组
  1116. let result = [];
  1117. for (let variable in map) {
  1118. // 将操作部分合并成一个字符串
  1119. let combinedOperations = map[variable].join("、");
  1120. result.push(
  1121. `查看<span class="variable">${variable}</span>的<span class="btn">${combinedOperations}</span>`
  1122. );
  1123. }
  1124. return result;
  1125. },
  1126. extractText(htmlString, regex) {
  1127. const matches = htmlString.match(regex);
  1128. return matches ? matches.map(match => match.replace(regex, "$1")) : [];
  1129. },
  1130. isMoreThanSeconds(time1, time2, exceed) {
  1131. // 将时间字符串转换为 Date 对象
  1132. let date1 = new Date(time1);
  1133. let date2 = new Date(time2);
  1134. // 获取时间戳(毫秒)
  1135. let timestamp1 = date1.getTime();
  1136. let timestamp2 = date2.getTime();
  1137. // 计算两个时间戳的差异(秒)
  1138. let diffInSeconds = Math.abs(timestamp2 - timestamp1) / 1000;
  1139. // 判断差异是否超过 10 秒
  1140. return diffInSeconds > exceed;
  1141. },
  1142. insertMemorandum(_html) {
  1143. // return;
  1144. //保存行为操作
  1145. //variable
  1146. //btn
  1147. let params = [
  1148. {
  1149. uid: this.userid,
  1150. courseId: this.courseId + (this.tcid2 ? this.tcid2 : ""),
  1151. content: _html
  1152. }
  1153. ];
  1154. this.ajax
  1155. .post(
  1156. this.$store.state.api + "insert_systemOperation_countdownBehavior",
  1157. params
  1158. )
  1159. .then(res => {
  1160. if (res.data == 1) {
  1161. console.log("保存操作成功");
  1162. } else {
  1163. console.log("保存操作失败");
  1164. }
  1165. })
  1166. .catch(e => {
  1167. console.log("保存操作失败");
  1168. console.log(e);
  1169. });
  1170. },
  1171. changeShowType(newType) {
  1172. this.showType = newType;
  1173. if (this.showType == 1) {
  1174. this.selectMemorandum();
  1175. }
  1176. },
  1177. changeType(newType) {
  1178. if (this.isCountdown || this.isKeepTime) return;
  1179. this.choiceBehavior = [];
  1180. this.type = newType;
  1181. },
  1182. changeBehaviorTagType(newType) {
  1183. if (this.isCountdown) return this.$message.error(this.lang.ssCountdownRunning);
  1184. if (this.isKeepTime) return this.$message.error(this.lang.ssTimerRunning);
  1185. if (this.behaviorTagType == newType) return;
  1186. this.choiceBehavior = [];
  1187. this.behaviorTagType = newType;
  1188. if (this.behaviorTagType == 1 && this.behaviorTagMore.length <= 0) {
  1189. this.getBehaviorTagMore();
  1190. }
  1191. },
  1192. setCountdownTime(newTime = 0) {
  1193. if (this.isCountdown) return this.$message.error(this.lang.ssCountdownRunning);
  1194. if (this.isKeepTime) return this.$message.error(this.lang.ssTimerRunning);
  1195. this.countdownTime = newTime;
  1196. },
  1197. addTime(time = 0) {
  1198. if (this.isCountdown) return console.log("正在计时");
  1199. if (this.countdownTime >= 3600) {
  1200. return this.$message.error(this.lang.ssCountdownMaxHour);
  1201. }
  1202. if (this.countdownTime + time > 3600) {
  1203. return (this.countdownTime = 3600);
  1204. }
  1205. this.countdownTime += time;
  1206. },
  1207. reduceTime(time = 0) {
  1208. if (this.isCountdown) return console.log("正在计时");
  1209. if (this.countdownTime - time < 0) return (this.countdownTime = 0);
  1210. this.countdownTime -= time;
  1211. },
  1212. choiceBehaviorTag(tag) {
  1213. if (this.isCountdown) return this.$message.error(this.lang.ssCountdownRunning);
  1214. if (this.isKeepTime) return this.$message.error(this.lang.ssTimerRunning);
  1215. let _index = this.choiceBehavior.findIndex(i => i == tag);
  1216. if (_index != -1) {
  1217. // 数组删除指定下标数据
  1218. this.choiceBehavior.splice(_index, 1);
  1219. } else {
  1220. this.choiceBehavior.push(tag);
  1221. }
  1222. },
  1223. countdownTimeFn() {
  1224. if (this.isCountdown) {
  1225. //取消
  1226. clearInterval(this.countdownTimeTimer);
  1227. this.countdownTimeTimer = null;
  1228. this.isCountdown = false;
  1229. if (this.$refs.audioRef.playing && this.sourceActive) {
  1230. this.$refs.audioRef.pause();
  1231. }
  1232. this.$message.success(this.lang.ssCountdownPaused);
  1233. } else {
  1234. //开始
  1235. if (this.countdownTime == 0)
  1236. return this.$message.error(this.lang.ssSetCountdownTime);
  1237. this.isCountdown = true;
  1238. this.$message.success(this.lang.ssCountdownStarted);
  1239. if (this.sourceActive) {
  1240. this.$refs.audioRef.setVolume(0);
  1241. this.$refs.audioRef.play();
  1242. }
  1243. if (this.countdownTime >= 20 && this.sourceActive) {
  1244. let volume = 0;
  1245. let sourceTimer = setInterval(() => {
  1246. volume += 1;
  1247. if (volume >= 10) {
  1248. volume = 10;
  1249. clearInterval(sourceTimer);
  1250. sourceTimer = null;
  1251. }
  1252. this.$refs.audioRef.setVolume(volume / 10);
  1253. }, 1000);
  1254. } else if (
  1255. this.countdownTime <= 20 &&
  1256. this.countdownTime > 10 &&
  1257. this.sourceActive
  1258. ) {
  1259. this.$refs.audioRef.setVolume(1);
  1260. } else if (this.countdownTime <= 10 && this.sourceActive) {
  1261. this.$refs.audioRef.stop();
  1262. this.$refs.endSourceUrlRef.setProgress(
  1263. (10 - this.countdownTime) / 10
  1264. );
  1265. this.$refs.endSourceUrlRef.play();
  1266. }
  1267. this.countdownTimeTimer = setInterval(() => {
  1268. this.isCountdown = true;
  1269. this.countdownTime -= 1;
  1270. }, 1000);
  1271. let timeShow = `${this.countdownTimeShow.m1}${this.countdownTimeShow.m2}${this.lang.ssMinuteWord}${this.countdownTimeShow.s1}${this.countdownTimeShow.s2}${this.lang.ssSecondWord}`;
  1272. this.insertMemorandum(
  1273. `${this.lang.ssSet}<span class="variable">${timeShow}</span><span class="btn">${this.lang.ssCountdown}</span>${
  1274. this.choiceBehavior.length > 0
  1275. ? this.lang.ssUsedFor +
  1276. '<span class="btn">' +
  1277. this.choiceBehavior.join("、") +
  1278. "</span>"
  1279. : ""
  1280. }`
  1281. );
  1282. }
  1283. },
  1284. countdownTimeFinish() {
  1285. clearInterval(this.countdownTimeTimer);
  1286. this.countdownTimeTimer = null;
  1287. this.isCountdown = false;
  1288. this.$parent.type = 1;
  1289. this.$parent.itemType = 3;
  1290. this.changeShowType(0);
  1291. if (this.$refs.audioRef.playing && this.sourceActive) {
  1292. this.$refs.audioRef.pause();
  1293. }
  1294. let _data = {
  1295. type: "countdown",
  1296. time: this.countdownTimeDefault,
  1297. tag: this.choiceBehavior
  1298. };
  1299. this.insertMemorandum(`<span class="btn">倒计时</span>结束`);
  1300. this.choiceBehavior = [];
  1301. this.insertData(_data);
  1302. },
  1303. keepTimeFn() {
  1304. if (this.isKeepTime) {
  1305. this.isKeepTime = false;
  1306. clearInterval(this.keepTimeTimer);
  1307. this.keepTimeTimer = null;
  1308. if (this.$refs.audioRef.playing && this.sourceActive) {
  1309. this.$refs.audioRef.pause();
  1310. }
  1311. this.$message.success(this.lang.ssTimerStopped);
  1312. } else {
  1313. this.isKeepTime = true;
  1314. if (this.sourceActive) {
  1315. this.$refs.audioRef.setVolume(1);
  1316. this.$refs.audioRef.play();
  1317. }
  1318. this.keepTimeTimer = setInterval(() => {
  1319. this.keepTime += 1;
  1320. }, 1000);
  1321. this.$message.success(this.lang.ssTimerStarted);
  1322. this.insertMemorandum(
  1323. `使用<span class="btn">计时器</span>${
  1324. this.choiceBehavior.length > 0
  1325. ? ",用于" +
  1326. '<span class="btn">' +
  1327. this.choiceBehavior.join("、") +
  1328. "</span>"
  1329. : ""
  1330. }`
  1331. );
  1332. }
  1333. },
  1334. music() {
  1335. this.sourceActive = !this.sourceActive;
  1336. if (
  1337. (this.$refs.audioRef.playing || this.$refs.endSourceUrlRef.playing) &&
  1338. !this.sourceActive
  1339. ) {
  1340. this.$refs.audioRef.pause();
  1341. this.$refs.endSourceUrlRef.stop();
  1342. } else if (this.sourceActive) {
  1343. if (this.isCountdown) {
  1344. if (this.countdownTime > 10) {
  1345. this.$refs.audioRef.play();
  1346. } else {
  1347. this.$refs.audioRef.stop();
  1348. this.$refs.endSourceUrlRef.setProgress(
  1349. (10 - this.countdownTime) / 10
  1350. );
  1351. this.$refs.endSourceUrlRef.play();
  1352. }
  1353. } else if (this.isKeepTime) {
  1354. this.$refs.audioRef.play();
  1355. }
  1356. }
  1357. },
  1358. reset() {
  1359. if (this.type == 0) {
  1360. if (this.isCountdown) {
  1361. this.$confirm(this.lang.ssConfirmResetCountdown, this.lang.ssTip, {
  1362. confirmButtonText: this.lang.ssConfirm,
  1363. cancelButtonText: this.lang.ssCancel,
  1364. type: "warning"
  1365. })
  1366. .then(_ => {
  1367. clearInterval(this.countdownTimeTimer);
  1368. this.countdownTimeTimer = null;
  1369. // this.countdownTime = this.countdownTimeDefault;
  1370. this.countdownTime = 0;
  1371. this.isCountdown = false;
  1372. this.choiceBehavior = [];
  1373. this.$message.success(this.lang.ssResetDone);
  1374. if (this.$refs.audioRef.playing) {
  1375. this.$refs.audioRef.pause();
  1376. }
  1377. })
  1378. .catch(_ => {
  1379. console.log("取消重置");
  1380. });
  1381. } else {
  1382. this.$confirm(this.lang.ssConfirmResetBasic, this.lang.ssTip, {
  1383. confirmButtonText: this.lang.ssConfirm,
  1384. cancelButtonText: this.lang.ssCancel,
  1385. type: "warning"
  1386. })
  1387. .then(_ => {
  1388. if (this.$refs.audioRef.playing) {
  1389. this.$refs.audioRef.pause();
  1390. }
  1391. // this.countdownTime = this.countdownTimeDefault;
  1392. this.countdownTime = 0;
  1393. this.isCountdown = false;
  1394. this.choiceBehavior = [];
  1395. this.$message.success(this.lang.ssResetDone);
  1396. })
  1397. .catch(_ => {
  1398. console.log("取消重置");
  1399. });
  1400. }
  1401. } else if (this.type == 1) {
  1402. if (this.isKeepTime) {
  1403. this.$confirm(this.lang.ssConfirmResetTimer, this.lang.ssTip, {
  1404. confirmButtonText: this.lang.ssConfirm,
  1405. cancelButtonText: this.lang.ssCancel,
  1406. type: "warning"
  1407. })
  1408. .then(_ => {
  1409. if (this.$refs.audioRef.playing) {
  1410. this.$refs.audioRef.pause();
  1411. }
  1412. clearInterval(this.keepTimeTimer);
  1413. this.keepTimeTimer = null;
  1414. let _data = {
  1415. type: "keepTime",
  1416. time: this.keepTime,
  1417. tag: this.choiceBehavior
  1418. };
  1419. let timeShow = `${this.keepTimeShow.m1}${this.keepTimeShow.m2}${this.lang.ssMinuteWord}${this.keepTimeShow.s1}${this.keepTimeShow.s2}${this.lang.ssSecondWord}`;
  1420. this.insertMemorandum(
  1421. `${this.lang.ssEndTimer}<span class="btn">${this.lang.ssTimerWord}</span><span class="variable">${timeShow}</span>${
  1422. this.choiceBehavior.length > 0
  1423. ? this.lang.ssUsedFor +
  1424. '<span class="btn">' +
  1425. this.choiceBehavior.join("、") +
  1426. "</span>"
  1427. : ""
  1428. }`
  1429. );
  1430. this.keepTime = 0;
  1431. this.isKeepTime = false;
  1432. this.insertData(_data);
  1433. })
  1434. .catch(_ => {
  1435. console.log("取消重置");
  1436. });
  1437. } else {
  1438. let _data = {
  1439. type: "keepTime",
  1440. time: this.keepTime,
  1441. tag: this.choiceBehavior
  1442. };
  1443. if (this.$refs.audioRef.playing) {
  1444. this.$refs.audioRef.pause();
  1445. }
  1446. this.insertData(_data);
  1447. let timeShow = `${this.keepTimeShow.m1}${this.keepTimeShow.m2}${this.lang.ssMinuteWord}${this.keepTimeShow.s1}${this.keepTimeShow.s2}${this.lang.ssSecondWord}`;
  1448. this.insertMemorandum(
  1449. `${this.lang.ssEndTimer}<span class="btn">${this.lang.ssTimerWord}</span><span class="variable">${timeShow}</span>${
  1450. this.choiceBehavior.length > 0
  1451. ? this.lang.ssUsedFor +
  1452. '<span class="btn">' +
  1453. this.choiceBehavior.join("、") +
  1454. "</span>"
  1455. : ""
  1456. }`
  1457. );
  1458. this.keepTime = 0;
  1459. this.isKeepTime = false;
  1460. // this.choiceBehavior = [];
  1461. this.$message.success("已重置");
  1462. }
  1463. }
  1464. },
  1465. getLang() {
  1466. let lang = "";
  1467. if (this.lang.lang == 'cn') {
  1468. lang = "Chinese.";
  1469. } else if (this.lang.lang == 'hk') {
  1470. lang = "Traditional Chinese.";
  1471. } else if (this.lang.lang == 'com') {
  1472. lang = "English.";
  1473. }
  1474. return lang;
  1475. },
  1476. getBehaviorTagMore() {
  1477. this.behaviorTagMoreLoading = true;
  1478. let _textData = `课程名称:${this.courseDetail.title}\n分类:${this.courseDetail.name}\n\n`;
  1479. let _chapters = JSON.parse(this.courseDetail.chapters);
  1480. _chapters.forEach((i1, index1) => {
  1481. if (i1.dyName) {
  1482. _textData += `阶段${index1 + 1}:${i1.dyName}\n`;
  1483. }
  1484. i1.chapterInfo[0].taskJson.forEach((i2, index2) => {
  1485. if (i2.task) {
  1486. _textData += `任务${index2 + 1}:${i2.task}\n`;
  1487. _textData += `${i2.taskDetail}\n`;
  1488. }
  1489. });
  1490. _textData += "\n";
  1491. });
  1492. // 根据语言生成任务描述和格式示例
  1493. let taskDescription = "";
  1494. let formatExample = "";
  1495. if (this.lang.lang == 'cn') {
  1496. taskDescription = "在以下课堂中,如果老师设置一个倒计时,他可能想开展哪些教学活动?每个教学活动使用4个字,进行简洁精确的描述,请返回所有可能的行为名称,不需要额外的解释。请返回最有可能的12个活动类型。";
  1497. formatExample = '["小组汇报","小组讨论","动手实验","课堂游戏","自主学习","作品展示","学生演讲","学生分享","随堂练习","快速问答","阅读资料","观察记录"]';
  1498. } else if (this.lang.lang == 'hk') {
  1499. taskDescription = "在以下課堂中,如果老師設置一個倒計時,他可能想開展哪些教學活動?每個教學活動使用4個字,進行簡潔精確的描述,請返回所有可能的行為名稱,不需要額外的解釋。請返回最有可能的12個活動類型。";
  1500. formatExample = '["小組匯報","小組討論","動手實驗","課堂遊戲","自主學習","作品展示","學生演講","學生分享","隨堂練習","快速問答","閱讀資料","觀察記錄"]';
  1501. } else if (this.lang.lang == 'com') {
  1502. taskDescription = "In the following classroom context, if a teacher sets a countdown timer, what teaching activities might they want to conduct? Each teaching activity should be described in 4 words (or short phrases), be concise and precise. Return all possible activity names without additional explanations. Return the 12 most likely activity types.";
  1503. formatExample = '["Group Report","Group Discussion","Hands-on Experiment","Classroom Game","Independent Learning","Work Display","Student Speech","Student Share","Class Practice","Quick Q&A","Reading Materials","Observation Record"]';
  1504. }
  1505. let _msg = `## Language Requirement
  1506. CRITICAL: You MUST respond in ${this.getLang()} All output content, including activity names in the array, must be in ${this.getLang()}
  1507. ## ATTENTION
  1508. Use '##' to SPLIT SECTIONS, not '#'. Output format must strictly follow the "Format example".
  1509. ## Instruction
  1510. Based on the context provided, follow the "Format example" format and write content. IMPORTANT: All activity names in your response must be in ${this.getLang()}
  1511. ## Task
  1512. ${taskDescription}
  1513. ## Format example
  1514. ${formatExample}
  1515. ## Context
  1516. ${_textData}
  1517. `;
  1518. this.behaviorTagMore = [];
  1519. let params = {
  1520. assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
  1521. userId: this.userid,
  1522. message: [{ type: "text", text: _msg }],
  1523. session_name: uuidv4(),
  1524. file_ids: this.fileId,
  1525. model: "gpt-4o-2024-11-20"
  1526. };
  1527. this.ajax
  1528. // .post("https://gpt4.cocorobo.cn/chat", params)
  1529. // .post("https://claude3.cocorobo.cn/chat", params)
  1530. .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
  1531. .then(res => {
  1532. // console.log(res)
  1533. let _data = res.data.FunctionResponse.message;
  1534. _data = _data.replaceAll("```json", "").replaceAll("```", "");
  1535. const match = _data.match(/\[\s*[^]*\s*\]/);
  1536. let _result = JSON.parse(match[0]);
  1537. this.behaviorTagMore = _result;
  1538. this.behaviorTagMoreLoading = false;
  1539. })
  1540. .catch(e => {
  1541. this.behaviorTagMoreLoading = false;
  1542. this.$message.error(this.lang.ssGetMoreTagsFailed);
  1543. this.behaviorTagType = 0;
  1544. this.behaviorTagMore = [];
  1545. console.log(e);
  1546. });
  1547. },
  1548. insertData(data = null) {
  1549. if (!data) return;
  1550. let params = [
  1551. {
  1552. uid: this.userid,
  1553. courseId: this.courseId,
  1554. content: JSON.stringify(data)
  1555. }
  1556. ];
  1557. this.ajax
  1558. .post(
  1559. this.$store.state.api + "insert_systemOperation_classRoomHelper",
  1560. params
  1561. )
  1562. .then(res => {
  1563. if (res.data == 1) {
  1564. console.log("保存成功");
  1565. } else {
  1566. console.log("保存失败");
  1567. }
  1568. })
  1569. .catch(e => {
  1570. console.log("保存失败👇");
  1571. console.log(e);
  1572. });
  1573. },
  1574. selectMemorandum() {
  1575. this.memorandumLoading = true;
  1576. let params = {
  1577. uid: this.userid,
  1578. courseId: this.courseId + (this.tcid2 ? this.tcid2 : "")
  1579. };
  1580. this.memorandumList = [];
  1581. this.ajax
  1582. .get(
  1583. this.$store.state.api + "select_systemOperation_countdownBehavior",
  1584. params
  1585. )
  1586. .then(res => {
  1587. let _data = res.data[0];
  1588. if (_data.length) {
  1589. // let _result = _data;
  1590. // console.log(_result)
  1591. this.memorandumList = _data;
  1592. } else {
  1593. this.memorandumList = [];
  1594. }
  1595. this.$nextTick(() => {
  1596. this.$refs.stepRef.scrollTop = this.$refs.stepRef.scrollHeight;
  1597. });
  1598. this.memorandumLoading = false;
  1599. })
  1600. .catch(err => {
  1601. console.log(err);
  1602. this.memorandumLoading = false;
  1603. this.$message.error(this.lang.ssGetMemoFailed);
  1604. });
  1605. },
  1606. changeShowInput1(type = true) {
  1607. if (this.isCountdown || this.isKeepTime) return;
  1608. if (type) {
  1609. this.showCountDownInput1 = true;
  1610. this.countDownInputValue1 =
  1611. this.countdownTimeShow.m1 * 10 + this.countdownTimeShow.m2;
  1612. this.countDownInputValue2 =
  1613. this.countdownTimeShow.s1 * 10 + this.countdownTimeShow.s2;
  1614. this.$nextTick(() => {
  1615. this.$refs.countDownInput1Ref.focus();
  1616. });
  1617. } else {
  1618. this.countdownTime =
  1619. this.countDownInputValue1 * 60 + this.countDownInputValue2;
  1620. this.showCountDownInput1 = false;
  1621. }
  1622. },
  1623. handleBlur1() {
  1624. this.changeShowInput1(false);
  1625. },
  1626. changeShowInput2(type = true) {
  1627. if (this.isCountdown || this.isKeepTime) return;
  1628. if (type) {
  1629. this.showCountDownInput2 = true;
  1630. this.countDownInputValue1 =
  1631. this.countdownTimeShow.m1 * 10 + this.countdownTimeShow.m2;
  1632. this.countDownInputValue2 =
  1633. this.countdownTimeShow.s1 * 10 + this.countdownTimeShow.s2;
  1634. this.$nextTick(() => {
  1635. this.$refs.countDownInput2Ref.focus();
  1636. });
  1637. } else {
  1638. this.countdownTime =
  1639. this.countDownInputValue1 * 60 + this.countDownInputValue2;
  1640. this.showCountDownInput2 = false;
  1641. }
  1642. },
  1643. handleBlur2() {
  1644. this.changeShowInput2(false);
  1645. },
  1646. getTimeDifferences(time1, time2) {
  1647. let _time1 = new Date(time1);
  1648. let _time2 = new Date(time2);
  1649. // 计算时间差,得到毫秒数
  1650. const diff = Math.abs(_time2 - _time1);
  1651. // 将毫秒数转换为小时、分钟和秒
  1652. const hours = Math.floor(diff / (1000 * 60 * 60));
  1653. const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
  1654. const seconds = Math.floor((diff % (1000 * 60)) / 1000);
  1655. // 格式化成 "01" 这种格式
  1656. const formatTimeUnit = unit => (unit < 10 ? "0" + unit : unit.toString());
  1657. return {
  1658. h: hours != 0 ? formatTimeUnit(hours) : null,
  1659. m:
  1660. minutes != 0
  1661. ? formatTimeUnit(minutes)
  1662. : hours > 0
  1663. ? formatTimeUnit(minutes)
  1664. : null,
  1665. s: formatTimeUnit(seconds)
  1666. };
  1667. },
  1668. changeSourceUrl(url){
  1669. if(this.isCountdown || this.isKeepTime)return this.$message.error(this.lang.ssStopTimerFirst);
  1670. if(this.sourceUrl == url)return this.showSourceList = false;
  1671. this.sourceUrl = url;
  1672. this.showSourceList = false;
  1673. }
  1674. }
  1675. };
  1676. </script>
  1677. <style scoped>
  1678. .countdown {
  1679. width: 100%;
  1680. height: 100%;
  1681. /* display: flex;
  1682. flex-direction: column;
  1683. align-items: center; */
  1684. /* justify-content: center; */
  1685. /* padding: auto;
  1686. overflow: auto; */
  1687. }
  1688. .c_timeBox {
  1689. width: 100%;
  1690. height: 100%;
  1691. position: relative;
  1692. display: flex;
  1693. flex-direction: column;
  1694. justify-content: flex-end;
  1695. }
  1696. .c_tb_top {
  1697. width: 100%;
  1698. max-height: calc(100% - 60px);
  1699. margin-top: auto;
  1700. overflow-x: hidden;
  1701. padding-bottom: 30px;
  1702. }
  1703. .c_behavior {
  1704. width: 100%;
  1705. height: 100%;
  1706. }
  1707. .c_changeType {
  1708. width: 100%;
  1709. height: 60px;
  1710. display: flex;
  1711. align-items: center;
  1712. justify-content: space-evenly;
  1713. border-top: solid 1px #e7e7e7;
  1714. box-sizing: border-box;
  1715. }
  1716. .c_changeType > span {
  1717. width: 2px;
  1718. height: 30px;
  1719. background-color: #e7e7e7;
  1720. }
  1721. .c_ct_btn {
  1722. width: 100px;
  1723. height: 90%;
  1724. display: flex;
  1725. justify-content: center;
  1726. align-items: center;
  1727. cursor: pointer;
  1728. position: relative;
  1729. }
  1730. .c_ct_btn > div {
  1731. font-size: 18px;
  1732. font-weight: bold;
  1733. }
  1734. .c_ct_btn > span {
  1735. position: absolute;
  1736. width: 60%;
  1737. height: 60%;
  1738. background: #6c8cff67;
  1739. filter: blur(20px);
  1740. border-radius: 50%;
  1741. }
  1742. .c_ct_btn > svg {
  1743. width: 30px;
  1744. height: 30px;
  1745. position: absolute;
  1746. margin-top: 30px;
  1747. }
  1748. .c_time {
  1749. width: 100%;
  1750. height: 200px;
  1751. display: flex;
  1752. align-items: center;
  1753. justify-content: center;
  1754. }
  1755. .c_t_item {
  1756. color: black;
  1757. display: flex;
  1758. align-items: center;
  1759. justify-content: center;
  1760. }
  1761. .c_t_i_card {
  1762. display: flex;
  1763. align-items: center;
  1764. justify-content: center;
  1765. position: relative;
  1766. padding: 0px 30px;
  1767. background-color: #fff;
  1768. margin: 0 10px;
  1769. box-shadow: 0px 0px 5px 2px #1d398314;
  1770. /* box-shadow: 1px 1px 20px 4px #1d39830d; */
  1771. border-radius: 8px;
  1772. }
  1773. .c_t_i_card > span {
  1774. position: absolute;
  1775. bottom: 25px;
  1776. right: 10px;
  1777. font-size: 16px;
  1778. }
  1779. .c_t_i_card > div {
  1780. display: flex;
  1781. flex-direction: column;
  1782. align-items: center;
  1783. justify-content: space-between;
  1784. }
  1785. .c_t_i_card > div > div {
  1786. font-size: 5em;
  1787. font-weight: bold;
  1788. margin: 0 5px;
  1789. }
  1790. .c_t_i_card > div > span {
  1791. margin: 0;
  1792. display: flex;
  1793. justify-content: center;
  1794. align-items: center;
  1795. width: 25px;
  1796. height: 25px;
  1797. position: absolute;
  1798. }
  1799. .c_t_i_c_inputBox {
  1800. width: 100px;
  1801. height: 91px;
  1802. display: flex;
  1803. }
  1804. .c_t_i_c_inputBox >>> .el-input {
  1805. width: 100%;
  1806. height: 100%;
  1807. border-color: none;
  1808. outline: none;
  1809. }
  1810. .c_t_i_c_inputBox >>> .el-input > input {
  1811. width: 100%;
  1812. height: 100%;
  1813. text-align: center;
  1814. border: none;
  1815. outline: none;
  1816. color: black;
  1817. padding: 0;
  1818. line-height: 0;
  1819. font-weight: bold;
  1820. }
  1821. .c_t_i_btnTop {
  1822. top: -30px;
  1823. }
  1824. .c_t_i_btnBottom {
  1825. bottom: -30px;
  1826. }
  1827. .c_t_i_btn {
  1828. font-size: 1.3em;
  1829. width: 25px;
  1830. height: 25px;
  1831. display: flex;
  1832. justify-content: center;
  1833. align-items: center;
  1834. padding: 0 !important;
  1835. background-color: #f0f2f5;
  1836. }
  1837. .c_choiceTime {
  1838. width: 100%;
  1839. height: auto;
  1840. box-sizing: border-box;
  1841. padding: 20px;
  1842. }
  1843. .c_title {
  1844. display: flex;
  1845. align-items: center;
  1846. justify-content: space-between;
  1847. width: 100%;
  1848. }
  1849. .c_title > span {
  1850. font-size: 20px;
  1851. font-weight: bold;
  1852. }
  1853. .c_t_btnArea {
  1854. margin-left: 20px;
  1855. display: flex;
  1856. justify-content: center;
  1857. align-items: center;
  1858. }
  1859. .c_t_btnArea > span {
  1860. width: 40px;
  1861. display: flex;
  1862. justify-content: center;
  1863. align-items: center;
  1864. margin-left: 10px;
  1865. cursor: pointer;
  1866. color: #999999;
  1867. position: relative;
  1868. font-size: 14px;
  1869. }
  1870. .c_t_ba_active {
  1871. color: black !important;
  1872. }
  1873. .c_t_ba_active::after {
  1874. content: "";
  1875. width: 100%;
  1876. height: 3px;
  1877. background-color: #3681fc;
  1878. position: absolute;
  1879. bottom: -7px;
  1880. left: 1px;
  1881. }
  1882. .c_ct_box {
  1883. width: 100%;
  1884. height: auto;
  1885. display: flex;
  1886. align-items: center;
  1887. justify-content: space-around;
  1888. flex-wrap: wrap;
  1889. padding-top: 10px;
  1890. }
  1891. .c_ct_box > span {
  1892. width: 20%;
  1893. height: 30px;
  1894. border-radius: 20px;
  1895. box-sizing: border-box;
  1896. border: 0.5px solid #e0eafb;
  1897. margin: 10px 2%;
  1898. background-color: #fff;
  1899. display: flex;
  1900. align-items: center;
  1901. justify-content: center;
  1902. transition: 0.1s;
  1903. cursor: pointer;
  1904. box-shadow: 0px 2px 5px 0px #1d398314;
  1905. box-shadow: 0.5px 0.5px 10px 2px #1d39830d;
  1906. }
  1907. .c_ct_box > span:hover {
  1908. background-color: #409eff;
  1909. border: solid 1px #409eff;
  1910. color: #fff;
  1911. }
  1912. .c_behaviorTag {
  1913. width: 100%;
  1914. height: auto;
  1915. box-sizing: border-box;
  1916. padding: 20px;
  1917. }
  1918. .c_bt_box {
  1919. width: 100%;
  1920. height: auto;
  1921. min-height: 100px;
  1922. display: flex;
  1923. align-items: flex-start;
  1924. justify-content: space-around;
  1925. flex-wrap: wrap;
  1926. overflow: auto;
  1927. margin-top: 10px;
  1928. }
  1929. .c_bt_box > span {
  1930. width: auto;
  1931. height: auto;
  1932. padding: 6px 10px;
  1933. border-radius: 50px;
  1934. border: 0.5px solid #e0eafb;
  1935. box-shadow: 0px 2px 5px 0px #1d398314;
  1936. box-shadow: 0.5px 0.5px 10px 2px #1d39830d;
  1937. margin: 10px 0;
  1938. background-color: #fff;
  1939. display: flex;
  1940. align-items: center;
  1941. justify-content: center;
  1942. transition: 0.1s;
  1943. cursor: pointer;
  1944. font-size: 15px;
  1945. }
  1946. .c_bt_b_active {
  1947. background-color: #409eff !important;
  1948. border: solid 1px #409eff !important;
  1949. color: #fff;
  1950. }
  1951. .c_bt_box > span:hover {
  1952. background-color: #409eff !important;
  1953. border: solid 1px #409eff !important;
  1954. color: #fff !important;
  1955. }
  1956. .c_btnArea {
  1957. width: 100%;
  1958. height: 100px;
  1959. display: flex;
  1960. align-items: center;
  1961. justify-content: center;
  1962. }
  1963. .c_btnArea > span {
  1964. width: auto;
  1965. height: auto;
  1966. padding: 5px 10px;
  1967. /* border: solid 1px #d0d0d0;
  1968. background-color: #fff; */
  1969. /* border-radius: 20px; */
  1970. cursor: pointer;
  1971. transition: 0.2s;
  1972. position: relative;
  1973. }
  1974. .c_b_musicListArea {
  1975. position: absolute;
  1976. left: -20px;
  1977. top: 10px;
  1978. width: 20px;
  1979. height: 20px;
  1980. }
  1981. .c_b_musicListArea > span {
  1982. width: 20px;
  1983. height: 20px;
  1984. display: flex;
  1985. justify-content: center;
  1986. align-items: center;
  1987. cursor: pointer;
  1988. }
  1989. .c_b_musicListArea > div {
  1990. width: 150px;
  1991. height: 200px;
  1992. position: absolute;
  1993. bottom: 40px;
  1994. left: -20px;
  1995. cursor: default;
  1996. border-radius: 5px;
  1997. box-sizing: border-box;
  1998. padding: 5px;
  1999. overflow: auto;
  2000. background-color: #fff;
  2001. box-shadow: 0px 0px 5px 2px #1d398314;
  2002. }
  2003. .c_b_musicListArea>div>div{
  2004. width: 100%;
  2005. height: 30px;
  2006. border-radius: 5px;
  2007. display: flex;
  2008. align-items: center;
  2009. box-sizing: border-box;
  2010. padding-left: 10px;
  2011. cursor: pointer;
  2012. transition: 0.2s;
  2013. margin-bottom: 5px;
  2014. }
  2015. .c_b_musicListArea>div>div:hover{
  2016. background-color: #f0f2f5;
  2017. }
  2018. .c_b_musicListArea_active{
  2019. background-color: #409eff !important;
  2020. color: #fff;
  2021. }
  2022. .c_btnArea > span > svg {
  2023. width: 30px;
  2024. height: 30px;
  2025. }
  2026. /* .c_btnArea > span:hover {
  2027. border: solid 1px #409eff;
  2028. background-color: #409eff;
  2029. color: #fff;
  2030. } */
  2031. .c_ba_startArea {
  2032. width: 60px;
  2033. height: 60px;
  2034. margin: 0 40px;
  2035. display: flex;
  2036. align-items: center;
  2037. justify-content: center;
  2038. }
  2039. .c_ba_startType0 {
  2040. width: 60px;
  2041. height: 60px;
  2042. display: flex;
  2043. align-items: center;
  2044. justify-content: center;
  2045. border-radius: 50%;
  2046. border: solid 8px #e0eafb;
  2047. color: #e0eafb;
  2048. cursor: pointer;
  2049. transition: 0.2s;
  2050. }
  2051. .c_ba_startType0 > svg {
  2052. fill: #afbff7;
  2053. height: 60%;
  2054. position: relative;
  2055. left: 3px;
  2056. transition: 0.2s;
  2057. }
  2058. .c_ba_startType {
  2059. width: 60px;
  2060. height: 60px;
  2061. display: flex;
  2062. align-items: center;
  2063. justify-content: center;
  2064. border-radius: 50%;
  2065. border: solid 8px #3681fc;
  2066. color: #3681fc;
  2067. cursor: pointer;
  2068. transition: 0.2s;
  2069. }
  2070. .c_ba_startType > svg {
  2071. fill: #677bf0;
  2072. height: 60%;
  2073. position: relative;
  2074. left: 3px;
  2075. transition: 0.2s;
  2076. }
  2077. .c_ba_startType2 {
  2078. width: 60px;
  2079. height: 60px;
  2080. display: flex;
  2081. align-items: center;
  2082. justify-content: center;
  2083. border-radius: 50%;
  2084. border: solid 8px #f5222d;
  2085. color: #f5222d;
  2086. cursor: pointer;
  2087. transition: 0.2s;
  2088. }
  2089. .c_ba_startType2 > svg {
  2090. fill: #f5222d;
  2091. height: 60%;
  2092. transition: 0.2s;
  2093. }
  2094. .sourceActive {
  2095. border: solid 1px #409eff !important;
  2096. background-color: #409eff !important;
  2097. color: #fff;
  2098. }
  2099. .c_step {
  2100. width: 100%;
  2101. height: calc(100% - 80px - 40px);
  2102. margin-top: 20px;
  2103. padding: 20px 50px;
  2104. padding-left: 120px;
  2105. box-sizing: border-box;
  2106. overflow: auto;
  2107. }
  2108. .c_step >>> .el-timeline-item .c_s_time {
  2109. width: 100px;
  2110. height: auto;
  2111. position: absolute;
  2112. display: flex;
  2113. justify-content: flex-end;
  2114. align-items: center;
  2115. top: 50%;
  2116. transform: translate(0, -25%);
  2117. left: -120px;
  2118. }
  2119. .c_step >>> .el-timeline-item .c_s_time > div {
  2120. padding: 2px 4px;
  2121. background-color: #e0eafb;
  2122. color: #3681fc;
  2123. font-size: 12px;
  2124. border-radius: 5px;
  2125. display: flex;
  2126. justify-content: center;
  2127. align-items: center;
  2128. }
  2129. .c_step >>> .el-timeline-item .c_s_time > div > span {
  2130. margin: 0;
  2131. }
  2132. .c_step >>> .el-timeline .btn {
  2133. color: #2972f4;
  2134. }
  2135. .c_step >>> .el-timeline .variable {
  2136. color: #319b62;
  2137. }
  2138. .c_step >>> .blue .el-timeline-item__tail {
  2139. border-left: 6px solid #b3ccfa !important;
  2140. }
  2141. .c_step >>> .el-timeline-item__tail::after {
  2142. content: "";
  2143. width: 10px;
  2144. height: 95%;
  2145. position: absolute;
  2146. left: -20px;
  2147. bottom: -5px;
  2148. border: solid 1px #68a1fd;
  2149. border-right: none;
  2150. }
  2151. .c_step >>> .green .el-timeline-item__tail {
  2152. border-left: 6px solid #b7eacb !important;
  2153. }
  2154. .c_step >>> .el-timeline-item__node {
  2155. background-color: #ffffff;
  2156. box-sizing: border-box;
  2157. border: 2px solid #b3ccfa;
  2158. position: relative;
  2159. left: -0.5px;
  2160. }
  2161. .c_s_item {
  2162. display: flex;
  2163. justify-content: center;
  2164. align-items: center;
  2165. }
  2166. .ActivityMemo {
  2167. width: 100%;
  2168. height: 30px;
  2169. display: flex;
  2170. align-items: center;
  2171. margin-top: 20px;
  2172. box-sizing: border-box;
  2173. padding-left: 20px;
  2174. }
  2175. .ActivityMemo > span {
  2176. display: flex;
  2177. align-items: center;
  2178. cursor: pointer;
  2179. }
  2180. .ActivityMemo > span > svg {
  2181. margin-left: 5px;
  2182. position: relative;
  2183. top: 1px;
  2184. width: 20px;
  2185. height: 20px;
  2186. }
  2187. .behaviorBack {
  2188. width: 100%;
  2189. height: 30px;
  2190. display: flex;
  2191. align-items: center;
  2192. margin-top: 20px;
  2193. box-sizing: border-box;
  2194. padding-left: 20px;
  2195. }
  2196. .behaviorBack > span {
  2197. display: flex;
  2198. align-items: center;
  2199. cursor: pointer;
  2200. width: 80px;
  2201. }
  2202. .behaviorBack > span > svg {
  2203. margin-right: 5px;
  2204. position: relative;
  2205. top: 1px;
  2206. width: 20px;
  2207. height: 20px;
  2208. transform: rotate(180deg);
  2209. }
  2210. .c_b_btnArea {
  2211. display: flex;
  2212. justify-content: center;
  2213. align-items: center;
  2214. margin-top: 10px;
  2215. position: relative;
  2216. }
  2217. .c_b_btnArea > span {
  2218. position: absolute;
  2219. right: 20px;
  2220. width: 30px;
  2221. height: 30px;
  2222. cursor: pointer;
  2223. }
  2224. .c_b_btnArea > span > svg {
  2225. width: 100%;
  2226. height: 100%;
  2227. }
  2228. </style>