SentenceInput.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. <!-- -->
  2. <template>
  3. <div class="Big-Book-prev-Textdes" v-if="curQue">
  4. <h2 v-if="curQue.title">{{ curQue.title }}</h2>
  5. <ul>
  6. <li v-for="(items, indexs) in curQue.option" :key="indexs">
  7. <b class="xuhao" v-if="items.number">{{ items.number }}</b>
  8. <p
  9. :class="[oldsrc == items.mp3_list[0].id ? palyClass : '']"
  10. @click="handlePlayVoice(items.mp3_list[0].id)"
  11. v-if="items.mp3_list && items.mp3_list.length > 0"
  12. ></p>
  13. <!-- 句子内容 -->
  14. <div class="item-content">
  15. <!-- 如果不是填空题 不替换 -->
  16. <template v-if="dataType.indexOf('sentence_input_chs') == -1">
  17. <template v-if="items.detail.wordsList.length == 0">
  18. <p :class="['content-con']" v-if="items.detail.sentence">
  19. {{ items.detail.sentence }}
  20. </p>
  21. </template>
  22. <template v-else>
  23. <div class="con-box">
  24. <div
  25. :class="['con-item', indexCon === 0 ? 'con-item-0' : '']"
  26. v-for="(itemCon, indexCon) in items.detail.resArr"
  27. :key="indexCon"
  28. v-show="itemCon.isShow"
  29. >
  30. <template
  31. v-if="
  32. items.detail.wordsList[indexCon + 1] &&
  33. items.detail.wordsList[indexCon + 1].chs &&
  34. chsFhList.indexOf(
  35. items.detail.wordsList[indexCon + 1].chs
  36. ) > -1
  37. "
  38. >
  39. <div class="synthesis-box">
  40. <div>
  41. <span
  42. class="pinyin"
  43. :class="[
  44. noFont.indexOf(itemCon.pinyin) > -1 ? 'noFont' : '',
  45. ]"
  46. >{{ itemCon.pinyin }}</span
  47. >
  48. <span class="hanzi content-con">{{ itemCon.chs }}</span>
  49. </div>
  50. <div style="text-align: left">
  51. <span
  52. class="pinyin"
  53. :class="[
  54. noFont.indexOf(
  55. items.detail.wordsList[indexCon + 1].pinyin
  56. ) > -1
  57. ? 'noFont'
  58. : '',
  59. ]"
  60. >{{
  61. items.detail.wordsList[indexCon + 1].pinyin
  62. }}</span
  63. >
  64. <span class="hanzi content-con">{{
  65. items.detail.wordsList[indexCon + 1].chs
  66. }}</span>
  67. </div>
  68. </div>
  69. </template>
  70. <template v-else>
  71. <span
  72. class="pinyin"
  73. :class="[
  74. noFont.indexOf(itemCon.pinyin) > -1 ? 'noFont' : '',
  75. ]"
  76. >{{ itemCon.pinyin }}</span
  77. >
  78. <span class="hanzi content-con">{{ itemCon.chs }}</span>
  79. </template>
  80. </div>
  81. </div>
  82. </template>
  83. <b class="content-en" v-if="items.en">{{ items.en }}</b>
  84. </template>
  85. <template v-else>
  86. <div class="chs_pinyin">
  87. <div
  88. v-for="(conent, conIndex) in items.detail.wordsList"
  89. :key="conIndex + 'con'"
  90. >
  91. <template v-if="items.detail.pyPosition == 'top'">
  92. <!-- <div
  93. v-if="conent.pinyin == '__'"
  94. contenteditable="true"
  95. class="input pinyin"
  96. v-html="answerList[indexs].pinyin"
  97. @change="changeAnswerList($event, indexs, 'pinyin')"
  98. ></div> -->
  99. <!--
  100. v-model="answerList[indexs].pinyin"
  101. -->
  102. <p class="pinyin" v-if="conent.pinyin != '__'">
  103. {{ conent.pinyin }}
  104. </p>
  105. </template>
  106. <template v-if="conent.chs == '__'">
  107. <div
  108. contenteditable="true"
  109. class="input chs"
  110. v-html="answerList[indexs].chs"
  111. @change="changeAnswerList($event, indexs, 'chs')"
  112. @copy.native.capture.prevent="handleFalse"
  113. @paste.native.capture.prevent="handleFalse"
  114. @cut.native.capture.prevent="handleFalse"
  115. ></div>
  116. </template>
  117. <template v-else>
  118. <p class="chs">
  119. {{ conent.chs }}
  120. </p>
  121. </template>
  122. <template
  123. v-if="items.detail.pyPosition == 'bottom' && conent.pinyin"
  124. >
  125. <!-- <div
  126. v-if="conent.pinyin == '__'"
  127. contenteditable="true"
  128. class="input pinyin"
  129. v-html="answerList[indexs].pinyin"
  130. @change="changeAnswerList($event, indexs, 'pinyin')"
  131. ></div> -->
  132. <p class="pinyin" v-if="conent.pinyin != '__'">
  133. {{ conent.pinyin }}
  134. </p>
  135. </template>
  136. </div>
  137. </div>
  138. </template>
  139. </div>
  140. <template v-if="dataType.indexOf('sentence_answer_chs') > -1">
  141. <input
  142. @input="handleInput"
  143. :class="['item-input']"
  144. v-model="curQue.Bookanswer[indexs]"
  145. placeholder="输入"
  146. />
  147. </template>
  148. <template v-if="dataType.indexOf('sentence_judge_chs') > -1">
  149. <div class="judge-box">
  150. <a
  151. :class="[
  152. 'right-btn',
  153. curQue.Bookanswer[indexs] == 'right' ? 'active' : '',
  154. ]"
  155. @click="handleSelectJudge('right', indexs)"
  156. ></a>
  157. <a
  158. :class="[
  159. 'error-btn',
  160. curQue.Bookanswer[indexs] == 'error' ? 'active' : '',
  161. ]"
  162. @click="handleSelectJudge('error', indexs)"
  163. ></a>
  164. </div>
  165. </template>
  166. <template v-if="dataType.indexOf('sentence_record_chs') > -1">
  167. <template v-if="dataType.indexOf('sentence_input_chs') != -1">
  168. <Soundrecord
  169. @handleWav="handleWav"
  170. type="normal"
  171. v-if="items.IsRecord"
  172. />
  173. </template>
  174. <template v-else>
  175. <Soundrecord
  176. @handleWav="handleWav"
  177. type="mini"
  178. class="luyin-box"
  179. v-if="items.IsRecord"
  180. />
  181. </template>
  182. </template>
  183. </li>
  184. </ul>
  185. </div>
  186. </template>
  187. <script>
  188. import Soundrecord from "../preview/Soundrecord.vue"; // 录音模板
  189. export default {
  190. components: { Soundrecord },
  191. props: ["curQue"],
  192. data() {
  193. return {
  194. audio: new Audio(),
  195. oldsrc: "", // 存储播放音频的src 用来比对是否点击的是同一个音频
  196. palyClass: "",
  197. dataType: [], // 题型
  198. chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
  199. noFont: ["~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")"], // 对应不要拼音字体
  200. answerList: [],
  201. };
  202. },
  203. computed: {},
  204. watch: {},
  205. //方法集合
  206. methods: {
  207. // input 输入时
  208. handleInput(e) {
  209. e.target.value = e.target.value ? e.target.value.trim() : "";
  210. },
  211. handlePlayVoice(url) {
  212. let _this = this;
  213. if (!url) {
  214. return;
  215. }
  216. if (!this.audio.paused && this.oldsrc == url) {
  217. this.audio.pause();
  218. } else if (this.audio.paused && this.oldsrc == url) {
  219. this.audio.play();
  220. } else {
  221. _this.audio.pause();
  222. _this.audio.load();
  223. _this.audio.src = url;
  224. _this.oldsrc = url;
  225. _this.audio.loop = false;
  226. _this.audio.play();
  227. }
  228. },
  229. // 处理数据
  230. handleData() {
  231. let _this = this;
  232. this.dataType = [];
  233. if (!this.curQue.Bookanswer) {
  234. let curCorrect = [];
  235. this.curQue.option.forEach((item) => {
  236. curCorrect.push("");
  237. });
  238. this.$set(this.curQue, "Bookanswer", curCorrect);
  239. }
  240. this.curQue.fn_list.forEach((item) => {
  241. if (item.isFn) {
  242. _this.dataType.push(item.type);
  243. }
  244. });
  245. let curQue = JSON.parse(JSON.stringify(this.curQue));
  246. curQue.option.forEach((dItem, dIndex) => {
  247. let paraArr = [];
  248. dItem.detail.wordsList.forEach((sItem, sIndex) => {
  249. this.mergeWordSymbol(dItem.detail.wordsList, sItem, sIndex);
  250. let obj = {
  251. pinyin: sItem.pinyin,
  252. chs: sItem.chs,
  253. isShow: sItem.isShow,
  254. };
  255. paraArr.push(obj);
  256. });
  257. this.$set(_this.curQue.option[dIndex].detail, "resArr", paraArr);
  258. console.log();
  259. if (paraArr.length == 0) {
  260. let str = "就那天___";
  261. let arrs = str.split(/_{2,}/g);
  262. }
  263. });
  264. },
  265. //词和标点合一起
  266. mergeWordSymbol(sItem, wItem, curIndex) {
  267. let leg = sItem.length;
  268. if (curIndex < leg - 1) {
  269. if (this.chsFhList.indexOf(wItem.chs) > -1) {
  270. wItem.isShow = false;
  271. } else {
  272. wItem.isShow = true;
  273. }
  274. }
  275. },
  276. // 判断题选择
  277. handleSelectJudge(obj, index) {
  278. this.$set(this.curQue.Bookanswer, index, obj);
  279. },
  280. handleWav(data) {},
  281. handleDatas(str, type) {
  282. str = str.trim();
  283. str = str.replace(/_{2,}/g, "^ ");
  284. str =
  285. type == "hanzi" ? str.replace(/\s+/g, "") : str.replace(/\s+/g, " ");
  286. let resArr = type == "hanzi" ? str.split("") : str.split(/\s+/);
  287. return resArr;
  288. },
  289. changeAnswerList(e, index, type) {
  290. if (type == "pinyin") {
  291. this.answerList[index].pinyin += e.target.innerHTML;
  292. } else {
  293. this.answerList[index].chs += e.target.innerHTML;
  294. console.log(e.target.innerHTML)
  295. }
  296. },
  297. handleFalse(){
  298. return false;
  299. }
  300. },
  301. //生命周期 - 创建完成(可以访问当前this实例)
  302. created() {
  303. this.handleData();
  304. if (this.dataType.indexOf("sentence_input_chs") != -1) {
  305. this.curQue.option.forEach((item) => {
  306. item.answer.forEach((it) => {
  307. this.answerList.push({
  308. chs: "",
  309. pinyin: "",
  310. });
  311. });
  312. });
  313. }
  314. },
  315. //生命周期 - 挂载完成(可以访问DOM元素)
  316. mounted() {
  317. let _this = this;
  318. _this.audio.addEventListener("play", function () {
  319. _this.palyClass = "active";
  320. });
  321. _this.audio.addEventListener("pause", function () {
  322. _this.palyClass = "";
  323. });
  324. _this.audio.addEventListener("ended", function () {
  325. _this.palyClass = "";
  326. });
  327. },
  328. beforeCreate() {}, //生命周期 - 创建之前
  329. beforeMount() {}, //生命周期 - 挂载之前
  330. beforeUpdate() {}, //生命周期 - 更新之前
  331. updated() {}, //生命周期 - 更新之后
  332. beforeDestroy() {}, //生命周期 - 销毁之前
  333. destroyed() {}, //生命周期 - 销毁完成
  334. activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
  335. };
  336. </script>
  337. <style lang='scss' scoped>
  338. //@import url(); 引入公共css类
  339. .Big-Book-prev-Textdes {
  340. width: 100%;
  341. h2 {
  342. font-weight: normal;
  343. font-size: 16px;
  344. line-height: 150%;
  345. color: #000000;
  346. margin: 0 2px 8px 2px;
  347. }
  348. ul {
  349. display: flex;
  350. flex-flow: wrap;
  351. justify-content: start;
  352. list-style: none;
  353. li {
  354. width: 100%;
  355. background: #ffffff;
  356. border: 1px solid rgba(0, 0, 0, 0.1);
  357. box-sizing: border-box;
  358. border-radius: 8px;
  359. display: flex;
  360. align-items: center;
  361. padding: 8px 12px;
  362. margin-bottom: 8px;
  363. > b {
  364. width: 24px;
  365. line-height: 24px;
  366. font-size: 16px;
  367. text-align: center;
  368. margin-right: 8px;
  369. font-weight: 400;
  370. color: #ffffff;
  371. // margin-top: 4px;
  372. font-family: "FZJCGFKTK";
  373. border-radius: 50%;
  374. }
  375. > p {
  376. width: 24px;
  377. height: 24px;
  378. cursor: pointer;
  379. background: url("../../../assets/newImage/common/icon-voice.png") left
  380. center no-repeat;
  381. background-size: 24px;
  382. margin: 0px 8px 0 0;
  383. &.active {
  384. background: url("../../../assets/newImage/common/icon-voice-play-zise.png")
  385. left center no-repeat;
  386. background-size: 24px;
  387. }
  388. }
  389. .item-content {
  390. flex: 1;
  391. .chs_pinyin {
  392. display: flex;
  393. margin-left: 8px;
  394. .input {
  395. margin-left: 16px;
  396. margin-right: 8px;
  397. min-width: 50px;
  398. border-bottom: 1px solid black;
  399. }
  400. .pinyin {
  401. font-weight: "GB-PINYINOK-B";
  402. font-size: 14px;
  403. line-height: 130%;
  404. color: rgba(0, 0, 0, 0.6);
  405. margin-top: 8px;
  406. }
  407. .chs {
  408. font-family: "FZJCGFKTK";
  409. font-style: normal;
  410. font-weight: normal;
  411. font-size: 20px;
  412. line-height: 150%;
  413. color: #000000;
  414. }
  415. p {
  416. margin: 0;
  417. }
  418. }
  419. .content-con {
  420. font-size: 20px;
  421. line-height: 150%;
  422. color: #000000;
  423. font-family: "FZJCGFKTK";
  424. margin: 0;
  425. &.content-con-small {
  426. font-size: 16px;
  427. }
  428. }
  429. .content-en {
  430. font-weight: normal;
  431. font-size: 16px;
  432. line-height: 150%;
  433. color: #000000;
  434. font-family: "robot";
  435. }
  436. .con-box {
  437. display: flex;
  438. flex-flow: wrap;
  439. .con-item {
  440. text-align: center;
  441. padding: 0 3px;
  442. &.con-item-0 {
  443. text-align: left;
  444. padding-left: 0;
  445. }
  446. }
  447. span {
  448. display: block;
  449. }
  450. .pinyin {
  451. font-family: "GB-PINYINOK-B";
  452. font-size: 14px;
  453. line-height: 130%;
  454. color: #000000;
  455. height: 18px;
  456. &.noFont {
  457. font-family: initial;
  458. }
  459. }
  460. .synthesis-box {
  461. display: flex;
  462. }
  463. }
  464. }
  465. input {
  466. width: 68px;
  467. border: 1px solid rgba(0, 0, 0, 0.15);
  468. box-sizing: border-box;
  469. border-radius: 4px;
  470. outline: none;
  471. height: 32px;
  472. padding: 4px 8px;
  473. color: #000000;
  474. text-align: center;
  475. font-size: 16px;
  476. line-height: 150%;
  477. }
  478. .judge-box {
  479. display: flex;
  480. justify-content: center;
  481. a {
  482. width: 32px;
  483. height: 32px;
  484. background: #fff url("../../../assets/newImage/common/right-btn.png")
  485. center no-repeat;
  486. background-size: 24px;
  487. border-radius: 8px;
  488. border: 1px solid rgba(0, 0, 0, 0.1);
  489. &:hover,
  490. &.active {
  491. background-color: #e5fff0;
  492. border-color: #00c850;
  493. }
  494. }
  495. a.error-btn {
  496. background: #fff url("../../../assets/newImage/common/error-btn.png")
  497. center no-repeat;
  498. background-size: 24px;
  499. margin-left: 4px;
  500. &:hover,
  501. &.active {
  502. background-color: #ffe5e5;
  503. border-color: #de4444;
  504. }
  505. }
  506. }
  507. .luyin-box {
  508. border: 1px solid rgba(0, 0, 0, 0.1);
  509. border-radius: 8px;
  510. width: 64px;
  511. }
  512. }
  513. }
  514. }
  515. .NPC-Big-Book-preview-green {
  516. .Big-Book-prev-Textdes {
  517. b.xuhao {
  518. background: #24b99e;
  519. }
  520. }
  521. }
  522. .NPC-Big-Book-preview-brown {
  523. .Big-Book-prev-Textdes {
  524. b.xuhao {
  525. background: #bd8865;
  526. }
  527. }
  528. }
  529. </style>