index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <!-- -->
  2. <template>
  3. <div
  4. class="NNPE-Book-Article Big-Book-Maxwidth"
  5. v-if="curQue"
  6. v-loading="loading"
  7. >
  8. <div class="Big-Book-img">
  9. <UploadArt
  10. :change-fill-id="changeImage"
  11. :datafile-list="fileCon.img_list"
  12. upload-type="image"
  13. class="article_pdf"
  14. :filleNumber="imageNumber"
  15. />
  16. <ul
  17. class="uploadArt_list"
  18. v-if="curQue.img_list && curQue.img_list.length > 0"
  19. >
  20. <li
  21. v-for="(artItem, artIndex) in curQue.img_list"
  22. :key="'articleImgList' + artIndex"
  23. >
  24. <img :src="artItem.url" style="width: 26px" />
  25. <span class="art_name">{{ artItem.name }}</span>
  26. <p>
  27. 图片放到第<el-input
  28. class="imgNumber"
  29. type="number"
  30. v-model="artItem.imgNumber"
  31. size="mini"
  32. @input="forceUpdate"
  33. ></el-input
  34. >段落的后面
  35. </p>
  36. <img
  37. src="@/assets/adult/del-close.png"
  38. class="del-close"
  39. @click="delImage(artIndex)"
  40. />
  41. </li>
  42. </ul>
  43. </div>
  44. <div class="Big-Book-mp3">
  45. <Upload
  46. type="mp3"
  47. :changeFillId="changeMp3"
  48. :datafileList="fileCon.mp3_list"
  49. :filleNumber="mp3Number"
  50. :uploadType="'mp3'"
  51. />
  52. </div>
  53. <div
  54. class="NPC-dia-art-option"
  55. v-for="(item, index) in curQue.option"
  56. :key="'daChs' + index"
  57. >
  58. <!--对话角色-->
  59. <div class="NPC-da-role">
  60. <!-- <RoleChs :roleCon="item.role" /> -->
  61. <el-button type="primary" @click="editRole(item, index)"
  62. >编辑角色</el-button
  63. >
  64. </div>
  65. <!--对话内容-->
  66. <div class="NPC-da-article">
  67. <el-button type="primary" @click="editDialogue(item, index)"
  68. >编辑对话内容</el-button
  69. >
  70. </div>
  71. <!--标注信息-->
  72. <div class="NPC-da-tag">
  73. <el-button type="primary">编辑标注</el-button>
  74. </div>
  75. </div>
  76. <el-dialog title="段落分句字幕打点" :visible.sync="cTVisible" width="30%">
  77. <Createtimelist ref="createtimelist" :curQue="curQue" />
  78. <span slot="footer" class="dialog-footer">
  79. <el-button @click="cTVisible = false">取 消</el-button>
  80. <el-button type="primary" @click="saveTimeList">保 存</el-button>
  81. </span>
  82. </el-dialog>
  83. <el-dialog title="编辑角色" :visible.sync="isEditRole" width="60%">
  84. <template v-if="curOption">
  85. <RoleChs ref="roleChs" :curRole="curOption.role" />
  86. </template>
  87. <span slot="footer" class="dialog-footer">
  88. <el-button @click="isEditRole = false">取 消</el-button>
  89. <el-button type="primary" @click="saveRole">保 存</el-button>
  90. </span>
  91. </el-dialog>
  92. <el-dialog
  93. title="编辑对话内容"
  94. top="30px"
  95. :visible.sync="isEditDia"
  96. width="60%"
  97. >
  98. <template v-if="curOption">
  99. <el-steps
  100. :active="active"
  101. finish-status="success"
  102. simple
  103. style="margin-top: 20px"
  104. >
  105. <el-step title="对话内容"></el-step>
  106. <el-step title="分段结果"></el-step>
  107. <el-step title="分句结果"></el-step>
  108. <el-step title="分词结果"></el-step>
  109. </el-steps>
  110. <template v-if="active == 1">
  111. <ArticleChs
  112. ref="articleChs"
  113. :curOption="curOption"
  114. :changeActive="changeActive"
  115. />
  116. </template>
  117. <template v-if="active == 2">
  118. <ParagraphChs
  119. ref="articleChs"
  120. :curOption="curOption"
  121. :changeActive="changeActive"
  122. />
  123. </template>
  124. </template>
  125. <span slot="footer" class="dialog-footer">
  126. <el-button @click="isEditDia = false">取 消</el-button>
  127. <el-button type="primary" @click="saveDialogue">保 存</el-button>
  128. </span>
  129. </el-dialog>
  130. </div>
  131. </template>
  132. <script>
  133. import { segSentences, BatchSegContent, createPinyin } from "@/api/ajax";
  134. const Base64 = require("js-base64").Base64;
  135. import Upload from "../../common/Upload.vue";
  136. import UploadArt from "../../common/UploadArt.vue";
  137. import ParagraphChs from "./components/ParagraphChs.vue";
  138. import Clauseresult from "./components/ClauseresultChs.vue";
  139. import Segbyword from "./components/SegbywordChs.vue";
  140. import Createtimelist from "./components/CreatetimelistChs.vue";
  141. import RoleChs from "./components/RoleChs.vue";
  142. import ArticleChs from "./components/ArticleChs.vue";
  143. export default {
  144. name: "DialogueArticleChs",
  145. components: {
  146. Upload,
  147. UploadArt,
  148. ParagraphChs,
  149. Clauseresult,
  150. Segbyword,
  151. Createtimelist,
  152. RoleChs,
  153. ArticleChs,
  154. },
  155. props: ["curQue", "changeCurQue", "tmIndex"],
  156. data() {
  157. return {
  158. imageNumber: 1000,
  159. mp3Number: 1,
  160. fileCon: {
  161. img_list: [],
  162. mp3_list: [],
  163. },
  164. isClause: false,
  165. isByWord: false,
  166. paraIndex: 0, //段落索引
  167. cTVisible: false,
  168. loading: false,
  169. segList: null,
  170. isEditRole: false,
  171. isEditDia: false,
  172. curOpIndex: -1,
  173. curOption: null,
  174. active: 1,
  175. data_structure: {
  176. type: "dialog_article_chs",
  177. name: "对话课文",
  178. model: 1,
  179. pyPosition: "top", //top 拼音在上面;bottom 拼音在下面
  180. title: "", //描述
  181. option: [
  182. {
  183. site: "left",
  184. role: {
  185. roleName: "",
  186. fullName: "",
  187. segList: [],
  188. seg_words: "",
  189. wordsList: [],
  190. namePinyin: "",
  191. },
  192. article: "",
  193. detail: [],
  194. },
  195. ],
  196. },
  197. };
  198. },
  199. computed: {},
  200. watch: {},
  201. //方法集合
  202. methods: {
  203. changeMp3(fileList) {
  204. const articleImgList = JSON.parse(JSON.stringify(fileList));
  205. const articleImgRes = [];
  206. articleImgList.forEach((item) => {
  207. if (item.response) {
  208. const obj = {
  209. name: item.name,
  210. duration: item.response.file_info_list[0].media_duration,
  211. url: item.response.file_info_list[0].file_url,
  212. id: "[FID##" + item.response.file_info_list[0].file_id + "#FID]",
  213. media_duration: item.response.file_info_list[0].media_duration, //音频时长
  214. };
  215. articleImgRes.push(obj);
  216. }
  217. });
  218. this.curQue.mp3_list = JSON.parse(JSON.stringify(articleImgRes));
  219. },
  220. changeImage(file) {
  221. console.log(file);
  222. if (file.response) {
  223. const obj = {
  224. name: file.name,
  225. url: file.response.file_info_list[0].file_url,
  226. id: "[FID##" + item.response.file_info_list[0].file_id + "#FID]",
  227. imgNumber: 0,
  228. };
  229. this.curQue.img_list.push(obj);
  230. this.$forceUpdate();
  231. }
  232. },
  233. forceUpdate() {
  234. this.$forceUpdate();
  235. },
  236. delImage(index) {
  237. this.curQue.img_list.splice(index, 1);
  238. this.fileCon.img_list.splice(index, 1);
  239. },
  240. //生成分句
  241. sureSeg() {
  242. let detail = JSON.parse(JSON.stringify(this.curQue.detail));
  243. let leg = detail.length;
  244. let flag = false;
  245. for (let i = 0; i < leg; i++) {
  246. if (!detail[i].para) {
  247. flag = true;
  248. break;
  249. }
  250. }
  251. if (!flag) {
  252. let textList = [];
  253. detail.forEach((item) => {
  254. let str = Base64.encode(item.para);
  255. textList.push(str);
  256. });
  257. this.loading = true;
  258. let data = {
  259. text: textList,
  260. };
  261. segSentences(data).then((res) => {
  262. this.loading = false;
  263. let result = res.data.result;
  264. result.forEach((item, index) => {
  265. this.$set(this.curQue.detail[index], "sentences", item);
  266. });
  267. this.isClause = true;
  268. });
  269. } else {
  270. this.$message.warning("段落不能为空");
  271. }
  272. },
  273. changeIsClause(isClause) {
  274. this.isClause = isClause;
  275. },
  276. //生成分词
  277. segByWord(sentences, paraIndex) {
  278. console.log(sentences);
  279. this.loading = true;
  280. let textList = [];
  281. sentences.forEach((item) => {
  282. let str = Base64.encode(item);
  283. textList.push(str);
  284. });
  285. let data = {
  286. textList: textList,
  287. };
  288. BatchSegContent(data).then((res) => {
  289. this.paraIndex = paraIndex;
  290. this.loading = false;
  291. let list = res.data.result.list;
  292. this.$set(this.curQue.detail[paraIndex], "segList", list);
  293. this.segList = list;
  294. this.isByWord = true;
  295. });
  296. },
  297. uploadLRC() {
  298. this.cTVisible = true;
  299. },
  300. //保存字幕节点
  301. saveTimeList() {
  302. this.cTVisible = false;
  303. let detail = JSON.parse(JSON.stringify(this.$refs.createtimelist.detail));
  304. let detailRes = detail.map((item) => {
  305. let timeList = item.time_str.split("\n");
  306. item.timeList = this.handleTimeReg(timeList);
  307. return item;
  308. });
  309. this.curQue.detail = JSON.parse(JSON.stringify(detailRes));
  310. console.log(this.curQue.detail);
  311. },
  312. handleTimeReg(list) {
  313. list = list.map((item) => {
  314. let regArr = item.split("]");
  315. let reg = regArr[0];
  316. item = reg.replace("[", "");
  317. return item;
  318. });
  319. return list;
  320. },
  321. //点击字幕节点
  322. editTimeList() {
  323. this.cTVisible = true;
  324. },
  325. initCurQueData() {
  326. let res_data = JSON.parse(JSON.stringify(this.data_structure));
  327. this.changeCurQue(res_data);
  328. },
  329. //编辑角色
  330. editRole(item, index) {
  331. this.isEditRole = true;
  332. this.curOption = item;
  333. this.curOpIndex = index;
  334. },
  335. //保存角色
  336. saveRole() {
  337. this.isEditRole = false;
  338. console.log(this.curQue);
  339. },
  340. //编辑对话内容
  341. editDialogue(item, index) {
  342. this.isEditDia = true;
  343. this.curOption = item;
  344. this.curOpIndex = index;
  345. },
  346. //保存对话内容
  347. saveDialogue() {},
  348. changeActive(active) {
  349. this.active = active;
  350. },
  351. },
  352. //生命周期 - 创建完成(可以访问当前this实例)
  353. created() {},
  354. //生命周期 - 挂载完成(可以访问DOM元素)
  355. mounted() {
  356. console.log("ArticleTem");
  357. console.log(this.curQue);
  358. if (this.curQue) {
  359. // if (this.curQue.detail[0].sentences.length > 0) {
  360. // this.isClause = true;
  361. // }
  362. // if (this.curQue.detail[0].seg_words.length > 0) {
  363. // this.isByWord = true;
  364. // }
  365. // if (!this.curQue.img_list) {
  366. // this.curQue.img_list = [];
  367. // }
  368. // if (!this.curQue.mp3_list) {
  369. // this.curQue.mp3_list = [];
  370. // }
  371. // this.fileCon.img_list = JSON.parse(JSON.stringify(this.curQue.img_list));
  372. // this.fileCon.mp3_list = JSON.parse(JSON.stringify(this.curQue.mp3_list));
  373. } else {
  374. this.initCurQueData();
  375. }
  376. },
  377. beforeCreate() {}, //生命周期 - 创建之前
  378. beforeMount() {}, //生命周期 - 挂载之前
  379. beforeUpdate() {}, //生命周期 - 更新之前
  380. updated() {}, //生命周期 - 更新之后
  381. beforeDestroy() {}, //生命周期 - 销毁之前
  382. destroyed() {}, //生命周期 - 销毁完成
  383. activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
  384. };
  385. </script>
  386. <style lang='scss' scoped>
  387. //@import url(); 引入公共css类
  388. p {
  389. margin: 0;
  390. padding: 0;
  391. }
  392. .uploadArt_list {
  393. border: 1px #ccc solid;
  394. border-bottom: 0;
  395. margin-top: 10px;
  396. > li {
  397. display: flex;
  398. justify-content: flex-start;
  399. align-items: center;
  400. border-bottom: 1px #ccc solid;
  401. > span {
  402. width: 320px;
  403. word-wrap: break-word;
  404. font-size: 14px;
  405. color: rgb(112, 110, 110);
  406. border-right: 1px #ccc solid;
  407. padding: 5px 10px;
  408. }
  409. > p {
  410. flex: 1;
  411. padding: 5px 10px;
  412. }
  413. .imgNumber {
  414. width: 80px;
  415. }
  416. .del-close {
  417. width: 24px;
  418. height: 24px;
  419. cursor: pointer;
  420. margin-right: 10px;
  421. }
  422. }
  423. }
  424. .NNPE-Book-Article {
  425. > div {
  426. margin-bottom: 20px;
  427. }
  428. }
  429. .NNPE-Book-model {
  430. display: flex;
  431. justify-content: flex-start;
  432. align-items: center;
  433. > span {
  434. margin: 0;
  435. }
  436. }
  437. .lrc-box {
  438. display: flex;
  439. justify-content: flex-start;
  440. align-items: center;
  441. > span {
  442. font-size: 14px;
  443. margin-right: 16px;
  444. }
  445. }
  446. .NPC-dia-art-option {
  447. display: flex;
  448. justify-content: flex-start;
  449. align-items: center;
  450. > div {
  451. margin-right: 10px;
  452. cursor: pointer;
  453. }
  454. }
  455. </style>