cread.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. <template>
  2. <div class="cread" v-loading="loading">
  3. <Header v-if="!userID" />
  4. <div class="go-back-box" :class="[userID ? 'go-back-box-user' : '']" v-if="!isPreview">
  5. <a v-if="!userID" class="go-back" :class="[editCardflag ? '' : 'go-back-preview']" @click="goBack">
  6. <i class="el-icon-arrow-left"></i>
  7. 返回
  8. </a>
  9. <template v-if="editCardflag">
  10. <div class="name-box">
  11. <label>卡片名称</label>
  12. <el-input v-model="saveName"></el-input>
  13. </div>
  14. <div class="btn-box">
  15. <el-button small @click="addCard"><i class="el-icon-plus"></i>增加卡片</el-button>
  16. <el-upload
  17. ref="upload"
  18. :action="url"
  19. accept=".xlsx,.xls"
  20. :limit="9999"
  21. :on-exceed="handleExceed"
  22. :on-success="handleSuccess"
  23. :show-file-list="false"
  24. class="btn"
  25. style="margin: 0 8px"
  26. >
  27. <el-button>通过模版导入</el-button>
  28. </el-upload>
  29. <el-button type="primary" plain small @click="save">结束编辑并保存</el-button>
  30. </div>
  31. </template>
  32. <template v-else>
  33. <h3>{{ saveName }}</h3>
  34. <div class="btn-box">
  35. <el-button @click="changeRowLength">{{ showRoeText[showRowLength] }}</el-button>
  36. <el-button small @click="editCardflag = true"><i class="el-icon-edit"></i>编辑</el-button>
  37. <el-button small @click="download2"><img src="../../assets/teacherdev/word-eyes.png" alt="" />打印</el-button>
  38. </div>
  39. </template>
  40. </div>
  41. <div
  42. class="content"
  43. :class="[editCardflag ? '' : 'content-flex content-flex-' + showRowLength]"
  44. :style="{ minHeight: innerHeight - 172 + 'px' }"
  45. >
  46. <div v-for="(item, index) in newEditTable" :key="index" :class="[editCardflag ? '' : 'item-flex']">
  47. <writeTable
  48. :editCardflag="editCardflag"
  49. :dataConfig="writeTableData"
  50. :data="item"
  51. :pageNumber="index + 1"
  52. :totalNumber="showRowLength"
  53. :isPreview="true"
  54. @handleDelItem="handleDelItem"
  55. />
  56. </div>
  57. </div>
  58. <!-- <div class="preview_dv" v-if="isPreview" :style="{ top: userID ? '0' : '' }">
  59. <img class="close" src="../../assets/teacherdev/creadCad-close.png" alt="" @click="closepreviewEvent" />
  60. <el-button type="primary" class="print-btn" small @click="download2">打印</el-button>
  61. <div class="preview_main">
  62. <img
  63. class="left"
  64. src="../../assets/teacherdev/creadCad-left.png"
  65. alt=""
  66. @click="changepreviewIndex('remove')"
  67. />
  68. <div class="word_main">
  69. <div class="word_main_table">
  70. <writeTable
  71. :type="typeIndex"
  72. :dataConfig="newEditTable"
  73. :data="newEditTable[previewIndex]"
  74. :pageNumber="previewIndex + 1"
  75. :totalNumber="newEditTable.length"
  76. :isPreview="true"
  77. :showLeft="showLeft"
  78. @changeShowLeft="changeShowLeft"
  79. ref="writeTable"
  80. />
  81. </div>
  82. </div>
  83. <img class="right" src="../../assets/teacherdev/creadCad-right.png" alt="" @click="changepreviewIndex('add')" />
  84. </div>
  85. </div> -->
  86. </div>
  87. </template>
  88. <script>
  89. //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  90. //例如:import 《组件名称》from ‘《组件路径》';
  91. import Header from '@/components/Header';
  92. import { getLogin, LearnWebSI, getHZChineseInfo, getContentFile } from '@/api/api';
  93. import writeTable from './writeTableNew.vue';
  94. import { getToken } from '@/utils/auth';
  95. import html2canvas from 'html2canvas';
  96. import { jsPDF } from 'jspdf';
  97. import canvg from 'canvg';
  98. import cnchar from 'cnchar';
  99. import 'cnchar-radical';
  100. import FileSaver from 'file-saver';
  101. import htmlDocx from 'html-docx-js/dist/html-docx';
  102. export default {
  103. //import引入的组件需要注入到对象中才能使用
  104. components: {
  105. Header,
  106. writeTable,
  107. },
  108. props: {},
  109. data() {
  110. //这里存放数据
  111. return {
  112. saveName: '',
  113. typeIndex: 0,
  114. loading: false,
  115. writeTableData: null,
  116. isPreview: false,
  117. previewIndex: 0,
  118. saveShow: false,
  119. hzDetailList: null,
  120. userID: this.$route.query.userID ? this.$route.query.userID : '',
  121. editCardflag: this.$route.query.id ? false : true, // 是否编辑卡片
  122. newEditTable: [
  123. // {
  124. // borderColor: '#243C97',
  125. // fontColor: '#243C97',
  126. // fontAlign: 'left',
  127. // label: '',
  128. // headerCon: '',
  129. // left: {
  130. // fileList: [],
  131. // con: '',
  132. // },
  133. // right: {
  134. // definition: '',
  135. // collocation: '',
  136. // exampleSent: '',
  137. // hz_info: [],
  138. // pinyin: '',
  139. // audio_file: '',
  140. // cixing: '',
  141. // },
  142. // },
  143. ],
  144. showLeft: true,
  145. showRowLength: 1, // 一页展示几个,有一行一列,一行两列,一行三列和两行两列
  146. showRoeText: {
  147. 1: '一行一列',
  148. 2: '一行两列',
  149. 3: '一行三列',
  150. 4: '多行两列',
  151. },
  152. innerHeight: window.innerHeight,
  153. };
  154. },
  155. //计算属性 类似于data概念
  156. computed: {
  157. url() {
  158. let userInfo = getToken()
  159. ? JSON.parse(getToken())
  160. : sessionStorage.getItem('GCLS_Token_Tc')
  161. ? JSON.parse(sessionStorage.getItem('GCLS_Token_Tc'))
  162. : null;
  163. if (!userInfo) return `${process.env.VUE_APP_BASE_API}/GCLSFileServer/WebFileUpload`;
  164. return `${process.env.VUE_APP_BASE_API}/GCLSFileServer/WebFileUpload?AccessToken=${userInfo.access_token}&SecurityLevel=Mid"`;
  165. },
  166. },
  167. //监控data中数据变化
  168. watch: {},
  169. //方法集合
  170. methods: {
  171. addCard() {
  172. this.newEditTable.push({
  173. borderColor: '#243C97',
  174. fontColor: '#243C97',
  175. fontAlign: 'left',
  176. label: '',
  177. headerCon: '',
  178. left: {
  179. fileList: [],
  180. con: '',
  181. },
  182. right: {
  183. definition: '',
  184. collocation: '',
  185. exampleSent: '',
  186. hz_info: [],
  187. pinyin: '',
  188. audio_file: '',
  189. cixing: '',
  190. hideHanzi: false,
  191. },
  192. });
  193. },
  194. // 删除一条卡片
  195. handleDelItem(index) {
  196. this.newEditTable.splice(index, 1);
  197. },
  198. // 返回上一页
  199. goBack() {
  200. this.$router.push({
  201. path: '/wordcard/table',
  202. });
  203. },
  204. // 保存
  205. save() {
  206. if (!this.saveName || !this.saveName.trim()) {
  207. this.$message.warning('请填写卡片名称');
  208. return;
  209. }
  210. this.loading = this.$loading({
  211. lock: true,
  212. text: 'Loading',
  213. spinner: 'el-icon-loading',
  214. background: 'rgba(0, 0, 0, 0.7)',
  215. });
  216. let text = '';
  217. this.newEditTable.forEach((items) => {
  218. text += items.left.con.trim() + '\n';
  219. });
  220. if (this.$route.query.id) {
  221. // 编辑
  222. let Mname = 'tr_tool-wsc_manager-UpdateMyWordSentenceCard';
  223. LearnWebSI(Mname, {
  224. id: this.$route.query.id,
  225. name: this.saveName,
  226. type: this.typeIndex == 0 ? 'WORD' : 'SENTENCE',
  227. text: text,
  228. content: JSON.stringify(this.newEditTable),
  229. update_scope: 0,
  230. })
  231. .then((res) => {
  232. this.loading.close();
  233. this.loading = false;
  234. this.editCardflag = false;
  235. this.$message.success('保存成功');
  236. this.showRowLength = this.newEditTable.length > 3 ? 4 : this.newEditTable.length;
  237. })
  238. .catch((res) => {
  239. this.loading.close();
  240. this.loading = false;
  241. });
  242. } else {
  243. // 新建
  244. let Mname = 'tr_tool-wsc_manager-CreateMyWordSentenceCard';
  245. LearnWebSI(Mname, {
  246. name: this.saveName,
  247. type: this.typeIndex == 0 ? 'WORD' : 'SENTENCE',
  248. text: text,
  249. content: JSON.stringify(this.newEditTable),
  250. app_user_id: this.userID,
  251. })
  252. .then((res) => {
  253. this.$router.replace({
  254. path: '/wordcard/cread',
  255. query: {
  256. id: res.id,
  257. userID: this.userID,
  258. },
  259. });
  260. this.loading.close();
  261. this.loading = false;
  262. this.editCardflag = false;
  263. this.$message.success('保存成功');
  264. this.showRowLength = this.newEditTable.length > 3 ? 4 : this.newEditTable.length;
  265. })
  266. .catch((res) => {
  267. this.loading.close();
  268. this.loading = false;
  269. });
  270. }
  271. },
  272. // 字句详情
  273. getdetai() {
  274. this.loading = true;
  275. let Mname = 'tr_tool-wsc_manager-GetWordSentenceCard';
  276. LearnWebSI(Mname, {
  277. id: this.$route.query.id,
  278. })
  279. .then((res) => {
  280. console.log(789);
  281. this.saveName = res.name;
  282. this.newEditTable = JSON.parse(res.content);
  283. this.loading = false;
  284. this.showRowLength = this.newEditTable.length > 3 ? 4 : this.newEditTable.length;
  285. })
  286. .catch((res) => {
  287. this.loading = false;
  288. });
  289. },
  290. // 预览
  291. previewEvent() {
  292. this.previewIndex = 0;
  293. this.showLeft = true;
  294. this.isPreview = true;
  295. },
  296. // 关闭预览
  297. closepreviewEvent() {
  298. this.isPreview = false;
  299. },
  300. changepreviewIndex(type) {
  301. if (type == 'add') {
  302. if (this.previewIndex == this.newEditTable.length - 1) {
  303. this.$message.warning('当前已经是最后一页');
  304. return;
  305. }
  306. this.previewIndex++;
  307. } else {
  308. if (this.previewIndex == 0) {
  309. this.$message.warning('当前已经是第一页');
  310. return;
  311. }
  312. this.previewIndex--;
  313. }
  314. this.$refs.writeTable.changeRota();
  315. this.showLeft = true;
  316. this.$forceUpdate();
  317. },
  318. changeShowLeft() {
  319. this.showLeft = !this.showLeft;
  320. },
  321. download2() {
  322. this.$nextTick(() => {
  323. if (this.newEditTable) {
  324. let str = JSON.stringify(this.newEditTable);
  325. localStorage.setItem('newEditTable', str);
  326. this.$router.replace({
  327. path: '/wordcard/printNew',
  328. query: {
  329. userID: this.userID,
  330. id: this.$route.query.id,
  331. },
  332. });
  333. }
  334. });
  335. },
  336. async handleSuccess(res, file, fileList) {
  337. if (res.status !== 1) {
  338. this.$message.error(res.message);
  339. return;
  340. }
  341. let file_id = file.response.file_info_list[0].file_id;
  342. this.loading = true;
  343. // 通过 fileList 的 response 判断是否已全部完成上传
  344. this.loading = true;
  345. this.$refs.upload.clearFiles();
  346. await LearnWebSI('tr_tool-wsc_manager-ParseWordSentenceCardImportFile', {
  347. file_id: file_id,
  348. })
  349. .then((res) => {
  350. this.loading = false;
  351. this.$message.success('导入成功');
  352. res.content_json_text.forEach((items) => {
  353. if (
  354. items.headerCon ||
  355. items.label ||
  356. items.left.con ||
  357. items.right.cixing ||
  358. items.right.collocation ||
  359. items.right.definition ||
  360. items.right.exampleSent ||
  361. items.right.pinyin
  362. ) {
  363. items.borderColor = '#243C97';
  364. items.fontAlign = 'left';
  365. items.fontColor = '#243C97';
  366. let con = items.left.con.trim();
  367. if (con) {
  368. let MethodName = 'hz_resource_manager-GetMultHZStrokesContent';
  369. let data = {
  370. hz_str: con,
  371. };
  372. getLogin(MethodName, data)
  373. .then((res) => {
  374. this.loading = false;
  375. for (let key in res) {
  376. if (key != 'status' && key != ',' && res[key]) {
  377. res[key] = JSON.parse(res[key]);
  378. }
  379. }
  380. let hzDetailList = res;
  381. let hz_list = [];
  382. con.split('').forEach((items) => {
  383. let res = JSON.parse(JSON.stringify(hzDetailList[items]));
  384. let obj = {
  385. con: items,
  386. hzDetail: {
  387. hz_json: res,
  388. },
  389. };
  390. hz_list.push(obj);
  391. });
  392. items.right.hz_info = hz_list;
  393. let MethodName = 'tool-TextToVoiceFile';
  394. if (con) {
  395. let datas = {
  396. text: con,
  397. };
  398. getLogin(MethodName, datas).then((res) => {
  399. if (res.status === 1) {
  400. items.right.audio_file = res.file_id;
  401. }
  402. });
  403. }
  404. })
  405. .catch(() => {
  406. this.loading = false;
  407. });
  408. }
  409. this.newEditTable.push(items);
  410. }
  411. });
  412. })
  413. .catch((res) => {
  414. this.loading = false;
  415. });
  416. },
  417. handleExceed(files) {
  418. this.$message.warning(`当前限制选择 9999 个文件,本次选择了 ${files.length} 个文件`);
  419. },
  420. changeRowLength() {
  421. if (this.showRowLength === 4) {
  422. this.showRowLength = 1;
  423. } else {
  424. this.showRowLength++;
  425. }
  426. },
  427. },
  428. //生命周期 - 创建完成(可以访问当前this实例)
  429. created() {},
  430. //生命周期 - 挂载完成(可以访问DOM元素)
  431. mounted() {},
  432. //生命周期-创建之前
  433. beforeCreated() {},
  434. //生命周期-挂载之前
  435. beforeMount() {},
  436. //生命周期-更新之前
  437. beforUpdate() {},
  438. //生命周期-更新之后
  439. updated() {},
  440. //生命周期-销毁之前
  441. beforeDestory() {},
  442. //生命周期-销毁完成
  443. destoryed() {},
  444. //如果页面有keep-alive缓存功能,这个函数会触发
  445. activated() {
  446. if (this.$route.query.cachesType == 'pop') {
  447. this.saveName = '';
  448. this.typeIndex = 0;
  449. this.loading = false;
  450. this.newEditTable = [
  451. // {
  452. // borderColor: '#243C97', // 卡片边框颜色
  453. // fontColor: '#243C97', // 字体颜色
  454. // fontAlign: 'left', // 页眉对齐方式
  455. // label: '', // 标签内容
  456. // headerCon: '', // 页眉内容
  457. // left: {
  458. // fileList: [], // 上传文件
  459. // con: '', // 字词卡片内容(即卡片显示的字词)
  460. // },
  461. // right: {
  462. // definition: '', // 释义
  463. // collocation: '', // 搭配
  464. // exampleSent: '', // 例句
  465. // hz_info: [], // 汉字笔顺等内容
  466. // pinyin: '', // 拼音
  467. // audio_file: '', // 字词生成的音频
  468. // cixing: '', // 词性
  469. // },
  470. // },
  471. ];
  472. this.previewIndex = 0;
  473. this.saveShow = false;
  474. this.showLeft = true;
  475. this.editCardflag = this.$route.query.id ? false : true;
  476. this.isPreview = false;
  477. if (this.$route.query.id) {
  478. // 需要请求详情接口
  479. this.getdetai();
  480. }
  481. }
  482. },
  483. };
  484. </script>
  485. <style lang="scss" scoped>
  486. /* @import url(); 引入css类 */
  487. .cread {
  488. min-height: 100%;
  489. position: relative;
  490. background: #f2f2f2;
  491. .go-back-box {
  492. width: 1200px;
  493. display: flex;
  494. border-radius: 8px;
  495. background: #fff;
  496. padding: 8px;
  497. margin: 20px auto;
  498. // position: fixed;
  499. // top: 83px;
  500. // left: 50%;
  501. // margin-left: -610px;
  502. // z-index: 1000;
  503. border: 1px solid rgba(0, 0, 0, 0.15);
  504. &-user {
  505. top: 19px;
  506. }
  507. h3 {
  508. font-size: 24px;
  509. font-weight: 500;
  510. line-height: 150%;
  511. flex: 1;
  512. text-align: center;
  513. }
  514. img {
  515. width: 20px;
  516. margin-right: 6px;
  517. }
  518. .el-button {
  519. padding: 8px 16px;
  520. height: 40px;
  521. line-height: 24px;
  522. }
  523. }
  524. .go-back {
  525. display: flex;
  526. color: #333;
  527. font-size: 24px;
  528. font-weight: 500;
  529. line-height: 36px;
  530. padding: 0 16px 0 0;
  531. align-items: center;
  532. cursor: pointer;
  533. &-preview {
  534. width: 184px;
  535. }
  536. .el-icon-arrow-left {
  537. font-size: 16px;
  538. margin-right: 8px;
  539. }
  540. }
  541. .name-box {
  542. flex: 1;
  543. display: flex;
  544. align-items: center;
  545. label {
  546. color: #4e5969;
  547. font-size: 14px;
  548. font-weight: 400;
  549. line-height: 22px;
  550. margin-right: 16px;
  551. }
  552. .el-input {
  553. width: 227px;
  554. border-radius: 2px;
  555. background: #f2f3f5;
  556. }
  557. }
  558. .btn-box {
  559. display: flex;
  560. i {
  561. margin-right: 8px;
  562. font-size: 16px;
  563. }
  564. }
  565. .content {
  566. // padding-top: 88px;
  567. &-flex {
  568. display: flex;
  569. width: 1470px;
  570. margin: 0 auto;
  571. flex-flow: wrap;
  572. gap: 30px 50px;
  573. justify-content: center;
  574. align-content: center;
  575. &-3,
  576. &-4 {
  577. .item-flex {
  578. width: 450px !important;
  579. }
  580. }
  581. &-2,
  582. &-4 {
  583. justify-content: start;
  584. }
  585. &-1 {
  586. width: 500px;
  587. }
  588. &-2 {
  589. width: 1060px;
  590. }
  591. &-4 {
  592. width: 960px;
  593. }
  594. }
  595. .item-flex {
  596. width: 500px;
  597. flex-shrink: 0;
  598. }
  599. }
  600. }
  601. .preview_dv {
  602. position: absolute;
  603. left: 0;
  604. top: 64px;
  605. width: 100%;
  606. min-height: calc(100% - 64px);
  607. background: #f2f2f2;
  608. > img {
  609. width: 40px;
  610. height: 40px;
  611. cursor: pointer;
  612. position: absolute;
  613. top: 24px;
  614. right: 31px;
  615. }
  616. .print-btn {
  617. cursor: pointer;
  618. position: absolute;
  619. top: 24px;
  620. left: 31px;
  621. }
  622. .preview_main {
  623. padding: 24px 0;
  624. width: 740px;
  625. display: flex;
  626. align-items: center;
  627. height: 450px;
  628. position: absolute;
  629. top: 50%;
  630. margin-top: -225px;
  631. left: 50%;
  632. margin-left: -370px;
  633. > div {
  634. margin: 0 24px;
  635. }
  636. img {
  637. width: 48px;
  638. height: 48px;
  639. cursor: pointer;
  640. }
  641. }
  642. }
  643. </style>
  644. <style lang="scss">
  645. .cread {
  646. .name-box {
  647. .el-input__inner {
  648. border-radius: 2px;
  649. background: #f2f3f5;
  650. border: none;
  651. }
  652. }
  653. .btn-box {
  654. .el-button {
  655. span {
  656. display: flex;
  657. align-items: center;
  658. }
  659. }
  660. }
  661. }
  662. </style>