cread.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  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. 5: '两行三列',
  152. },
  153. innerHeight: window.innerHeight,
  154. };
  155. },
  156. //计算属性 类似于data概念
  157. computed: {
  158. url() {
  159. let userInfo = getToken()
  160. ? JSON.parse(getToken())
  161. : sessionStorage.getItem('GCLS_Token_Tc')
  162. ? JSON.parse(sessionStorage.getItem('GCLS_Token_Tc'))
  163. : null;
  164. if (!userInfo) return `${process.env.VUE_APP_BASE_API}/GCLSFileServer/WebFileUpload`;
  165. return `${process.env.VUE_APP_BASE_API}/GCLSFileServer/WebFileUpload?AccessToken=${userInfo.access_token}&SecurityLevel=Mid"`;
  166. },
  167. },
  168. //监控data中数据变化
  169. watch: {},
  170. //方法集合
  171. methods: {
  172. addCard() {
  173. this.newEditTable.push({
  174. borderColor: '#243C97',
  175. fontColor: '#243C97',
  176. fontAlign: 'left',
  177. label: '',
  178. headerCon: '',
  179. left: {
  180. fileList: [],
  181. con: '',
  182. },
  183. right: {
  184. definition: '',
  185. collocation: '',
  186. exampleSent: '',
  187. hz_info: [],
  188. pinyin: '',
  189. audio_file: '',
  190. cixing: '',
  191. hideHanzi: false,
  192. },
  193. });
  194. },
  195. // 删除一条卡片
  196. handleDelItem(index) {
  197. this.newEditTable.splice(index, 1);
  198. },
  199. // 返回上一页
  200. goBack() {
  201. this.$router.push({
  202. path: '/wordcard/table',
  203. });
  204. },
  205. // 保存
  206. save() {
  207. if (!this.saveName || !this.saveName.trim()) {
  208. this.$message.warning('请填写卡片名称');
  209. return;
  210. }
  211. this.loading = this.$loading({
  212. lock: true,
  213. text: 'Loading',
  214. spinner: 'el-icon-loading',
  215. background: 'rgba(0, 0, 0, 0.7)',
  216. });
  217. let text = '';
  218. this.newEditTable.forEach((items) => {
  219. text += items.left.con.trim() + '\n';
  220. });
  221. if (this.$route.query.id) {
  222. // 编辑
  223. let Mname = 'tr_tool-wsc_manager-UpdateMyWordSentenceCard';
  224. LearnWebSI(Mname, {
  225. id: this.$route.query.id,
  226. name: this.saveName,
  227. type: this.typeIndex == 0 ? 'WORD' : 'SENTENCE',
  228. text: text,
  229. content: JSON.stringify(this.newEditTable),
  230. update_scope: 0,
  231. })
  232. .then((res) => {
  233. this.loading.close();
  234. this.loading = false;
  235. this.editCardflag = false;
  236. this.$message.success('保存成功');
  237. this.showRowLength = this.newEditTable.length > 3 ? 4 : this.newEditTable.length;
  238. })
  239. .catch((res) => {
  240. this.loading.close();
  241. this.loading = false;
  242. });
  243. } else {
  244. // 新建
  245. let Mname = 'tr_tool-wsc_manager-CreateMyWordSentenceCard';
  246. LearnWebSI(Mname, {
  247. name: this.saveName,
  248. type: this.typeIndex == 0 ? 'WORD' : 'SENTENCE',
  249. text: text,
  250. content: JSON.stringify(this.newEditTable),
  251. app_user_id: this.userID,
  252. })
  253. .then((res) => {
  254. this.$router.replace({
  255. path: '/wordcard/cread',
  256. query: {
  257. id: res.id,
  258. userID: this.userID,
  259. },
  260. });
  261. this.loading.close();
  262. this.loading = false;
  263. this.editCardflag = false;
  264. this.$message.success('保存成功');
  265. this.showRowLength = this.newEditTable.length > 3 ? 4 : this.newEditTable.length;
  266. })
  267. .catch((res) => {
  268. this.loading.close();
  269. this.loading = false;
  270. });
  271. }
  272. },
  273. // 字句详情
  274. getdetai() {
  275. this.loading = true;
  276. let Mname = 'tr_tool-wsc_manager-GetWordSentenceCard';
  277. LearnWebSI(Mname, {
  278. id: this.$route.query.id,
  279. })
  280. .then((res) => {
  281. console.log(789);
  282. this.saveName = res.name;
  283. this.newEditTable = JSON.parse(res.content);
  284. this.loading = false;
  285. this.showRowLength = this.newEditTable.length > 3 ? 4 : this.newEditTable.length;
  286. })
  287. .catch((res) => {
  288. this.loading = false;
  289. });
  290. },
  291. // 预览
  292. previewEvent() {
  293. this.previewIndex = 0;
  294. this.showLeft = true;
  295. this.isPreview = true;
  296. },
  297. // 关闭预览
  298. closepreviewEvent() {
  299. this.isPreview = false;
  300. },
  301. changepreviewIndex(type) {
  302. if (type == 'add') {
  303. if (this.previewIndex == this.newEditTable.length - 1) {
  304. this.$message.warning('当前已经是最后一页');
  305. return;
  306. }
  307. this.previewIndex++;
  308. } else {
  309. if (this.previewIndex == 0) {
  310. this.$message.warning('当前已经是第一页');
  311. return;
  312. }
  313. this.previewIndex--;
  314. }
  315. this.$refs.writeTable.changeRota();
  316. this.showLeft = true;
  317. this.$forceUpdate();
  318. },
  319. changeShowLeft() {
  320. this.showLeft = !this.showLeft;
  321. },
  322. download2() {
  323. this.$nextTick(() => {
  324. if (this.newEditTable) {
  325. let str = JSON.stringify(this.newEditTable);
  326. localStorage.setItem('newEditTable', str);
  327. this.$router.replace({
  328. path: '/wordcard/printNew',
  329. query: {
  330. userID: this.userID,
  331. id: this.$route.query.id,
  332. },
  333. });
  334. }
  335. });
  336. },
  337. async handleSuccess(res, file, fileList) {
  338. if (res.status !== 1) {
  339. this.$message.error(res.message);
  340. return;
  341. }
  342. let file_id = file.response.file_info_list[0].file_id;
  343. this.loading = true;
  344. // 通过 fileList 的 response 判断是否已全部完成上传
  345. this.loading = true;
  346. this.$refs.upload.clearFiles();
  347. await LearnWebSI('tr_tool-wsc_manager-ParseWordSentenceCardImportFile', {
  348. file_id: file_id,
  349. })
  350. .then((res) => {
  351. this.loading = false;
  352. this.$message.success('导入成功');
  353. res.content_json_text.forEach((items) => {
  354. if (
  355. items.headerCon ||
  356. items.label ||
  357. items.left.con ||
  358. items.right.cixing ||
  359. items.right.collocation ||
  360. items.right.definition ||
  361. items.right.exampleSent ||
  362. items.right.pinyin
  363. ) {
  364. items.borderColor = '#243C97';
  365. items.fontAlign = 'left';
  366. items.fontColor = '#243C97';
  367. let con = items.left.con.trim();
  368. if (con) {
  369. let MethodName = 'hz_resource_manager-GetMultHZStrokesContent';
  370. let data = {
  371. hz_str: con,
  372. };
  373. getLogin(MethodName, data)
  374. .then((res) => {
  375. this.loading = false;
  376. for (let key in res) {
  377. if (key != 'status' && key != ',' && res[key]) {
  378. res[key] = JSON.parse(res[key]);
  379. }
  380. }
  381. let hzDetailList = res;
  382. let hz_list = [];
  383. con.split('').forEach((items) => {
  384. let res = JSON.parse(JSON.stringify(hzDetailList[items]));
  385. let obj = {
  386. con: items,
  387. hzDetail: {
  388. hz_json: res,
  389. },
  390. };
  391. hz_list.push(obj);
  392. });
  393. items.right.hz_info = hz_list;
  394. let MethodName = 'tool-TextToVoiceFile';
  395. if (con) {
  396. let datas = {
  397. text: con,
  398. };
  399. getLogin(MethodName, datas).then((res) => {
  400. if (res.status === 1) {
  401. items.right.audio_file = res.file_id;
  402. }
  403. });
  404. }
  405. })
  406. .catch(() => {
  407. this.loading = false;
  408. });
  409. }
  410. this.newEditTable.push(items);
  411. }
  412. });
  413. })
  414. .catch((res) => {
  415. this.loading = false;
  416. });
  417. },
  418. handleExceed(files) {
  419. this.$message.warning(`当前限制选择 9999 个文件,本次选择了 ${files.length} 个文件`);
  420. },
  421. changeRowLength() {
  422. if (this.showRowLength === 5) {
  423. this.showRowLength = 1;
  424. } else {
  425. this.showRowLength++;
  426. }
  427. },
  428. },
  429. //生命周期 - 创建完成(可以访问当前this实例)
  430. created() {},
  431. //生命周期 - 挂载完成(可以访问DOM元素)
  432. mounted() {},
  433. //生命周期-创建之前
  434. beforeCreated() {},
  435. //生命周期-挂载之前
  436. beforeMount() {},
  437. //生命周期-更新之前
  438. beforUpdate() {},
  439. //生命周期-更新之后
  440. updated() {},
  441. //生命周期-销毁之前
  442. beforeDestory() {},
  443. //生命周期-销毁完成
  444. destoryed() {},
  445. //如果页面有keep-alive缓存功能,这个函数会触发
  446. activated() {
  447. if (this.$route.query.cachesType == 'pop') {
  448. this.saveName = '';
  449. this.typeIndex = 0;
  450. this.loading = false;
  451. this.newEditTable = [
  452. // {
  453. // borderColor: '#243C97', // 卡片边框颜色
  454. // fontColor: '#243C97', // 字体颜色
  455. // fontAlign: 'left', // 页眉对齐方式
  456. // label: '', // 标签内容
  457. // headerCon: '', // 页眉内容
  458. // left: {
  459. // fileList: [], // 上传文件
  460. // con: '', // 字词卡片内容(即卡片显示的字词)
  461. // },
  462. // right: {
  463. // definition: '', // 释义
  464. // collocation: '', // 搭配
  465. // exampleSent: '', // 例句
  466. // hz_info: [], // 汉字笔顺等内容
  467. // pinyin: '', // 拼音
  468. // audio_file: '', // 字词生成的音频
  469. // cixing: '', // 词性
  470. // },
  471. // },
  472. ];
  473. this.previewIndex = 0;
  474. this.saveShow = false;
  475. this.showLeft = true;
  476. this.editCardflag = this.$route.query.id ? false : true;
  477. this.isPreview = false;
  478. if (this.$route.query.id) {
  479. // 需要请求详情接口
  480. this.getdetai();
  481. }
  482. }
  483. },
  484. };
  485. </script>
  486. <style lang="scss" scoped>
  487. /* @import url(); 引入css类 */
  488. .cread {
  489. min-height: 100%;
  490. position: relative;
  491. background: #f2f2f2;
  492. .go-back-box {
  493. width: 1200px;
  494. display: flex;
  495. border-radius: 8px;
  496. background: #fff;
  497. padding: 8px;
  498. margin: 20px auto;
  499. // position: fixed;
  500. // top: 83px;
  501. // left: 50%;
  502. // margin-left: -610px;
  503. // z-index: 1000;
  504. border: 1px solid rgba(0, 0, 0, 0.15);
  505. &-user {
  506. top: 19px;
  507. }
  508. h3 {
  509. font-size: 24px;
  510. font-weight: 500;
  511. line-height: 150%;
  512. flex: 1;
  513. text-align: center;
  514. }
  515. img {
  516. width: 20px;
  517. margin-right: 6px;
  518. }
  519. .el-button {
  520. padding: 8px 16px;
  521. height: 40px;
  522. line-height: 24px;
  523. }
  524. }
  525. .go-back {
  526. display: flex;
  527. color: #333;
  528. font-size: 24px;
  529. font-weight: 500;
  530. line-height: 36px;
  531. padding: 0 16px 0 0;
  532. align-items: center;
  533. cursor: pointer;
  534. &-preview {
  535. width: 184px;
  536. }
  537. .el-icon-arrow-left {
  538. font-size: 16px;
  539. margin-right: 8px;
  540. }
  541. }
  542. .name-box {
  543. flex: 1;
  544. display: flex;
  545. align-items: center;
  546. label {
  547. color: #4e5969;
  548. font-size: 14px;
  549. font-weight: 400;
  550. line-height: 22px;
  551. margin-right: 16px;
  552. }
  553. .el-input {
  554. width: 227px;
  555. border-radius: 2px;
  556. background: #f2f3f5;
  557. }
  558. }
  559. .btn-box {
  560. display: flex;
  561. i {
  562. margin-right: 8px;
  563. font-size: 16px;
  564. }
  565. }
  566. .content {
  567. // padding-top: 88px;
  568. &-flex {
  569. display: flex;
  570. width: 1470px;
  571. margin: 0 auto;
  572. flex-flow: wrap;
  573. gap: 50px 120px;
  574. justify-content: center;
  575. align-content: center;
  576. padding: 10px 0;
  577. &-3,
  578. &-4 {
  579. gap: 50px 80px;
  580. .item-flex {
  581. width: 350px !important;
  582. }
  583. }
  584. &-2,
  585. &-4,
  586. &-5 {
  587. justify-content: start;
  588. }
  589. &-1 {
  590. width: 500px;
  591. }
  592. &-2 {
  593. width: 920px;
  594. }
  595. &-4 {
  596. width: 780px;
  597. }
  598. &-5 {
  599. width: 1120px;
  600. gap: 50px 80px;
  601. .item-flex {
  602. width: 320px !important;
  603. }
  604. }
  605. }
  606. .item-flex {
  607. width: 400px;
  608. flex-shrink: 0;
  609. }
  610. }
  611. }
  612. .preview_dv {
  613. position: absolute;
  614. left: 0;
  615. top: 64px;
  616. width: 100%;
  617. min-height: calc(100% - 64px);
  618. background: #f2f2f2;
  619. > img {
  620. width: 40px;
  621. height: 40px;
  622. cursor: pointer;
  623. position: absolute;
  624. top: 24px;
  625. right: 31px;
  626. }
  627. .print-btn {
  628. cursor: pointer;
  629. position: absolute;
  630. top: 24px;
  631. left: 31px;
  632. }
  633. .preview_main {
  634. padding: 24px 0;
  635. width: 740px;
  636. display: flex;
  637. align-items: center;
  638. height: 450px;
  639. position: absolute;
  640. top: 50%;
  641. margin-top: -225px;
  642. left: 50%;
  643. margin-left: -370px;
  644. > div {
  645. margin: 0 24px;
  646. }
  647. img {
  648. width: 48px;
  649. height: 48px;
  650. cursor: pointer;
  651. }
  652. }
  653. }
  654. </style>
  655. <style lang="scss">
  656. .cread {
  657. .name-box {
  658. .el-input__inner {
  659. border-radius: 2px;
  660. background: #f2f3f5;
  661. border: none;
  662. }
  663. }
  664. .btn-box {
  665. .el-button {
  666. span {
  667. display: flex;
  668. align-items: center;
  669. }
  670. }
  671. }
  672. }
  673. </style>