index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <template>
  2. <div class="upload-file">
  3. <el-upload
  4. multiple
  5. v-if="isShowUploadBtn"
  6. :action="uploadFileUrl"
  7. :before-upload="handleBeforeUpload"
  8. :on-error="uploadedSuccessfully"
  9. :on-success="handleUploadSuccess"
  10. :file-list="fileList"
  11. :limit="limit"
  12. :accept="accept"
  13. :http-request="uploadFile"
  14. :show-file-list="true"
  15. :on-remove="handleDelete"
  16. :on-exceed="handleExceed"
  17. :on-preview="onPreview"
  18. :before-remove="beforeRemove"
  19. :headers="headers"
  20. class="upload-file-uploader"
  21. ref="fileUpload"
  22. >
  23. <el-button size="small" type="primary" v-if="showTip">点击上传</el-button>
  24. <!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> -->
  25. <!-- <i class="el-icon-upload"></i> -->
  26. <!-- 上传按钮 -->
  27. <!-- <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> -->
  28. <!-- <el-button size="mini" type="primary">{{ btnName }}</el-button> -->
  29. <!-- 上传提示 -->
  30. <div class="el-upload__tip" slot="tip" v-if="showTip">
  31. 文件<template v-if="fileSize"
  32. >大小不超过<b style="color: #f56c6c">{{ fileSize }}MB</b></template
  33. >
  34. <template v-if="fileType">
  35. 格式为<b style="color: #f56c6c">{{ fileType.join("/") }}</b></template
  36. >
  37. 的文件
  38. </div>
  39. </el-upload>
  40. <!-- 详情页面显示列表 -->
  41. <transition-group
  42. v-if="!isShowUploadBtn"
  43. class="upload-file-list el-upload-list el-upload-list--text"
  44. name="el-fade-in-linear"
  45. tag="ul"
  46. >
  47. <li
  48. :key="file.url"
  49. class="el-upload-list__item ele-upload-list__item-content"
  50. v-for="file in fileList"
  51. >
  52. <div v-if="showHow(file.url)">
  53. <el-image
  54. style="width: 100px; height: 100px"
  55. :src="file.url"
  56. fit="fit"
  57. :preview-src-list="getpreviewSrcList(file.url)">
  58. ></el-image>
  59. </div>
  60. <el-link v-else :href="file.url" :underline="false" target="_blank">
  61. <span class="el-icon-document"> {{ file.name }}</span>
  62. </el-link>
  63. </li>
  64. </transition-group>
  65. </div>
  66. </template>
  67. <script>
  68. import { getToken } from "@/utils/auth";
  69. import { upload } from "@/api/system/public";
  70. export default {
  71. name: "W-FileUpload",
  72. props: {
  73. // 值
  74. value: [String, Object, Array],
  75. defaultValue: [String, Object, Array],
  76. // 数量限制
  77. limit: {
  78. type: Number,
  79. default: 5,
  80. },
  81. // 大小限制(MB)
  82. fileSize: {
  83. type: Number,
  84. default: 20,
  85. },
  86. // 文件类型, 例如['png', 'jpg', 'jpeg']
  87. fileType: {
  88. type: Array,
  89. default: () => ["pdf", "jpg", "png", "bmp", "zip", "rar", "7z"],
  90. },
  91. // 是否显示提示
  92. isShowTip: {
  93. type: Boolean,
  94. default: true,
  95. },
  96. isRem: {
  97. type: Boolean,
  98. default: true,
  99. },
  100. showBut: {
  101. type: Boolean,
  102. default: true,
  103. },
  104. // 是否文件上传按钮或者拖拽框
  105. isShowUploadBtn: {
  106. type: Boolean,
  107. default: true,
  108. },
  109. btnName: {
  110. type: String,
  111. default: "选取文件",
  112. },
  113. },
  114. data() {
  115. return {
  116. number: 0,
  117. uploadList: [],
  118. uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传文件服务器地址
  119. headers: {
  120. Authorization: "Bearer " + getToken(),
  121. },
  122. fileList: [],
  123. fileValueList: [],
  124. accept: this.getAcceptByFileType(), //".pdf,.jpg,.png,.bmp",
  125. };
  126. },
  127. watch: {
  128. defaultValue: {
  129. handler(val) {
  130. if (val) {
  131. let temp = 1;
  132. // this.fileList=val;
  133. // 首先将值转为数组
  134. const list = Array.isArray(val) ? val : this.value.split(",");
  135. // console.log("watch fileList", list);
  136. if (list.length > this.limit) {
  137. this.handleExceed();
  138. return;
  139. }
  140. // 然后将数组转为对象数组
  141. this.fileList = list.map((item) => {
  142. if (typeof item === "string") {
  143. // console.log("watch fileList item", item)
  144. let itemObj = JSON.parse(item);
  145. // console.log("watch fileList itemObj", itemObj)
  146. if ("name" in itemObj && "url" in itemObj) {
  147. item = itemObj;
  148. } else {
  149. item = { name: item, url: item };
  150. }
  151. }
  152. item.uid = item.uid || new Date().getTime() + temp++;
  153. return item;
  154. });
  155. this.fileValueList = [...this.fileList];
  156. this.$emit("input", this.listToTagObj(this.fileValueList));
  157. } else {
  158. this.fileList = [];
  159. this.fileValueList = [];
  160. return [];
  161. }
  162. },
  163. deep: true,
  164. immediate: true,
  165. },
  166. value: {
  167. handler(val) {},
  168. deep: true,
  169. immediate: true,
  170. },
  171. },
  172. computed: {
  173. // 是否显示提示
  174. showTip() {
  175. return this.isShowTip && (this.fileType || this.fileSize);
  176. },
  177. },
  178. methods: {
  179. beforeRemove(file, fileList) {
  180. if (this.isRem) {
  181. return true;
  182. }
  183. // 返回 false 可以阻止删除操作
  184. return false;
  185. },
  186. showHow(url) {
  187. // console.log(url, "sss");
  188. if (url.endsWith("jpg") || url.endsWith("png") || url.endsWith("bmp")) {
  189. return true;
  190. }
  191. return false;
  192. },
  193. getpreviewSrcList(url)
  194. {
  195. return [url];
  196. },
  197. getAcceptByFileType() {
  198. if (this.fileType) {
  199. let arr = this.fileType.map((x) => "." + x);
  200. return arr.join(",");
  201. }
  202. return "";
  203. },
  204. // 上传前校检格式和大小
  205. handleBeforeUpload(file) {
  206. // 校检文件类型
  207. if (this.fileType) {
  208. const fileName = file.name.split(".");
  209. const fileExt = fileName[fileName.length - 1];
  210. const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
  211. if (!isTypeOk) {
  212. this.$modal.msgError(
  213. `文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`
  214. );
  215. return false;
  216. }
  217. }
  218. // 校检文件大小
  219. if (this.fileSize) {
  220. const isLt = file.size / 1024 / 1024 < this.fileSize;
  221. if (!isLt) {
  222. this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
  223. return false;
  224. }
  225. }
  226. if (this.fileList.findIndex((x) => x.name == file.name) > -1) {
  227. console.log(this.fileList, "this.fileListwww");
  228. this.$modal.msgError(`不能上传相同名称的文件或图片!`);
  229. return false;
  230. }
  231. this.$modal.loading("正在上传文件,请稍候...");
  232. this.number++;
  233. return true;
  234. },
  235. // 文件个数超出
  236. handleExceed() {
  237. this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
  238. },
  239. // 上传失败
  240. handleUploadError(err) {
  241. this.$modal.msgError("上传文件失败,请重试");
  242. this.$modal.closeLoading();
  243. },
  244. // 上传成功回调
  245. handleUploadSuccess(res, file, fileList) {
  246. // console.log("handleUploadSuccess", res, file, fileList);
  247. this.fileList = fileList;
  248. // console.log(this.fileList,"this.fileList")
  249. this.$emit("input", this.listToTagObj(this.fileValueList));
  250. },
  251. // 删除文件
  252. handleDelete(item) {
  253. if (item && item.status === "success") {
  254. // console.log("handleDelete1 index", item);
  255. //this.fileList.splice(item, 1);
  256. // console.log("handleDelete2", item, this.fileValueList);
  257. let index = this.fileValueList.findIndex((x) => x.name == item.name);
  258. // console.log("handleDelete3", index, this.fileValueList);
  259. if (index > -1) {
  260. this.fileValueList.splice(index, 1);
  261. }
  262. //this.fileValueList.splice(item, 1);
  263. // console.log("handleDelete4 deleted", this.fileValueList);
  264. this.fileList = this.listToTagObj(this.fileValueList);
  265. this.$emit("input", this.listToTagObj(this.fileValueList));
  266. }
  267. },
  268. // 上传失败结束处理 必须调用,否则失败文件也会显示
  269. uploadedSuccessfully(err, file, fileList) {},
  270. // 获取文件名称
  271. getFileName(name) {
  272. // 将字符串的 JSON 转换为对象
  273. const fileObj = JSON.parse(name);
  274. // 返回 name 属性
  275. return fileObj.name;
  276. },
  277. // 获取文件url
  278. getFileUrl(name) {
  279. // 将字符串的 JSON 转换为对象
  280. const fileObj = JSON.parse(name);
  281. // 返回 name 属性
  282. return fileObj.url;
  283. },
  284. //自定义上传方式(自带的成功回调及失败回调会失效)
  285. uploadFile(fileObj) {
  286. let formData = new FormData();
  287. formData.append("file", fileObj.file);
  288. // console.log("this.fileValueList.length", this.fileValueList.length);
  289. if (this.fileValueList.length <= this.limit) {
  290. upload(formData)
  291. .then((res) => {
  292. /*上传成功*/
  293. this.$modal.closeLoading();
  294. //let imgUrl = process.env.VUE_APP_BASE_API + res.data.url;
  295. let arr = [];
  296. arr.push({ name: res.data.realName, url: res.data.url });
  297. this.fileValueList = this.fileValueList.concat(arr);
  298. this.$modal.msgSuccess("上传成功!");
  299. fileObj.onSuccess();
  300. this.$emit("success", );
  301. })
  302. .catch((err) => {
  303. /*上传失败*/
  304. this.$modal.closeLoading();
  305. fileObj.onError();
  306. this.$emit("success", );
  307. });
  308. }
  309. },
  310. // 对象转成指定字符串分隔
  311. listToString(list, separator) {
  312. let strs = "";
  313. separator = separator || ",";
  314. for (let i in list) {
  315. strs += list[i].url + separator;
  316. }
  317. return strs != "" ? strs.substring(0, strs.length - 1) : "";
  318. },
  319. listToTagObj(list) {
  320. let tempArry = [];
  321. for (let i in list) {
  322. // console.log("listToString2 i",i);
  323. tempArry.push({ url: list[i].url, name: list[i].name });
  324. }
  325. console.log("fileList", tempArry);
  326. return tempArry;
  327. },
  328. onPreview(file) {
  329. // console.log(file);
  330. var name = file.name;
  331. let index = this.fileValueList.findIndex((x) => x.name == file.name);
  332. this.fileValueList[index];
  333. var url = this.fileValueList[index].url;
  334. if (process.env.VUE_APP_BASE_API !== "/") {
  335. url = process.env.VUE_APP_BASE_API + this.fileValueList[index].url;
  336. }
  337. // console.log("process.env.VUE_APP_BASE_API",process.env.VUE_APP_BASE_API,process)
  338. // console.log("process.env.VUE_APP_BASE_API url",url)
  339. const a = document.createElement("a");
  340. a.setAttribute("download", name);
  341. a.setAttribute("target", "_blank");
  342. a.setAttribute("href", url);
  343. a.click();
  344. },
  345. clearFiles() {
  346. if (this.$refs["fileUpload"]) this.$refs["fileUpload"].clearFiles();
  347. this.fileList = [];
  348. this.fileValueList = [];
  349. },
  350. },
  351. };
  352. </script>
  353. <style scoped lang="scss">
  354. .upload-file-uploader {
  355. margin-bottom: 5px;
  356. }
  357. .el-upload-list__item {
  358. transition: none !important;
  359. }
  360. .upload-file-list .el-upload-list__item {
  361. // border: 1px solid #e4e7ed;
  362. // line-height: 2;
  363. // margin-bottom: 5px;
  364. position: relative;
  365. }
  366. .upload-file-list .ele-upload-list__item-content {
  367. display: flex;
  368. justify-content: space-between;
  369. align-items: center;
  370. color: inherit;
  371. }
  372. .ele-upload-list__item-content-action .el-link {
  373. margin-right: 10px;
  374. }
  375. </style>