UploadFile.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <div>
  3. <div style="display: flex">
  4. <Input class="upload-input" :value="fileUrls" disabled />
  5. <BasicUpload
  6. :maxSize="20"
  7. :maxNumber="fileNum"
  8. @change="handleChange"
  9. :api="uploadApi"
  10. class="my-3"
  11. :accept="['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'xls', 'xlsx']"
  12. />
  13. <a-button
  14. @click="openChooseModal"
  15. style="position: relative; top: 12px; margin: 0 5px"
  16. type="danger"
  17. preIcon="ic:sharp-view-list"
  18. :iconSize="16"
  19. >
  20. 选择
  21. </a-button>
  22. <span class="tip-span" v-if="tipShow">{{ tip }}</span>
  23. </div>
  24. <div class="file-list" v-if="file_list.length">
  25. <div v-for="(item, index) in file_list" :key="index">
  26. <div class="file-item" v-if="item !== ''">
  27. <div class="file-wrap">
  28. <a-image v-if="isAssetTypeAnImage(item)" width="70px" :src="imgUrlPrefix + item" />
  29. <a
  30. v-if="!isAssetTypeAnImage(item)"
  31. :href="imgUrlPrefix + item"
  32. :download="getFilename(item)"
  33. ><i class="fa fa-file file-font" aria-hidden="true"></i
  34. ></a>
  35. </div>
  36. <div class="dele-file" @click="deleteFile(item, index)">
  37. <Icon icon="ri:delete-bin-5-fill" />
  38. </div>
  39. </div>
  40. </div>
  41. </div>
  42. <ChooseModal :type="type" @register="chooseModalRegister" @checked="checked" />
  43. </div>
  44. </template>
  45. <script lang="ts">
  46. import { defineComponent, watch, reactive, toRefs, ref } from 'vue';
  47. import { BasicUpload } from '/@/components/Upload';
  48. // import { useMessage } from '/@/hooks/web/useMessage';
  49. import { uploadApi } from '/@/api/sys/upload';
  50. import ChooseModal from './ChooseModal.vue';
  51. import { useGlobSetting } from '/@/hooks/setting';
  52. import { useModal } from '/@/components/Modal';
  53. import { Image, Input } from 'ant-design-vue';
  54. import Icon from '/@/components/Icon';
  55. const props = {
  56. value: { type: String, default: '' },
  57. tip: { type: String, default: '' },
  58. type: { type: String, default: '' },
  59. errMsg: { type: String, default: '' },
  60. rules: { type: Array, default: [] },
  61. };
  62. interface PropsType {
  63. value: string;
  64. tip: string;
  65. type: string;
  66. errMsg: string;
  67. rules: [];
  68. }
  69. export default defineComponent({
  70. components: { BasicUpload, ChooseModal, aImage: Image, Input, Icon },
  71. props,
  72. emits: ['change'],
  73. setup(props, { emit }) {
  74. // const { createMessage } = useMessage();
  75. const fileNum = ref(1);
  76. if (props.type === 'files') {
  77. fileNum.value = 10;
  78. }
  79. const { imgUrlPrefix } = useGlobSetting();
  80. const [chooseModalRegister, { openModal }] = useModal();
  81. function openChooseModal() {
  82. openModal(true);
  83. }
  84. const state = reactive({
  85. fileUrls: props.value,
  86. file_list: [] as string[],
  87. tipShow: false,
  88. });
  89. state.file_list = props.value.split(',');
  90. function deleteFile(url, index) {
  91. console.log(`url`, url);
  92. const arr = state.fileUrls.split(',');
  93. arr.splice(index, 1);
  94. state.fileUrls = arr.toString();
  95. emit('change', state.fileUrls);
  96. }
  97. function checked(files) {
  98. if (props.type === 'file') {
  99. state.fileUrls = files[0].url;
  100. } else {
  101. let urls: string[] = [];
  102. files.map((item) => {
  103. urls.push(item.url);
  104. });
  105. state.fileUrls += ',' + urls.toString();
  106. }
  107. emit('change', state.fileUrls);
  108. }
  109. watch(props, (props: PropsType) => {
  110. state.file_list = props.value.split(',');
  111. });
  112. function getFilename(filePath) {
  113. //获取最后一个\的位置
  114. const index = filePath.lastIndexOf('\\');
  115. //获取后缀
  116. const filename = filePath.substr(index + 1);
  117. return filename;
  118. }
  119. function isAssetTypeAnImage(filePath) {
  120. //获取最后一个.的位置
  121. const index = filePath.lastIndexOf('.');
  122. //获取后缀
  123. const ext = filePath.substr(index + 1);
  124. return (
  125. ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'].indexOf(
  126. ext.toLowerCase()
  127. ) !== -1
  128. );
  129. }
  130. return {
  131. handleChange: (list: string[]) => {
  132. if (props.type === 'file') {
  133. state.fileUrls = list[0];
  134. } else {
  135. state.fileUrls = list.toString();
  136. }
  137. emit('change', state.fileUrls);
  138. },
  139. checked,
  140. fileNum,
  141. imgUrlPrefix,
  142. getFilename,
  143. isAssetTypeAnImage,
  144. openChooseModal,
  145. deleteFile,
  146. uploadApi,
  147. chooseModalRegister,
  148. openModal,
  149. ...toRefs(props),
  150. ...toRefs(state),
  151. };
  152. },
  153. });
  154. </script>
  155. <style scoped>
  156. .upload-input {
  157. position: relative;
  158. top: 11px;
  159. width: 45%;
  160. height: 34px;
  161. margin-right: 5px;
  162. }
  163. .file-list {
  164. display: flex;
  165. flex-wrap: wrap;
  166. width: 70%;
  167. }
  168. .file-item {
  169. width: 120px;
  170. margin: 0 5px;
  171. text-align: center;
  172. }
  173. .file-wrap {
  174. display: flex;
  175. align-items: center;
  176. justify-content: space-around;
  177. width: 100%;
  178. height: 80px;
  179. border: 1px solid #ddd;
  180. border-radius: 2px;
  181. }
  182. .file-font {
  183. font-size: 60px;
  184. }
  185. .dele-file {
  186. height: 20px;
  187. margin: 8px 0;
  188. color: #fff;
  189. background: #e74c3c;
  190. border-radius: 2px;
  191. }
  192. .tip-span {
  193. position: relative;
  194. top: 11px;
  195. font-size: 13px;
  196. line-height: 250%;
  197. color: gray;
  198. }
  199. </style>