CreateArticle.vue 38 KB

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