CharacterStructurePreview.vue 15 KB

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