Notes.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <template>
  2. <div>
  3. <label>标题:</label>
  4. <RichText
  5. v-if="property.isGetContent"
  6. ref="richText"
  7. v-model="data.title_con"
  8. :inline="true"
  9. :placeholder="'输入标题'"
  10. toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright"
  11. class="title-box"
  12. :font-size="unifiedAttrib?.font_size"
  13. :font-family="unifiedAttrib?.font"
  14. :font-color="unifiedAttrib?.text_color"
  15. />
  16. <el-table :data="data.option" border style="width: 100%">
  17. <!-- <el-table-column fixed prop="number" label="序号" width="70">
  18. <template slot-scope="scope">
  19. <el-input v-model="scope.row.number" />
  20. </template>
  21. </el-table-column> -->
  22. <el-table-column fixed prop="matchNotes" label="课文内容" width="120px"> </el-table-column>
  23. <el-table-column fixed prop="con" label="气泡">
  24. <template slot-scope="scope">
  25. <RichText
  26. v-if="property.isGetContent"
  27. ref="richText"
  28. v-model="scope.row.con"
  29. :inline="true"
  30. :item-index="scope.$index"
  31. :font-size="unifiedAttrib?.font_size"
  32. :font-family="unifiedAttrib?.font"
  33. :font-color="unifiedAttrib?.text_color"
  34. toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright image media link"
  35. @handleRichTextBlur="handleBlurCon"
  36. />
  37. </template>
  38. </el-table-column>
  39. <!-- <el-table-column v-if="isEnable(data.property.view_pinyin)" prop="con" label="拼音" width="150">
  40. <template slot-scope="scope">
  41. <RichText
  42. v-if="property.isGetContent"
  43. ref="richText"
  44. v-model="scope.row.pinyin"
  45. :inline="true"
  46. :font-size="unifiedAttrib?.pinyin_size"
  47. :font-color="unifiedAttrib?.text_color"
  48. :font-family="'League'"
  49. toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright image media link"
  50. />
  51. </template>
  52. </el-table-column>
  53. <el-table-column prop="interpret" label="翻译" width="200">
  54. <template slot-scope="scope">
  55. <RichText
  56. v-if="property.isGetContent"
  57. ref="richText"
  58. v-model="scope.row.interpret"
  59. :inline="true"
  60. toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright image media link"
  61. :font-size="unifiedAttrib?.font_size"
  62. :font-family="unifiedAttrib?.font"
  63. :font-color="unifiedAttrib?.text_color"
  64. />
  65. </template>
  66. </el-table-column>
  67. <el-table-column prop="note" label="注释" width="200">
  68. <template slot-scope="scope">
  69. <RichText
  70. v-if="property.isGetContent"
  71. ref="richText"
  72. v-model="scope.row.note"
  73. :inline="true"
  74. toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright image media link"
  75. :font-size="unifiedAttrib?.font_size"
  76. :font-family="unifiedAttrib?.font"
  77. :font-color="unifiedAttrib?.text_color"
  78. />
  79. </template>
  80. </el-table-column> -->
  81. <!-- <el-table-column prop="img_list" label="图片" width="300">
  82. <template slot-scope="scope">
  83. <UploadPicture
  84. :file-info="scope.row.file_list[0]"
  85. :item-index="scope.$index"
  86. :show-upload="!scope.row.file_list[0]"
  87. @upload="uploadPic"
  88. @deleteFile="deletePic"
  89. />
  90. </template>
  91. </el-table-column> -->
  92. <el-table-column prop="notesColor" label="在课文中的颜色" width="130">
  93. <template slot-scope="scope">
  94. <el-color-picker v-model="scope.row.notesColor" @change="handleChangeColor(scope.$index)"></el-color-picker>
  95. </template>
  96. </el-table-column>
  97. <el-table-column label="操作" width="150">
  98. <template slot-scope="scope">
  99. <el-button size="mini" type="text" @click="handleDelete(scope.$index)">删除</el-button>
  100. <el-button size="mini" type="text" @click="moveElement(scope.row, scope.$index, 'up')">上移</el-button>
  101. <el-button size="mini" type="text" @click="moveElement(scope.row, scope.$index, 'down')">下移</el-button>
  102. </template>
  103. </el-table-column>
  104. </el-table>
  105. <!-- <el-button icon="el-icon-plus" style="margin: 24px 0" @click="addElement">增加一个</el-button> -->
  106. <el-form :model="data.property" label-width="72px" label-position="left" style="margin: 24px 0">
  107. <!-- <el-form-item label="拼音">
  108. <el-switch v-model="data.property.view_pinyin" active-value="true" inactive-value="false" />
  109. </el-form-item>
  110. <el-form-item label="拼音位置">
  111. <el-radio
  112. v-for="{ value, label } in pinyinPositionLists"
  113. :key="value"
  114. v-model="data.property.pinyin_position"
  115. :label="value"
  116. :disabled="!isEnable(data.property.view_pinyin)"
  117. >
  118. {{ label }}
  119. </el-radio>
  120. </el-form-item>
  121. <el-form-item label="">
  122. <el-checkbox
  123. v-model="data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case"
  124. :disabled="!isEnable(data.property.view_pinyin)"
  125. true-label="true"
  126. false-label="false"
  127. >句首大写</el-checkbox
  128. >
  129. </el-form-item> -->
  130. <el-form-item label="预览展示">
  131. <el-switch v-model="data.property.is_show" active-value="true" inactive-value="false" />
  132. </el-form-item>
  133. </el-form>
  134. </div>
  135. </template>
  136. <script>
  137. import ModuleMixin from '../../common/ModuleMixin';
  138. import RichText from '@/components/RichText.vue';
  139. import UploadPicture from '../new_word/components/UploadPicture.vue';
  140. import { pinyinPositionLists } from '@/views/book/courseware/data/notes';
  141. import { isEnable } from '@/views/book/courseware/data/common';
  142. import { PinyinBuild_OldFormat } from '@/api/book';
  143. export default {
  144. name: 'NotesPage',
  145. components: {
  146. RichText,
  147. UploadPicture,
  148. },
  149. props: ['dataNotes', 'unifiedAttrib'],
  150. mixins: [ModuleMixin],
  151. data() {
  152. return {
  153. data: this.dataNotes,
  154. pinyinPositionLists,
  155. isEnable,
  156. };
  157. },
  158. watch: {
  159. 'data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case': {
  160. handler(val, oldVal) {
  161. if (val === oldVal) return;
  162. if (isEnable(this.data.property.view_pinyin)) {
  163. this.handlePinyin();
  164. }
  165. },
  166. deep: true,
  167. },
  168. },
  169. methods: {
  170. // 删除行
  171. handleDelete(index) {
  172. this.$confirm('确定要删除此条气泡吗?', '提示', {
  173. confirmButtonText: '确定',
  174. cancelButtonText: '取消',
  175. type: 'warning',
  176. })
  177. .then(() => {
  178. this.$emit('handleSyncCon', this.data.option[index], 'delete');
  179. this.data.option.splice(index, 1);
  180. })
  181. .catch(() => {});
  182. },
  183. // 上移下移
  184. moveElement(dItem, index, type) {
  185. let obj = JSON.parse(JSON.stringify(dItem));
  186. if (type == 'up' && index > 0) {
  187. this.data.option.splice(index - 1, 0, obj);
  188. this.data.option.splice(index + 1, 1);
  189. }
  190. if (type == 'down' && index < this.data.option.length - 1) {
  191. this.data.option[index] = this.data.option.splice(index + 1, 1, this.data.option[index])[0];
  192. }
  193. },
  194. // 增加
  195. addElement() {
  196. this.data.option.push(this.getOption());
  197. },
  198. getOption() {
  199. return {
  200. number: '',
  201. con: '',
  202. pinyin: '',
  203. interpret: '', // 翻译
  204. note: '', // 注释
  205. img_list: [],
  206. file_list: [''], // 图片
  207. notesColor: '#8206BF', // 在课文中预览的注释颜色
  208. };
  209. },
  210. uploadPic(file_id, index) {
  211. this.data.option[index].file_list[0] = file_id;
  212. this.data.file_id_list.push(file_id);
  213. this.refreshKey = Math.random();
  214. },
  215. deletePic(file_id, index) {
  216. this.data.option[index].file_list[0] = '';
  217. this.data.file_id_list = this.data.file_id_list.filter((item) => item !== file_id);
  218. },
  219. async handleBlurCon(i) {
  220. let text = this.data.option[i].con.replace(/<[^>]+>/g, '');
  221. if (text) {
  222. this.data.option[i].pinyin = await this.handlePinyins(
  223. text,
  224. this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
  225. );
  226. }
  227. this.$emit('handleSyncCon', this.data.option[i]);
  228. // this.data.option[i].pinyin = cnchar
  229. // .spell(
  230. // text,
  231. // 'array',
  232. // this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' ? 'high' : 'low',
  233. // 'tone',
  234. // )
  235. // .join(' ');
  236. },
  237. handleChangeColor(i) {
  238. this.$emit('handleSyncCon', this.data.option[i]);
  239. },
  240. async handlePinyin() {
  241. for (const item of this.data.option) {
  242. let text = item.con.replace(/<[^>]+>/g, '');
  243. if (text) {
  244. item.pinyin = await this.handlePinyins(
  245. text,
  246. this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
  247. );
  248. }
  249. }
  250. // this.data.option.forEach((item) => {
  251. // let text = item.con.replace(/<[^>]+>/g, '');
  252. // item.pinyin = cnchar
  253. // .spell(
  254. // text,
  255. // 'array',
  256. // this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' ? 'high' : 'low',
  257. // 'tone',
  258. // )
  259. // .join(' ');
  260. // });
  261. },
  262. // 自动生成拼音
  263. handlePinyins(text, flag) {
  264. let data = {
  265. text: text,
  266. is_rich_text: 'false',
  267. is_first_sentence_first_hz_pinyin_first_char_upper_case: flag ? flag : 'false',
  268. is_fill_space: 'false',
  269. is_custom_fc: 'false',
  270. };
  271. return new Promise((resolve, reject) => {
  272. PinyinBuild_OldFormat(data).then((res) => {
  273. if (res.parsed_text) {
  274. let mergedData = '';
  275. res.parsed_text.paragraph_list.map((outerArr, i) =>
  276. outerArr.map((innerArr, j) =>
  277. innerArr.map((newItem, k) => {
  278. mergedData += newItem.pinyin + ' ';
  279. }),
  280. ),
  281. );
  282. resolve(mergedData);
  283. }
  284. });
  285. });
  286. },
  287. },
  288. };
  289. </script>
  290. <style lang="scss" scoped>
  291. .upload-file {
  292. display: flex;
  293. column-gap: 12px;
  294. align-items: center;
  295. margin: 8px 0;
  296. .file-name {
  297. display: flex;
  298. column-gap: 14px;
  299. align-items: center;
  300. justify-content: space-between;
  301. max-width: 360px;
  302. padding: 8px 12px;
  303. font-size: 14px;
  304. color: #1d2129;
  305. background-color: #f7f8fa;
  306. span {
  307. display: flex;
  308. column-gap: 14px;
  309. align-items: center;
  310. }
  311. }
  312. .svg-icon {
  313. cursor: pointer;
  314. }
  315. }
  316. .title-box {
  317. padding: 5px;
  318. margin: 5px 0;
  319. background-color: #f2f3f5;
  320. border: 1px solid #f2f3f5;
  321. border-radius: 4px;
  322. :deep p {
  323. margin: 0;
  324. }
  325. }
  326. </style>
  327. <style lang="scss">
  328. .tox .tox-editor-header {
  329. z-index: 3 !important;
  330. }
  331. </style>