CharacterStructurePreview.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="structure-preview" :style="[getAreaStyle(), getComponentStyle()]">
  4. <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
  5. <div class="main">
  6. <div
  7. class="option"
  8. :style="{
  9. background: data.unified_attrib && data.unified_attrib.assist_color ? data.unified_attrib.assist_color : '',
  10. }"
  11. >
  12. <draggable
  13. v-model="SortArr"
  14. animation="300"
  15. group="site"
  16. class="content-box"
  17. :disabled="disabled"
  18. @start="onStart($event)"
  19. @end="onEnd($event)"
  20. @choose="choose($event)"
  21. >
  22. <transition-group>
  23. <div
  24. v-for="(item, i) in data.structure_select_list"
  25. :id="item.id"
  26. :key="'op' + i"
  27. class="option_one"
  28. :style="{
  29. background:
  30. data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  31. }"
  32. >
  33. <img
  34. :src="item.type === 'local' ? require('@/assets/structure/' + item.value) : item.value"
  35. class="small-img"
  36. />
  37. </div>
  38. </transition-group>
  39. </draggable>
  40. </div>
  41. <div class="one-box">
  42. <div
  43. v-for="(items, row) in data.option_list"
  44. :key="'row' + row"
  45. class="one"
  46. :class="[!items.pinyin ? 'one_nopy' : '']"
  47. :style="{ marginRight: (row + 1) % 3 == 0 ? '' : '16px' }"
  48. >
  49. <div
  50. class="number"
  51. :style="{
  52. background: data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  53. }"
  54. >
  55. {{ row + 1 }}
  56. </div>
  57. <div class="hzpinyin">
  58. <div
  59. v-if="isEnable(data.property.view_pinyin)"
  60. class="pinyin"
  61. :style="{
  62. fontSize: data.unified_attrib && data.unified_attrib.pinyin_size ? data.unified_attrib.pinyin_size : '',
  63. }"
  64. >
  65. {{ items.pinyin }}
  66. </div>
  67. <template v-if="items.hz_info.length > 0">
  68. <!-- @click="writeWord(conItem, items.pinyin)" -->
  69. <div
  70. class="strockplay-newWord"
  71. :style="{
  72. borderColor:
  73. data.unified_attrib && data.unified_attrib.topic_color
  74. ? data.unified_attrib.topic_color
  75. : '#346CDA',
  76. }"
  77. >
  78. <Strockplay
  79. class-name="adult-strockplay"
  80. :Book_text="items.hz_info[0].con"
  81. :play-storkes="true"
  82. :stroke-play-color="
  83. data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '#346CDA'
  84. "
  85. :stroke-color="'#000000'"
  86. :paly-width="'18px'"
  87. :BoxbgType="'0'"
  88. :cur-item="items.hz_info[0].hzDetail.hz_json"
  89. :target-div="'writeTops-item-' + '-' + items.hz_info[0].con + row"
  90. class="writeTop-item"
  91. :style="{
  92. borderColor:
  93. data.unified_attrib && data.unified_attrib.topic_color
  94. ? data.unified_attrib.topic_color
  95. : '#346CDA',
  96. }"
  97. />
  98. </div>
  99. </template>
  100. </div>
  101. <div class="image">
  102. <img src="@/assets/drag-arrows.png" alt="" />
  103. </div>
  104. <div class="answer">
  105. <!-- :disabled="TaskModel == 'ANSWER' ? true : items.is_example ? true : false" -->
  106. <draggable
  107. v-model="answer.answer_list[row].answer_list"
  108. animation="300"
  109. group="site"
  110. :disabled="items.is_example"
  111. class="content-box content-boxs"
  112. :move="onMove"
  113. >
  114. <transition-group>
  115. <div
  116. v-for="(answer, i) in answer.answer_list[row].answer_list"
  117. :key="'op' + i"
  118. class="option_one"
  119. :class="[items.is_example ? 'option_one_example' : classNameJudge(items, row)]"
  120. :index="'form' + i"
  121. :style="{
  122. borderColor:
  123. data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  124. }"
  125. >
  126. <img
  127. v-if="answer.img_url || answer.value"
  128. :src="
  129. answer.img_url
  130. ? answer.img_url
  131. : answer.type === 'local'
  132. ? require('@/assets/structure/' + answer.value)
  133. : answer.value
  134. "
  135. alt=""
  136. />
  137. </div>
  138. <div
  139. v-if="answer.answer_list[row].answer_list.length == 0"
  140. :key="row"
  141. class="option_one"
  142. :class="[isJudgingRightWrong && items.answer ? 'wrong' : '']"
  143. :style="{
  144. borderColor:
  145. data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  146. }"
  147. ></div>
  148. </transition-group>
  149. </draggable>
  150. </div>
  151. </div>
  152. </div>
  153. <PreviewOperation @showAnswerAnalysis="showAnswerAnalysis" @retry="retry" />
  154. <AnswerCorrect
  155. :answer-correct="data?.answer_correct"
  156. :visible.sync="visibleAnswerCorrect"
  157. @closeAnswerCorrect="closeAnswerCorrect"
  158. />
  159. <AnswerAnalysis
  160. :visible.sync="visibleAnswerAnalysis"
  161. :answer-list="data.answer_list"
  162. :analysis-list="data.analysis_list"
  163. @closeAnswerAnalysis="closeAnswerAnalysis"
  164. >
  165. <div slot="right-answer">
  166. <div class="one-box">
  167. <div
  168. v-for="(items, row) in data.option_list"
  169. :key="'row' + row"
  170. class="one"
  171. :class="[!items.pinyin ? 'one_nopy' : '']"
  172. :style="{ marginRight: (row + 1) % 3 == 0 ? '' : '16px' }"
  173. >
  174. <div
  175. class="number"
  176. :style="{
  177. background:
  178. data.unified_attrib && data.unified_attrib.topic_color
  179. ? data.unified_attrib.topic_color
  180. : '#346CDA',
  181. }"
  182. >
  183. {{ row + 1 }}
  184. </div>
  185. <div class="hzpinyin">
  186. <div v-if="isEnable(data.property.view_pinyin)" class="pinyin">
  187. {{ items.pinyin }}
  188. </div>
  189. <template v-if="items.hz_info.length > 0">
  190. <div
  191. class="strockplay-newWord"
  192. :style="{
  193. borderColor:
  194. data.unified_attrib && data.unified_attrib.topic_color
  195. ? data.unified_attrib.topic_color
  196. : '#346CDA',
  197. }"
  198. >
  199. <Strockplay
  200. class-name="adult-strockplay"
  201. :Book_text="items.hz_info[0].con"
  202. :play-storkes="true"
  203. :stroke-play-color="
  204. data.unified_attrib && data.unified_attrib.topic_color
  205. ? data.unified_attrib.topic_color
  206. : '#346CDA'
  207. "
  208. :stroke-color="'#000000'"
  209. :paly-width="'18px'"
  210. :BoxbgType="'0'"
  211. :cur-item="items.hz_info[0].hzDetail.hz_json"
  212. :target-div="'writeTops-item-right' + '-' + items.hz_info[0].con"
  213. class="writeTop-item"
  214. :style="{
  215. borderColor:
  216. data.unified_attrib && data.unified_attrib.topic_color
  217. ? data.unified_attrib.topic_color
  218. : '#346CDA',
  219. }"
  220. />
  221. </div>
  222. </template>
  223. </div>
  224. <div class="image">
  225. <img src="@/assets/drag-arrows.png" alt="" />
  226. </div>
  227. <div class="answer">
  228. <div
  229. class="option_one"
  230. :class="[items.is_example ? 'option_one_example' : '']"
  231. :style="{
  232. borderColor:
  233. data.unified_attrib && data.unified_attrib.topic_color
  234. ? data.unified_attrib.topic_color
  235. : '#346CDA',
  236. }"
  237. >
  238. <img
  239. v-if="items.answer"
  240. :src="
  241. items.answer.length > 3
  242. ? data.file_list.find((p) => p.file_id === items.answer).file_url
  243. : require('@/assets/structure/structure-' + items.answer + '.png')
  244. "
  245. alt=""
  246. />
  247. </div>
  248. </div>
  249. </div>
  250. </div>
  251. </div>
  252. </AnswerAnalysis>
  253. </div>
  254. </div>
  255. </template>
  256. <script>
  257. import { getCharacterStructureData } from '@/views/book/courseware/data/characterStructure';
  258. import PreviewMixin from '../common/PreviewMixin';
  259. import draggable from 'vuedraggable';
  260. import Strockplay from '../new_word/components/Strockplay.vue';
  261. export default {
  262. name: 'CharacterStructurePreview',
  263. components: { draggable, Strockplay },
  264. mixins: [PreviewMixin],
  265. data() {
  266. return {
  267. data: getCharacterStructureData(),
  268. dragData: [],
  269. SortArr: [],
  270. single: [],
  271. drag: false,
  272. currentId: null,
  273. isPraShow: false,
  274. curData: null,
  275. userErrorList: [],
  276. correctArr: [],
  277. };
  278. },
  279. // 计算属性 类似于data概念
  280. computed: {},
  281. watch: {
  282. 'data.option_list': {
  283. handler(val) {
  284. if (val) {
  285. this.handleData();
  286. }
  287. },
  288. deep: true,
  289. immediate: true,
  290. },
  291. },
  292. methods: {
  293. onMove(e) {
  294. return false;
  295. },
  296. choose(e) {
  297. let index = e.item.outerHTML.indexOf('id');
  298. let formIndex = e.item.outerHTML[index + 4];
  299. let formIndex2 = e.item.outerHTML[index + 5];
  300. if (!isNaN(Number(formIndex))) {
  301. this.currentId = Number(formIndex);
  302. }
  303. if (!isNaN(Number(formIndex2))) {
  304. this.currentId = (String(this.currentId) + formIndex2) * 1;
  305. }
  306. },
  307. // 开始拖拽事件
  308. onStart() {
  309. this.drag = true;
  310. this.dragData = JSON.parse(JSON.stringify(this.SortArr));
  311. },
  312. // 拖拽结束事件
  313. onEnd(e) {
  314. this.drag = false;
  315. let formIndex = Number(e.to.firstChild.attributes[1].value[4]);
  316. if (`${formIndex}` !== 'NaN') {
  317. if (this.answer.answer_list[formIndex].answer_list.length > 1) {
  318. let arr = [];
  319. this.data.option_list.forEach((item) => {
  320. if (item.id === this.currentId) {
  321. arr.push(item);
  322. }
  323. });
  324. this.answer.answer_list[formIndex].answer_list = JSON.parse(JSON.stringify(arr));
  325. }
  326. }
  327. this.SortArr = JSON.parse(JSON.stringify(this.dragData));
  328. },
  329. handleData() {
  330. this.single = [];
  331. this.data.structure_select_list.forEach((item) => {
  332. let items = this.data.file_list.find((p) => p.file_id === item.file_id);
  333. if (items) {
  334. item.value = items.file_url;
  335. }
  336. });
  337. this.data.option_list.forEach((items) => {
  338. if (items.is_example) {
  339. let obj = {
  340. id: items.answer,
  341. img_list: [],
  342. img_url:
  343. items.answer.length > 3
  344. ? this.data.structure_select_list.find((p) => p.file_id === items.answer)
  345. ? this.data.structure_select_list.find((p) => p.file_id === items.answer).value
  346. : ''
  347. : require(`@/assets/structure/structure-${items.answer}.png`),
  348. userAnswerJudge: 'example',
  349. };
  350. this.single.push({
  351. answer_list: [obj],
  352. });
  353. } else {
  354. this.single.push({
  355. answer_list: [],
  356. });
  357. }
  358. });
  359. this.data.structure_select_list.forEach((item, i) => {
  360. item.id = i;
  361. this.SortArr.push(item);
  362. });
  363. if (!this.isJudgingRightWrong) {
  364. this.$set(this.answer, 'answer_list', this.single);
  365. }
  366. },
  367. classNameJudge(item, index) {
  368. let classname = '';
  369. if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
  370. return '';
  371. }
  372. if (item.answer && this.isJudgingRightWrong) {
  373. if (item.answer === this.answer.answer_list[index].answer_list[0].file_id) {
  374. classname = 'right';
  375. } else {
  376. classname = 'wrong';
  377. }
  378. }
  379. return classname;
  380. },
  381. // 重做
  382. retry() {
  383. this.handleData([]);
  384. },
  385. },
  386. };
  387. </script>
  388. <style lang="scss" scoped>
  389. @use '@/styles/mixin.scss' as *;
  390. .structure-preview {
  391. .content-box {
  392. span {
  393. display: flex;
  394. flex-wrap: wrap;
  395. }
  396. }
  397. .content-boxs {
  398. height: 80px;
  399. overflow: hidden;
  400. }
  401. .option {
  402. display: flex;
  403. flex-wrap: wrap;
  404. padding: 10px 15px;
  405. background: #deebff;
  406. border-radius: 4px;
  407. .option_one {
  408. display: flex;
  409. align-items: center;
  410. justify-content: center;
  411. width: 72px;
  412. height: 72px;
  413. margin: 10px 15px;
  414. overflow: hidden;
  415. cursor: pointer;
  416. background: #9dcaff;
  417. border-radius: 4px;
  418. img {
  419. max-width: 100%;
  420. max-height: 100%;
  421. // position: relative;
  422. // top: 2px;
  423. opacity: 0.8;
  424. }
  425. }
  426. }
  427. .strockplay-newWord {
  428. position: relative;
  429. box-sizing: border-box;
  430. width: 80px;
  431. height: 80px;
  432. // padding: 5px;
  433. overflow: hidden;
  434. background: #fff;
  435. background-size: cover;
  436. border: 2px solid #346cda;
  437. border-radius: 4px;
  438. }
  439. .one {
  440. display: flex;
  441. align-items: center;
  442. margin: 35px 0 32px;
  443. &.one_nopy {
  444. margin: 16px 0;
  445. }
  446. .number {
  447. display: block;
  448. width: 24px;
  449. height: 24px;
  450. margin-right: 16px;
  451. font-family: 'arial';
  452. font-size: 14px;
  453. font-weight: bold;
  454. line-height: 24px;
  455. color: #fff;
  456. text-align: center;
  457. background: #346cda;
  458. border-radius: 100%;
  459. }
  460. .hzpinyin {
  461. position: relative;
  462. .pinyin {
  463. position: absolute;
  464. top: -28px;
  465. width: 100%;
  466. font-family: 'League';
  467. font-size: 16px;
  468. font-weight: 400;
  469. color: rgba($color: #000, $alpha: 50%);
  470. text-align: center;
  471. }
  472. }
  473. .image {
  474. img {
  475. width: 15px;
  476. margin: 0 9px;
  477. }
  478. }
  479. .answer {
  480. width: 80px;
  481. height: 80px;
  482. .option_one {
  483. display: flex;
  484. align-items: center;
  485. justify-content: center;
  486. width: 80px;
  487. height: 80px;
  488. overflow: hidden;
  489. border: 2px solid #346cda;
  490. border-radius: 4px;
  491. &.right {
  492. background: #e9f7f2 !important;
  493. border-color: $right-color !important;
  494. }
  495. &.wrong {
  496. border-color: $error-color !important;
  497. }
  498. img {
  499. max-width: 100%;
  500. max-height: 100%;
  501. // position: relative;
  502. // left: -2px;
  503. opacity: 0.8;
  504. }
  505. }
  506. }
  507. .answer:hover {
  508. // @include background_color("theme_color");
  509. }
  510. }
  511. .one-box {
  512. display: flex;
  513. flex-flow: wrap;
  514. column-gap: 16px;
  515. padding: 20px 0;
  516. }
  517. }
  518. </style>