WriteBasePreview.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="write-base-preview" :style="getAreaStyle()">
  4. <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
  5. <div v-if="width" class="main">
  6. <h2>{{ convertText('书写区') }}</h2>
  7. <template v-if="isJudgingRightWrong">
  8. <img
  9. v-if="data.write_base64[0]"
  10. style="background-color: #f7f8fa"
  11. :src="data.write_base64[0]"
  12. alt="write-show"
  13. />
  14. <div class="esign-box" v-else :style="{ width: width + 'px', height: '150px' }"></div>
  15. </template>
  16. <div class="esign-box" v-else>
  17. <vue-esign
  18. ref="esign"
  19. class="esign-canvas"
  20. :width="width"
  21. :height="150"
  22. :is-crop="isCrop"
  23. :line-width="lineWidth"
  24. :line-color="lineColor"
  25. :bg-color.sync="bgColor"
  26. />
  27. <div class="btn-box">
  28. <SvgIcon icon-class="clear" size="24" title="清除" @click="handleReset" />
  29. <SvgIcon icon-class="camera" size="24" title="保存" @click="handleGenerate" />
  30. </div>
  31. </div>
  32. <!-- <template v-if="data.write_base64[0]">
  33. <h2>{{ convertText('展示区') }}</h2>
  34. <img style="background-color: #f7f8fa" :src="data.write_base64[0]" alt="write-show" />
  35. </template> -->
  36. </div>
  37. </div>
  38. </template>
  39. <script>
  40. import { getWriteBaseData } from '@/views/book/courseware/data/writeBase';
  41. import PreviewMixin from '../common/PreviewMixin';
  42. import vueEsign from 'vue-esign';
  43. export default {
  44. name: 'WriteBasePreview',
  45. components: { vueEsign },
  46. mixins: [PreviewMixin],
  47. data() {
  48. return {
  49. data: getWriteBaseData(),
  50. lineWidth: 2,
  51. lineColor: '#000000',
  52. bgColor: '#f7f8fa',
  53. isCrop: false,
  54. width: 0,
  55. };
  56. },
  57. computed: {},
  58. watch: {
  59. isJudgingRightWrong(val) {
  60. if (!val) return;
  61. this.data.write_base64 = this.answer.answer_list;
  62. },
  63. },
  64. mounted() {
  65. this.width = document.getElementsByClassName('write-base-preview')[0].clientWidth;
  66. if (!this.isJudgingRightWrong) {
  67. this.answer.answer_list = this.data.write_base64;
  68. }
  69. },
  70. methods: {
  71. handleReset() {
  72. this.$refs.esign.reset();
  73. this.$nextTick(() => {
  74. this.bgColor = '#f7f8fa';
  75. });
  76. },
  77. handleGenerate() {
  78. this.$refs.esign
  79. .generate({ format: 'png', quality: 0.8 })
  80. .then((res) => {
  81. this.data.write_base64[0] = res;
  82. this.$forceUpdate();
  83. this.$message.success('保存成功');
  84. })
  85. .catch((err) => {
  86. console.error(err);
  87. // alert('生成图片失败:' + err.message);
  88. });
  89. },
  90. /**
  91. * 获取无文本内容的数据结构,用于保存为个人模板时的样式模板
  92. */
  93. getNoTextContentData() {
  94. let noTextContentData = JSON.parse(JSON.stringify(this.data));
  95. const resetFieldMap = {
  96. write_base64: [''],
  97. answer_list: [], // 答案列表
  98. analysis_list: [], // 解析列表
  99. };
  100. Object.assign(noTextContentData, resetFieldMap);
  101. if (noTextContentData.answer) {
  102. noTextContentData.answer.answer_list = [];
  103. noTextContentData.answer.reference_answer = '';
  104. }
  105. return noTextContentData;
  106. },
  107. },
  108. };
  109. </script>
  110. <style lang="scss" scoped>
  111. @use '@/styles/mixin.scss' as *;
  112. .write-base-preview {
  113. @include preview-base;
  114. display: block;
  115. .main {
  116. h2 {
  117. margin: 5px 0;
  118. font-size: 14px;
  119. }
  120. .esign-box {
  121. position: relative;
  122. background-color: #f7f8fa;
  123. border-radius: 4px;
  124. .btn-box {
  125. position: absolute;
  126. right: 10px;
  127. bottom: 10px;
  128. display: flex;
  129. gap: 5px;
  130. cursor: pointer;
  131. }
  132. }
  133. }
  134. }
  135. </style>