CreateArticle.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. <template>
  2. <div class="manage-root create-article">
  3. <Header/>
  4. <breadcrumb :breadcrumbList="breadcrumbList" class="breadcrumb-box"></breadcrumb>
  5. <div class="manage-root-contain" v-loading="subtitleLoading">
  6. <div class="manage-root-contain-inner" :style="{height:tableHeight+'px'}">
  7. <el-form :inline="true" :model="articleForm" :rules="articleRules" ref="articleForm" label-width="100px" class="registerForm" label-position="top">
  8. <el-form-item label="标题" prop="art_title" class="title-box">
  9. <el-input v-model="articleForm.art_title" autocomplete="off" placeholder="请输入标题" @blur="handleTrim('articleForm','art_title')" >
  10. </el-input>
  11. </el-form-item>
  12. <el-form-item label="来源" prop="art_author" class="source-box">
  13. <el-input v-model="articleForm.art_author" autocomplete="off" placeholder="请输入来源" @blur="handleTrim('articleForm','art_author')" >
  14. </el-input>
  15. </el-form-item>
  16. <el-form-item label="Page" prop="page_no_in_pub" class="page-box">
  17. <el-input v-model="articleForm.page_no_in_pub" autocomplete="off" placeholder="请输入" type="number" :min="1">
  18. </el-input>
  19. </el-form-item>
  20. </el-form>
  21. <template v-if="en_flag===1">
  22. <label class="item-label">课文读音</label>
  23. <div class="article-mp3-box">
  24. <ul v-if="articleForm.articleMp3&&articleForm.articleMp3.length>0" class="article-mp3-list">
  25. <li v-for="(item,index) in articleForm.articleMp3" :key="index">
  26. <a><svg-icon :icon-class="'mp3'" class="icon-logo"></svg-icon><span>{{item.name}}</span></a>
  27. <i class="el-icon-error" @click="handleDelResource(index)"></i>
  28. </li>
  29. </ul>
  30. <upload :class="['article-mp3']" :datafileList="articleForm.articleMp3" :changeFillId="handleAvatarSuccess" :fileName="'articleMp3'" uploadType="mp3" tips=' ' :filleNumber="1" :showList="true" />
  31. <!-- <el-button type="primary" size="small" @click="handleSubtitle" :loading="subtitleLoading" v-if="!substitleReault">生成字幕</el-button>
  32. <el-button size="small" @click="handleSubtitle" :loading="subtitleLoading" v-else>重新生成</el-button>
  33. <p class="error-tips"><svg-icon icon-class="error-warning-line"></svg-icon>生成失败</p> -->
  34. </div>
  35. </template>
  36. <Editor
  37. id="article-cn"
  38. v-model="articleForm.art_content"
  39. :init="init"
  40. />
  41. <template v-if="en_flag===0">
  42. </template>
  43. <template v-else>
  44. <!-- <el-input
  45. style="width: 100%"
  46. type="textarea"
  47. :autosize="{ minRows: 20 }"
  48. placeholder="请输入文章"
  49. v-model="articleForm.articleEn"
  50. @blur="handleTrim('articleForm', 'articleEn')"
  51. ></el-input> -->
  52. <el-form :model="articleRecourseForm" ref="articleResourceForm" label-width="40px" class="registerForm" style="margin-top:16px">
  53. <el-form-item label="生词" prop="newWordList">
  54. <el-button type="primary" size="small" plain class="add-btn" @click="handleAddWords()"><i class="el-icon-plus"></i> 添加生词</el-button>
  55. </el-form-item>
  56. <new-word-list :list="wordLit" :colorObj="colorObj" @handleAddWords="handleAddWords" v-if="wordLit.length>0"></new-word-list>
  57. <el-form-item label="短语" prop="newWordList">
  58. <el-button type="primary" size="small" plain class="add-btn" @click="handleAddPhrase()"><i class="el-icon-plus"></i> 添加短语</el-button>
  59. </el-form-item>
  60. <phrase-list class="newWord-list" :list="phraseList" :colorObj="colorObj" @handleAddPhrase="handleAddPhrase" v-if="phraseList.length>0"></phrase-list>
  61. <el-form-item label="注释" prop="newWordList">
  62. <el-button type="primary" size="small" plain class="add-btn" @click="handleAddExplain()"><i class="el-icon-plus"></i> 添加注释</el-button>
  63. </el-form-item>
  64. <annotation-list class="newWord-list" :list="annotationList" :colorObj="colorObj" @handleAddExplain="handleAddExplain" v-if="annotationList.length>0"></annotation-list>
  65. <!-- <el-form-item label="图片" prop="pictureList">
  66. <upload :datafileList="articleRecourseForm.pictureList" :changeFillId="handleAvatarSuccess" :uploadType="'image'" :fileName="'pictureList'" :filleNumber="99" tips="支持上传jpg、png格式图片,单张大小不超过2mb" :showList="true" />
  67. <ul v-if="articleRecourseForm.pictureList.length>0" class="resource-list">
  68. <li v-for="(itemR,indexR) in articleRecourseForm.pictureList" :key="indexR">
  69. <div>
  70. <el-image
  71. :src="itemR.url"
  72. fit="contain" style="width:40px;height:40px;margin-right:12px"
  73. :preview-src-list="[itemR.url]">
  74. </el-image>
  75. <span>{{itemR.name}}</span>
  76. <svg-icon icon-class="download" style="cursor: pointer;" @click="handlePreview(itemR)"></svg-icon>
  77. </div>
  78. <i class="el-icon-delete" @click="handleDelPicture(indexR)"></i>
  79. </li>
  80. </ul>
  81. </el-form-item> -->
  82. <!-- <el-divider></el-divider>
  83. <el-form-item label="讲解教师" prop="teacher">
  84. <el-input v-model="articleRecourseForm.teacher" autocomplete="off" placeholder="请输入" @blur="handleTrim('articleRecourseForm','teacher')" >
  85. </el-input>
  86. </el-form-item>
  87. <el-form-item label="讲解内容" prop="explanContent">
  88. <upload :datafileList="articleRecourseForm.explanContent" :changeFillId="handleAvatarSuccess" :uploadType="'video&radio'" :fileName="'explanContent'" :filleNumber="99" tips="支持上传mp3, wav格式音频文件及 mp4, mov格式视频文件,音频大小不超过50mb,视频大小不超过 500mb。" :showList="true" />
  89. <ul v-if="articleRecourseForm.explanContent.length>0" class="resource-list">
  90. <li v-for="(itemR,indexR) in articleRecourseForm.explanContent" :key="indexR">
  91. <a @click="handlePreview(itemR)"><svg-icon :icon-class="itemR.type" class="icon-logo"></svg-icon><span>{{itemR.name}}</span></a>
  92. <i class="el-icon-delete" @click="handleDelExplanContent(indexR)"></i>
  93. </li>
  94. </ul>
  95. </el-form-item> -->
  96. </el-form>
  97. </template>
  98. </div>
  99. <div class="save-btn">
  100. <el-button type="primary" size="small" @click="handleSaveArticle('articleForm')" :loading="loading">下一步</el-button>
  101. <el-button size="small" @click="onCancel('articleForm')">取消</el-button>
  102. </div>
  103. <el-button type="primary" size="small" class="preview-btn">预览</el-button>
  104. </div>
  105. <el-dialog
  106. :visible.sync="resourceFlag"
  107. :show-close="true"
  108. :close-on-click-modal="false"
  109. :modal-append-to-body="false"
  110. width="1000px"
  111. class="login-dialog"
  112. v-if="resourceFlag">
  113. <iframe
  114. :src="resourceUrl"
  115. width="100%"
  116. height="600px"
  117. ></iframe>
  118. </el-dialog>
  119. <el-dialog
  120. :visible.sync="newWordFlag"
  121. :show-close="false"
  122. :close-on-click-modal="false"
  123. :append-to-body="true"
  124. width="1200px"
  125. class="login-dialog"
  126. v-if="newWordFlag">
  127. <new-words @closeDialog="closeDialog" :itemData="newWordObj" :articleId="id||articleId" :vlInfo="vlInfo" :sentenceList="sentenceList"></new-words>
  128. </el-dialog>
  129. <el-dialog
  130. :visible.sync="explainFlag"
  131. :show-close="false"
  132. :close-on-click-modal="false"
  133. :append-to-body="true"
  134. width="510px"
  135. class="login-dialog"
  136. v-if="explainFlag">
  137. <explain @closeDialog="closeDialog" :itemData="explainObj" :articleId="id||articleId" :sentenceList="sentenceList"></explain>
  138. </el-dialog>
  139. <el-dialog
  140. :visible.sync="pharseFlag"
  141. :show-close="false"
  142. :close-on-click-modal="false"
  143. :append-to-body="true"
  144. width="1200px"
  145. class="login-dialog"
  146. v-if="pharseFlag">
  147. <phrase @closeDialog="closeDialog" :itemData="pharseObj" :articleId="id||articleId" :sentenceList="sentenceList"></phrase>
  148. </el-dialog>
  149. </div>
  150. </template>
  151. <script>
  152. //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  153. //例如:import 《组件名称》from ‘《组件路径》';
  154. import Header from "../../../components/Header.vue";
  155. import Breadcrumb from '../../../components/Breadcrumb.vue';
  156. import { getLogin } from "@/api/ajax";
  157. import tinymce from "tinymce/tinymce";
  158. import Editor from "@tinymce/tinymce-vue";
  159. import "tinymce/icons/default/icons";
  160. import "tinymce/themes/silver";
  161. // 引入富文本编辑器主题的js和css
  162. import "tinymce/themes/silver/theme.min";
  163. import "tinymce/skins/ui/oxide/skin.min.css";
  164. // 扩展插件
  165. // import "tinymce/plugins/"
  166. import "tinymce/plugins/image";
  167. import "tinymce/plugins/link";
  168. import "tinymce/plugins/code";
  169. import "tinymce/plugins/table";
  170. import "tinymce/plugins/lists";
  171. import "tinymce/plugins/wordcount"; // 字数统计插件
  172. import "tinymce/plugins/media"; // 插入视频插件
  173. import "tinymce/plugins/template"; // 模板插件
  174. import "tinymce/plugins/fullscreen";
  175. import "tinymce/plugins/paste";
  176. import "tinymce/plugins/preview";
  177. import "tinymce/plugins/contextmenu";
  178. import "tinymce/plugins/textcolor";
  179. import "tinymce/plugins/colorpicker";
  180. import Upload from "../../../components/Upload.vue"
  181. const Base64 = require("js-base64").Base64;
  182. import { mapState } from 'vuex';
  183. import { getToken } from '@/utils/auth'
  184. import NewWords from "./NewWords.vue"
  185. import NewWordList from './components/NewWordList.vue';
  186. import Explain from "./Explain.vue"
  187. import AnnotationList from './components/AnnotationList.vue'
  188. import PhraseList from './components/PhraseList.vue';
  189. import Phrase from './Phrase.vue'
  190. export default {
  191. //import引入的组件需要注入到对象中才能使用
  192. components: { Header, Breadcrumb, Editor, Upload, NewWords, NewWordList, Explain, AnnotationList, PhraseList, Phrase },
  193. props: {},
  194. data() {
  195. //这里存放数据
  196. const validatePage = (rule, value, callback) => {
  197. if (value === null) {
  198. callback();
  199. } else {
  200. if (value<1) {
  201. callback(new Error('Page不能小于1'));
  202. } else {
  203. callback();
  204. }
  205. }
  206. };
  207. return {
  208. id:this.$route.query.id?this.$route.query.id:'',
  209. en_flag:this.$route.query.en_flag?this.$route.query.en_flag*1:0,
  210. breadcrumbList:[
  211. {
  212. icon:'file-list-line',
  213. url:'',
  214. text:''
  215. },
  216. {
  217. icon:'',
  218. url:'',
  219. notLink: true,
  220. text:'...'
  221. },
  222. {
  223. icon:'',
  224. url:'',
  225. text:this.$route.query.isCreate?'创建报纸':'编辑报纸'
  226. },
  227. {
  228. icon:'',
  229. url:'',
  230. text:this.$route.query.id?this.$route.query.en_flag*1===1?'编辑英文内容':'编辑中文内容':this.$route.query.en_flag*1===1?'创建英文内容':'创建中文内容'
  231. }
  232. ],
  233. tableHeight: "",
  234. loading: false,
  235. articleForm: {
  236. art_title:'', // 标题
  237. art_author: '', // 来源
  238. page_no_in_pub: null, // 页码
  239. art_content: '', // 中文文章
  240. articleEn: '', // 英文文章
  241. articleMp3: [], // 课文音频
  242. articleMp3_id: '', // 音频文件id
  243. },
  244. articleRecourseForm:{
  245. newWordList: [], // 生词
  246. pharseList: [], // 短语
  247. annotationList: [], // 注释
  248. pictureList: [], // 图片
  249. teacher: '', // 讲解教师
  250. explanContent: [], // 讲解内容
  251. },
  252. articleRules:{
  253. art_title:[
  254. { required: true, message: '请输入标题', trigger: 'blur' }
  255. ],
  256. art_author:[
  257. { required: true, message: '请输入来源', trigger: 'blur' }
  258. ],
  259. page_no_in_pub:[
  260. { validator: validatePage, trigger: 'blur' }
  261. ],
  262. art_content: [
  263. { required: true, message: '请输入', trigger: 'blur' }
  264. ],
  265. articleEn:[
  266. { required: true, message: '请输入', trigger: 'blur' }
  267. ],
  268. },
  269. init: null,
  270. subtitleLoading: false, //生成字幕loading
  271. substitleReault: false,
  272. resourceUrl: '', // 课节资源预览地址
  273. resourceFlag: false,
  274. vlInfo: null, // 词表信息
  275. sentenceList: [], // 句子信息
  276. articleId: null,
  277. newWordFlag: false, // 添加生词flag
  278. newWordObj: null, // 生词obj
  279. explainObj: null,
  280. explainFlag: false,
  281. pharseObj: null,
  282. pharseFlag: false,
  283. colorObj: {
  284. type:'white',
  285. contentBg:'#F2F3F5',
  286. contentInnerBg:'#FFFFFF',
  287. navBg:'#FFFFFF',
  288. border:'#E5E6EB',
  289. bg:'#FFFFFF',
  290. border_active:'#3459D2',
  291. boxBorder:'#E5E6EB',
  292. titleColor:'#1F2C5C',
  293. sourceColor:'#929CA8',
  294. contentColor:'#2F3742',
  295. btnColor:'#3459D2',
  296. glossaryTitle:'#2F3742',
  297. glossarySubtitle:'#4E5969',
  298. glossaryBg:'#F7F8FA',
  299. newWordColor:'#175DFF',
  300. newWordOtherColor:'#667180',
  301. newWordStar:'#FFB224',
  302. newWordType:{
  303. 'daochu':{
  304. text:'导出',
  305. color:'#F5319D',
  306. bg:'#FFE8F1'
  307. },
  308. 'xuanbi':{
  309. text:'选必',
  310. color:'#175DFF',
  311. bg:'#D9E2FC'
  312. }
  313. },
  314. phraseColor:'#ED5F00',
  315. phraseOhterColor:'#2F3742',
  316. annotationTitle:'#4E5969',
  317. annotationOhter:'#667180',
  318. statisticTitle:'#2F3742',
  319. statisticValue:'#3459D2',
  320. menuBg:'#EEF3FF',
  321. audiobg:'#FFFFFF',
  322. audioBorder:'#EBEBEB'
  323. },
  324. wordLit:[],
  325. annotationList: [],
  326. phraseList: []
  327. }
  328. },
  329. //计算属性 类似于data概念
  330. computed: {
  331. ...mapState(['file_preview_url']),
  332. },
  333. //监控data中数据变化
  334. watch: {},
  335. //方法集合
  336. methods: {
  337. getTableHeight() {
  338. let tableH = 236; //距离页面下方的高度
  339. let tableHeightDetil = window.innerHeight - tableH;
  340. if (tableHeightDetil <= 300) {
  341. this.tableHeight = 300;
  342. } else {
  343. this.tableHeight = window.innerHeight - tableH;
  344. }
  345. },
  346. // 取消 恢复到修改前状态
  347. onCancel(){
  348. this.$router.go(-1)
  349. },
  350. handleSaveArticle(formName,flag){
  351. this.$refs[formName].validate((valid) => {
  352. if (valid) {
  353. let MethodName = '/PaperServer/Manager/ArticleManager/AddArticle'
  354. let data = {
  355. art_title: this.articleForm.art_title,
  356. page_no_in_pub: this.articleForm.page_no_in_pub*1,
  357. art_author: this.articleForm.art_author,
  358. art_content: this.articleForm.art_content,
  359. iss_id: this.$route.query.issueId,
  360. chn_item: this.$route.query.chn_name,
  361. en_flag: this.en_flag
  362. }
  363. if(this.id||this.articleId){
  364. MethodName = '/PaperServer/Manager/ArticleManager/EditArticle'
  365. data.id = this.id||this.articleId,
  366. data.updater_id = JSON.parse(getToken()).user_id
  367. }
  368. if(!this.articleForm.art_content.trim()){
  369. this.$message.warning('文章内容不能为空')
  370. return false
  371. }
  372. if(this.en_flag===0){
  373. }else{
  374. data.art_content = this.id||this.articleId?this.articleForm.art_content:null
  375. data.art_org_content = this.articleForm.art_content.trim()
  376. data.art_sounds = this.articleForm.articleMp3_id?[this.articleForm.articleMp3_id]:null
  377. // let resource_file_id_list = []
  378. // this.articleRecourseForm.pictureList.forEach(item => {
  379. // if(item.file_id){
  380. // resource_file_id_list.push(item.file_id)
  381. // }else if(item.response&&item.response.file_info_list&&item.response.file_info_list[0]){
  382. // resource_file_id_list.push(item.response.file_info_list[0].file_id)
  383. // }
  384. // });
  385. // data.art_images = resource_file_id_list
  386. }
  387. getLogin(MethodName, data)
  388. .then((res) => {
  389. if(res.status===1){
  390. if(flag){
  391. this.articleId = res.data.art.id
  392. this.vlInfo = res.data.vl.levelList
  393. this.sentenceList = res.data.art.art_corpus_data?res.data.art.art_corpus_data.sentList:[]
  394. if(flag==='newWord'){
  395. this.newWordObj = null
  396. this.newWordFlag = true
  397. }else if(flag === 'pharse'){
  398. this.pharseObj = null
  399. this.pharseFlag = true
  400. }else if(flag === 'explain'){
  401. this.explainObj = null
  402. this.explainFlag = true
  403. }
  404. }else{
  405. this.$message.success('文章保存成功')
  406. this.$router.go(-1)
  407. }
  408. }
  409. })
  410. } else {
  411. return false;
  412. }
  413. });
  414. },
  415. // 去掉前后空格
  416. handleTrim(form,fild){
  417. this[form][fild] = this[form][fild].trim()
  418. },
  419. handleAvatarSuccess(fileList,name) {
  420. if(name==='articleMp3'){
  421. this.articleForm.articleMp3 = fileList
  422. this.articleForm.articleMp3_id = fileList[0]&&fileList[0].response&&fileList[0].response.file_info_list&&fileList[0].response.file_info_list[0]?fileList[0].response.file_info_list[0].file_id:''
  423. this.$forceUpdate()
  424. }else if(name==='pictureList'){
  425. // fileList.forEach(item=>{
  426. // if(item.response&&item.response.file_info_list&&item.response.file_info_list[0]){
  427. // item.name = item.response.file_info_list[0].file_name
  428. // item.file_id = item.response.file_info_list[0].file_id
  429. // item.url = item.response.file_info_list[0].file_url
  430. // }
  431. // })
  432. // this.articleRecourseForm.pictureList = fileList
  433. }else if(name==='explanContent'){
  434. fileList.forEach(item=>{
  435. if(item.response&&item.response.file_info_list&&item.response.file_info_list[0]){
  436. let index = item.response.file_info_list[0].file_name.lastIndexOf('.');
  437. item.name = item.response.file_info_list[0].file_name
  438. let type = item.response.file_info_list[0].file_name.substring(index + 1).toLowerCase()
  439. item.type = this.handleJudgeType(type)
  440. item.file_id = item.response.file_info_list[0].file_id
  441. }
  442. })
  443. this.articleRecourseForm.explanContent = fileList
  444. }
  445. },
  446. // 判断文件类型
  447. handleJudgeType(type){
  448. let finalType = ''
  449. if(type==='wav'){
  450. finalType = 'mp3'
  451. }else if(type==='png'||type==='jpg'||type==='jpeg'){
  452. finalType = 'jpg'
  453. }else if(type==='avi'||type==='wmv'||type==='mpeg'||type==='mov'){
  454. finalType = 'mp4'
  455. }else if(type==='rar'||type==='jar'||type==='arj'||type==='z'||type==='jar'){
  456. finalType = 'zip'
  457. }else if(type==='docx'){
  458. finalType = 'doc'
  459. }else if(type==='xls'){
  460. finalType = 'xlsx'
  461. }else if(type==='pptx'){
  462. finalType = 'ppt'
  463. }else{
  464. finalType = type
  465. }
  466. return finalType
  467. },
  468. // 删除资源文件
  469. handleDelResource(i){
  470. this.$confirm("确定删除吗?", "提示", {
  471. confirmButtonText: "确定",
  472. cancelButtonText: "取消",
  473. type: "warning",
  474. }).then(() => {
  475. this.articleForm.articleMp3.splice(i, 1);
  476. this.$forceUpdate()
  477. });
  478. },
  479. handleDelPicture(i){
  480. this.$confirm("确定删除吗?", "提示", {
  481. confirmButtonText: "确定",
  482. cancelButtonText: "取消",
  483. type: "warning",
  484. }).then(() => {
  485. this.articleRecourseForm.pictureList.splice(i, 1);
  486. });
  487. },
  488. handleDelExplanContent(i){
  489. this.$confirm("确定删除吗?", "提示", {
  490. confirmButtonText: "确定",
  491. cancelButtonText: "取消",
  492. type: "warning",
  493. }).then(() => {
  494. this.articleRecourseForm.explanContent.splice(i, 1);
  495. });
  496. },
  497. // 生成字幕
  498. handleSubtitle(){
  499. this.subtitleLoading = true
  500. this.substitleReault = true
  501. },
  502. // 下载图片
  503. handleDownloadPic(url){
  504. window.open(url, "_blank");
  505. },
  506. // 预览文件
  507. handlePreview(item){
  508. let MethodName = '/FileServer/GetFileInfo'
  509. if(item.file_id){
  510. let data = {
  511. file_id: item.file_id
  512. }
  513. getLogin(MethodName, data)
  514. .then((res) => {
  515. if(res.status===1){
  516. window.open(res.file_url, "_blank");
  517. }
  518. })
  519. }else{
  520. window.open(item.url, "_blank");
  521. }
  522. },
  523. // 获取文章信息
  524. getArticleInfo(){
  525. this.subtitleLoading = true
  526. let MethodName = '/PaperServer/Manager/ArticleManager/FindArticleById'
  527. let data = {
  528. id: this.id||this.articleId
  529. }
  530. getLogin(MethodName, data)
  531. .then((res) => {
  532. if(res.status===1){
  533. this.articleForm = JSON.parse(JSON.stringify(res.data.art))
  534. this.vlInfo = res.data.vl?res.data.vl.levelList:[]
  535. this.sentenceList = res.data.art.art_corpus_data?res.data.art.art_corpus_data.sentList:[]
  536. this.articleForm.articleEn = JSON.parse(JSON.stringify(res.data.art)).art_org_content
  537. if(res.data.art.art_sounds&&res.data.art.art_sounds.length>0){
  538. this.articleForm.articleMp3_id = res.data.art.art_sounds[0]
  539. if(res.data.art.art_sounds[0].indexOf('http')==-1){
  540. getLogin('/FileServer/GetFileInfo', {file_id:res.data.art.art_sounds[0]})
  541. .then((res) => {
  542. if(res.status===1){
  543. this.articleForm.articleMp3=[{
  544. name:res.file_name,
  545. }]
  546. }
  547. })
  548. }else{
  549. this.articleForm.articleMp3=[{
  550. name:'音频文件.mp3',
  551. }]
  552. }
  553. }else{
  554. this.articleForm.articleMp3_id = ''
  555. this.articleForm.articleMp3 = []
  556. }
  557. // this.articleRecourseForm.pictureList = []
  558. // if(res.data.art.art_images&&res.data.art.art_images.length>0){
  559. // res.data.art.art_images.forEach((item,index)=>{
  560. // if(item.indexOf('http')==-1){
  561. // getLogin('/FileServer/GetFileInfo', {file_id:item})
  562. // .then((res) => {
  563. // if(res.status===1){
  564. // this.articleRecourseForm.pictureList.push({
  565. // name:res.file_name,
  566. // url:res.file_url,
  567. // file_id: item
  568. // })
  569. // }
  570. // })
  571. // }else{
  572. // this.articleRecourseForm.pictureList.push({
  573. // name:'图片'+(index+1),
  574. // url:item,
  575. // file_id: ''
  576. // })
  577. // }
  578. // })
  579. // }
  580. if(res.data.art.art_voc_data&&res.data.art.art_voc_data.length>0){
  581. this.wordLit = []
  582. res.data.art.art_voc_data.forEach(items=>{
  583. let obj = {
  584. src: items.ph_file_url?items.ph_file_url:'',
  585. word: items.word_name,
  586. symbol: items.word_explain.ph?items.word_explain.ph:'',
  587. paraList: items.word_explain.word_para_list,
  588. type: items.word_explain.vl_level?items.word_explain.vl_level:'',
  589. typeCn: items.word_explain.vl_level_name?items.word_explain.vl_level_name:'',
  590. rate: items.word_explain.star?items.word_explain.star:null,
  591. originalObj: items,
  592. hasVoice: items.word_explain.ph_mp3_id||items.word_explain.ph_file_url?true:false
  593. }
  594. this.wordLit.push(obj)
  595. })
  596. }
  597. if(res.data.art.art_explain_data&&res.data.art.art_explain_data.length>0){
  598. this.annotationList = res.data.art.art_explain_data
  599. }
  600. if(res.data.art.art_phrase_data&&res.data.art.art_phrase_data.length>0){
  601. this.phraseList = res.data.art.art_phrase_data
  602. }
  603. this.subtitleLoading = false
  604. }
  605. }).catch(()=>{
  606. this.subtitleLoading = false
  607. })
  608. },
  609. // 添加生词
  610. handleAddWords(obj){
  611. if(obj){
  612. this.newWordObj = obj.originalObj?obj.originalObj:obj
  613. this.newWordFlag = true
  614. }else{
  615. if(this.id||this.articleId){
  616. this.newWordObj = null
  617. this.newWordFlag = true
  618. }else{
  619. this.handleSaveArticle('articleForm','newWord')
  620. }
  621. }
  622. },
  623. // 添加注释
  624. handleAddExplain(obj){
  625. if(obj){
  626. this.explainObj = obj
  627. this.explainFlag = true
  628. }else{
  629. if(this.id||this.articleId){
  630. this.explainObj = null
  631. this.explainFlag = true
  632. }else{
  633. this.handleSaveArticle('articleForm','explain')
  634. }
  635. }
  636. },
  637. handleAddPhrase(obj){
  638. if(obj){
  639. this.pharseObj = obj
  640. this.pharseFlag = true
  641. }else{
  642. if(this.id||this.articleId){
  643. this.pharseObj = null
  644. this.pharseFlag = true
  645. }else{
  646. this.handleSaveArticle('articleForm','phrase')
  647. }
  648. }
  649. },
  650. closeDialog(flag){
  651. this[flag] = false
  652. this.getArticleInfo()
  653. },
  654. },
  655. //生命周期 - 创建完成(可以访问当前this实例)
  656. created() {
  657. this.getTableHeight()
  658. let lang_url = "";
  659. let language = "";
  660. let skin_url =
  661. process.env.NODE_ENV == "development"
  662. ? "/tinymce/skins/ui/oxide"
  663. : window.g.zh_CN_URL + "/tinymce/skins/ui/oxide";
  664. lang_url =
  665. process.env.NODE_ENV == "development"
  666. ? "/tinymce/langs/zh_CN.js"
  667. : window.g.zh_CN_URL + "/tinymce/langs/zh_CN.js";
  668. language = "zh_CN";
  669. this.init = {
  670. language_url: lang_url,
  671. language: language,
  672. skin_url: skin_url,
  673. height: 600,
  674. plugins: "link lists image code table wordcount preview",
  675. toolbar:
  676. "preview bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat",
  677. branding: false,
  678. extended_valid_elements: 'p[class|pno|sno|tsno|id|explain],span[class|pno|sno|tsno|id|explain],div[class|pno|sno|tsno|id|explain],ul[class|pno|sno|tsno|id|explain],ol[class|pno|sno|tsno|id|explain],li[class|pno|sno|tsno|id|explain],table[class|pno|sno|tsno|id|explain],th[class|pno|sno|tsno|id|explain],td[class|pno|sno|tsno|id|explain],b[class|pno|sno|tsno|id|explain],i[class|pno|sno|tsno|id|explain],strong[class|pno|sno|tsno|id|explain],em[class|pno|sno|tsno|id|explain]'
  679. }; //富文本初始化
  680. if(this.id){
  681. this.getArticleInfo()
  682. }
  683. },
  684. //生命周期 - 挂载完成(可以访问DOM元素)
  685. mounted() {
  686. tinymce.init({
  687. selector: `#article-cn`,
  688. });
  689. },
  690. //生命周期-创建之前
  691. beforeCreated() { },
  692. //生命周期-挂载之前
  693. beforeMount() { },
  694. //生命周期-更新之前
  695. beforUpdate() { },
  696. //生命周期-更新之后
  697. updated() { },
  698. //生命周期-销毁之前
  699. beforeDestory() { },
  700. //生命周期-销毁完成
  701. destoryed() { },
  702. //如果页面有keep-alive缓存功能,这个函数会触发
  703. activated() { }
  704. }
  705. </script>
  706. <style lang="scss" scoped>
  707. /* @import url(); 引入css类 */
  708. .breadcrumb-box {
  709. left: 24px;
  710. }
  711. .manage-root-contain{
  712. margin: 56px 24px 24px;
  713. height: calc(100vh - 132px);
  714. border-radius: 4px;
  715. background: #FFF;
  716. padding: 24px 24px 80px 24px;
  717. display: block;
  718. position: relative;
  719. &-inner{
  720. overflow-y: auto;
  721. }
  722. .save-btn,.preview-btn{
  723. position: absolute;
  724. bottom: 24px;
  725. left: 24px;
  726. }
  727. .preview-btn{
  728. right: 24px;
  729. left: auto;
  730. }
  731. }
  732. .el-form--inline{
  733. display: flex;
  734. width: 100%;
  735. }
  736. .title-box{
  737. flex: 1;
  738. .el-input{
  739. width: 100%;
  740. }
  741. }
  742. .source-box{
  743. .el-input{
  744. width: 205px;
  745. }
  746. }
  747. .page-box{
  748. .el-input{
  749. width: 190px;
  750. }
  751. }
  752. .item-label{
  753. color: #4E5969;
  754. font-size: 14px;
  755. font-weight: 400;
  756. line-height: 22px;
  757. }
  758. .article-mp3-box{
  759. display: flex;
  760. height: 32px;
  761. align-items: center;
  762. margin: 8px 0 20px 0;
  763. }
  764. .article-mp3{
  765. width: 82px;
  766. height: 32px;
  767. &-has{
  768. width: 320px;
  769. }
  770. }
  771. .article-mp3-list{
  772. list-style: none;
  773. margin: 0;
  774. padding: 0;
  775. display: inline-block;
  776. width: 226px;
  777. li{
  778. padding: 5px 12px;
  779. height: 32px;
  780. border-radius: 2px 0px 0px 2px;
  781. background: #F2F3F5;
  782. display: flex;
  783. align-items: center;
  784. a{
  785. color: #1D2129;
  786. display: flex;
  787. align-items: center;
  788. flex: 1;
  789. span{
  790. overflow:hidden;
  791. text-overflow:ellipsis;
  792. white-space: nowrap;
  793. flex: 1;
  794. display: block;
  795. font-size: 14px;
  796. line-height: 22px;
  797. }
  798. .svg-icon{
  799. width: 16px;
  800. height: 16px;
  801. margin-right: 4px;
  802. color: #1D2129;
  803. }
  804. }
  805. .el-icon-error{
  806. color: #4E5969;
  807. cursor: pointer;
  808. margin-left: 4px;
  809. }
  810. }
  811. }
  812. .error-tips{
  813. font-size: 14px;
  814. font-weight: 500;
  815. line-height: 22px;
  816. color: #F53F3F;
  817. margin-left: 16px;
  818. .svg-icon{
  819. width: 12px;
  820. height: 12px;
  821. margin-right: 4px;
  822. }
  823. }
  824. .resource-list{
  825. list-style: none;
  826. margin: 12px 0;
  827. padding: 0;
  828. li{
  829. display: flex;
  830. align-items: center;
  831. margin-bottom: 16px;
  832. a,>div{
  833. width: 360px;
  834. padding: 7px 12px;
  835. background: #F7F8FA;
  836. border-radius: 2px;
  837. color: #1D2129;
  838. display: flex;
  839. align-items: center;
  840. span{
  841. overflow:hidden;
  842. text-overflow:ellipsis;
  843. white-space: nowrap;
  844. flex: 1;
  845. display: block;
  846. font-size: 14px;
  847. line-height: 22px;
  848. }
  849. .svg-icon{
  850. width: 16px;
  851. height: 16px;
  852. margin-right: 8px;
  853. color: #4E5969;
  854. }
  855. }
  856. .el-icon-delete{
  857. color: #4E5969;
  858. cursor: pointer;
  859. margin-left: 12px;
  860. &:hover{
  861. color: #165DFF;
  862. }
  863. }
  864. >div{
  865. display: flex;
  866. }
  867. }
  868. }
  869. .add-btn{
  870. padding: 2px 12px;
  871. border-radius: 2px;
  872. border: 1px solid #165DFF;
  873. color: #165DFF;
  874. font-size: 12px;
  875. font-weight: 400;
  876. line-height: 20px;
  877. background: #FFF;
  878. .el-icon-plus{
  879. margin-right: 8px;
  880. }
  881. &:hover{
  882. background: #FFF;
  883. color: #165DFF;
  884. }
  885. }
  886. </style>
  887. <style lang="scss">
  888. .create-article{
  889. .el-divider{
  890. width: 600px;
  891. }
  892. }
  893. </style>