questionBank.vue 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807
  1. <template>
  2. <view class="questionBank">
  3. <uni-nav-bar @clickLeft="clickLeft" left-icon="back" ref="navbar" :statusBar="true"
  4. :title="examData.examName"></uni-nav-bar>
  5. <swiper class="swiper" :current="current" @change="swiperChange">
  6. <swiper-item v-for="(bank, bankIndex) in questionList" :key="bankIndex">
  7. <view class="pageContent">
  8. <view class="pad_8 titBox">
  9. <view class="firstLetter">
  10. <view class="leftLetters">
  11. <view class="btnType">
  12. <text v-if="bank.type == 1">单选</text>
  13. <text v-if="bank.type == 2">多选</text>
  14. <text v-if="bank.type == 3">判断</text>
  15. <text v-if="bank.type == 4">案例</text>
  16. <text v-if="bank.type == 5">简答</text>
  17. </view>
  18. <text>{{ bankIndex + 1 }}/{{ questionList.length }}</text>
  19. </view>
  20. <view style="color: #666; font-size: 28rpx">{{
  21. countdown(lastTime)
  22. }}</view>
  23. </view>
  24. <view class="titles" @click="showPhoto(bank.content)"><rich-text
  25. :nodes="bank.content"></rich-text></view>
  26. </view>
  27. <template v-if="bank.type == 1">
  28. <view class="pad_8 titBox no-margin">
  29. <view v-if="!bank.ques">
  30. <view v-for="(item, index) in bank.jsonStr" :key="index" class="lisSty"
  31. @click="radioSelect(item.optionsId, bankIndex)">
  32. <view class="activeTI">{{ ast[index] }}</view>
  33. <view class="flex_auto">{{ item.content }}
  34. <view v-if="item.imgUrl">
  35. <image style="width: 600rpx" mode="widthFix"
  36. :src="$method.splitImgHost(item.imgUrl)"></image>
  37. </view>
  38. </view>
  39. </view>
  40. </view>
  41. <view v-if="bank.ques">
  42. <view v-for="(item, index) in bank.jsonStr" :key="index" class="lisSty"
  43. @click="radioSelect(item.optionsId, bankIndex)">
  44. <text :class="{
  45. right:
  46. bankType == 1 &&
  47. (item.optionsId == bank.ques ||
  48. item.optionsId == bank.ans),
  49. wrong:
  50. bankType == 1 &&
  51. item.optionsId == bank.ques &&
  52. bank.ques != bank.ans,
  53. user_choose: bankType == 2 && item.optionsId == bank.ques,
  54. }" class="activeTI">
  55. {{ ast[index] }}
  56. </text>
  57. <view class="flex_auto">
  58. {{ item.content }}
  59. <view v-if="item.imgUrl">
  60. <image style="width: 600rpx" mode="widthFix"
  61. :src="$method.splitImgHost(item.imgUrl)"></image>
  62. </view>
  63. </view>
  64. </view>
  65. </view>
  66. </view>
  67. <view v-if="bankType == 1 && bank.ques">
  68. <view class="pad_8 answer">
  69. <view>题目答案:{{ ast[bank.ans - 1] }} </view>
  70. <view>我的答案:{{ ast[bank.ques - 1] }}</view>
  71. </view>
  72. <view class="pad_8 answerInfos">
  73. <view class="answerTitle">答案解析</view>
  74. <view class="answerContent"><rich-text :nodes="bank.analysisContent"></rich-text></view>
  75. </view>
  76. </view>
  77. </template>
  78. <template v-if="bank.type == 2">
  79. <view class="pad_8 titBox no-margin">
  80. <view v-if="!bank.ques">
  81. <view v-for="(item, index) in bank.jsonStr" :key="index" class="lisSty"
  82. @click="checkboxSelect(item.optionsId, bankIndex, index)">
  83. <view :class="{ checked: item.checked }" class="activeTI">{{
  84. ast[index]
  85. }}</view>
  86. <view class="flex_auto">
  87. {{ item.content }}
  88. <view v-if="item.imgUrl">
  89. <image style="width: 600rpx" mode="widthFix"
  90. :src="$method.splitImgHost(item.imgUrl)"></image>
  91. </view>
  92. </view>
  93. </view>
  94. </view>
  95. <view v-if="bank.ques">
  96. <view v-for="(item, index) in bank.jsonStr" :key="index" class="lisSty"
  97. @click="checkboxSelect(item.optionsId, bankIndex, index)">
  98. <text :class="{
  99. right:
  100. bankType == 1 &&
  101. (bank.ques.indexOf(item.optionsId) != -1 ||
  102. bank.ans.indexOf(item.optionsId) != -1),
  103. wrong:
  104. bankType == 1 &&
  105. bank.ques.indexOf(item.optionsId) != -1 &&
  106. bank.ans.indexOf(item.optionsId) == -1,
  107. user_choose: bankType == 2 && item.checked,
  108. }" class="activeTI">
  109. {{ ast[index] }}
  110. </text>
  111. <view class="flex_auto">
  112. {{ item.content }}
  113. <view v-if="item.imgUrl">
  114. <image style="width: 600rpx" mode="widthFix"
  115. :src="$method.splitImgHost(item.imgUrl)"></image>
  116. </view>
  117. </view>
  118. </view>
  119. </view>
  120. <view v-if="bankType == 2 || (bankType == 1 && !bank.ques)" class="submit_checkbox"
  121. :class="{ disabled: !isCheckboxChecked(bank.jsonStr) }"
  122. @click="checkboxSubmit(bankIndex)">确认答案</view>
  123. </view>
  124. <view v-if="bankType == 1 && bank.ques">
  125. <view class="pad_8 answer">
  126. <view>
  127. 题目答案:
  128. <text v-for="(ansItem, ansIndex) in bank.ans"
  129. :key="ansIndex">{{ ast[ansItem - 1] }}</text>
  130. </view>
  131. <view>
  132. 我的答案:
  133. <text v-for="(quesItem, quesIndex) in bank.ques"
  134. :key="quesIndex">{{ ast[quesItem - 1] }}</text>
  135. </view>
  136. </view>
  137. <view class="pad_8 answerInfos">
  138. <view class="answerTitle">答案解析</view>
  139. <view class="answerContent"><rich-text :nodes="bank.analysisContent"></rich-text></view>
  140. </view>
  141. </view>
  142. </template>
  143. <template v-if="bank.type == 3">
  144. <view class="pad_8 titBox no-margin">
  145. <view v-if="!bank.ques">
  146. <view v-for="(item, index) in judge" :key="index" class="lisSty"
  147. @click="judgeSelect(index, bankIndex)">
  148. <view class="activeTI">{{ ast[index] }}</view>
  149. <view class="flex_auto">
  150. {{ item }}
  151. <view v-if="item.imgUrl">
  152. <image style="width: 600rpx" mode="widthFix"
  153. :src="$method.splitImgHost(item.imgUrl)"></image>
  154. </view>
  155. </view>
  156. </view>
  157. </view>
  158. <view v-if="bank.ques">
  159. <view v-for="(item, index) in judge" :key="index" class="lisSty"
  160. @click="judgeSelect(index, bankIndex)">
  161. <!-- right: bankType == 1 && (index == bank.ques || index == bank.ans),
  162. wrong: bankType == 1 && (index == bank.ques && bank.ques != bank.ans),
  163. user_choose: bankType == 2 && (index == bank.ques), -->
  164. <text :class="{
  165. right:
  166. bankType == 1 &&
  167. (index == (bank.ques == 1 ? 0 : 1) ||
  168. index != bank.ans),
  169. wrong:
  170. bankType == 1 &&
  171. index == (bank.ques == 1 ? 0 : 1) &&
  172. bank.ques != bank.ans,
  173. user_choose:
  174. bankType == 2 && index == (bank.ques == 1 ? 0 : 1),
  175. }" class="activeTI">
  176. {{ ast[index] }}
  177. </text>
  178. <view class="flex_auto">
  179. {{ item }}
  180. <view v-if="item.imgUrl">
  181. <image style="width: 600rpx" mode="widthFix"
  182. :src="$method.splitImgHost(item.imgUrl)"></image>
  183. </view>
  184. </view>
  185. </view>
  186. </view>
  187. </view>
  188. <view v-if="bankType == 1 && bank.ques">
  189. <view class="pad_8 answer">
  190. <view>题目答案:{{ ast[bank.ans == 1 ? 0 : 1] }}</view>
  191. <view>我的答案:{{ ast[bank.ques == 1 ? 0 : 1] }}</view>
  192. </view>
  193. <view class="pad_8 answerInfos">
  194. <view class="answerTitle">答案解析</view>
  195. <view class="answerContent"><rich-text :nodes="bank.analysisContent"></rich-text></view>
  196. </view>
  197. </view>
  198. </template>
  199. <!-- 简答题 -->
  200. <template v-if="bank.type == 5">
  201. <view class="pad_8 titBox">
  202. <view class="ans">
  203. <view class="ans_input" v-if="
  204. bankType == 2 ||
  205. (bankType == 1 &&
  206. (!bank.ques ||
  207. (!bank.ques.imageList.length && !bank.ques.text)))
  208. ">
  209. <view class="top flex">
  210. <image :data-index="bankIndex" class="icon" @click="chooseImg(bankIndex)"
  211. src="/static/camera.png" mode=""></image>
  212. <view class="progress">{{ bank.ansText.imageList.length || "0" }}/4</view>
  213. <view class="submit" :class="{ disabled: !bank.ansText.text && hasImgs(bank) }"
  214. @click="submitAns(bankIndex)">确认答案</view>
  215. </view>
  216. <view class="textarea">
  217. <textarea v-model="bank.ansText.text" placeholder="在此输入答案"></textarea>
  218. </view>
  219. <view class="imgs">
  220. <view class="img" v-for="(img, imgIndex) in bank.ansText.imageList"
  221. :key="imgIndex">
  222. <text @click="deleteImg(imgIndex, bankIndex)">x</text>
  223. <image :src="$method.splitImgHost(img, true)"></image>
  224. </view>
  225. </view>
  226. </view>
  227. <view class="ans_submit answerInfos" v-if="
  228. bankType == 1 &&
  229. bank.ques &&
  230. (bank.ques.imageList.length || bank.ques.text)
  231. ">
  232. <view class="answerTitle">我的答案:</view>
  233. {{ bank.ques.text }}
  234. <view class="imgs">
  235. <image class="img" :key="quesIndex"
  236. v-for="(ques, quesIndex) in bank.ques.imageList"
  237. :src="$method.splitImgHost(ques, true)"></image>
  238. </view>
  239. </view>
  240. </view>
  241. </view>
  242. <view v-if="
  243. bankType == 1 &&
  244. bank.ques &&
  245. (bank.ques.imageList.length || bank.ques.text)
  246. ">
  247. <view class="pad_8 answerInfos">
  248. <view class="answerTitle">答案解析:</view>
  249. <view class="answerContent"><rich-text :nodes="bank.analysisContent"></rich-text></view>
  250. </view>
  251. </view>
  252. </template>
  253. <!-- 案例题 -->
  254. <template v-if="bank.type == 4">
  255. <view class="tabs">
  256. <view class="tab" :class="{ current: tabIndex == bank.current }" :key="tabIndex"
  257. v-for="(tab, tabIndex) in bank.jsonStr" @click="tabSelect(tabIndex, bankIndex)">
  258. 问题{{ tabIndex + 1 }}
  259. </view>
  260. </view>
  261. <view v-for="(ansItem, ansIndex) in bank.jsonStr" v-if="bank.current == ansIndex"
  262. :key="ansIndex">
  263. <template v-if="ansItem.type == 1">
  264. <view class="pad_8 titBox">
  265. <view class="leftLetters">
  266. <view class="btnType">
  267. <text>单选</text>
  268. </view>
  269. </view>
  270. <view class="titles"><rich-text :nodes="ansItem.content"></rich-text></view>
  271. <view v-if="!bank.ques[ansIndex]">
  272. <view v-for="(option, childIndex) in ansItem.optionsList" :key="childIndex"
  273. class="lisSty" @click="
  274. radioSelectChild(option.optionsId, ansIndex, bankIndex)
  275. ">
  276. <view class="activeTI">{{ ast[childIndex] }}</view>
  277. <view class="flex_auto">
  278. <rich-text class="textChild" :nodes="option.content"></rich-text>
  279. <view v-if="option.imgUrl">
  280. <image style="width: 600rpx" mode="widthFix"
  281. :src="$method.splitImgHost(option.imgUrl)"></image>
  282. </view>
  283. </view>
  284. </view>
  285. </view>
  286. <view v-if="bank.ques[ansIndex]">
  287. <view v-for="(option, childIndex) in ansItem.optionsList" :key="childIndex"
  288. class="lisSty" @click="
  289. radioSelectChild(option.optionsId, ansIndex, bankIndex)
  290. ">
  291. <text :class="{
  292. right:
  293. bankType == 1 &&
  294. (option.optionsId == bank.ques[ansIndex] ||
  295. option.optionsId == bank.ans[ansIndex]),
  296. wrong:
  297. bankType == 1 &&
  298. option.optionsId == bank.ques[ansIndex] &&
  299. bank.ques[ansIndex] != bank.ans[ansIndex],
  300. user_choose:
  301. bankType == 2 &&
  302. option.optionsId == bank.ques[ansIndex],
  303. }" class="activeTI">
  304. {{ ast[childIndex] }}
  305. </text>
  306. <view class="flex_auto">
  307. <rich-text :nodes="option.content"></rich-text>
  308. <view v-if="option.imgUrl">
  309. <image style="width: 600rpx" mode="widthFix"
  310. :src="$method.splitImgHost(option.imgUrl)"></image>
  311. </view>
  312. </view>
  313. </view>
  314. </view>
  315. </view>
  316. <view v-if="bankType == 1 && bank.ques[ansIndex]">
  317. <view class="pad_8 answer">
  318. <view>题目答案:{{ ast[bank.ans[ansIndex] - 1] }}</view>
  319. <view>我的答案:{{ ast[bank.ques[ansIndex] - 1] }}</view>
  320. </view>
  321. <view class="pad_8 answerInfos">
  322. <view class="answerTitle">答案解析</view>
  323. <view class="answerContent"><rich-text
  324. :nodes="option.analysisContent"></rich-text></view>
  325. </view>
  326. </view>
  327. </template>
  328. <template v-if="ansItem.type == 2">
  329. <view class="pad_8 titBox">
  330. <view class="leftLetters">
  331. <view class="btnType">
  332. <text>多选</text>
  333. </view>
  334. </view>
  335. <view class="titles"><rich-text :nodes="ansItem.content"></rich-text></view>
  336. <view v-if="!bank.ques[ansIndex]">
  337. <view v-for="(option, childindex) in ansItem.optionsList" :key="childindex"
  338. class="lisSty" @click="
  339. checkboxSelectChild(bankIndex, ansIndex, childindex)
  340. ">
  341. <view :class="{ checked: option.checked }" class="activeTI">
  342. {{ ast[childindex] }}</view>
  343. <view class="flex_auto">
  344. <rich-text :nodes="option.content"></rich-text>
  345. <view v-if="option.imgUrl">
  346. <image style="width: 600rpx" mode="widthFix"
  347. :src="$method.splitImgHost(option.imgUrl)"></image>
  348. </view>
  349. </view>
  350. </view>
  351. </view>
  352. <view v-if="
  353. bankType == 2 || (bankType == 1 && !bank.ques[ansIndex])
  354. " class="submit_checkbox" :class="{
  355. disabled: !isCheckboxChecked(ansItem.optionsList),
  356. }" @click="checkboxSubmitChild(bankIndex, ansIndex)">确认答案</view>
  357. <view v-if="bank.ques && bank.ques[ansIndex]">
  358. <view v-for="(option, childindex) in ansItem.optionsList" :key="childindex"
  359. class="lisSty" @click="
  360. checkboxSelectChild(bankIndex, ansIndex, childindex)
  361. ">
  362. <text :class="{
  363. right:
  364. bankType == 1 && right(bankIndex, ansIndex, option),
  365. wrong:
  366. bankType == 1 && wrong(bankIndex, ansIndex, option),
  367. user_choose: bankType == 2 && option.checked,
  368. }" class="activeTI">
  369. {{ ast[childindex] }}
  370. </text>
  371. <view class="flex_auto">
  372. <rich-text :nodes="option.content"></rich-text>
  373. <view v-if="option.imgUrl">
  374. <image style="width: 600rpx" mode="widthFix"
  375. :src="$method.splitImgHost(option.imgUrl)"></image>
  376. </view>
  377. </view>
  378. </view>
  379. </view>
  380. </view>
  381. <view v-if="bankType == 1 && bank.ques[ansIndex]">
  382. <view class="pad_8 answer">
  383. <view>
  384. 题目答案:
  385. <text :key="ansItemIndex1"
  386. v-for="(ansItem1, ansItemIndex1) in bank.ans[ansIndex]">{{ ast[ansItem1 - 1] }}</text>
  387. </view>
  388. <view>
  389. 我的答案:
  390. <text :key="quesItemIndex"
  391. v-for="(quesItem, quesItemIndex) in bank.ques[ansIndex]">{{ ast[quesItem - 1] }}</text>
  392. </view>
  393. </view>
  394. <view class="pad_8 answerInfos">
  395. <view class="answerTitle">答案解析</view>
  396. <view class="answerContent"><rich-text
  397. :nodes="ansItem.analysisContent"></rich-text></view>
  398. </view>
  399. </view>
  400. </template>
  401. <template v-if="ansItem.type == 3">
  402. <view class="pad_8 titBox">
  403. <view class="leftLetters">
  404. <view class="btnType">
  405. <text>判断</text>
  406. </view>
  407. </view>
  408. <view class="titles"><rich-text :nodes="ansItem.content"></rich-text></view>
  409. <view v-if="!bank.ques[ansIndex]">
  410. <view v-for="(option, childindex) in judge" :key="childindex" class="lisSty"
  411. @click="judgeSelectChild(ansIndex, childindex, bankIndex)">
  412. <view class="activeTI">{{ ast[childindex] }}</view>
  413. <view class="flex_auto">
  414. {{ option }}
  415. <view v-if="option.imgUrl">
  416. <image style="width: 600rpx" mode="widthFix"
  417. :src="$method.splitImgHost(option.imgUrl)"></image>
  418. </view>
  419. </view>
  420. </view>
  421. </view>
  422. <view v-if="bank.ques[ansIndex]">
  423. <view v-for="(option, childindex) in judge" :key="childindex" class="lisSty"
  424. @click="judgeSelectChild(ansIndex, childindex, bankIndex)">
  425. <text :class="{
  426. right:
  427. bankType == 1 &&
  428. (childindex == (bank.ques[ansIndex] == 1 ? 0 : 1) ||
  429. childindex != bank.ans[ansIndex]),
  430. wrong:
  431. bankType == 1 &&
  432. childindex == (bank.ques[ansIndex] == 1 ? 0 : 1) &&
  433. bank.ques[ansIndex] != bank.ans[ansIndex],
  434. user_choose:
  435. bankType == 2 &&
  436. childindex == (bank.ques[ansIndex] == 1 ? 0 : 1),
  437. }" class="activeTI">
  438. {{ ast[childindex] }}
  439. </text>
  440. <view class="flex_auto">
  441. {{ option }}
  442. <view v-if="option.imgUrl">
  443. <image style="width: 600rpx" mode="widthFix"
  444. :src="$method.splitImgHost(option.imgUrl)"></image>
  445. </view>
  446. </view>
  447. </view>
  448. </view>
  449. </view>
  450. <view v-if="bankType == 1 && bank.ques[ansIndex]">
  451. <view class="pad_8 answer">
  452. <view>题目答案:{{
  453. ast[bank.ans[ansIndex] == 1 ? 0 : 1]
  454. }}</view>
  455. <view>我的答案:{{
  456. ast[bank.ques[ansIndex] == 1 ? 0 : 1]
  457. }}</view>
  458. </view>
  459. <view class="pad_8 answerInfos">
  460. <view class="answerTitle">答案解析</view>
  461. <view class="answerContent"><rich-text
  462. :nodes="ansItem.analysisContent"></rich-text></view>
  463. </view>
  464. </view>
  465. </template>
  466. <!-- 简答题 -->
  467. <template v-if="ansItem.type == 5">
  468. <view class="pad_8 titBox_title">
  469. <view class="leftLetters">
  470. <view class="btnType">
  471. <text>简答</text>
  472. </view>
  473. </view>
  474. <view><rich-text :nodes="ansItem.content"></rich-text></view>
  475. </view>
  476. <view class="pad_8 titBox_title">
  477. <view class="ans">
  478. <view class="ans_input" v-if="
  479. bankType == 2 ||
  480. (bankType == 1 &&
  481. (!bank.ques[ansIndex] ||
  482. (!bank.ques[ansIndex].text &&
  483. !bank.ques[ansIndex].imageList.length)))
  484. ">
  485. <view class="top flex">
  486. <image class="icon" @click="chooseImgChild(bankIndex, ansIndex)"
  487. src="/static/camera.png" mode=""></image>
  488. <view class="progress">{{ ansItem.ansText.imageList.length || "0" }}/4
  489. </view>
  490. <view class="submit" :class="{
  491. disabled: !ansItem.ansText.text && hasImgs(ansItem),
  492. }" @click="submitAnsChild(bankIndex, ansIndex)">确认答案</view>
  493. </view>
  494. <view class="textarea">
  495. <textarea v-model="ansItem.ansText.text"
  496. placeholder="在此输入答案"></textarea>
  497. </view>
  498. <view class="imgs">
  499. <view class="img" v-for="(img, imgIndex) in ansItem.ansText.imageList"
  500. :key="imgIndex">
  501. <text @click="
  502. deleteImgChild(imgIndex, bankIndex, ansIndex)
  503. ">x</text>
  504. <image :src="$method.splitImgHost(img, true)"></image>
  505. </view>
  506. </view>
  507. </view>
  508. <view class="ans_submit answerInfos" v-if="
  509. bankType == 1 &&
  510. bank.ques[ansIndex] &&
  511. (bank.ques[ansIndex].imageList.length ||
  512. bank.ques[ansIndex].text)
  513. ">
  514. <view class="answerTitle">我的答案</view>
  515. {{ bank.ques[ansIndex].text || "" }}
  516. <view class="imgs">
  517. <image class="img" v-for="(ques, quesIndex) in bank.ques[ansIndex]
  518. .imageList" :key="quesIndex" :src="$method.splitImgHost(ques, true)"></image>
  519. </view>
  520. </view>
  521. </view>
  522. </view>
  523. <view v-if="
  524. bankType == 1 &&
  525. (bank.ques[ansIndex].imageList.length ||
  526. bank.ques[ansIndex].text)
  527. ">
  528. <view class="pad_8 answerInfos">
  529. <view class="answerTitle">答案解析</view>
  530. <view class="answerContent"><rich-text
  531. :nodes="ansItem.analysisContent"></rich-text></view>
  532. </view>
  533. </view>
  534. </template>
  535. </view>
  536. </template>
  537. <view class="footer_btn">
  538. <view class="collect" :class="{ show: goodsId && !isFromVideo ? true : false }"
  539. @click="collect(collectList[bankIndex], bankIndex)">
  540. <view v-if="collectList[bankIndex]">
  541. <image src="/static/icon/collected.png" mode=""></image>
  542. <view>取消收藏</view>
  543. </view>
  544. <view v-if="!collectList[bankIndex]">
  545. <image src="/static/icon/collect.png" mode=""></image>
  546. <view>收藏</view>
  547. </view>
  548. </view>
  549. <view class="flex_center" @click="openFooterTab">
  550. <view class="up-icon">
  551. <image src="/static/up.png"></image>
  552. </view>
  553. 答题卡
  554. </view>
  555. <view class="collect show" @click="pdsubmit">
  556. <view>
  557. <image src="/static/jj.png" mode=""></image>
  558. <view>交卷</view>
  559. </view>
  560. </view>
  561. </view>
  562. </view>
  563. </swiper-item>
  564. </swiper>
  565. <u-popup v-model="show" mode="bottom" border-radius="14" height="680rpx">
  566. <view class="popupView">
  567. <view class="popupTops">
  568. <view class="topIcon"></view>
  569. 点击编号即可跳转至对应题目
  570. </view>
  571. <view class="popupContent">
  572. <scroll-view scroll-y="true" style="height: 506rpx">
  573. <view class="boxSty">
  574. <view v-for="(item, index) in questionList" :key="index" @click="changeIndex(index)" :class="{
  575. isRight: bankType == 1 && isRight(item, index),
  576. isWrong: bankType == 1 && isWrong(item, index),
  577. isPart: bankType == 1 && isPart(item, index),
  578. isOver: bankType == 1 && isOver(item, index),
  579. check_ans: bankType == 2 && isCheck(item, index),
  580. }" class="liListSty">
  581. {{ index + 1 }}
  582. </view>
  583. </view>
  584. </scroll-view>
  585. </view>
  586. </view>
  587. </u-popup>
  588. <view class="dialog" v-if="showDialog">
  589. <image class="pointer" src="/static/pointer.png" mode=""></image>
  590. <view class="text">左右滑动切换上下题</view>
  591. <view class="btn" @click="showDialog = false">我知道了</view>
  592. </view>
  593. <view class="dialog-arrow" v-if="showArrow">
  594. <image class="pointer" src="/static/arrow-left.png" mode=""></image>
  595. <view class="text">您当前正在测试, 若想退出请点击左上角返回按钮。</view>
  596. <view class="btn" @click="showArrow = false">我知道了</view>
  597. </view>
  598. <view class="dialog_wrap" v-if="testOver">
  599. <view class="bg"></view>
  600. <view class="dialog">
  601. <view class="title">温馨提示</view>
  602. <view class="content">
  603. <view>您已完成所有题目,</view>
  604. <view>快去交卷吧!</view>
  605. </view>
  606. <view class="btns">
  607. <view class="btn" @click="noSubmit()">暂不交卷</view>
  608. <view class="btn active" @click="submitNow()">立即交卷</view>
  609. </view>
  610. </view>
  611. </view>
  612. <view class="dialog_wrap" v-if="isLastCount">
  613. <view class="bg"></view>
  614. <view class="dialog">
  615. <view class="title">温馨提示</view>
  616. <view class="content">
  617. <view>您当前正在测试,还剩{{ lastCount }}道题未完成,离开视为交卷</view>
  618. </view>
  619. <view class="btns">
  620. <view class="btn" @click="noLeave()">暂不离开</view>
  621. <view class="btn active" @click="leaveNow()">继续离开</view>
  622. </view>
  623. </view>
  624. </view>
  625. <u-popup v-model="showpopups" mode="center" border-radius="24" height="439rpx" width="640rpx"
  626. :mask-close-able="false">
  627. <view class="popboxs">
  628. <view class="classTops">温馨提示</view>
  629. <view class="textStys">
  630. {{
  631. cgType === 7
  632. ? "您还未交卷,确定结束做题吗?"
  633. : cgType === 8
  634. ? `您还有${lastCount}道题未作答, 现在继续作答,还是下次继续?`
  635. : cgType === 6
  636. ? `您还有${lastCount}道题未作答, 您确定要交卷吗?`
  637. : cgType == 9
  638. ? `您已完成所有题目,快去交卷吧!`
  639. : ""
  640. }}
  641. </view>
  642. <view class="classFootsty" v-if="cgType === 6">
  643. <view class="btnsty btns1" @click="submit">立即交卷</view>
  644. <view class="btnsty btns2" @click="showpopups = false">继续做题</view>
  645. </view>
  646. <view class="classFootsty" v-if="cgType === 7">
  647. <view class="btnsty btns1" @click="backPages">下次继续</view>
  648. <view class="btnsty btns2" @click="submit">结束做题</view>
  649. </view>
  650. <view class="classFootsty" v-if="cgType === 8">
  651. <view class="btnsty btns1" @click="backPages()">下次继续</view>
  652. <view class="btnsty btns2" @click="showpopups = false">继续作答</view>
  653. </view>
  654. <view class="classFootsty" v-if="cgType === 9">
  655. <view class="btnsty btns1" @click="showpopups = false">暂不交卷</view>
  656. <view class="btnsty btns2" @click="submit">立即交卷</view>
  657. </view>
  658. </view>
  659. </u-popup>
  660. </view>
  661. </template>
  662. <script>
  663. import {
  664. goodsExamIsCanLearn,
  665. examClientCanLearn
  666. } from "@/utils/authority";
  667. export default {
  668. data() {
  669. return {
  670. showpopups: false,
  671. id: "",
  672. current: 0,
  673. questionList: [],
  674. ast: ["A", "B", "C", "D", "E", "F", "G"],
  675. judge: ["正确", "错误"],
  676. ans: [],
  677. ques: [],
  678. show: false,
  679. showDialog: false,
  680. bankList: [],
  681. collectList: [],
  682. goodsId: "",
  683. recordId: "",
  684. isSubmit: false,
  685. lastTime: 0, //剩余考试时长
  686. allTimes: 0, //总考试时长
  687. timer: null,
  688. wrongList: [],
  689. bankType: 0, //试卷类型
  690. needBack: false, //是否是考试
  691. testOver: false,
  692. isLastCount: false, //是否有未答题目
  693. lastCount: 0, //剩余没有回答的题目数
  694. chapterId: 0,
  695. moduleId: 0,
  696. showArrow: false, //退出提示
  697. isFromVideo: "",
  698. gradeId: "",
  699. examData: {},
  700. orderGoodsId: "",
  701. cgType: 0, //对应设计稿弹窗编码
  702. // courseId: '',
  703. entryType: "", // 进入做题页面的入口类型,daily-每日一练进来,random-随机练习, 其他的-题库做题进入
  704. bankNum: 5, // 随机练习的题目数量
  705. simulateExamId: undefined,
  706. };
  707. },
  708. async onLoad(option) {
  709. await goodsExamIsCanLearn(option.goodsid);
  710. this.entryType = option.entryType || "";
  711. this.bankNum = option.bankNum;
  712. // this.courseId = option.courseId || ''
  713. this.orderGoodsId = option.orderGoodsId || 0;
  714. this.current = +option.current || 0;
  715. this.id = option.id;
  716. this.goodsId = option.goodsid;
  717. this.chapterId = option.chapterId || 0;
  718. this.moduleId = option.moduleId || 0;
  719. this.isFromVideo = option.isFromVideo || "";
  720. this.gradeId = option.gradeId || "";
  721. let isBack = option.isback;
  722. let showDialog = uni.getStorageSync("showDialog");
  723. if (showDialog) {
  724. this.showDialog = false;
  725. } else {
  726. this.showDialog = true;
  727. uni.setStorageSync("showDialog", "1");
  728. }
  729. //考试被迫返回
  730. if (isBack) {
  731. let app = getApp();
  732. let globalData = app.globalData;
  733. for (var k in globalData.bankData) {
  734. this[k] = globalData.bankData[k];
  735. }
  736. this.showArrow = true;
  737. this.timer = setInterval(() => {
  738. if (this.lastTime <= 0) {
  739. clearInterval(this.timer);
  740. uni.showToast({
  741. icon: "none",
  742. mask: true,
  743. title: "考试时间已到,系统将自动交卷",
  744. duration: 10000,
  745. });
  746. this.submit();
  747. return;
  748. }
  749. this.lastTime--;
  750. }, 1000);
  751. } else {
  752. if (this.entryType == "random") {
  753. this.bankType = 1; // 随机练习全部都是练习类型
  754. this.randomQuestionList();
  755. } else {
  756. //进入页面
  757. await this.bankExam();
  758. // 请求题目列表
  759. this.goodsQuestionList();
  760. }
  761. }
  762. },
  763. onUnload() {
  764. if (this.isSubmit) {
  765. clearInterval(this.timer);
  766. return;
  767. }
  768. //考试试卷 阻止ios手势返回,自动跳回答题页
  769. if (this.needBack) {
  770. let app = getApp();
  771. app.globalData.bankData = this.$data;
  772. clearInterval(this.timer);
  773. uni.navigateTo({
  774. url: "/pages2/bank/questionBank?id=" +
  775. this.id +
  776. "&goodsid=" +
  777. this.goodsId +
  778. "&isback=true&orderGoodsId=" +
  779. this.orderGoodsId,
  780. });
  781. } else {
  782. //点击返回按钮确认允许退出,记录答题记录
  783. clearInterval(this.timer);
  784. this.examRecordEdit();
  785. }
  786. },
  787. methods: {
  788. /**
  789. * 是否有上传图片
  790. */
  791. hasImgs(bank) {
  792. return bank.ansText.imageList.length == 0;
  793. },
  794. /**
  795. * 获取试卷类型2考试,1练习
  796. * bank/exam + data
  797. */
  798. bankExam() {
  799. return new Promise((resolve, reject) => {
  800. this.$api.bankExam(this.id).then((res) => {
  801. const {
  802. doType,
  803. examLimitClient
  804. } = res.data.data;
  805. if (!examClientCanLearn(examLimitClient)) {
  806. return;
  807. }
  808. if (this.entryType == "daily") {
  809. // 每日一练类型都是为练习
  810. this.bankType = 1;
  811. } else {
  812. this.bankType = doType;
  813. }
  814. this.examData = res.data.data;
  815. this.allTimes = this.examData.answerTime * 60;
  816. this.lastTime =
  817. this.examData.answerTime && this.examData.answerTime * 60;
  818. if (this.bankType == 2) {
  819. this.needBack = true;
  820. }
  821. resolve();
  822. });
  823. });
  824. },
  825. /**
  826. * 点击后退按钮
  827. */
  828. clickLeft() {
  829. if (this.bankType == 1) {
  830. let ansCount = this.questionOverNum(true); //已答题数
  831. this.lastCount = this.questionList.length - ansCount; //统计未答完的题数
  832. //所有题目答完
  833. if (this.lastCount == 0) {
  834. // this.testOver = true;
  835. this.cgType = 7;
  836. //未答完
  837. } else {
  838. this.cgType = 8;
  839. // this.isLastCount = true;
  840. }
  841. this.showpopups = true;
  842. } else if (this.bankType == 2) {
  843. let ansCount = this.questionOverNum(true); //已答题数
  844. this.lastCount = this.questionList.length - ansCount; //统计未答完的题数
  845. //所有题目答完
  846. if (this.lastCount == 0) {
  847. this.testOver = true;
  848. //未答完
  849. } else {
  850. this.isLastCount = true;
  851. }
  852. }
  853. },
  854. /**
  855. * 返回上一页
  856. */
  857. backPages() {
  858. this.needBack = false;
  859. uni.navigateBack({
  860. delta: 1,
  861. });
  862. },
  863. /**
  864. * 获取已经回答的题目数
  865. * hasSpecail (是否包含简答和案例)
  866. */
  867. questionOverNum(hasSpecail) {
  868. let count = 0;
  869. this.questionList.forEach((item) => {
  870. if (item.type == 1 || item.type == 2 || item.type == 3) {
  871. if (item.ques) {
  872. count++;
  873. }
  874. } else if (item.type == 4) {
  875. //案例题
  876. if (hasSpecail) {
  877. let isOver = item.jsonStr.every((jsonItem, indexs) => {
  878. if (
  879. jsonItem.type == 1 ||
  880. jsonItem.type == 2 ||
  881. jsonItem.type == 3
  882. ) {
  883. if (item.ques[indexs]) {
  884. return true;
  885. } else {
  886. return false;
  887. }
  888. } else if (jsonItem.type == 5) {
  889. if (
  890. item.ques[indexs] &&
  891. (item.ques[indexs].text || item.ques[indexs].imageList.length)
  892. ) {
  893. console.log("chil");
  894. return true;
  895. } else {
  896. return false;
  897. }
  898. }
  899. });
  900. if (isOver) {
  901. count++;
  902. }
  903. }
  904. } else if (item.type == 5) {
  905. //简答题
  906. if (hasSpecail) {
  907. if (item.ques && (item.ques.text || item.ques.imageList.length)) {
  908. console.log(5, item);
  909. count++;
  910. }
  911. }
  912. }
  913. });
  914. return count;
  915. },
  916. /**
  917. * 是否做完所有题目
  918. */
  919. isDoOver() {
  920. let questionOverNum = this.questionOverNum(true); //获取已经回答的题目数(包括简答和案例)
  921. if (this.questionList.length == questionOverNum) {
  922. //全部做完弹窗
  923. this.cgType = 9;
  924. this.showpopups = true;
  925. }
  926. },
  927. /**
  928. * 暂不交卷
  929. */
  930. noSubmit() {
  931. //设为允许退出页面
  932. this.needBack = false;
  933. uni.navigateBack({
  934. delta: 1,
  935. });
  936. },
  937. /**
  938. * 不离开
  939. */
  940. noLeave() {
  941. this.isLastCount = false;
  942. },
  943. /**
  944. * 立即离开并交卷
  945. */
  946. leaveNow() {
  947. this.needBack = false;
  948. this.isSubmit = true;
  949. this.submit(false);
  950. uni.navigateBack({
  951. delta: 1,
  952. });
  953. },
  954. /**
  955. * 立即交卷
  956. */
  957. submitNow() {
  958. this.showpopups = false;
  959. this.needBack = false;
  960. this.submit();
  961. },
  962. /**
  963. * 离开页面统计回答正确题数
  964. */
  965. examRecordEdit() {
  966. if (!this.isSubmit) {
  967. let {
  968. doQuestionNum,
  969. doQuestionIds,
  970. rightQuestionNum,
  971. historyExamJson,
  972. } = this.$method.calculateScore(this.questionList);
  973. this.$api
  974. .examRecordEdit({
  975. orderGoodsId: this.orderGoodsId,
  976. examId: this.id,
  977. goodsId: this.goodsId,
  978. recordId: this.recordId,
  979. doQuestionIds,
  980. rightQuestionNum,
  981. moduleExamId: this.moduleId || 0,
  982. chapterExamId: this.chapterId || 0,
  983. status: 0,
  984. doQuestionNum,
  985. historyExamJson,
  986. })
  987. .then((res) => {
  988. if (res.data.code == 200) {
  989. this.entryType == "daily" && this.dailyExam();
  990. }
  991. });
  992. }
  993. },
  994. /**
  995. * 记录总题数
  996. * hasSpecial (是否包含简答和案例) true 包含 false 不包含
  997. */
  998. examRecord(hasSpecial) {
  999. let questionList = 0;
  1000. // if(!hasSpecial) {
  1001. this.questionList.forEach((item, index) => {
  1002. if (item.type == 1 || item.type == 2 || item.type == 3) {
  1003. questionList++;
  1004. }
  1005. });
  1006. // } else {
  1007. // questionList = this.questionList.length;
  1008. // }
  1009. // #ifdef MP-WEIXIN
  1010. let fromPlat = 1
  1011. // #endif
  1012. // #ifdef H5
  1013. let fromPlat = 3
  1014. // #endif
  1015. this.$api
  1016. .examRecord({
  1017. fromPlat: fromPlat, //"来源平台 1小程序 2PC网站 3h5"
  1018. chapterExamId: this.chapterId || 0,
  1019. orderGoodsId: this.orderGoodsId,
  1020. moduleExamId: this.moduleId || 0,
  1021. examId: this.id,
  1022. goodsId: this.goodsId,
  1023. totalQuestionNum: questionList,
  1024. allQuestionNum: this.questionList.length,
  1025. doMode: this.doMode,
  1026. simulateExamId: this.simulateExamId,
  1027. })
  1028. .then((res) => {
  1029. this.recordId = res.data.data;
  1030. //获取recordId 初始化先提交题目 以防突然下次继续做题退出报错
  1031. if (this.bankType == 1) {
  1032. this.examRecordEdit();
  1033. }
  1034. });
  1035. },
  1036. /**
  1037. * @param {Object} second倒计时过滤器
  1038. */
  1039. countdown(second) {
  1040. if (second) {
  1041. let h = parseInt((second / 60 / 60) % 24); // 计算小时
  1042. let m = parseInt((second / 60) % 60); // 计算分数
  1043. let s = parseInt(second % 60); // 计算当前秒数
  1044. if (h < 10) h = "0" + h;
  1045. if (m < 10) m = "0" + m;
  1046. if (s < 10) s = "0" + s;
  1047. return h + ":" + m + ":" + s;
  1048. } else {
  1049. return "";
  1050. }
  1051. },
  1052. hideDialog() {
  1053. this.showDialog = false;
  1054. },
  1055. // 请求随机练习题目列表
  1056. randomQuestionList() {
  1057. this.$http({
  1058. url: "/bank/exam/temp",
  1059. method: "post",
  1060. data: {
  1061. goodsId: this.goodsId,
  1062. orderGoodsId: this.orderGoodsId,
  1063. number: this.bankNum,
  1064. },
  1065. }).then((res) => {
  1066. if (res.data.code == 200) {
  1067. this.examData = res.data.data || {};
  1068. this.id = this.examData.examId;
  1069. if (!this.examData.questionList.length) {
  1070. return this.noListTip();
  1071. }
  1072. this.dataAnlyze(this.examData.questionList || []);
  1073. } else {
  1074. this.$u.toast(res.data.msg);
  1075. setTimeout(() => {
  1076. uni.navigateBack();
  1077. }, 2000);
  1078. }
  1079. });
  1080. },
  1081. noListTip(content = "该试卷暂无题目") {
  1082. this.hideDialog();
  1083. uni.showModal({
  1084. showCancel: false,
  1085. content,
  1086. success: (k) => {
  1087. if (k.confirm) {
  1088. this.isSubmit = true;
  1089. uni.navigateBack();
  1090. }
  1091. },
  1092. });
  1093. },
  1094. /**
  1095. * 请求题目列表 app/common/bank/question/list
  1096. */
  1097. goodsQuestionList() {
  1098. this.$api[
  1099. this.doMode == 3 ? "goodsRandomQuestionList" : "goodsQuestionList"
  1100. ]({
  1101. examId: this.id,
  1102. goodsId: this.goodsId,
  1103. orderGoodsId: this.orderGoodsId,
  1104. from: 1,
  1105. }).then((res) => {
  1106. if (res.data.code == 500) {
  1107. return this.noListTip("你已完成所有题目");
  1108. }
  1109. let data = res.data.data;
  1110. if (this.doMode == 3) {
  1111. this.simulateExamId = data.simulateExamId;
  1112. data = data.questionList;
  1113. }
  1114. if (!data.length) {
  1115. return this.noListTip();
  1116. }
  1117. //考试时间到了自动交卷
  1118. if (this.lastTime) {
  1119. this.timer = setInterval(() => {
  1120. if (this.lastTime <= 0) {
  1121. clearInterval(this.timer);
  1122. uni.showToast({
  1123. icon: "none",
  1124. mask: true,
  1125. title: "考试时间已到,系统将自动交卷",
  1126. duration: 10000,
  1127. });
  1128. this.submit();
  1129. return;
  1130. }
  1131. this.lastTime--;
  1132. }, 1000);
  1133. } else {}
  1134. this.dataAnlyze(data);
  1135. });
  1136. },
  1137. dataAnlyze(datas = []) {
  1138. console.log("datas:", datas);
  1139. datas.forEach((item, index) => {
  1140. // if (typeof item.jsonStr == 'string') {
  1141. item.jsonStr = JSON.parse(item.jsonStr) || [];
  1142. if (item.type == 2) {
  1143. //多选
  1144. item.jsonStr.forEach((str) => {
  1145. str.optionsId = "" + str.optionsId;
  1146. });
  1147. let arr = item.answerQuestion.split(",");
  1148. arr.forEach((a, i) => {
  1149. arr[i] = "" + a;
  1150. });
  1151. item.ans = arr;
  1152. item.analysisContent &&
  1153. (item.analysisContent = item.analysisContent.replace(
  1154. /<img/gi,
  1155. '<img style="max-width:100%;"'
  1156. ));
  1157. item.content &&
  1158. (item.content = item.content.replace(
  1159. /<img/gi,
  1160. '<img style="max-width:100%;"'
  1161. ));
  1162. return;
  1163. } else if (item.type == 5) {
  1164. //简答题
  1165. item.ansText = {
  1166. text: "",
  1167. imageList: [],
  1168. };
  1169. item.ques = {
  1170. text: "",
  1171. imageList: [],
  1172. };
  1173. item.analysisContent &&
  1174. (item.analysisContent = item.analysisContent.replace(
  1175. /<img/gi,
  1176. '<img style="max-width:100%;"'
  1177. ));
  1178. item.content &&
  1179. (item.content = item.content.replace(
  1180. /<img/gi,
  1181. '<img style="max-width:100%;"'
  1182. ));
  1183. } else if (item.type == 4) {
  1184. //案例题
  1185. item.ques = [];
  1186. item.current = 0;
  1187. let ansArr = [];
  1188. item.jsonStr.forEach((json, index) => {
  1189. if (json.type == 1) {
  1190. ansArr[index] = json.answerQuestion;
  1191. json.content &&
  1192. (json.content = json.content.replace(
  1193. /<img/gi,
  1194. '<img style="max-width:100%;"'
  1195. ));
  1196. } else if (json.type == 2) {
  1197. json.optionsList.forEach((str) => {
  1198. str.optionsId = "" + str.optionsId;
  1199. });
  1200. let arr = json.answerQuestion.split(",");
  1201. arr.forEach((a, i) => {
  1202. arr[i] = "" + a;
  1203. });
  1204. ansArr[index] = arr;
  1205. json.content &&
  1206. (json.content = json.content.replace(
  1207. /<img/gi,
  1208. '<img style="max-width:100%;"'
  1209. ));
  1210. } else if (json.type == 3) {
  1211. ansArr[index] = json.answerQuestion;
  1212. json.content &&
  1213. (json.content = json.content.replace(
  1214. /<img/gi,
  1215. '<img style="max-width:100%;"'
  1216. ));
  1217. } else if (json.type == 5) {
  1218. ansArr[index] = {
  1219. text: json.answerQuestion,
  1220. imageList: [],
  1221. };
  1222. json.ansText = {
  1223. text: "",
  1224. imageList: [],
  1225. };
  1226. json.content &&
  1227. (json.content = json.content.replace(
  1228. /<img/gi,
  1229. '<img style="max-width:100%;"'
  1230. ));
  1231. }
  1232. });
  1233. item.analysisContent &&
  1234. (item.analysisContent = item.analysisContent.replace(
  1235. /<img/gi,
  1236. '<img style="max-width:100%;"'
  1237. ));
  1238. item.content &&
  1239. (item.content = item.content.replace(
  1240. /<img/gi,
  1241. '<img style="max-width:100%;"'
  1242. ));
  1243. item.ans = ansArr;
  1244. return;
  1245. }
  1246. item.analysisContent &&
  1247. (item.analysisContent = item.analysisContent.replace(
  1248. /<img/gi,
  1249. '<img style="max-width:100%;"'
  1250. ));
  1251. item.content &&
  1252. (item.content = item.content.replace(
  1253. /<img/gi,
  1254. '<img style="max-width:100%;"'
  1255. ));
  1256. item.ans = item.answerQuestion;
  1257. // }
  1258. });
  1259. this.questionList = datas;
  1260. this.lastCount = this.questionList.length;
  1261. this.examRecord();
  1262. this.getCollectInfo(this.current);
  1263. },
  1264. /**
  1265. * @param {Object} e单选点击
  1266. */
  1267. radioSelect(optionsId, bindex) {
  1268. // if (this.questionList[bindex].ques) return;
  1269. if (this.questionList[bindex].ques && this.bankType == 1) {
  1270. return;
  1271. }
  1272. this.$set(this.questionList[bindex], "ques", optionsId);
  1273. // if ((bindex + 1) < this.questionList.length) {
  1274. // this.current = bindex + 1
  1275. // }
  1276. this.isDoOver();
  1277. // 回答错误
  1278. // if (this.questionList[bindex].ques != this.questionList[bindex].ans) {
  1279. // // /exam/wwrong/record
  1280. // this.$api
  1281. // .examWrongRecord({
  1282. // orderGoodsId: this.orderGoodsId,
  1283. // examId: this.id,
  1284. // goodsId: this.goodsId,
  1285. // moduleExamId: this.moduleId || 0,
  1286. // chapterExamId: this.chapterId || 0,
  1287. // questionIds: [this.questionList[bindex].questionId],
  1288. // recordId: this.recordId,
  1289. // })
  1290. // .then((res) => {});
  1291. // } else {
  1292. // // let question = this.wrongList.find(item => item.questionId == this.questionList[bindex].questionId);
  1293. // // if(question) {
  1294. // // this.$api.wrongRecordDelete({
  1295. // // "examId": +this.id,
  1296. // // "goodsId": +this.goodsId,
  1297. // // "questionId": this.questionList[bindex].questionId,
  1298. // // }).then(res => {
  1299. // // })
  1300. // // }
  1301. // }
  1302. },
  1303. /**
  1304. * @param {Object} e案例单选点击
  1305. */
  1306. radioSelectChild(optionsId, ansIndex, bindex) {
  1307. // if (this.questionList[bindex].ques[ansIndex]) return;
  1308. if (this.questionList[bindex].ques[ansIndex] && this.bankType == 1) {
  1309. return;
  1310. }
  1311. this.$set(this.questionList[bindex].ques, ansIndex, optionsId);
  1312. this.isDoOver();
  1313. },
  1314. /**
  1315. * @param {Object} 多选点击
  1316. */
  1317. checkboxSelect(optionsId, bindex, index) {
  1318. if (this.questionList[bindex].ques && this.bankType == 1) {
  1319. return;
  1320. }
  1321. this.$set(
  1322. this.questionList[bindex].jsonStr[index],
  1323. "checked",
  1324. !this.questionList[bindex].jsonStr[index].checked
  1325. );
  1326. },
  1327. /**
  1328. * @param {Object} 案例多选点击
  1329. */
  1330. checkboxSelectChild(bindex, ansIndex, childIndex) {
  1331. if (this.questionList[bindex].ques[ansIndex] && this.bankType == 1) {
  1332. return;
  1333. }
  1334. this.$set(
  1335. this.questionList[bindex].jsonStr[ansIndex].optionsList[childIndex],
  1336. "checked",
  1337. !this.questionList[bindex].jsonStr[ansIndex].optionsList[childIndex]
  1338. .checked
  1339. );
  1340. },
  1341. isCheckboxChecked(arr) {
  1342. return arr.some((item) => {
  1343. if (item.checked) {
  1344. return true;
  1345. }
  1346. });
  1347. },
  1348. /**
  1349. * @param {Object} 多选确认
  1350. */
  1351. checkboxSubmit(bindex) {
  1352. if (this.questionList[bindex].ques && this.bankType == 1) {
  1353. return;
  1354. }
  1355. let arr = [];
  1356. this.questionList[bindex].jsonStr.forEach((item) => {
  1357. if (item.checked) {
  1358. arr.push(item.optionsId);
  1359. }
  1360. });
  1361. if (!arr.length) {
  1362. delete this.questionList[bindex].ques;
  1363. uni.showToast({
  1364. title: "请选择答案",
  1365. icon: "none",
  1366. });
  1367. return;
  1368. }
  1369. this.$set(this.questionList[bindex], "ques", arr);
  1370. this.$u.toast("已确认答案");
  1371. this.isDoOver();
  1372. // 切换下一题
  1373. if (
  1374. this.bankType != 1 &&
  1375. this.cgType != 9 &&
  1376. bindex != this.questionList.length - 1
  1377. ) {
  1378. this.current = bindex + 1;
  1379. this.getCollectInfo(this.current);
  1380. }
  1381. },
  1382. /**
  1383. * @param {Object} 案例多选确认
  1384. */
  1385. checkboxSubmitChild(bindex, ansIndex) {
  1386. // if (this.questionList[bindex].ques[ansIndex]) return;
  1387. if (this.questionList[bindex].ques[ansIndex] && this.bankType == 1) {
  1388. return;
  1389. }
  1390. let arr = [];
  1391. this.questionList[bindex].jsonStr[ansIndex].optionsList.forEach(
  1392. (item) => {
  1393. if (item.checked) {
  1394. arr.push(item.optionsId);
  1395. }
  1396. }
  1397. );
  1398. if (!arr.length) {
  1399. delete this.questionList[bindex].ques[ansIndex];
  1400. uni.showToast({
  1401. title: "请选择答案",
  1402. icon: "none",
  1403. });
  1404. return;
  1405. }
  1406. this.$set(this.questionList[bindex].ques, ansIndex, arr);
  1407. this.$u.toast("已确认答案");
  1408. this.isDoOver();
  1409. // 切换下一题
  1410. if (
  1411. this.bankType != 1 &&
  1412. this.cgType != 9 &&
  1413. ansIndex != this.questionList[bindex].ques.length - 1
  1414. ) {
  1415. this.questionList[bindex].current += 1;
  1416. }
  1417. },
  1418. /**
  1419. * @param {Object} index
  1420. * @param {Object} bindex
  1421. * 判断题
  1422. */
  1423. judgeSelect(index, bindex) {
  1424. // if (this.questionList[bindex].ques) return;
  1425. if (this.questionList[bindex].ques && this.bankType == 1) {
  1426. return;
  1427. } // 答案: 判断题1正确 0错误
  1428. this.$set(this.questionList[bindex], "ques", index == 0 ? "1" : "0");
  1429. console.log(
  1430. "this.questionList[bindex]:",
  1431. this.questionList[bindex].ques,
  1432. this.questionList[bindex].ans
  1433. );
  1434. this.isDoOver();
  1435. // 回答错误
  1436. // if (this.questionList[bindex].ques != this.questionList[bindex].ans) {
  1437. // this.$api
  1438. // .examWrongRecord({
  1439. // orderGoodsId: this.orderGoodsId,
  1440. // examId: this.id,
  1441. // goodsId: this.goodsId,
  1442. // moduleExamId: this.moduleId || 0,
  1443. // chapterExamId: this.chapterId || 0,
  1444. // questionIds: [this.questionList[bindex].questionId],
  1445. // recordId: this.recordId,
  1446. // })
  1447. // .then((res) => {});
  1448. // } else {
  1449. // // let question = this.wrongList.find(item => item.questionId == this.questionList[bindex].questionId);
  1450. // // if(question) {
  1451. // // this.$api.wrongRecordDelete({
  1452. // // "examId": +this.id,
  1453. // // "goodsId": +this.goodsId,
  1454. // // "questionId": this.questionList[bindex].questionId,
  1455. // // }).then(res => {
  1456. // // })
  1457. // // }
  1458. // }
  1459. },
  1460. /**
  1461. * @param {Object} ansindex
  1462. * @param {Object} childindex
  1463. * @param {Object} bindex
  1464. * 案例判断题
  1465. */
  1466. judgeSelectChild(ansindex, childindex, bindex) {
  1467. // if (this.questionList[bindex].ques[ansindex]) return;
  1468. if (this.questionList[bindex].ques[ansindex] && this.bankType == 1) {
  1469. return;
  1470. }
  1471. this.$set(
  1472. this.questionList[bindex].ques,
  1473. ansindex,
  1474. childindex == 0 ? "1" : "0"
  1475. );
  1476. this.isDoOver();
  1477. },
  1478. openFooterTab() {
  1479. this.show = true;
  1480. },
  1481. changeIndex(index) {
  1482. this.current = index;
  1483. },
  1484. swiperChange(e) {
  1485. this.current = e.detail.current;
  1486. this.getCollectInfo(this.current);
  1487. },
  1488. /**
  1489. * @param {Object} current
  1490. * 获取收藏信息
  1491. */
  1492. getCollectInfo(current) {
  1493. this.$api
  1494. .getCollectInfo({
  1495. examId: this.id,
  1496. questionId: this.questionList[current].questionId,
  1497. goodsId: this.goodsId,
  1498. orderGoodsId: this.orderGoodsId,
  1499. })
  1500. .then((res) => {
  1501. if (res.data.code == 500) {
  1502. this.$set(this.collectList, current, false);
  1503. } else if (res.data.code == 200) {
  1504. this.$set(this.collectList, current, res.data.data);
  1505. }
  1506. });
  1507. },
  1508. pdsubmit() {
  1509. // if (this.bankType == 1) {
  1510. let ansCount = this.questionOverNum(true); //已答题数
  1511. this.lastCount = this.questionList.length - ansCount; //统计未答完的题数
  1512. //没有答完
  1513. if (this.lastCount !== 0) {
  1514. this.cgType = 6;
  1515. this.showpopups = true;
  1516. return;
  1517. }
  1518. // }
  1519. if (this.bankType == 2) {
  1520. if (this.lastTime > 0) {
  1521. let lastTime = this.countdown(this.lastTime);
  1522. uni.showModal({
  1523. title: "提示",
  1524. content: `时间还剩余${lastTime},确定交卷吗?`,
  1525. confirmText: "交卷",
  1526. cancelText: "继续答题",
  1527. success: (res) => {
  1528. if (res.confirm) {
  1529. //确定
  1530. this.submit();
  1531. } else {
  1532. //取消
  1533. }
  1534. },
  1535. });
  1536. return;
  1537. }
  1538. }
  1539. this.submit();
  1540. },
  1541. /**
  1542. * 交卷
  1543. */
  1544. submit(isShowTip = true) {
  1545. let form = this.$method.calculateScore(this.questionList);
  1546. //交卷
  1547. this.$api
  1548. .examRecordEdit({
  1549. examId: this.id,
  1550. goodsId: this.goodsId,
  1551. recordId: this.recordId,
  1552. orderGoodsId: this.orderGoodsId,
  1553. status: 1, // 1是交卷 2是中途离开
  1554. moduleExamId: this.moduleId || 0,
  1555. chapterExamId: this.chapterId || 0,
  1556. examTime: parseInt(this.allTimes),
  1557. doTime: parseInt(this.allTimes) - parseInt(this.lastTime),
  1558. ...form,
  1559. })
  1560. .then((res) => {
  1561. this.isSubmit = true;
  1562. if (res.data.code == 200) {
  1563. this.entryType == "daily" && this.dailyExam();
  1564. if (!isShowTip) {
  1565. return;
  1566. }
  1567. uni.showToast({
  1568. title: "交卷成功",
  1569. duration: 1000,
  1570. icon: "none",
  1571. });
  1572. setTimeout(() => {
  1573. uni.redirectTo({
  1574. url: "/pages2/bank/question_report?goodsId=" +
  1575. this.goodsId +
  1576. "&chapterId=" +
  1577. this.chapterId +
  1578. "&moduleId=" +
  1579. this.moduleId +
  1580. "&examId=" +
  1581. this.id +
  1582. "&id=" +
  1583. this.recordId +
  1584. "&orderGoodsId=" +
  1585. this.orderGoodsId +
  1586. "&entryType=" +
  1587. this.entryType +
  1588. "&bankNum=" +
  1589. this.bankNum +
  1590. "&doMode=" +
  1591. this.doMode +
  1592. "&courseType=1",
  1593. });
  1594. }, 1000);
  1595. }
  1596. });
  1597. //错题集id提交(客观题)
  1598. this.$api.examWrongRecord({
  1599. examId: this.id,
  1600. goodsId: this.goodsId,
  1601. orderGoodsId: this.orderGoodsId,
  1602. questionIds: form.questionIds,
  1603. recordId: this.recordId,
  1604. type: 1, // 题库试卷传1
  1605. doMode: this.doMode,
  1606. });
  1607. },
  1608. // 每日一练试卷打卡
  1609. dailyExam() {
  1610. const dateStamp = parseInt(
  1611. new Date(new Date().toLocaleDateString()).getTime() / 1000
  1612. );
  1613. this.$http({
  1614. url: "/bank/question/special/exam/record",
  1615. method: "post",
  1616. data: {
  1617. examId: this.id,
  1618. chapterExamId: this.chapterId, // 章卷ID
  1619. moduleExamId: this.moduleId, //模块卷ID
  1620. goodsId: this.goodsId,
  1621. recordTime: dateStamp, // 传当天0点时间戳(秒)
  1622. },
  1623. }).then((res) => {
  1624. if (res.data.code == 200) {}
  1625. });
  1626. },
  1627. /**
  1628. * @param {Object} state
  1629. * @param {Object} index
  1630. * 收藏
  1631. */
  1632. collect(state, index) {
  1633. if (!state) {
  1634. this.$api
  1635. .collectQuestion({
  1636. examId: this.id,
  1637. questionId: this.questionList[index].questionId,
  1638. goodsId: this.goodsId || "",
  1639. orderGoodsId: this.orderGoodsId,
  1640. doMode: this.doMode,
  1641. })
  1642. .then((res) => {
  1643. if (res.data.code == 200) {
  1644. this.$set(this.collectList, index, true);
  1645. uni.showToast({
  1646. title: "收藏成功",
  1647. duration: 2000,
  1648. icon: "none",
  1649. });
  1650. this.getCollectInfo(index);
  1651. }
  1652. });
  1653. } else {
  1654. this.$api
  1655. .deleteCollectQuestion(this.collectList[index].collectQuestionId)
  1656. .then((res) => {
  1657. if (res.data.code == 200) {
  1658. this.$set(this.collectList, index, false);
  1659. uni.showToast({
  1660. title: "取消收藏成功",
  1661. duration: 2000,
  1662. icon: "none",
  1663. });
  1664. }
  1665. });
  1666. }
  1667. return;
  1668. },
  1669. /**
  1670. * @param {Object} imgIndex
  1671. * @param {Object} bankIndex
  1672. * 删除简答图片
  1673. */
  1674. deleteImg(imgIndex, bankIndex) {
  1675. this.questionList[bankIndex].ansText.imageList.splice(imgIndex, 1);
  1676. },
  1677. /**
  1678. * @param {Object} imgIndex
  1679. * @param {Object} bankIndex
  1680. * @param {Object} ansIndex
  1681. * 删除案例题简答图片
  1682. */
  1683. deleteImgChild(imgIndex, bankIndex, ansIndex) {
  1684. this.questionList[bankIndex].jsonStr[ansIndex].ansText.imageList.splice(
  1685. imgIndex,
  1686. 1
  1687. );
  1688. },
  1689. /**
  1690. * @param {Object} bankindex
  1691. * 选择上传图片
  1692. */
  1693. chooseImg(bankindex) {
  1694. if (
  1695. this.questionList[bankindex] &&
  1696. this.questionList[bankindex].ansText &&
  1697. this.questionList[bankindex].ansText.imageList.length >= 4
  1698. ) {
  1699. uni.showToast({
  1700. icon: "none",
  1701. title: "最多选择4张",
  1702. });
  1703. return;
  1704. }
  1705. uni.chooseImage({
  1706. count: 1, //默认9
  1707. sizeType: ["compressed"], //可以指定是原图还是压缩图,默认二者都有
  1708. sourceType: ["album", "camera"], //从相册选择
  1709. success: (res) => {
  1710. let self = this;
  1711. // console.log(JSON.stringify(res.tempFilePaths));
  1712. let img = res.tempFilePaths[0];
  1713. uni.getImageInfo({
  1714. src: img,
  1715. success: async (res) => {
  1716. let canvasWidth = res.width; //图片原始长宽
  1717. let canvasHeight = res.height;
  1718. if (canvasWidth > 1000 || canvasHeight > 1000) {
  1719. uni.compressImage({
  1720. src: img,
  1721. quality: 75,
  1722. width: "50%",
  1723. height: "50%",
  1724. success: async (rest) => {
  1725. const dir = await self.uploadFile(rest
  1726. .tempFilePath, 0);
  1727. this.questionList[bankindex].ansText
  1728. .imageList.push(dir);
  1729. },
  1730. });
  1731. } else {
  1732. const dir = await self.uploadFile(img, 0);
  1733. this.questionList[bankindex].ansText.imageList.push(dir);
  1734. }
  1735. },
  1736. });
  1737. },
  1738. });
  1739. },
  1740. /**
  1741. * @param {Object} bankindex
  1742. * @param {Object} ansindex
  1743. * 案例题选择上传图片
  1744. */
  1745. chooseImgChild(bankindex, ansindex) {
  1746. if (
  1747. this.questionList[bankindex].jsonStr[ansindex] &&
  1748. this.questionList[bankindex].jsonStr[ansindex].ansText &&
  1749. this.questionList[bankindex].jsonStr[ansindex].ansText.imageList
  1750. .length >= 4
  1751. ) {
  1752. uni.showToast({
  1753. icon: "none",
  1754. title: "最多选择4张",
  1755. });
  1756. return;
  1757. }
  1758. uni.chooseImage({
  1759. count: 1, //默认9
  1760. sizeType: ["compressed"], //可以指定是原图还是压缩图,默认二者都有
  1761. sourceType: ["album", "camera"], //从相册选择
  1762. success: (res) => {
  1763. let self = this;
  1764. // console.log(JSON.stringify(res.tempFilePaths));
  1765. let img = res.tempFilePaths[0];
  1766. uni.getImageInfo({
  1767. src: img,
  1768. success: async (res) => {
  1769. let canvasWidth = res.width; //图片原始长宽
  1770. let canvasHeight = res.height;
  1771. if (canvasWidth > 1000 || canvasHeight > 1000) {
  1772. uni.compressImage({
  1773. src: img,
  1774. quality: 75,
  1775. width: "50%",
  1776. height: "50%",
  1777. success: async (rest) => {
  1778. const dir = await self.uploadFile(rest
  1779. .tempFilePath, 0);
  1780. this.questionList[bankindex].jsonStr[
  1781. ansindex
  1782. ].ansText.imageList.push(dir);
  1783. },
  1784. });
  1785. } else {
  1786. const dir = await self.uploadFile(img, 0);
  1787. this.questionList[bankindex].jsonStr[
  1788. ansindex
  1789. ].ansText.imageList.push(dir);
  1790. }
  1791. },
  1792. });
  1793. },
  1794. });
  1795. },
  1796. uploadFile(options, int) {
  1797. var self = this;
  1798. return new Promise((resolve, reject) => {
  1799. var data = {
  1800. orderGoodsId: this.orderGoodsId,
  1801. imageStatus: int,
  1802. };
  1803. self.$api.aliyunpolicy(data).then((res) => {
  1804. console.log(res.data, 6);
  1805. if (res.data.code != 200) {
  1806. self.$method.showToast("签名错误" + JSON.stringify(res.data));
  1807. return;
  1808. }
  1809. var ossToken = res.data.data.resultContent;
  1810. if (ossToken.host == null || ossToken.host == undefined) {
  1811. self.$method.showToast("上传路径报错" + JSON.stringify(res.data));
  1812. return;
  1813. }
  1814. uni.uploadFile({
  1815. url: ossToken.host,
  1816. name: "file",
  1817. filePath: options,
  1818. fileType: "image",
  1819. header: {
  1820. AuthorizationToken: "WX " + uni.getStorageSync("token"),
  1821. },
  1822. formData: {
  1823. key: ossToken.dir,
  1824. OSSAccessKeyId: ossToken.accessid,
  1825. policy: ossToken.policy,
  1826. Signature: ossToken.signature,
  1827. callback: ossToken.callback,
  1828. success_action_status: 200,
  1829. },
  1830. success: (result) => {
  1831. // if (result.statusCode === 200) {
  1832. resolve(ossToken.dir);
  1833. // } else {
  1834. // uni.showToast({
  1835. // title: "上传失败",
  1836. // icon: "none",
  1837. // });
  1838. // return;
  1839. // }
  1840. },
  1841. fail: (error) => {
  1842. uni.showToast({
  1843. title: "上传接口报错" + error,
  1844. icon: "none",
  1845. });
  1846. return;
  1847. },
  1848. });
  1849. });
  1850. });
  1851. },
  1852. /**
  1853. * @param {Object} type
  1854. * @param {Object} bankindex
  1855. * 简答题答案确认
  1856. */
  1857. submitAns(bankindex) {
  1858. if (
  1859. !this.questionList[bankindex].ansText.text &&
  1860. !this.questionList[bankindex].ansText.imageList.length
  1861. ) {
  1862. uni.showToast({
  1863. title: "请输入内容或上传图片",
  1864. duration: 2000,
  1865. icon: "none",
  1866. });
  1867. return;
  1868. }
  1869. this.$set(this.questionList[bankindex], "ques", {
  1870. imageList: this.questionList[bankindex].ansText.imageList || [],
  1871. text: this.questionList[bankindex].ansText.text || "",
  1872. });
  1873. this.$u.toast("已确认答案");
  1874. this.isDoOver();
  1875. },
  1876. /**
  1877. * @param {Object} bankindex
  1878. * @param {Object} ansindex
  1879. * 案例题简答答案确认
  1880. */
  1881. submitAnsChild(bankindex, ansindex) {
  1882. if (
  1883. !this.questionList[bankindex].jsonStr[ansindex].ansText.text &&
  1884. !this.questionList[bankindex].jsonStr[ansindex].ansText.imageList.length
  1885. ) {
  1886. uni.showToast({
  1887. title: "请输入内容或上传图片",
  1888. duration: 2000,
  1889. icon: "none",
  1890. });
  1891. return;
  1892. }
  1893. this.$set(this.questionList[bankindex].ques, ansindex, {
  1894. imageList: this.questionList[bankindex].jsonStr[ansindex].ansText.imageList || [],
  1895. text: this.questionList[bankindex].jsonStr[ansindex].ansText.text || "",
  1896. });
  1897. this.$u.toast("已确认答案");
  1898. this.isDoOver();
  1899. },
  1900. isCheck(item, index) {
  1901. // 案例题处理
  1902. let {
  1903. ques,
  1904. type,
  1905. ans
  1906. } = item;
  1907. if (type == 4) {
  1908. return ans.length == ques.length;
  1909. }
  1910. if (ques) {
  1911. return true;
  1912. }
  1913. },
  1914. isRight(item, index) {
  1915. //单选
  1916. if (this.questionList[index].ques) {
  1917. if (item.type == 1) {
  1918. return this.questionList[index].ques == this.questionList[index].ans;
  1919. //多选
  1920. } else if (item.type == 2) {
  1921. //每一项都相等
  1922. return this.questionList[index].ans.every((item, i) => {
  1923. return item == this.questionList[index].ques[i];
  1924. });
  1925. //判断
  1926. } else if (item.type == 3) {
  1927. return this.questionList[index].ques == this.questionList[index].ans;
  1928. // } else if (item.type == 5) {
  1929. // if(this.questionList[index].ques.text){
  1930. // return true
  1931. // }else{
  1932. // return false
  1933. // }
  1934. } else {
  1935. return false;
  1936. }
  1937. } else {
  1938. return false;
  1939. }
  1940. },
  1941. right(bankIndex, ansIndex, option) {
  1942. if (
  1943. this.questionList[bankIndex].ques[ansIndex] &&
  1944. this.questionList[bankIndex].ans[ansIndex]
  1945. ) {
  1946. if (
  1947. this.questionList[bankIndex].ques[ansIndex].indexOf(
  1948. option.optionsId
  1949. ) != -1 ||
  1950. this.questionList[bankIndex].ans[ansIndex].indexOf(
  1951. option.optionsId
  1952. ) != -1
  1953. ) {
  1954. return true;
  1955. } else {
  1956. return false;
  1957. }
  1958. } else {
  1959. return false;
  1960. }
  1961. },
  1962. wrong(bankIndex, ansIndex, option) {
  1963. if (
  1964. this.questionList[bankIndex].ques[ansIndex] &&
  1965. this.questionList[bankIndex].ans[ansIndex]
  1966. ) {
  1967. if (
  1968. this.questionList[bankIndex].ques[ansIndex].indexOf(
  1969. option.optionsId
  1970. ) != -1 &&
  1971. this.questionList[bankIndex].ans[ansIndex].indexOf(
  1972. option.optionsId
  1973. ) == -1
  1974. ) {
  1975. return true;
  1976. } else {
  1977. return false;
  1978. }
  1979. } else {
  1980. return false;
  1981. }
  1982. },
  1983. isWrong(item, index) {
  1984. if (this.questionList[index].ques) {
  1985. //单选
  1986. if (item.type == 1) {
  1987. return this.questionList[index].ques != this.questionList[index].ans;
  1988. //多选
  1989. } else if (item.type == 2) {
  1990. //每一项都相等
  1991. return this.questionList[index].ques.some((item, i) => {
  1992. return this.questionList[index].ans.indexOf(item) == -1;
  1993. });
  1994. //判断
  1995. } else if (item.type == 3) {
  1996. return this.questionList[index].ques != this.questionList[index].ans;
  1997. } else {
  1998. return false;
  1999. }
  2000. } else {
  2001. return false;
  2002. }
  2003. },
  2004. isPart(item, index) {
  2005. if (this.questionList[index].ques) {
  2006. if (item.type == 2) {
  2007. let isWrong = this.questionList[index].ques.some((item, i) => {
  2008. return this.questionList[index].ans.indexOf(item) == -1;
  2009. });
  2010. let isRight = this.questionList[index].ans.every((item, i) => {
  2011. return item == this.questionList[index].ques[i];
  2012. });
  2013. if (!isRight && !isWrong) {
  2014. return true;
  2015. }
  2016. }
  2017. } else {
  2018. return false;
  2019. }
  2020. },
  2021. isOver(item, index) {
  2022. if (this.questionList[index].ques) {
  2023. if (item.type == 4) {
  2024. //案例题
  2025. let isOver = item.jsonStr.every((jsonItem, indexs) => {
  2026. if (
  2027. jsonItem.type == 1 ||
  2028. jsonItem.type == 2 ||
  2029. jsonItem.type == 3
  2030. ) {
  2031. if (item.ques[indexs]) {
  2032. return true;
  2033. } else {
  2034. return false;
  2035. }
  2036. } else if (jsonItem.type == 5) {
  2037. if (
  2038. item.ques[indexs] &&
  2039. (item.ques[indexs].text || item.ques[indexs].imageList.length)
  2040. ) {
  2041. console.log("chil");
  2042. return true;
  2043. } else {
  2044. return false;
  2045. }
  2046. }
  2047. });
  2048. if (isOver) {
  2049. return true;
  2050. } else {
  2051. return false;
  2052. }
  2053. } else if (item.type == 5) {
  2054. //简答题
  2055. //每一项都相等
  2056. if (item.ques && (item.ques.imageList.length || item.ques.text)) {
  2057. return true;
  2058. }
  2059. //判断
  2060. } else {
  2061. return false;
  2062. }
  2063. } else {
  2064. return false;
  2065. }
  2066. },
  2067. tabSelect(index, bankindex) {
  2068. this.$set(this.questionList[bankindex], "current", index);
  2069. },
  2070. showPhoto(contentStr) {
  2071. if (contentStr && typeof contentStr == "string") {
  2072. let reg = /<img[^>]*src[=\'\"\s]+([^\'\"]*)[\'\"]?[^>]*>/gi;
  2073. let strArr = contentStr.match(reg);
  2074. strArr.forEach((str, index) => {
  2075. strArr[index] = str.replace(reg, "$1");
  2076. });
  2077. // 预览图片
  2078. uni.previewImage({
  2079. urls: strArr,
  2080. longPressActions: {
  2081. itemList: ["发送给朋友", "保存图片", "收藏"],
  2082. success: function(data) {
  2083. console.log(
  2084. "选中了第" +
  2085. (data.tapIndex + 1) +
  2086. "个按钮,第" +
  2087. (data.index + 1) +
  2088. "张图片"
  2089. );
  2090. },
  2091. fail: function(err) {
  2092. console.log(err.errMsg);
  2093. },
  2094. },
  2095. });
  2096. }
  2097. },
  2098. },
  2099. computed: {
  2100. doMode() {
  2101. // 做题模式 1章卷 2随机练习 3模拟组卷
  2102. if (this.entryType == "sd") {
  2103. return 4;
  2104. }
  2105. return this.examData.simulateStatus ?
  2106. 3 :
  2107. this.entryType == "random" ?
  2108. 2 :
  2109. 1;
  2110. },
  2111. },
  2112. };
  2113. </script>
  2114. <style lang="scss" scoped>
  2115. .questionBank {
  2116. width: 100%;
  2117. height: 100vh;
  2118. display: flex;
  2119. flex-direction: column;
  2120. }
  2121. .swiper {
  2122. width: 100%;
  2123. flex: 1;
  2124. }
  2125. .lisSty {
  2126. margin-bottom: 16rpx;
  2127. display: flex;
  2128. align-items: center;
  2129. .flex_auto {
  2130. word-break: break-all;
  2131. flex: 1;
  2132. }
  2133. }
  2134. .activeTI {
  2135. vertical-align: middle;
  2136. display: inline-block;
  2137. border: 1rpx solid #eee;
  2138. border-radius: 50rpx;
  2139. height: 48rpx;
  2140. line-height: 46rpx;
  2141. text-align: center;
  2142. width: 48rpx;
  2143. margin-right: 15rpx;
  2144. color: #666;
  2145. font-size: 30rpx;
  2146. &.right {
  2147. color: #fff;
  2148. background: #36c75a;
  2149. }
  2150. &.wrong {
  2151. color: #fff;
  2152. background: #ff3b30;
  2153. }
  2154. &.checked,
  2155. &.user_choose {
  2156. color: #fff;
  2157. background: #007aff;
  2158. }
  2159. }
  2160. .submit_checkbox {
  2161. position: fixed;
  2162. left: 0;
  2163. right: 0;
  2164. bottom: 120rpx;
  2165. margin: 20rpx auto;
  2166. width: 526rpx;
  2167. height: 80rpx;
  2168. background: rgba(0, 122, 255, 1);
  2169. color: #fff;
  2170. text-align: center;
  2171. line-height: 80rpx;
  2172. font-size: 30rpx;
  2173. border-radius: 40rpx;
  2174. &.disabled {
  2175. opacity: 0.6;
  2176. }
  2177. }
  2178. .titles {
  2179. overflow: hidden;
  2180. margin-bottom: 24rpx;
  2181. }
  2182. .titBox {
  2183. padding: 41rpx 25rpx 24rpx 25rpx;
  2184. }
  2185. .titBox_title {
  2186. padding: 21rpx;
  2187. }
  2188. .tabs {
  2189. margin: 10rpx;
  2190. display: flex;
  2191. .tab {
  2192. margin: 0 4rpx;
  2193. padding: 10rpx 13rpx;
  2194. text-align: center;
  2195. color: #007aff;
  2196. font-size: 28rpx;
  2197. border-radius: 16rpx;
  2198. background: #fff;
  2199. &.current {
  2200. color: #fff;
  2201. background: #007aff;
  2202. }
  2203. }
  2204. }
  2205. .ans {
  2206. margin: 8rpx 8rpx 8rpx;
  2207. .ans_input {
  2208. border-radius: 16rpx;
  2209. background: #fff;
  2210. .top {
  2211. border-bottom: 1rpx solid #eeeeee;
  2212. padding: 16rpx;
  2213. display: flex;
  2214. align-items: center;
  2215. .icon {
  2216. margin-right: 20rpx;
  2217. width: 40rpx;
  2218. height: 38rpx;
  2219. }
  2220. .progress {
  2221. flex: 1;
  2222. }
  2223. .submit {
  2224. width: 168rpx;
  2225. height: 48rpx;
  2226. line-height: 48rpx;
  2227. text-align: center;
  2228. color: #fff;
  2229. font-size: 30rpx;
  2230. background: #007aff;
  2231. border-radius: 24rpx;
  2232. &.disabled {
  2233. opacity: 0.6;
  2234. }
  2235. }
  2236. }
  2237. .textarea {
  2238. textarea {
  2239. width: 100%;
  2240. height: 287rpx;
  2241. padding: 10rpx;
  2242. }
  2243. }
  2244. .imgs {
  2245. overflow: hidden;
  2246. display: flex;
  2247. width: 100%;
  2248. .img {
  2249. width: 104rpx;
  2250. height: 104rpx;
  2251. border-radius: 8rpx;
  2252. position: relative;
  2253. margin: 20rpx;
  2254. text {
  2255. position: absolute;
  2256. right: -15rpx;
  2257. top: -15rpx;
  2258. width: 30rpx;
  2259. height: 30rpx;
  2260. text-align: center;
  2261. line-height: 30rpx;
  2262. color: #fff;
  2263. background: #ff3b30;
  2264. border-radius: 50%;
  2265. }
  2266. image {
  2267. width: 100%;
  2268. height: 100%;
  2269. }
  2270. }
  2271. }
  2272. }
  2273. .ans_submit {
  2274. padding: 16rpx;
  2275. border-radius: 16rpx;
  2276. background: #fff;
  2277. .imgs {
  2278. overflow: hidden;
  2279. display: flex;
  2280. width: 100%;
  2281. .img {
  2282. width: 104rpx;
  2283. height: 104rpx;
  2284. border-radius: 8rpx;
  2285. position: relative;
  2286. margin: 20rpx;
  2287. image {
  2288. width: 100%;
  2289. height: 100%;
  2290. }
  2291. }
  2292. }
  2293. }
  2294. }
  2295. .leftLetters {
  2296. display: flex;
  2297. align-items: center;
  2298. width: 220rpx;
  2299. .btnType {
  2300. padding: 5rpx 10rpx;
  2301. border: 1rpx solid #007aff;
  2302. border-radius: 10rpx;
  2303. background-color: rgba(0, 122, 255, 0.1);
  2304. font-size: 28rpx;
  2305. color: #007aff;
  2306. margin-right: 15rpx;
  2307. }
  2308. }
  2309. .firstLetter {
  2310. display: flex;
  2311. justify-content: space-between;
  2312. align-items: center;
  2313. margin-bottom: 30rpx;
  2314. }
  2315. .popupView {
  2316. height: 100%;
  2317. padding-bottom: 100rpx;
  2318. .popupTops {
  2319. height: 77rpx;
  2320. border-bottom: 1rpx solid #eee;
  2321. text-align: center;
  2322. line-height: 77rpx;
  2323. font-size: 24rpx;
  2324. color: #999;
  2325. position: relative;
  2326. .topIcon {
  2327. position: absolute;
  2328. top: 10rpx;
  2329. left: 50%;
  2330. transform: translateX(-50%);
  2331. width: 80rpx;
  2332. height: 8rpx;
  2333. background-color: #999;
  2334. border-radius: 4rpx;
  2335. }
  2336. }
  2337. .popupContent {}
  2338. }
  2339. .pageContent {
  2340. position: relative;
  2341. background-color: #eaeef1;
  2342. height: 100%;
  2343. padding-top: 8rpx;
  2344. padding-bottom: 100rpx;
  2345. overflow-y: scroll;
  2346. }
  2347. .pad_8 {
  2348. background-color: #fff;
  2349. margin: 0rpx 8rpx 8rpx;
  2350. border-radius: 16rpx;
  2351. &.no-margin {
  2352. margin-top: -16rpx;
  2353. border-radius: 0 0 16rpx 16rpx;
  2354. }
  2355. }
  2356. .answer {
  2357. height: 80rpx;
  2358. line-height: 80rpx;
  2359. padding: 0rpx 24rpx;
  2360. display: flex;
  2361. align-items: center;
  2362. justify-content: space-between;
  2363. color: #666;
  2364. font-size: 30rpx;
  2365. }
  2366. .footer_btn {
  2367. background-color: #fff;
  2368. z-index: 10078;
  2369. position: fixed;
  2370. bottom: 0rpx;
  2371. display: flex;
  2372. align-items: center;
  2373. justify-content: space-between;
  2374. width: 100%;
  2375. height: 98rpx;
  2376. padding: 0rpx 38rpx;
  2377. border-top: 1rpx solid #eee;
  2378. .flex_center {
  2379. flex: 1;
  2380. display: flex;
  2381. justify-content: center;
  2382. align-items: center;
  2383. flex-direction: column;
  2384. margin: 0 200rpx;
  2385. font-size: 24rpx;
  2386. color: #999999;
  2387. .up-icon {
  2388. margin-bottom: 18rpx;
  2389. width: 100%;
  2390. display: flex;
  2391. justify-content: center;
  2392. image {
  2393. width: 58rpx;
  2394. height: 21rpx;
  2395. }
  2396. }
  2397. }
  2398. .collect {
  2399. visibility: hidden;
  2400. width: 100rpx;
  2401. &.show {
  2402. visibility: visible;
  2403. }
  2404. >view {
  2405. display: flex;
  2406. flex-direction: column;
  2407. align-items: center;
  2408. justify-content: center;
  2409. image {
  2410. width: 32rpx;
  2411. height: 32rpx;
  2412. margin-bottom: 6rpx;
  2413. }
  2414. view {
  2415. font-size: 24rpx;
  2416. color: #999999;
  2417. }
  2418. }
  2419. }
  2420. }
  2421. .boxSty {
  2422. padding: 44rpx 41rpx 0rpx;
  2423. }
  2424. .liListSty {
  2425. border: 1rpx solid #eeeeee;
  2426. width: 88rpx;
  2427. height: 88rpx;
  2428. border-radius: 32rpx;
  2429. text-align: center;
  2430. line-height: 88rpx;
  2431. color: #333;
  2432. font-size: 32rpx;
  2433. float: left;
  2434. margin: 20rpx 23rpx;
  2435. &.isRight {
  2436. border: 1rpx solid #eeeeee;
  2437. color: #fff;
  2438. background: #36c75a;
  2439. }
  2440. &.isWrong {
  2441. border: 1rpx solid #eeeeee;
  2442. color: #fff;
  2443. background: #ff3b30;
  2444. }
  2445. &.isPart {
  2446. border: 1rpx solid #eeeeee;
  2447. color: #fff;
  2448. background: #ffc53d;
  2449. }
  2450. &.isOver {
  2451. border: 1rpx solid #eeeeee;
  2452. color: #fff;
  2453. background: blue;
  2454. }
  2455. &.check_ans {
  2456. border: 1rpx solid #eeeeee;
  2457. color: #fff;
  2458. background: #007aff;
  2459. }
  2460. }
  2461. .answerInfos {
  2462. padding: 25rpx 25rpx 25rpx 23rpx;
  2463. }
  2464. .answerTitle {
  2465. margin-bottom: 28rpx;
  2466. color: #666;
  2467. font-size: 30rpx;
  2468. }
  2469. .answerContent {
  2470. font-size: 30rpx;
  2471. color: #666;
  2472. }
  2473. .textChild {
  2474. display: inline-block;
  2475. vertical-align: middle;
  2476. }
  2477. .dialog {
  2478. position: fixed;
  2479. left: 0;
  2480. top: 0;
  2481. width: 100%;
  2482. height: 100%;
  2483. background-color: rgba(0, 0, 0, 0.8);
  2484. display: flex;
  2485. flex-direction: column;
  2486. align-items: center;
  2487. justify-content: center;
  2488. z-index: 20000;
  2489. .pointer {
  2490. width: 338rpx;
  2491. height: 240rpx;
  2492. }
  2493. .text {
  2494. font-size: 32rpx;
  2495. color: #ffffff;
  2496. text-align: center;
  2497. }
  2498. .btn {
  2499. width: 242rpx;
  2500. height: 82rpx;
  2501. border: 2rpx solid #ffffff;
  2502. border-radius: 16rpx;
  2503. text-align: center;
  2504. line-height: 82rpx;
  2505. margin: 41rpx auto;
  2506. color: #fff;
  2507. font-size: 32rpx;
  2508. }
  2509. }
  2510. .dialog-arrow {
  2511. padding-top: 124rpx;
  2512. position: fixed;
  2513. left: 0;
  2514. top: 0;
  2515. width: 100%;
  2516. height: 100%;
  2517. background-color: rgba(0, 0, 0, 0.8);
  2518. z-index: 20000;
  2519. .pointer {
  2520. margin-left: 87rpx;
  2521. display: block;
  2522. width: 95rpx;
  2523. height: 98rpx;
  2524. }
  2525. .text {
  2526. padding-left: 177rpx;
  2527. font-size: 32rpx;
  2528. color: #ffffff;
  2529. }
  2530. .btn {
  2531. width: 242rpx;
  2532. height: 82rpx;
  2533. border: 2rpx solid #ffffff;
  2534. border-radius: 16rpx;
  2535. text-align: center;
  2536. line-height: 82rpx;
  2537. margin: 500rpx auto 0;
  2538. color: #fff;
  2539. font-size: 32rpx;
  2540. }
  2541. }
  2542. .dialog_wrap {
  2543. position: fixed;
  2544. left: 0;
  2545. top: 0;
  2546. width: 100%;
  2547. height: 100%;
  2548. z-index: 9999999999;
  2549. .bg {
  2550. background: rgba(0, 0, 0, 0.3);
  2551. position: absolute;
  2552. left: 0;
  2553. top: 0;
  2554. width: 100%;
  2555. height: 100%;
  2556. }
  2557. .dialog {
  2558. position: absolute;
  2559. left: 50%;
  2560. top: 50%;
  2561. transform: translate3D(-50%, -50%, 0);
  2562. width: 640rpx;
  2563. height: 439rpx;
  2564. background: #ffffff;
  2565. border-radius: 24rpx;
  2566. .title {
  2567. font-size: 30rpx;
  2568. font-weight: bold;
  2569. color: #333333;
  2570. line-height: 48rpx;
  2571. text-align: center;
  2572. margin-top: 40rpx;
  2573. }
  2574. .content {
  2575. margin: 35rpx 35rpx 0;
  2576. font-size: 30rpx;
  2577. color: #666666;
  2578. line-height: 48rpx;
  2579. }
  2580. .btns {
  2581. margin-top: 35rpx;
  2582. display: flex;
  2583. align-items: center;
  2584. justify-content: center;
  2585. .btn {
  2586. width: 200rpx;
  2587. height: 80rpx;
  2588. line-height: 80rpx;
  2589. text-align: center;
  2590. background: #f5f5f5;
  2591. border-radius: 40rpx;
  2592. font-size: 30rpx;
  2593. color: rgba(0, 122, 255, 1);
  2594. background: #f5f5f5;
  2595. margin: 0 20rpx;
  2596. &.active {
  2597. color: #f5f5f5;
  2598. background: rgba(0, 122, 255, 1);
  2599. }
  2600. }
  2601. }
  2602. }
  2603. }
  2604. .popboxs {
  2605. width: 100%;
  2606. height: 100%;
  2607. display: flex;
  2608. flex-direction: column;
  2609. align-items: center;
  2610. }
  2611. .classTops {
  2612. flex-shrink: 0;
  2613. padding: 39rpx 0rpx 4rpx;
  2614. font-weight: bold;
  2615. color: #333;
  2616. font-size: 30rpx;
  2617. }
  2618. .textStys {
  2619. width: 100%;
  2620. flex: 1;
  2621. padding: 36rpx;
  2622. }
  2623. .classFootsty {
  2624. flex-shrink: 0;
  2625. display: flex;
  2626. align-items: center;
  2627. justify-content: center;
  2628. padding: 10rpx 0rpx 40rpx;
  2629. .btnsty {
  2630. width: 200rpx;
  2631. height: 80rpx;
  2632. border-radius: 40rpx;
  2633. font-weight: bold;
  2634. font-size: 30rpx;
  2635. text-align: center;
  2636. line-height: 80rpx;
  2637. }
  2638. .btns1 {
  2639. background-color: #f5f5f5;
  2640. color: #007aff;
  2641. }
  2642. .btns2 {
  2643. margin-left: 40rpx;
  2644. background-color: #007aff;
  2645. color: #ffffff;
  2646. }
  2647. }
  2648. </style>