instupdata.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. <template>
  2. <div style="width: 100%; height: 100%; padding: 10px; box-sizing: border-box" v-loading="loading">
  3. <div class="intPage">
  4. <div class="tit">H5页面说明上传后台</div>
  5. <div>
  6. <div>请选择ai探究中心课程</div>
  7. <el-select v-model="id" @change="cutCourse" placeholder="请选择">
  8. <el-option
  9. v-for="item in courseList"
  10. :key="item.id"
  11. :label="item.name"
  12. :value="item.id">
  13. </el-option>
  14. </el-select>
  15. <!-- <el-input v-model.trim="id" placeholder="请输入内容"></el-input> -->
  16. </div>
  17. <div>
  18. <div>请输入使用说明</div>
  19. <editor-bar
  20. class="addEditor"
  21. style="margin: 0"
  22. placeholder="请输入"
  23. v-model="inData.content"
  24. @change="change"
  25. ></editor-bar>
  26. </div>
  27. <div>
  28. <div>请上传附件(只能上传pdf)</div>
  29. <button style="position: relative;padding: 1px 10px;box-sizing: border-box;">
  30. 上传
  31. <input
  32. type="file"
  33. accept="PDF"
  34. style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;opacity: 0;"
  35. multiple="multiple"
  36. @change="beforeUpload1($event)"
  37. />
  38. </button>
  39. </div>
  40. <div style="display: flex;flex-direction: column;gap: 10px;">
  41. <div style="display: flex;gap: 30px;" v-for="(i,ind) in inData.file" :key="ind">
  42. <span>{{ i.name }}</span>
  43. <span style="color: red;cursor: pointer;" @click="delFile(ind)">删除</span>
  44. </div>
  45. </div>
  46. <div>
  47. <el-button type="primary" @click="uploadCon">提交</el-button>
  48. </div>
  49. </div>
  50. </div>
  51. </template>
  52. <script>
  53. import EditorBar from "./wangEnduit";
  54. import { addOp, updateinst,selectAiExp } from "@/api/user";
  55. import { mapGetters } from "vuex";
  56. export default {
  57. name: "instUpdata",
  58. computed: {
  59. ...mapGetters(["userid"])
  60. },
  61. components:{
  62. EditorBar
  63. },
  64. data() {
  65. return {
  66. id: "",
  67. inData: {
  68. userid: this.userid,
  69. content: "",
  70. file: [],
  71. },
  72. loading:false,
  73. courseList:[],
  74. progress: 0,
  75. proVisible: false,
  76. };
  77. },
  78. mounted(){
  79. this.getData()
  80. },
  81. methods: {
  82. cutCourse(val){
  83. console.log('val',val);
  84. this.inData = {
  85. userid: this.userid,
  86. content: "",
  87. file: [],
  88. }
  89. let data = this.courseList.filter(e=> e.id == val)[0]
  90. console.log('data',data);
  91. if (data.inst) {
  92. this.inData.content = JSON.parse(data.inst).content
  93. this.inData.file = JSON.parse(data.inst).file
  94. }
  95. },
  96. getData(){
  97. this.loading = true;
  98. let params = {
  99. cl:1
  100. };
  101. selectAiExp(params)
  102. .then(async (res) => {
  103. console.log(res);
  104. this.courseList = res.data[1]
  105. this.loading = false;
  106. })
  107. .catch((error) => {
  108. this.loading = false;
  109. console.error("请求失败,错误信息:", error);
  110. });
  111. },
  112. change(val) {
  113. // this.$forceUpdate();
  114. console.log(val);
  115. },
  116. delFile(ind){
  117. this.inData.file.splice(ind,1)
  118. },
  119. addImg(e) {
  120. var el = e.currentTarget;
  121. console.log(el);
  122. el.getElementsByTagName("input")[0].click();
  123. e.target.value = "";
  124. },
  125. uploadCon() {
  126. if (!this.id) return this.$message.error("上传课程id");
  127. let params = {
  128. idL: this.id,
  129. con: JSON.stringify(this.inData),
  130. };
  131. console.log("params", params);
  132. updateinst(params)
  133. .then(async (response) => {
  134. if (response) {
  135. console.log("response", response);
  136. await addOp({
  137. uid: this.userid,
  138. cid: "",
  139. type: "user_op",
  140. content: `修改了${this.id}课程说明`,
  141. });
  142. this.$message({
  143. type: "success",
  144. message: "修改成功",
  145. });
  146. this.getData()
  147. this.id = "";
  148. this.inData = {
  149. userid: this.userid,
  150. content: "",
  151. file: [],
  152. };
  153. }
  154. })
  155. .catch((error) => {
  156. console.error("请求失败,错误信息:", error);
  157. });
  158. },
  159. beforeUpload(event) {
  160. // const loading = this.openLoading();
  161. // var file = "";
  162. // for (let cfindex = 0; cfindex < event.target.files.length; cfindex++) {
  163. console.log("event.target.files", event.target.files);
  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 imgA = [
  173. "png",
  174. "jpg",
  175. "jpeg",
  176. "bmp",
  177. "gif",
  178. "webp",
  179. "psd",
  180. "svg",
  181. "tiff",
  182. ];
  183. if (
  184. imgA.indexOf(file.name.split(".")[file.name.split(".").length - 1]) ==
  185. -1
  186. ) {
  187. this.$message.error("图片格式错误");
  188. return;
  189. }
  190. // this.imgLoading = true;
  191. var _this = this;
  192. // this.inputShow = false;
  193. // this.progress = 0;
  194. this.proVisible = true;
  195. // this.isFinishSize = 0;
  196. // this.isAllSize = (file.size / 1024 / 1024).toFixed(2);
  197. _this.$forceUpdate();
  198. if (file) {
  199. var params = {
  200. Key:
  201. file.name.split(".")[0] +
  202. new Date().getTime() +
  203. "." +
  204. file.name.split(".")[file.name.split(".").length - 1],
  205. ContentType: file.type,
  206. Body: file,
  207. "Access-Control-Allow-Credentials": "*",
  208. ACL: "public-read",
  209. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  210. var options = {
  211. partSize: 2048 * 1024 * 1024,
  212. queueSize: 2,
  213. leavePartsOnError: true,
  214. };
  215. bucket
  216. .upload(params, options)
  217. .on("httpUploadProgress", function () {
  218. //这里可以写进度条
  219. // _this.progress = parseInt((evt.loaded / evt.total) * 100);
  220. // _this.isFinishSize = (evt.loaded / 1024 / 1024).toFixed(2);
  221. _this.$forceUpdate();
  222. })
  223. .send(function (err, data) {
  224. // _this.imgLoading = false;
  225. // loading.close();
  226. // _this.progress = 100;
  227. // _this.isFinishSize = _this.isAllSize;
  228. _this.$forceUpdate();
  229. setTimeout(() => {
  230. _this.proVisible = false;
  231. _this.$forceUpdate();
  232. }, 1000);
  233. // _this.inputShow = true;
  234. if (err) {
  235. _this.$message.error("上传失败");
  236. } else {
  237. let quill = _this.$refs.myQuillEditor.quill;
  238. // 如果上传成功
  239. let length = quill.getSelection().index;
  240. // 插入图片 res.url为服务器返回的图片地址
  241. quill.insertEmbed(length, "image", data.Location);
  242. // 调整光标到最后
  243. quill.setSelection(length + 1);
  244. // if (!res) {
  245. // // 获取光标所在位置
  246. // } else {
  247. // this.$message.error("图片插入失败");
  248. // }
  249. // loading动画消失
  250. this.quillUpdateImg = false;
  251. // _this.recordData.recordImg.push(data.Location);
  252. _this.$forceUpdate();
  253. // console.log(_this.checkJson);
  254. // console.log(data.Location);
  255. }
  256. });
  257. }
  258. // }
  259. // var file = event.target.files[0];
  260. },
  261. onEditorChange({ html }) {
  262. //内容改变事件
  263. // console.log("---内容改变事件---");
  264. this.inData.content = html;
  265. // console.log(html);
  266. },
  267. async beforeUpload1(event) {
  268. var files = Array.from(event.target.files);
  269. console.log("上传文件列表:", files);
  270. if (files.length === 0) {
  271. this.$message.warning("请选择文件");
  272. return;
  273. }
  274. // 检查文件格式
  275. var photoA = ["PDF"];
  276. var invalidFiles = files.filter((file) => {
  277. var extension = file.name.split(".")[file.name.split(".").length - 1].toLocaleUpperCase();
  278. return photoA.indexOf(extension) === -1;
  279. });
  280. if (invalidFiles.length > 0) {
  281. this.$message.error("请只上传PDF格式文件!");
  282. return;
  283. }
  284. // AWS配置
  285. var credentials = {
  286. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  287. secretAccessKey: "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",
  288. };
  289. window.AWS.config.update(credentials);
  290. window.AWS.config.region = "cn-northwest-1";
  291. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } });
  292. var _this = this;
  293. var uploadedCount = 0;
  294. var failedFiles = [];
  295. // 顺序上传每个文件
  296. for (let i = 0; i < files.length; i++) {
  297. let file = files[i];
  298. try {
  299. var result = await new Promise((resolve, reject) => {
  300. var params = {
  301. Key:
  302. file.name.split(".")[0] +
  303. new Date().getTime() +
  304. "_" +
  305. i + // 添加索引避免重复
  306. "." +
  307. file.name.split(".")[file.name.split(".").length - 1],
  308. ContentType: file.type,
  309. Body: file,
  310. "Access-Control-Allow-Credentials": "*",
  311. ACL: "public-read",
  312. };
  313. var options = {
  314. partSize: 1024 * 1024 * 1024,
  315. queueSize: 2,
  316. leavePartsOnError: true,
  317. };
  318. bucket
  319. .upload(params, options)
  320. .on("httpUploadProgress", function (progress) {
  321. // 显示单个文件的上传进度
  322. console.log(
  323. `文件 ${file.name} 上传进度: ${(
  324. (progress.loaded / progress.total) *
  325. 100
  326. ).toFixed(2)}%`
  327. );
  328. })
  329. .send(function (err, data) {
  330. if (err) {
  331. reject(err);
  332. } else {
  333. resolve(data);
  334. }
  335. });
  336. });
  337. console.log('result',result);
  338. _this.inData.file.push({
  339. name:files[i].name,
  340. url:result.Location,
  341. });
  342. uploadedCount++;
  343. console.log(`文件 ${file.name} 上传成功:`, result.Location);
  344. } catch (error) {
  345. console.error(`文件 ${file.name} 上传失败:`, error);
  346. failedFiles.push({
  347. fileName: file.name,
  348. error: error.message,
  349. });
  350. }
  351. }
  352. // 显示最终结果
  353. if (uploadedCount > 0) {
  354. this.$message.success(`成功上传 ${uploadedCount} 个文件`);
  355. }
  356. if (failedFiles.length > 0) {
  357. this.$message.error(`${failedFiles.length} 个文件上传失败`);
  358. console.error("失败的文件:", failedFiles);
  359. }
  360. },
  361. },
  362. };
  363. </script>
  364. <style scoped>
  365. .intPage {
  366. display: flex;
  367. flex-direction: column;
  368. gap: 15px;
  369. padding: 20px 10%;
  370. box-sizing: border-box;
  371. width: 100%;
  372. height: 100%;
  373. overflow: auto;
  374. background: #fff;
  375. border-radius: 8px;
  376. }
  377. .tit {
  378. font-size: 25px;
  379. font-weight: 600;
  380. text-align: center;
  381. }
  382. .editer {
  383. width: 100%;
  384. }
  385. .editer >>> .ql-align-center {
  386. text-align: center !important;
  387. }
  388. .editer >>> .ql-editor {
  389. height: 300px;
  390. }
  391. /* .editer >>> .el-picker-panel__icon-btn {
  392. button {
  393. padding: 10px 20px !important;
  394. }
  395. } */
  396. .avatar-uploader {
  397. opacity: 0;
  398. height: 0;
  399. margin: 0 20px;
  400. }
  401. .avatar-uploader .el-upload {
  402. border: 1px dashed #d9d9d9;
  403. border-radius: 6px;
  404. cursor: pointer;
  405. position: relative;
  406. overflow: hidden;
  407. }
  408. .avatar-uploader .el-upload:hover {
  409. border-color: #409eff;
  410. }
  411. .avatar-uploader-icon {
  412. font-size: 28px;
  413. color: #8c939d;
  414. width: 178px;
  415. height: 178px;
  416. line-height: 178px;
  417. text-align: center;
  418. }
  419. .addEditor >>> .text {
  420. height: auto;
  421. min-height: 200px;
  422. }
  423. .addEditor >>> .w-e-text-container {
  424. min-height: 100px;
  425. }
  426. </style>