uploadModal.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <BasicModal
  3. v-bind="$attrs"
  4. @register="register"
  5. :title="fileFlow.title"
  6. @visible-change="handleVisibleChange"
  7. @cancel="resetFields"
  8. @ok="handleSubmit"
  9. :okText="loading ? `上传中 ${fileFlow.complete}%` : '确认'"
  10. :confirmLoading="loading"
  11. :min-height="250"
  12. :height="700"
  13. >
  14. <div class="pt-2px pr-3px myzdyfrmo">
  15. <BasicForm @register="registerForm" :model="model">
  16. <template #text="{ model, field }">
  17. {{ model[field] }}
  18. </template>
  19. <template #file="{ model, field }">
  20. <Upload
  21. :key="isAnimation"
  22. style="width: 300px"
  23. :disabled="!fileFlow.dictId"
  24. :accept="!isAnimation?'.jpg, .png, .jpeg, .mp4, .wav, .mp3, .shp, .zip':'.glb, .zip'"
  25. v-model:file-list="fileList"
  26. :beforeUpload="beforeUpload"
  27. @remove="handleRemove"
  28. >
  29. <a-button :disabled="!fileFlow.dictId"> 上传 </a-button>
  30. </Upload>
  31. </template>
  32. </BasicForm>
  33. <div style="padding: 0 0 0 82px" v-if="!isAnimation">
  34. <div style="margin-bottom: 10px"
  35. >支持jpg、png、jpeg、mp4、wav、mp3 、shp格式文件上传。文件大小 ≤ 2G</div
  36. >
  37. <!-- <span>注意:模型需使用zip包上传。包含贴图、模型、mtl文件,包内不得包含文件夹。</span> -->
  38. <div style="margin-bottom: 10px">
  39. <div>
  40. 上传
  41. obj:需使用zip包上传。包含贴图、模型、mtl文件,包内不得包含文件夹,文件名不得使用中文。如图:</div
  42. >
  43. <img style="width: 150px" :src="obj" alt="" />
  44. </div>
  45. <div style="margin-bottom: 10px">
  46. <div>
  47. 上传 osgb:需使用zip包上传。包含 Data 文件夹、xml
  48. 文件,包内不得包含文件夹,文件名不得使用中文。如图:</div
  49. >
  50. <img style="width: 150px" :src="osgb" alt="" />
  51. </div>
  52. </div>
  53. <div v-else style="padding: 0 0 0 82px">
  54. <div style="margin-bottom: 10px"
  55. >支持obj、glb格式文件上传。文件大小 ≤ 5MB</div
  56. >
  57. <!-- <span>注意:模型需使用zip包上传。包含贴图、模型、mtl文件,包内不得包含文件夹。</span> -->
  58. <div style="margin-bottom: 10px">
  59. <div>
  60. 上传
  61. obj:需使用zip包上传。包含贴图、模型、mtl文件,包内不得包含文件夹,文件名不得使用中文。如图:</div
  62. >
  63. <img style="width: 150px" :src="obj" alt="" />
  64. </div>
  65. </div>
  66. </div>
  67. </BasicModal>
  68. </template>
  69. <script lang="ts">
  70. import { defineComponent, ref, nextTick, onMounted, reactive, unref } from 'vue';
  71. import { Upload } from 'ant-design-vue';
  72. import { BasicModal, useModalInner } from '/@/components/Modal';
  73. import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
  74. import { useMessage } from '/@/hooks/web/useMessage';
  75. import { addOrUpdate, uploadApi, getByKey } from '/@/api/media';
  76. import obj from '/@/assets/images/obj.jpg';
  77. import osgb from '/@/assets/images/osgb.jpg';
  78. import { useI18n } from '/@/hooks/web/useI18n';
  79. import type { UploadProps } from 'ant-design-vue';
  80. import { debounce } from 'lodash-es';
  81. const { t } = useI18n();
  82. export default defineComponent({
  83. components: { BasicModal, BasicForm, Upload },
  84. props: {
  85. userData: { type: Object },
  86. },
  87. emits: ['update', 'register'],
  88. setup(props, { emit }) {
  89. const modelRef = ref({});
  90. const isAnimation = ref(false)
  91. const fileList = ref<UploadProps['fileList']>([]);
  92. const loading = ref(false);
  93. const fileFlow = reactive({
  94. file: null,
  95. title: '上传',
  96. complete: 0,
  97. dictId: null,
  98. });
  99. const { createMessage } = useMessage();
  100. const schemas: FormSchema[] = [
  101. {
  102. field: 'file',
  103. component: 'InputTextArea',
  104. // component: 'Upload',
  105. label: t('routes.product.file'),
  106. slot: 'file',
  107. // rules: [{ required: true, message: t('common.uploadMessge') }],
  108. // // helpMessage: t('routes.corporation.uploadHelp'),
  109. // itemProps: {
  110. // validateTrigger: 'onBlur',
  111. // },
  112. // componentProps: {
  113. // api: uploadApi,
  114. // maxNumber: 1,
  115. // maxSize: 2000,
  116. // fileFlow: true,
  117. // accept: ['jpg', 'jpg', 'png', 'jpeg', 'mp4', 'wav', 'mp3', 'shp', 'zip'],
  118. // afterFetch: function (data) {
  119. // console.log('afterFetch', data);
  120. // // Reflect.set(data, 'url', data.name);
  121. // fileFlow.file = data.file;
  122. // return data;
  123. // },
  124. // },
  125. colProps: {
  126. span: 16,
  127. },
  128. },
  129. {
  130. field: 'dictId',
  131. label: '分组',
  132. component: 'ApiSelect',
  133. // required: true,
  134. componentProps: {
  135. api: getByKey,
  136. style: 'width: 350px',
  137. labelField: 'dictName',
  138. listHeight: 150,
  139. valueField: 'id',
  140. params: {
  141. type: 1,
  142. },
  143. onChange: (val,text) => {
  144. fileFlow.dictId = val
  145. fileList.value = [];
  146. isAnimation.value = text.useType == "animation"
  147. },
  148. },
  149. itemProps: {
  150. autoLink: false,
  151. },
  152. colProps: {
  153. xl: 18,
  154. xxl: 18,
  155. },
  156. },
  157. ];
  158. const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({
  159. labelWidth: 120,
  160. schemas,
  161. showActionButtonGroup: false,
  162. actionColOptions: {
  163. span: 24,
  164. },
  165. });
  166. onMounted(() => {});
  167. let addListFunc = () => {};
  168. const [register, { closeModal }] = useModalInner((data) => {
  169. console.log(data);
  170. data && onDataReceive(data);
  171. });
  172. function onDataReceive(data) {
  173. modelRef.value = data;
  174. resetFields();
  175. fileList.value = [];
  176. setFieldsValue({
  177. type: data.sceneName,
  178. });
  179. }
  180. const handleSubmit = debounce(async () => {
  181. let file = fileList.value[0];
  182. if (!file) {
  183. createMessage.warning('请上传文件');
  184. return;
  185. }
  186. console.log('handleSubmit', file, file.value);
  187. loading.value = true;
  188. fileFlow.complete = 0;
  189. try {
  190. const params = await validate();
  191. const apiData = {
  192. file: file,
  193. data: {
  194. dictId: params.dictId,
  195. },
  196. };
  197. console.log('res', apiData, params);
  198. function onUploadProgress(progressEvent: ProgressEvent) {
  199. const complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
  200. fileFlow.complete = complete;
  201. }
  202. await uploadApi(apiData, onUploadProgress);
  203. closeModal();
  204. resetFields();
  205. loading.value = false;
  206. createMessage.success('上传成功。');
  207. emit('update');
  208. } catch (error) {
  209. loading.value = false;
  210. console.log('not passing', error);
  211. }
  212. }, 300);
  213. function handleVisibleChange(v) {
  214. // console.log(v);
  215. // v && props.userData && nextTick(() => onDataReceive(props.userData));
  216. }
  217. const handleRemove = (file) => {
  218. const index = fileList.value.indexOf(file);
  219. const newFileList = fileList.value.slice();
  220. newFileList.splice(index, 1);
  221. fileList.value = newFileList;
  222. };
  223. const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  224. console.log('beforeUpload', file);
  225. const filetype = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
  226. const isExcel = ['jpg', 'jpg', 'png', 'jpeg', 'mp4', 'wav', 'mp3', 'shp', 'zip'].includes(
  227. filetype,
  228. ); // 调用上面代码
  229. const isdonghua = ['glb', 'zip'].includes(
  230. filetype,
  231. );
  232. if (!isExcel && isAnimation.value) {
  233. createMessage.error('支持obj、glb格式文件上传');
  234. fileList.value = [];
  235. return Upload.LIST_IGNORE;
  236. }
  237. if (!isdonghua && !isAnimation.value) {
  238. createMessage.error('支持jpg、png、jpeg、mp4、wav、mp3 、shp、zip格式文件上传');
  239. fileList.value = [];
  240. return Upload.LIST_IGNORE;
  241. }
  242. const isLt10M = file.size / 1024 / 1024 < 2000;
  243. const isLt5M = file.size / 1024 / 1024 < 5;
  244. if (!isLt10M && !isAnimation.value) {
  245. fileList.value = [];
  246. createMessage.error('上传文件不能超过 2G!');
  247. return Upload.LIST_IGNORE;
  248. }
  249. if (!isLt5M && isAnimation.value) {
  250. fileList.value = [];
  251. createMessage.error('上传文件不能超过 5MB!');
  252. return Upload.LIST_IGNORE;
  253. }
  254. fileList.value = [file];
  255. return false;
  256. };
  257. return {
  258. register,
  259. schemas,
  260. registerForm,
  261. model: modelRef,
  262. fileFlow,
  263. handleVisibleChange,
  264. handleSubmit,
  265. addListFunc,
  266. resetFields,
  267. t,
  268. obj,
  269. osgb,
  270. loading,
  271. fileList,
  272. handleRemove,
  273. beforeUpload,
  274. isAnimation,
  275. };
  276. },
  277. });
  278. </script>
  279. <style lang="less">
  280. .myzdyfrmo {
  281. .ant-upload-span {
  282. max-width: 340px !important;
  283. }
  284. }
  285. </style>