file.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. <template>
  2. <div class="c_box">
  3. <!-- <div class="mask"></div> -->
  4. <div v-if="!checkJson">暂未设置题目</div>
  5. <div v-else class="choice_box">
  6. <!-- <div class="title"><div>{{ `(${option[checkJson.type].name})` }}</div><div v-html="checkJson.title"></div></div> -->
  7. <div class="c_title">
  8. <div class="title">
  9. {{ `(${option[checkJson.type].name})` + checkJson.title }}<span style="color: #efa030;"
  10. v-if="checkJson.score">({{ '分值:' + checkJson.score + '分' }})</span>
  11. </div>
  12. <!-- </div><div v-html="checkJson.title"></div> -->
  13. <div class="p_box" v-if="isTeacher == 1 && checkJson.score">
  14. <el-input v-model="checkJson.score2" class="c_input" @change="numberPan"
  15. placeholder="请输入得分"></el-input><span style="margin: 0 10px;">/</span><span>{{ checkJson.score
  16. }}分</span>
  17. </div>
  18. <div class="p_box" v-if="isTeacher == 2 && checkJson.score2">
  19. <span>{{ checkJson.score2 }}分</span><span style="margin: 0 10px;">/</span><span>{{ checkJson.score
  20. }}分</span>
  21. </div>
  22. </div>
  23. <div class="choices">
  24. <div class="binfo_input">
  25. <div class="fileBox" v-if="checkJson.file && checkJson.file.length">
  26. <div class="fileC">
  27. <div class="file" v-for="(item, index) in checkJson.file" :key="index" v-loading="downLoading == item.url" @click.stop="checkFile(item)">
  28. <img class="del" src="../../../../../assets/icon/fileIcon/deleteworks.png" @click.stop="delFile(index)" v-if="checktype == 1" />
  29. <img class="download" src="../../../../../assets/icon/fileIcon/download.png" @click.stop="downloadFile(item)" :style="{right: checktype != 1 ? '10px' : '45px'}" />
  30. <img class="img" :src="wordIcon" alt="" v-if="item.type == 1" />
  31. <img class="img" :src="videoIcon" alt="" v-if="item.type == 2" />
  32. <img class="img" :src="item.url" alt="" v-if="item.type == 3" />
  33. <img class="img" :src="wordIcon" alt="" v-if="item.type == 4" />
  34. <img class="img" :src="fileIcon" alt="" v-if="item.type == 5" />
  35. <div class="name">
  36. <el-tooltip :content="item.name" placement="top" effect="dark">
  37. <span>{{ item.name }}</span>
  38. </el-tooltip>
  39. </div>
  40. </div>
  41. </div>
  42. <div class="btn" @click.stop="addImg($event)" v-if="checktype == 1">
  43. <span>点击添加本地文件</span>
  44. <input type="file" accept="*" style="display: none" @change="beforeUpload($event)" />
  45. </div>
  46. </div>
  47. <div class="uploadQ" @click.stop="addImg($event)" v-else-if="checktype == 1">
  48. <span>点击添加本地文件</span>
  49. <input type="file" accept="*" style="display: none" @change="beforeUpload($event)" />
  50. </div>
  51. <div class="uploadQ" v-else>
  52. <span>暂无添加附件</span>
  53. </div>
  54. <div v-if="proVisible" class="mask">
  55. <div class="progressBox">
  56. <div class="lbox">
  57. <img src="../../../../../assets/loading.gif" />上传中,请稍后
  58. </div>
  59. <div style="margin-bottom: 10px">
  60. <span>{{
  61. isFinishSize
  62. }}M</span>
  63. /
  64. <span>{{
  65. isAllSize
  66. }}M</span>
  67. </div>
  68. <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
  69. ? progress
  70. : 0
  71. " style="width: 80%"></el-progress>
  72. </div>
  73. </div>
  74. </div>
  75. <!-- <textarea :readonly="checktype == 2" rows="2" v-autoHeight="68" class="binfo_input binfo_textarea" cols v-model="checkJson.answer2"
  76. placeholder=""></textarea> -->
  77. </div>
  78. </div>
  79. <wpdf :dialogVisiblePdf.sync="dialogVisiblePdf" :url="wurl"></wpdf>
  80. <wVideo :dialogVisibleVideo.sync="dialogVisibleVideo" :url="wurl"></wVideo>
  81. <wOffice :dialogVisibleOffice.sync="dialogVisibleOffice" :url="wurl"></wOffice>
  82. </div>
  83. </template>
  84. <script>
  85. import "../../../../../common/aws-sdk-2.235.1.min.js";
  86. import videoIcon from '../../../../../assets/icon/fileIcon/isVideo.png'
  87. import wordIcon from '../../../../../assets/icon/fileIcon/isWord.png'
  88. import fileIcon from '../../../../../assets/icon/fileIcon/word2.png'
  89. import wpdf from "../../../test/file/wPdf2.vue";
  90. import wVideo from "../../../test/file/wVideo.vue";
  91. import wOffice from "../../../test/file/wOffice.vue";
  92. export default {
  93. components: {
  94. wpdf,
  95. wVideo,
  96. wOffice,
  97. },
  98. props: {
  99. cJson: {
  100. type: Object,
  101. },
  102. checktype: {
  103. type: Number,
  104. default: 1
  105. },
  106. see: {
  107. type: Boolean,
  108. default: false
  109. },
  110. isTeacher: {
  111. type: Number,
  112. default: 2
  113. }
  114. },
  115. data() {
  116. return {
  117. option: {
  118. 1: { name: '附件' },
  119. },
  120. checkJson: undefined,
  121. progress: 0,
  122. isFinishSize: 0,
  123. proVisible: false,
  124. isAllSize: 0,
  125. videoIcon: videoIcon,
  126. wordIcon: wordIcon,
  127. fileIcon: fileIcon,
  128. downLoading: '',
  129. dialogVisiblePdf:false,
  130. dialogVisibleVideo:false,
  131. dialogVisibleOffice:false,
  132. wurl: "",
  133. }
  134. },
  135. watch: {
  136. checkJson: {
  137. handler(newValue) {
  138. this.$emit('update:cJson', newValue)
  139. },
  140. deep: true
  141. },
  142. },
  143. methods: {
  144. depthCopy(s) {
  145. return JSON.parse(JSON.stringify(s));
  146. },
  147. addImg(e) {
  148. var el = e.currentTarget;
  149. el.getElementsByTagName("input")[0].click();
  150. e.target.value = "";
  151. },
  152. numberPan() {
  153. if (/[^\d]/.test(this.checkJson.score2) || this.checkJson.score2 < 0) {
  154. this.$message.error('请输入大于0的数字')
  155. this.checkJson.score2 = ''
  156. }
  157. if(parseInt(this.checkJson.score2) > parseInt(this.checkJson.score)){
  158. this.$message.error('不能输入大于得分的数字')
  159. this.checkJson.score2 = this.checkJson.score
  160. }
  161. },
  162. beforeUpload(event, type) {
  163. // const loading = this.openLoading();
  164. var file = event.target.files[0];
  165. var credentials = {
  166. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  167. secretAccessKey: "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",
  168. }; //秘钥形式的登录上传
  169. window.AWS.config.update(credentials);
  170. window.AWS.config.region = "cn-northwest-1"; //设置区域
  171. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
  172. var _this = this;
  173. _this.progress = 0;
  174. _this.proVisible = true;
  175. _this.isFinishSize = 0;
  176. _this.isAllSize = (file.size / 1024 / 1024).toFixed(2);
  177. _this.$forceUpdate();
  178. if (file) {
  179. var params = {
  180. Key:
  181. file.name.split(".")[0] +
  182. new Date().getTime() +
  183. "." +
  184. file.name.split(".")[file.name.split(".").length - 1],
  185. ContentType: file.type,
  186. Body: file,
  187. "Access-Control-Allow-Credentials": "*",
  188. ACL: "public-read",
  189. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  190. var options = {
  191. partSize: 2048 * 1024 * 1024,
  192. queueSize: 2,
  193. leavePartsOnError: true,
  194. };
  195. bucket
  196. .upload(params, options)
  197. .on("httpUploadProgress", function (evt) {
  198. //这里可以写进度条
  199. // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
  200. _this.progress = parseInt((evt.loaded / evt.total) * 100);
  201. _this.isFinishSize = (evt.loaded / 1024 / 1024).toFixed(2);
  202. _this.$forceUpdate();
  203. })
  204. .send(function (err, data) {
  205. _this.progress = 100;
  206. _this.isFinishSize = _this.isAllSize;
  207. _this.$forceUpdate();
  208. setTimeout(() => {
  209. _this.proVisible = false;
  210. _this.$forceUpdate();
  211. }, 1000);
  212. // loading.close();
  213. if (err) {
  214. _this.$message.error("上传失败");
  215. } else {
  216. let _type = 2;
  217. var imgA = [
  218. "png",
  219. "jpg",
  220. "jpeg",
  221. "bmp",
  222. "gif",
  223. "webp",
  224. "psd",
  225. "svg",
  226. "tiff",
  227. ];
  228. var fileA = [
  229. "DOC",
  230. "DOCX",
  231. "DOCM",
  232. "DOTM",
  233. "DOTX",
  234. "PPTX",
  235. "PPSX",
  236. "PPT",
  237. "PPS",
  238. "PPTM",
  239. "POTM",
  240. "PPAM",
  241. "POTX",
  242. "PPSM",
  243. "XLSX",
  244. "XLS",
  245. ];
  246. var videoA = [
  247. "AVI",
  248. "NAVI",
  249. "MPEG",
  250. "ASF",
  251. "MOV",
  252. "WMV",
  253. "3GP",
  254. "RM",
  255. "RMVB",
  256. "FLV",
  257. "F4V",
  258. "H.264",
  259. "H.265",
  260. "REAL VIDEO",
  261. "MKV",
  262. "WebM",
  263. "HDDVD",
  264. "MP4",
  265. "MPG",
  266. "M4V",
  267. "MGV",
  268. "OGV",
  269. "QTM",
  270. "STR",
  271. "AMC",
  272. "DVX",
  273. "EVO",
  274. "DAT",
  275. "OGG",
  276. "OGM",
  277. ];
  278. if (
  279. fileA.indexOf(
  280. data.Location.split(".")[
  281. data.Location.split(".").length - 1
  282. ].toLocaleUpperCase()
  283. ) != -1
  284. ) {
  285. _type = 1; //word 文件
  286. } else if (
  287. videoA.indexOf(
  288. data.Location.split(".")[
  289. data.Location.split(".").length - 1
  290. ].toLocaleUpperCase()
  291. ) != -1
  292. ) {
  293. _type = 2; //视频
  294. } else if (
  295. imgA.indexOf(
  296. data.Location.split(".")[
  297. data.Location.split(".").length - 1
  298. ].toLocaleLowerCase()
  299. ) != -1
  300. ) {
  301. _type = 3; //图片
  302. } else if (
  303. 'pdf'.indexOf(
  304. data.Location.split(".")[
  305. data.Location.split(".").length - 1
  306. ].toLocaleLowerCase()
  307. ) != -1
  308. ) {
  309. _type = 4; //pdf
  310. } else {
  311. _type = 5; //文件
  312. }
  313. if (_this.checkJson.file) {
  314. _this.checkJson.file.push({
  315. name: file.name,
  316. url: data.Location,
  317. type: _type,
  318. });
  319. } else {
  320. _this.checkJson.file = []
  321. _this.checkJson.file.push({
  322. name: file.name,
  323. url: data.Location,
  324. type: _type,
  325. });
  326. }
  327. _this.$forceUpdate();
  328. console.log(_this.checkJson);
  329. console.log(data.Location);
  330. }
  331. });
  332. }
  333. },
  334. downloadFile(f) {
  335. var credentials = {
  336. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  337. secretAccessKey: "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",
  338. }; //秘钥形式的登录上传
  339. window.AWS.config.update(credentials);
  340. window.AWS.config.region = "cn-northwest-1"; //设置区域
  341. let url2 = f.url;
  342. let _url2 = "";
  343. if (
  344. url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
  345. ) {
  346. _url2 = url2.split(
  347. "https://view.officeapps.live.com/op/view.aspx?src="
  348. )[1];
  349. } else {
  350. _url2 = url2;
  351. }
  352. let _this = this;
  353. _this.downLoading = _url2
  354. var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
  355. let name = decodeURIComponent(_url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1])
  356. var params = {
  357. Bucket: "ccrb",
  358. Key: name
  359. };
  360. s3.getObject(params, function (err, data) {
  361. _this.downLoading = ''
  362. if (err) console.log(err, err.stack); // an error occurred
  363. else {
  364. let url = window.URL.createObjectURL(new Blob([data.Body]));
  365. let a = document.createElement("a");
  366. a.name = f.name;
  367. a.href = url;
  368. a.download = f.name;
  369. a.click();
  370. console.log(data);
  371. } // sxuccessful response
  372. });
  373. },
  374. checkFile(item){
  375. if(item.type == 3){
  376. this.$hevueImgPreview(item.url);
  377. }else if(item.type == 5){
  378. this.downloadFile(item);
  379. }else if(item.type == 1){
  380. this.dialogVisibleOffice = true
  381. this.wurl = item.url
  382. }else if(item.type == 2){
  383. this.dialogVisibleVideo = true
  384. this.wurl = item.url
  385. }else if(item.type == 4){
  386. this.dialogVisiblePdf = true
  387. this.wurl = item.url
  388. }
  389. },
  390. delFile(index) {
  391. this.checkJson.file.splice(index, 1)
  392. }
  393. },
  394. mounted() {
  395. this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined
  396. }
  397. }
  398. </script>
  399. <style scoped>
  400. .c_box {
  401. width: 100%;
  402. position: relative;
  403. }
  404. .mask {
  405. position: absolute;
  406. height: 100%;
  407. width: 100%;
  408. z-index: 2;
  409. }
  410. .choice_box {}
  411. .choice_box>.title {
  412. font-weight: bold;
  413. width: 100%;
  414. word-break: break-all;
  415. }
  416. .choice_box>.choices {
  417. margin-top: 10px;
  418. }
  419. .binfo_input {
  420. width: 100%;
  421. margin: 0;
  422. padding: 12px 14px;
  423. display: block;
  424. min-width: 0;
  425. outline: none;
  426. box-sizing: border-box;
  427. background: none;
  428. border: none;
  429. border-radius: 4px;
  430. background: #fff;
  431. font-size: 16px;
  432. resize: none;
  433. font-family: 'Microsoft YaHei';
  434. min-height: 120px;
  435. /* border: 1px solid #3682fc00; */
  436. border: 1.5px solid #CAD1DC;
  437. position: relative;
  438. }
  439. .binfo_input>.uploadQ {
  440. border: 1px dashed #CAD1DC;
  441. height: 120px;
  442. width: 100%;
  443. display: flex;
  444. align-items: center;
  445. justify-content: center;
  446. background: rgb(243, 244, 246);
  447. color: rgb(124, 124, 124);
  448. border-radius: 5px;
  449. cursor: pointer;
  450. }
  451. .mask {
  452. background-color: rgb(0 0 0 / 30%);
  453. /* position: fixed; */
  454. position: absolute;
  455. top: 0;
  456. left: 0;
  457. width: 100%;
  458. height: 100%;
  459. z-index: 90;
  460. display: flex;
  461. align-items: center;
  462. justify-content: center;
  463. }
  464. .progressBox {
  465. width: 300px;
  466. height: 150px;
  467. background: #fff;
  468. border-radius: 10px;
  469. box-shadow: 0 0 6px 1px #bfbfbf;
  470. display: flex;
  471. align-items: center;
  472. justify-content: center;
  473. flex-direction: column;
  474. position: relative;
  475. color: #6c6c6c;
  476. }
  477. .progressBox>>>.el-progress-bar__outer {
  478. background-color: #d1dfff !important;
  479. }
  480. .progressBox .lbox {
  481. height: 50px;
  482. font-size: 19px;
  483. display: flex;
  484. align-items: center;
  485. color: #747474;
  486. }
  487. .progressBox .lbox img {
  488. width: 40px;
  489. margin-right: 20px;
  490. }
  491. .closeCss {
  492. position: absolute;
  493. top: 8px;
  494. right: 8px;
  495. cursor: pointer;
  496. width: 20px;
  497. height: 20px;
  498. }
  499. .closeCss>img {
  500. width: 100%;
  501. height: 100%;
  502. }
  503. .binfo_input>.fileBox {}
  504. .binfo_input>.fileBox .fileC {
  505. display: flex;
  506. flex-wrap: wrap;
  507. width: 100%;
  508. cursor: pointer;
  509. }
  510. .binfo_input>.fileBox .fileC>.file {
  511. width: 200px;
  512. height: 140px;
  513. margin: 10px 10px 10px 0px;
  514. border-radius: 15px;
  515. box-shadow: rgb(223, 218, 218) 0px 0px 6px 1px;
  516. overflow: hidden;
  517. margin-right: 15px;
  518. position: relative;
  519. display: flex;
  520. flex-direction: column;
  521. }
  522. .binfo_input>.fileBox .fileC>.file>.img {
  523. width: 100%;
  524. height: calc(100% - 35px);
  525. object-fit: cover;
  526. }
  527. .binfo_input>.fileBox .fileC>.file>.del {
  528. position: absolute;
  529. width: 25px;
  530. top: 10px;
  531. right: 10px;
  532. cursor: pointer;
  533. }
  534. .binfo_input>.fileBox .fileC>.file>.download {
  535. position: absolute;
  536. width: 25px;
  537. top: 10px;
  538. right: 35px;
  539. cursor: pointer;
  540. opacity: .8;
  541. }
  542. .binfo_input>.fileBox .fileC>.file>.name {
  543. height: 35px;
  544. width: 100%;
  545. background: #f9f9f9;
  546. display: flex;
  547. align-items: center;
  548. padding: 0 10px;
  549. box-sizing: border-box;
  550. }
  551. .binfo_input>.fileBox .fileC>.file>.name>span {
  552. display: block;
  553. text-overflow: ellipsis;
  554. max-width: 100%;
  555. white-space: nowrap;
  556. overflow: hidden;
  557. }
  558. .binfo_input>.fileBox .btn {
  559. width: 100%;
  560. height: 40px;
  561. background: #007bff;
  562. color: #fff;
  563. border-radius: 15px;
  564. margin-top: 10px;
  565. display: flex;
  566. align-items: center;
  567. justify-content: center;
  568. cursor: pointer;
  569. }
  570. .choice_box> .c_title {
  571. display: flex;
  572. justify-content: space-between;
  573. }
  574. .choice_box> .c_title .title {
  575. font-weight: bold;
  576. width: 100%;
  577. word-break: break-all;
  578. }
  579. .choice_box> .c_title .p_box{
  580. margin-left: 5px;
  581. min-width: fit-content;
  582. display: flex;
  583. align-items: center;
  584. }
  585. .c_input {
  586. width: 90px;
  587. }
  588. .c_input >>> .el-input__inner{
  589. padding: 0 5px;
  590. text-align: right;
  591. }
  592. </style>