upload-image.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <div class="upload-video">
  3. <div class="upload-box">
  4. <input
  5. class="upload-input"
  6. ref="chooseFile"
  7. type="file"
  8. @change="addFile"
  9. multiple
  10. accept=".jpg,.png"
  11. />
  12. <i class="iconfont icon-empty"></i>
  13. <p>点击或将文件拖拽到这里上传</p>
  14. <p class="gray-font">
  15. 建议最佳:横版大图:宽高比16:9,1280*720≤尺寸≤2560*1440,
  16. </p>
  17. <p class="gray-font">竖版大图:宽高比9:16,720*1280≤尺寸≤1440*2560,</p>
  18. <p class="gray-font">小图:宽高比1.52,456*300≤尺寸≤1368*900,</p>
  19. <p class="gray-font">
  20. 支持JPG,PNG等图片格式。命名格式:推广书籍名称-需求方-文案
  21. </p>
  22. </div>
  23. <div class="upload-list">
  24. <div class="list-item" v-for="(item, index) in fileList" :key="index">
  25. <i class="iconfont icon-paper-clip"></i>
  26. <p>
  27. {{ item.name }}
  28. <i class="iconfont icon-guanbi" @click="deleteItem(index)"></i
  29. ><a-progress
  30. :showInfo="false"
  31. :percent="item.percent"
  32. status="active"
  33. />
  34. </p>
  35. </div>
  36. </div>
  37. <p class="gray-font footer-num">已选择:{{ fileList.length }}/20</p>
  38. </div>
  39. </template>
  40. <script lang="ts">
  41. import { defineComponent, reactive, toRefs, ref } from "vue";
  42. import { uploadImage } from "@/api";
  43. import { message, Progress } from "ant-design-vue";
  44. const UploadVideo = defineComponent({
  45. components: {},
  46. props: ["searchForm"],
  47. setup() {
  48. const formRef = ref();
  49. const state = reactive({
  50. fileList: ref<any[]>([]),
  51. });
  52. return { ...toRefs(state) };
  53. },
  54. mounted() {},
  55. methods: {
  56. // 选择视频后
  57. addFile(event: any) {
  58. event.target.files.forEach((item: any) => {
  59. this.getImgInfo(item).then((imgInfo: any) => {
  60. let { width, height } = imgInfo;
  61. // 校验文件尺寸大小比例
  62. // if (
  63. // height / width !== 16 / 9 &&
  64. // height / width !== 9 / 16 &&
  65. // height / width !== 1.52 &&
  66. // width / height !== 1.52
  67. // )
  68. // return message.warning(
  69. // `图片:${item.name} 宽高比例不符合要求比例,请修改后重新上传`
  70. // );
  71. if (height > 1368 || width > 1368)
  72. return message.warning(
  73. `图片:${item.name} 尺寸不符合要求尺寸,请修改后重新上传`
  74. );
  75. // 正则 /^[\u4E00-\u9FA5A-Za-z0-9]+(-|\/)[\u4E00-\u9FA5A-Za-z0-9]+(-|\/)[\u4E00-\u9FA5A-Za-z0-9]+$/ XX-XX-XX
  76. if (this.checkNumber(item.name) !== 2)
  77. return message.warning(
  78. `图片:${item.name} 不符合命名要求,请修改后重新上传`
  79. );
  80. this.fileList.push({
  81. file: item,
  82. name: item.name,
  83. percent: 0,
  84. materialSize: (item.size / 1024 / 1024).toFixed(2) + "MB",
  85. type: item.type.split("/")[0],
  86. width: width,
  87. height: height,
  88. });
  89. });
  90. });
  91. console.log("新增文件列表", this.fileList);
  92. },
  93. // 确定上传图片
  94. async onUploadImage() {
  95. if (this.fileList.length === 0) return message.warning("请选择图片");
  96. this.$emit("close");
  97. message.info("素材上传中...");
  98. let num = 0;
  99. if (this.fileList.length === 0) return message.error("请选择图片");
  100. this.fileList.forEach((item) => {
  101. let form: any = new FormData();
  102. form.append("is_public", this.$props.searchForm.is_public);
  103. form.append("image", item.file); //,item.name
  104. uploadImage(form)
  105. .catch((err) => {
  106. console.log("ERR", err);
  107. })
  108. .finally(() => {
  109. num++;
  110. console.log("NUM", num);
  111. if (num === this.fileList.length) message.success("素材上传完成");
  112. });
  113. });
  114. },
  115. // 获取图片宽高信息
  116. getImgInfo(file: any) {
  117. return new Promise((resolve, reject) => {
  118. let reader = new FileReader();
  119. reader.readAsDataURL(file); // 必须用file.raw
  120. reader.onload = () => {
  121. // 让页面中的img标签的src指向读取的路径
  122. let img: any = new Image();
  123. img.src = reader.result;
  124. img.onload = () => {
  125. resolve({
  126. width: img.width,
  127. height: img.height,
  128. });
  129. };
  130. };
  131. });
  132. },
  133. // 删除item
  134. deleteItem(index: number) {
  135. this.fileList.splice(index, 1);
  136. },
  137. // 工具函数 返回-出现在字符串中的次数
  138. checkNumber(str: string) {
  139. let num = 0;
  140. str.split("").forEach((item: any) => {
  141. if (item === "-") {
  142. num++;
  143. }
  144. });
  145. return num;
  146. },
  147. },
  148. });
  149. export default UploadVideo;
  150. </script>
  151. <style lang="scss" scoped>
  152. @import "@/assets/common-style/frame.scss";
  153. .upload-video {
  154. width: 100%;
  155. padding: 0 10%;
  156. .gray-font {
  157. color: gray;
  158. }
  159. .upload-box {
  160. cursor: pointer;
  161. background: rgb(250, 250, 250);
  162. border: 2px dashed rgb(212, 210, 210);
  163. border-radius: 6px;
  164. transition: all 0.3s;
  165. padding-bottom: 10px;
  166. position: relative;
  167. i {
  168. color: rgb(168, 167, 167);
  169. display: block;
  170. font-size: 60px;
  171. }
  172. i,
  173. p {
  174. text-align: center;
  175. transition: all 0.3s;
  176. }
  177. // 选择文件
  178. .upload-input {
  179. position: absolute;
  180. display: block;
  181. width: 100%;
  182. height: 100%;
  183. opacity: 0;
  184. cursor: pointer;
  185. }
  186. }
  187. .upload-box:hover {
  188. i,
  189. p {
  190. color: #39a4ff !important;
  191. }
  192. border-color: #39a4ff;
  193. }
  194. .upload-list {
  195. overflow: hidden;
  196. .list-item {
  197. margin-top: 10px;
  198. .icon-paper-clip {
  199. width: 14px;
  200. font-size: 12px;
  201. float: left;
  202. padding-top: 3px;
  203. }
  204. p {
  205. float: left;
  206. width: calc(100% - 14px);
  207. overflow: hidden;
  208. .icon-guanbi {
  209. display: block;
  210. float: right;
  211. font-size: 13px;
  212. cursor: pointer;
  213. &:hover {
  214. color: rgb(248, 10, 157);
  215. }
  216. }
  217. }
  218. }
  219. }
  220. .footer-num {
  221. position: relative;
  222. top: 56px;
  223. }
  224. }
  225. </style>