uploadFileToCreateClassDialog.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. <template>
  2. <div>
  3. <el-dialog
  4. :center="true"
  5. :visible.sync="show"
  6. :close-on-click-modal="false"
  7. :modal="true"
  8. width="auto"
  9. height="auto"
  10. :append-to-body="true"
  11. class="uploadFileToCreateClassDialog"
  12. >
  13. <div class="box">
  14. <div class="b_head">
  15. <span>文件上传与配置</span>
  16. <img
  17. src="../../../../assets/icon/classroomObservation/close.svg"
  18. @click="close()"
  19. />
  20. </div>
  21. <div class="b_main">
  22. <div class="b_m_left">
  23. <div class="b_m_l_fileList" v-if="fileList.length > 0">
  24. <div class="fl_item" v-for="item in fileList" :key="item.index">
  25. <div class="fl_i_left">
  26. <img
  27. v-if="item.type =='text/plain'"
  28. src="../../../../assets/icon/classroomObservation/textFile_icon.svg"
  29. />
  30. <img
  31. v-if="item.type =='audio/wav'"
  32. src="../../../../assets/icon/classroomObservation/audio_file.svg"
  33. />
  34. <img
  35. v-if="item.type =='video/mp4'"
  36. src="../../../../assets/icon/classroomObservation/videoFile_icon.svg"
  37. />
  38. </div>
  39. <div class="fl_i_center">
  40. <div class="fl_i_c_top">
  41. <span>{{ item.name }}</span>
  42. <div>
  43. <span v-if="item.status === 'wait'">等待上传</span>
  44. <span
  45. class="uploadingText"
  46. v-else-if="item.status === 'uploading'"
  47. >{{ item.progress.percent }}%</span
  48. >
  49. <span
  50. class="successText"
  51. v-else-if="item.status === 'success'"
  52. >上传成功
  53. </span>
  54. </div>
  55. </div>
  56. <div class="fl_i_c_bottom">
  57. <div class="f_i_c_progress">
  58. <div
  59. class="f_i_c_p_value"
  60. :class="{
  61. successProgress: item.status === 'success',
  62. uploadingProgress: item.status === 'uploading'
  63. }"
  64. :style="`width:${item.progress.percent}%`"
  65. ></div>
  66. </div>
  67. </div>
  68. </div>
  69. <div class="fl_i_right">
  70. <img
  71. @click="delUploadFile(item)"
  72. src="../../../../assets/icon/classroomObservation/del.svg"
  73. />
  74. </div>
  75. </div>
  76. </div>
  77. <div class="b_m_l_noFile" v-else @click="addFile()">
  78. <img
  79. src="../../../../assets/icon/classroomObservation/file_processing.svg"
  80. />
  81. <span>文件格式支持:mp4、wav、txt 文件</span>
  82. </div>
  83. </div>
  84. <div class="b_m_right">
  85. <span>配置</span>
  86. <div>
  87. <span>自动编码</span>
  88. <el-switch
  89. v-model="automaticCoding"
  90. active-color="#13ce66"
  91. inactive-color="#ff4949"
  92. >
  93. </el-switch>
  94. </div>
  95. <div>
  96. <span>分析模板</span>
  97. <el-cascader
  98. size="small"
  99. v-model="analysisTemplate"
  100. :options="options"
  101. ></el-cascader>
  102. </div>
  103. </div>
  104. </div>
  105. <div class="b_bottom">
  106. <el-button size="small" @click="close()">取消</el-button>
  107. <el-button size="small" type="primary" @click="submit"
  108. >确定添加</el-button
  109. >
  110. </div>
  111. <uploadFile
  112. v-for="(item, index) in fileList"
  113. v-if="item.status == 'uploading'"
  114. :ref="`uploadFileRef_${item.index}`"
  115. :key="item.index"
  116. :index="item.index"
  117. @progressUpdate="progressUpdate"
  118. @success="uploadSuccess"
  119. />
  120. </div>
  121. </el-dialog>
  122. </div>
  123. </template>
  124. <script>
  125. import uploadFile from "../newComponents/uploadFile.vue";
  126. import { v4 as uuidv4 } from "uuid";
  127. export default {
  128. components: {
  129. uploadFile
  130. },
  131. data() {
  132. return {
  133. loading: false,
  134. show: false,
  135. automaticCoding: false,
  136. analysisTemplate: [],
  137. userId: this.$route.query["userid"],
  138. fileList: [],
  139. options: [
  140. { value: "0", label: "社区", children: [] },
  141. { value: "1", label: "我的", children: [] },
  142. { value: "2", label: "收藏", children: [] }
  143. ]
  144. };
  145. },
  146. methods: {
  147. open(data) {
  148. this.init();
  149. this.getTemplateData();
  150. this.loading = false;
  151. this.show = true;
  152. },
  153. close() {
  154. this.show = false;
  155. this.init();
  156. },
  157. init() {
  158. this.fileList = [];
  159. this.analysisTemplate = [];
  160. this.automaticCoding = false
  161. this.loading = false;
  162. },
  163. submit() {
  164. if(this.fileList.length<=0)return this.$message.error("请上传文件");
  165. if(this.analysisTemplate.length<=1)return this.$message.error("请选择分析模板");
  166. if(this.fileList.some(i=>i.status==='wait' || i.status==='uploading'))return this.$message.error("请等待文件上传完毕");
  167. this.$emit('success',{fileList:this.fileList,automaticCoding:this.automaticCoding,analysisTemplate:this.analysisTemplate});
  168. },
  169. delUploadFile(item) {
  170. this.$confirm("确定要删除吗?", "提示", {
  171. confirmButtonText: "确定",
  172. cancelButtonText: "取消",
  173. type: "warning"
  174. })
  175. .then(() => {
  176. // 确定删除
  177. if (item.status === "uploading") {
  178. this.$refs[`uploadFileRef_${item.index}`][0].stopUpload();
  179. this.$refs[`uploadFileRef_${item.index}`][0].abortMultipartUpload(
  180. item.progress.key,
  181. item.progress.uploadid
  182. );
  183. }
  184. this.fileList = this.fileList.filter(i => i.index != item.index);
  185. this.$forceUpdate();
  186. })
  187. .catch(() => {
  188. // 取消删除
  189. });
  190. },
  191. progressUpdate(res) {
  192. console.log(res);
  193. this.fileList.find(i => i.index == res.index).progress.status =
  194. res.status;
  195. this.fileList.find(i => i.index == res.index).progress.percent =
  196. res.percent;
  197. this.fileList.find(i => i.index == res.index).progress.key = res.key;
  198. this.fileList.find(i => i.index == res.index).progress.uploadid =
  199. res.uploadid;
  200. },
  201. uploadSuccess(res) {
  202. let data = res.data;
  203. let _name = this.fileList.find(i => i.index == res.index).file.name;
  204. let size = this.fileList.find(i => i.index == res.index).file.size;
  205. let _type = this.fileList.find(i => i.index == res.index).type;
  206. console.log(data);
  207. this.fileList.find(i => i.index == res.index).successData = {
  208. name: _name,
  209. url: data.Location,
  210. type: _type,
  211. size: size
  212. };
  213. this.fileList.find(i => i.index == res.index).status = "success";
  214. let uploadingFile = this.fileList.find(file => file.status === "wait");
  215. if (uploadingFile) {
  216. this.fileList.find(file => file.status === "wait").status = "uploading";
  217. this.$nextTick(() => {
  218. this.$refs[`uploadFileRef_${uploadingFile.index}`][0].awsupload({
  219. file: uploadingFile.file
  220. });
  221. });
  222. } else {
  223. console.log("上传完成");
  224. }
  225. },
  226. addFile() {
  227. let input = document.createElement("input");
  228. input.type = "file";
  229. input.accept = "video/mp4, audio/wav, text/plain";
  230. input.multiple = true; // 支持多文件上传
  231. input.style.display = "none";
  232. input.click();
  233. input.addEventListener("change", e => {
  234. let files = e.target.files;
  235. for (let i = 0; i < files.length; i++) {
  236. if (
  237. ["video/mp4", "audio/wav", "text/plain"].includes(files[i].type)
  238. ) {
  239. this.fileList.push({
  240. file: files[i],
  241. index: uuidv4(),
  242. successData: null,
  243. name: files[i].name,
  244. type: files[i].type,
  245. progress: { status: "", percent: 0, key: "", uploadid: "" },
  246. status: "wait"
  247. });
  248. } else {
  249. this.$message.info("文件格式不支持,仅支持mp4、wav、txt文件。");
  250. }
  251. }
  252. if (!this.fileList.some(i => i.status === "uploading")) {
  253. let uploadingFile = this.fileList.find(
  254. file => file.status === "wait"
  255. );
  256. if (uploadingFile) {
  257. this.fileList.find(file => file.status === "wait").status =
  258. "uploading";
  259. this.$nextTick(() => {
  260. this.$refs[`uploadFileRef_${uploadingFile.index}`][0].awsupload({
  261. file: uploadingFile.file
  262. });
  263. });
  264. }
  265. }
  266. });
  267. },
  268. async getTemplateData() {
  269. const promises = this.options.map(option => {
  270. return new Promise((resolve, reject) => {
  271. const params = {
  272. uid: this.userId,
  273. txt: "",
  274. sub: "0",
  275. type1: option.value
  276. };
  277. this.ajax
  278. .get(this.$store.state.api + "selectClassroomTemplate", params)
  279. .then(res => {
  280. const _data = res.data[0].map(item => ({
  281. value: item.id,
  282. label: item.name
  283. }));
  284. this.options.find(
  285. option2 => option2.value === option.value
  286. ).children = _data;
  287. resolve();
  288. })
  289. .catch(err => {
  290. console.log(err);
  291. reject(err);
  292. });
  293. });
  294. });
  295. try {
  296. await Promise.all(promises);
  297. console.log("获取模板成功");
  298. } catch (error) {
  299. console.log("获取模板失败");
  300. }
  301. }
  302. }
  303. };
  304. </script>
  305. <style scoped>
  306. .uploadFileToCreateClassDialog >>> .el-dialog {
  307. width: 900px !important;
  308. border-radius: 8px;
  309. padding: 0;
  310. background-color: #fff;
  311. overflow: hidden;
  312. }
  313. .uploadFileToCreateClassDialog >>> .el-dialog__body {
  314. width: 900px !important;
  315. height: auto;
  316. flex-shrink: 0;
  317. padding: 0;
  318. box-sizing: border-box;
  319. overflow: auto;
  320. }
  321. .uploadFileToCreateClassDialog >>> .el-dialog__header {
  322. display: none !important;
  323. }
  324. .box {
  325. width: 900px;
  326. height: 500px;
  327. background: #fafafa;
  328. border-radius: 15px;
  329. box-shadow: 0px 6px 30px 5px rgba(0, 0, 0, 0.05),
  330. 0px 16px 24px 2px rgba(0, 0, 0, 0.04), 0px 8px 10px -5px rgba(0, 0, 0, 0.08);
  331. }
  332. .b_head {
  333. width: 100%;
  334. height: 50px;
  335. border-radius: 15px 15px 0 0;
  336. background: #fff;
  337. display: flex;
  338. align-items: center;
  339. justify-content: space-between;
  340. box-sizing: border-box;
  341. padding: 0 20px;
  342. }
  343. .b_head > span {
  344. font-size: 18px;
  345. font-weight: bold;
  346. color: #000;
  347. }
  348. .b_head > img {
  349. width: 20px;
  350. height: 20px;
  351. cursor: pointer;
  352. }
  353. .b_main {
  354. width: 100%;
  355. height: calc(100% - 50px - 70px);
  356. background: #fafafa;
  357. padding: 20px 20px 0 20px;
  358. box-sizing: border-box;
  359. display: flex;
  360. align-items: center;
  361. justify-content: space-around;
  362. }
  363. .b_bottom {
  364. width: 100%;
  365. height: 70px;
  366. display: flex;
  367. align-items: center;
  368. justify-content: flex-end;
  369. box-sizing: border-box;
  370. padding: 0 20px;
  371. }
  372. .b_main > div {
  373. border-radius: 15px;
  374. width: 400px;
  375. height: 350px;
  376. box-sizing: border-box;
  377. border: rgba(150, 155, 163, 1) 1px dashed;
  378. }
  379. .b_m_left {
  380. background-color: #fff;
  381. }
  382. .b_m_l_noFile {
  383. width: 100%;
  384. height: 100%;
  385. display: flex;
  386. flex-direction: column;
  387. align-items: center;
  388. justify-content: center;
  389. cursor: pointer;
  390. }
  391. .b_m_l_noFile > img {
  392. width: 140px;
  393. height: 140px;
  394. }
  395. .b_m_l_noFile > span {
  396. font-size: 16px;
  397. color: #000;
  398. }
  399. .b_m_right {
  400. box-sizing: border-box;
  401. padding: 20px;
  402. }
  403. .b_m_right > span {
  404. font-size: 18px;
  405. font-weight: bold;
  406. color: #000;
  407. }
  408. .b_m_right > div {
  409. margin-top: 20px;
  410. font-size: 16px;
  411. color: #000;
  412. }
  413. .b_m_l_fileList {
  414. width: 100%;
  415. height: 100%;
  416. display: flex;
  417. flex-direction: column;
  418. overflow: auto;
  419. box-sizing: border-box;
  420. padding: 5px 10px;
  421. }
  422. .fl_item {
  423. width: 100%;
  424. height: 60px;
  425. margin: 5px 0;
  426. display: flex;
  427. justify-content: space-between;
  428. align-items: center;
  429. }
  430. .fl_i_left {
  431. width: 50px;
  432. height: 100%;
  433. display: flex;
  434. align-items: center;
  435. justify-content: center;
  436. }
  437. .fl_i_left > img {
  438. width: 80%;
  439. height: 80%;
  440. }
  441. .fl_i_center {
  442. width: calc(100% - 90px);
  443. height: 100%;
  444. }
  445. .fl_i_right {
  446. width: 40px;
  447. height: 100%;
  448. display: flex;
  449. align-items: center;
  450. justify-content: center;
  451. }
  452. .fl_i_right > img {
  453. width: 25px;
  454. height: 25px;
  455. cursor: pointer;
  456. }
  457. .fl_i_c_top {
  458. width: 100%;
  459. display: flex;
  460. align-items: center;
  461. height: 50%;
  462. justify-content: space-between;
  463. }
  464. .fl_i_c_top > span {
  465. max-width: calc(100% - 100px);
  466. display: block;
  467. align-items: center;
  468. overflow: hidden;
  469. text-overflow: ellipsis;
  470. white-space: nowrap;
  471. }
  472. .fl_i_c_top > div {
  473. width: 100px;
  474. display: flex;
  475. justify-content: flex-end;
  476. font-size: 14px;
  477. }
  478. .fl_i_c_bottom {
  479. width: 100%;
  480. height: 50%;
  481. display: flex;
  482. align-items: center;
  483. }
  484. .f_i_c_progress {
  485. width: 100%;
  486. height: 6px;
  487. background-color: rgba(217, 217, 217, 1);
  488. border-radius: 5px;
  489. overflow: hidden;
  490. }
  491. .f_i_c_p_value {
  492. height: 100%;
  493. }
  494. .successText {
  495. color: rgba(188, 230, 133, 1);
  496. }
  497. .successProgress {
  498. background-color: rgba(188, 230, 133, 1);
  499. }
  500. .uploadingText {
  501. color: rgba(54, 129, 252, 1);
  502. }
  503. .uploadingProgress {
  504. background-color: rgba(54, 129, 252, 1);
  505. }
  506. </style>