NotesPreview.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="notes-preview" :style="getAreaStyle()">
  4. <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
  5. <div class="main">
  6. <div class="NPC-zhedie">
  7. <div class="topTitle">
  8. <div class="NPC-top-left">
  9. <span class="NPC-topTitle-text" v-html="data.title_con"></span>
  10. <span class="NPC-topTitle-text" v-if="showLang">
  11. {{ titleTrans[getLang()] }}
  12. </span>
  13. </div>
  14. <div class="NPC-top-right" @click="handleChangeTab">
  15. <span class="NPC-top-right-text">{{ wordShow ? '收起' : '展开' }}</span>
  16. <img v-if="wordShow" src="@/assets/down.png" alt="" />
  17. <img v-else class="rotate" src="@/assets/down.png" alt="" />
  18. </div>
  19. </div>
  20. <el-collapse-transition>
  21. <div v-show="wordShow" class="NPC-notes-list">
  22. <div v-for="(item, index) in data.option" :key="'NPC-notes' + index" class="NPC-notes">
  23. <div class="NPC-notes-con">
  24. <span class="NPC-notes-con-number" v-html="item.number"></span>
  25. <span class="NPC-notes-con-text" v-html="item.con"></span>
  26. <span class="multilingual" v-if="showLang">
  27. {{
  28. multilingualTextList[getLang()] &&
  29. multilingualTextList[getLang()][index] &&
  30. multilingualTextList[getLang()][index][0]
  31. ? multilingualTextList[getLang()][index][0]
  32. : ''
  33. }}
  34. </span>
  35. </div>
  36. <div class="NPC-notes-trans" v-html="item.interpret"></div>
  37. <div v-if="item.note" class="NPC-notes-note" v-html="item.note"></div>
  38. <div v-if="item.file_list[0]" class="NPC-notes-note-img">
  39. <el-image :src="item.pic_url" :preview-src-list="[item.pic_url]" fit="contain" />
  40. </div>
  41. <div class="NPC-notes-note" v-if="showLang">
  42. {{
  43. multilingualTextList[getLang()] &&
  44. multilingualTextList[getLang()][index] &&
  45. multilingualTextList[getLang()][index][1]
  46. ? multilingualTextList[getLang()][index][1]
  47. : ''
  48. }}
  49. </div>
  50. </div>
  51. </div>
  52. </el-collapse-transition>
  53. </div>
  54. </div>
  55. </div>
  56. </template>
  57. <script>
  58. import { getNotesData, isEnable } from '@/views/book/courseware/data/notes';
  59. import PreviewMixin from '../common/PreviewMixin';
  60. import { GetFileURLMap } from '@/api/app';
  61. export default {
  62. name: 'NotesPreview',
  63. components: {},
  64. props: ['notesData'],
  65. mixins: [PreviewMixin],
  66. data() {
  67. return {
  68. data: this.notesData ? this.notesData : getNotesData(),
  69. wordShow: true,
  70. multilingualTextList: {}, // 多语言对应的切割后的翻译
  71. titleTrans: {},
  72. };
  73. },
  74. computed: {},
  75. watch: {
  76. 'data.option.length': {
  77. handler(val) {
  78. if (val) {
  79. // this.wordShow = isEnable(this.data.property.is_word_show);
  80. this.handleData();
  81. }
  82. },
  83. deep: true,
  84. immediate: true,
  85. },
  86. },
  87. created() {},
  88. methods: {
  89. handleChangeTab() {
  90. this.wordShow = !this.wordShow;
  91. },
  92. handleData() {
  93. if (this.showLang) {
  94. this.data.multilingual.forEach((item) => {
  95. let trans_arr = item.translation.split('\n');
  96. this.$set(this.titleTrans, item.type, trans_arr[0] ? trans_arr[0] : '');
  97. let chunkSize = 2;
  98. let chunkedArr = trans_arr.splice(1).reduce((acc, curr, index) => {
  99. // 当索引是chunkSize的倍数时,开始一个新的子数组
  100. if (index % chunkSize === 0) {
  101. acc.push([curr]); // 开始新的子数组并添加当前元素
  102. } else {
  103. acc[acc.length - 1].push(curr); // 将当前元素添加到最后一个子数组中
  104. }
  105. return acc;
  106. }, []);
  107. this.$set(this.multilingualTextList, item.type, chunkedArr);
  108. });
  109. }
  110. this.data.option.forEach((item) => {
  111. if (item.file_list && item.file_list[0]) {
  112. GetFileURLMap({ file_id_list: item.file_list }).then(({ url_map }) => {
  113. this.$set(item, 'pic_url', url_map[item.file_list[0]]);
  114. });
  115. }
  116. });
  117. },
  118. },
  119. };
  120. </script>
  121. <style lang="scss" scoped>
  122. @use '@/styles/mixin.scss' as *;
  123. .notes-preview {
  124. @include preview-base;
  125. .NPC-zhedie {
  126. // margin-bottom: 24px;
  127. .topTitle {
  128. display: flex;
  129. justify-content: space-between;
  130. width: 100%;
  131. height: 48px;
  132. padding-right: 16px;
  133. padding-left: 24px;
  134. overflow: hidden;
  135. background: #e35454;
  136. border: 1px solid rgba(0, 0, 0, 10%);
  137. border-radius: 8px 8px 0 0;
  138. :deep p {
  139. margin: 0;
  140. }
  141. .NPC-top-left {
  142. display: flex;
  143. align-items: center;
  144. justify-content: flex-start;
  145. .NPC-topTitle-text {
  146. margin: 0 8px 0 0;
  147. font-family: 'sourceR';
  148. font-size: 16px;
  149. font-weight: bold;
  150. color: #fff;
  151. }
  152. }
  153. .NPC-top-right {
  154. display: flex;
  155. align-items: center;
  156. justify-content: flex-start;
  157. cursor: pointer;
  158. &-text {
  159. font-size: 14px;
  160. font-weight: normal;
  161. line-height: 16px;
  162. color: #fff;
  163. }
  164. img {
  165. width: 16px;
  166. height: 16px;
  167. margin-left: 4px;
  168. }
  169. }
  170. .rotate {
  171. animation-name: firstrotate;
  172. animation-timing-function: linear;
  173. animation-direction: 2s;
  174. animation-fill-mode: both;
  175. }
  176. }
  177. .NPC-notes-list {
  178. padding: 24px 24px 5px;
  179. border: 1px solid rgba(0, 0, 0, 10%);
  180. border-top: none;
  181. border-radius: 0 0 8px 8px;
  182. .NPC-notes {
  183. width: 100%;
  184. margin-bottom: 24px;
  185. :deep p {
  186. margin: 0;
  187. }
  188. .NPC-notes-con {
  189. display: flex;
  190. align-items: center;
  191. justify-content: flex-start;
  192. margin-bottom: 12px;
  193. > span {
  194. font-size: 14px;
  195. font-style: normal;
  196. font-weight: normal;
  197. line-height: 150%;
  198. color: #e35454;
  199. &.NPC-notes-con-number {
  200. font-family: 'robot';
  201. }
  202. &.NPC-notes-con-text {
  203. // flex: 1;
  204. margin: 0 5px;
  205. }
  206. }
  207. }
  208. .NPC-notes-trans {
  209. padding-left: 27px;
  210. margin-bottom: 12px;
  211. font-size: 14px;
  212. font-style: normal;
  213. font-weight: bold;
  214. line-height: 150%;
  215. color: #000;
  216. }
  217. .NPC-notes-note {
  218. font-size: 14px;
  219. font-style: normal;
  220. font-weight: normal;
  221. line-height: 150%;
  222. color: #000;
  223. text-indent: 27px;
  224. word-break: break-word;
  225. }
  226. }
  227. }
  228. .NPC-notes-note-img {
  229. width: 100%;
  230. > div {
  231. max-width: 100%;
  232. > img {
  233. max-width: 100%;
  234. }
  235. }
  236. }
  237. }
  238. @keyframes firstrotate {
  239. 0% {
  240. transform: rotateZ(0deg);
  241. }
  242. 100% {
  243. transform: rotateZ(180deg);
  244. }
  245. }
  246. @keyframes huifuRotate {
  247. 0% {
  248. transform: rotateZ(180deg);
  249. }
  250. 100% {
  251. transform: rotateZ(0deg);
  252. }
  253. }
  254. }
  255. </style>