PreviewMixin.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import SerialNumberPosition from './SerialNumberPosition.vue';
  2. import PinyinText from '@/components/PinyinText.vue';
  3. import { isEnable } from '@/views/book/courseware/data/common';
  4. import { ContentGetCoursewareComponentContent } from '@/api/book';
  5. import { sanitizeHTML } from '@/utils/common';
  6. const mixin = {
  7. data() {
  8. return {
  9. sanitizeHTML,
  10. typeList: ['interaction'],
  11. answer: { answer_list: [], is_right: false }, // 用户答案
  12. isJudgingRightWrong: false, // 是否判断对错
  13. isShowRightAnswer: false, // 是否显示正确答案
  14. disabled: false, // 是否禁用
  15. isShowParse: false, // 是否显示解析
  16. isEnable,
  17. loader: false,
  18. };
  19. },
  20. inject: ['getLang', 'getChinese', 'convertText', 'getTitleList'],
  21. props: {
  22. id: {
  23. type: String,
  24. default: '',
  25. },
  26. content: {
  27. type: String,
  28. default: '',
  29. },
  30. coursewareId: {
  31. type: String,
  32. default: '',
  33. },
  34. type: {
  35. type: String,
  36. default: '',
  37. },
  38. isMobile: {
  39. type: Boolean,
  40. default: false,
  41. },
  42. },
  43. computed: {
  44. showLang() {
  45. return this.getLang() !== 'ZH';
  46. },
  47. },
  48. watch: {
  49. content: {
  50. handler(newVal) {
  51. if (this.type === 'edit') return;
  52. if (!newVal) return;
  53. this.data = JSON.parse(newVal);
  54. },
  55. immediate: true,
  56. },
  57. },
  58. components: {
  59. SerialNumberPosition,
  60. PinyinText,
  61. },
  62. created() {
  63. // 这里分为 预览 和 编辑调整位置、视频互动组件 三种情况
  64. // 预览时,content 直接传入
  65. // 编辑调整位置时,content 需要通过接口获取
  66. if (this.type === 'edit') {
  67. this.getCoursewareComponentContent();
  68. }
  69. },
  70. methods: {
  71. getCoursewareComponentContent() {
  72. ContentGetCoursewareComponentContent({ courseware_id: this.coursewareId, component_id: this.id }).then(
  73. ({ content }) => {
  74. if (content) {
  75. let oldData = JSON.parse(content);
  76. if (oldData.type === 'audio') {
  77. let p = oldData.property || {};
  78. if (!p.file_name_display_mode) p.file_name_display_mode = 'true';
  79. if (p.view_method === 'independent' && !p.style_mode) {
  80. p.style_mode = 'middle';
  81. }
  82. if (!p.style_mode) p.style_mode = 'big';
  83. if (p.view_method === 'icon') {
  84. p.file_name_display_mode = 'false';
  85. p.view_method = 'independent';
  86. p.style_mode = 'small';
  87. }
  88. }
  89. this.data = oldData;
  90. }
  91. this.loader = true;
  92. },
  93. );
  94. },
  95. /**
  96. * 获取用户答案
  97. * @returns {array} 用户答案
  98. */
  99. getAnswer() {
  100. return this.answer;
  101. },
  102. /**
  103. * 显示答案
  104. * @param {boolean} isJudgingRightWrong 是否判断对错
  105. * @param {boolean} isShowRightAnswer 是否显示正确答案
  106. * @param {object} userAnswer 用户答案
  107. * @param {boolean} disabled 是否禁用
  108. */
  109. showAnswer(isJudgingRightWrong, isShowRightAnswer, userAnswer, disabled) {
  110. // if (this.loader === false) {
  111. // return setTimeout(() => this.showAnswer(isJudgingRightWrong, isShowRightAnswer, userAnswer, disabled), 100);
  112. // }
  113. this.isJudgingRightWrong = isJudgingRightWrong;
  114. this.isShowRightAnswer = isShowRightAnswer;
  115. this.disabled = disabled;
  116. if (userAnswer) this.answer = userAnswer;
  117. },
  118. /**
  119. * 得到序号外部样式
  120. */
  121. getAreaStyle() {
  122. if (!isEnable(this.data.property.sn_display_mode)) {
  123. return {
  124. grid: `"main" / 1fr`,
  125. };
  126. }
  127. const position = this.data.property.sn_position;
  128. let grid = '';
  129. if (position.includes('right')) {
  130. grid = `"main position" / 1fr auto`;
  131. } else if (position.includes('left')) {
  132. grid = `"position main" / auto 1fr`;
  133. } else if (position.includes('top')) {
  134. grid = `"position" auto "main" 1fr`;
  135. } else if (position.includes('bottom')) {
  136. grid = `"main" 1fr "position" auto`;
  137. }
  138. return {
  139. grid,
  140. };
  141. },
  142. /**
  143. * 得到背景图、背景色及边框样式
  144. */
  145. getComponentStyle() {
  146. let backgroundData = {};
  147. if (Object.hasOwn(this.data.property, 'background_image_url')) {
  148. // 保护性读取位置/大小值,避免 undefined 导致字符串 "undefined%"
  149. const { background_position: pos } = this.data.property;
  150. const widthPct = typeof pos.width === 'undefined' ? '' : pos.width;
  151. const heightPct = typeof pos.height === 'undefined' ? '' : pos.height;
  152. const leftPct = typeof pos.left === 'undefined' ? '' : pos.left;
  153. const topPct = typeof pos.top === 'undefined' ? '' : pos.top;
  154. backgroundData.backgroundImage = `url(${this.data.property.background_image_url})`;
  155. let bcSize = '';
  156. if (pos.image_mode === 'fill') {
  157. bcSize = '100% 100%';
  158. } else if (pos.image_mode === 'repeat') {
  159. bcSize = 'auto';
  160. } else {
  161. bcSize = `${widthPct}% ${heightPct}%`;
  162. }
  163. backgroundData.backgroundSize = bcSize;
  164. backgroundData.backgroundPosition = pos.image_mode === 'fill' ? '0% 0%' : `${leftPct}% ${topPct}%`;
  165. backgroundData.backgroundRepeat = pos.image_mode === 'repeat' ? 'repeat' : 'no-repeat';
  166. }
  167. let borderData = {};
  168. if (Object.hasOwn(this.data.property, 'is_border')) {
  169. const isBorder = isEnable(this.data.property.is_border);
  170. borderData.borderWidth = isBorder ? (this.data.property.border_style === 'double' ? '3px' : '1px') : '0px';
  171. borderData.borderStyle = isBorder ? this.data.property.border_style : 'none';
  172. borderData.borderColor = isBorder ? this.data.property.border_color : 'transparent';
  173. }
  174. return {
  175. backgroundColor: this.data.property?.background_color,
  176. ...backgroundData,
  177. ...borderData,
  178. };
  179. },
  180. },
  181. };
  182. export default mixin;