Ver código fonte

文件批量上传

tangning 1 ano atrás
pai
commit
7e6c356a58

+ 1 - 0
src/request/urls.ts

@@ -239,6 +239,7 @@ export const onLineCheck = "/web/fireProject/onLineCheck";
 // 照片制卷
 export const caseApiList = "/fusion-xj/caseImg/list";
 export const saveApiOrUpdate = "/fusion-xj/caseImg/saveOrUpdate";
+export const uploadImagesAndSave = "/fusion-xj/caseImg/addBatch";
 export const caseApiDel = "/fusion-xj/caseImg/delete";
 export const caseApiUpdateSort = "/fusion-xj/caseImg/updateSort";
 

+ 15 - 0
src/store/case.ts

@@ -9,6 +9,7 @@ import {
   updateCaseFile,
   caseApiList,
   saveApiOrUpdate,
+  uploadImagesAndSave,
   caseApiDel,
   caseApiUpdateSort,
   caseInquestInfo,
@@ -42,6 +43,17 @@ export type CaseImg = {
   sort: number | null;
 };
 
+export type filesItem = {
+  caseId: number;
+  imgInfo: string | null;
+  imgUrl: string | null;
+};
+
+export type AllSaveFile = {
+  imgUrls: filesItem[];
+};
+
+
 export const setCaseSharePWD = (params: { caseId: number; randCode: string }) =>
   axios.post(setCasePsw, params);
 
@@ -100,6 +112,9 @@ export const caseImgList = (caseId: number, orderBy: string | null) =>
 export const saveOrUpdate = (params: CaseImg) =>
   axios.post(saveApiOrUpdate, { ...params });
 
+export const saveOrAndSave = (params: AllSaveFile) =>
+  axios.post(uploadImagesAndSave, { ...params });
+
 export const caseDel = (id: number) => axios.post(caseApiDel, { id });
 
 export const caseUpdateSort = (list: [CaseImg]) =>

+ 190 - 0
src/view/case/addPhotoFileAll.vue

@@ -0,0 +1,190 @@
+<template>
+  <el-form
+    ref="form"
+    :model="caseFile"
+    label-width="90px"
+    class="camera-from dispatch-file-from"
+  >
+    <el-form-item label="附件:" class="mandatory">
+      <el-upload
+        class="upload-demo"
+        :multiple="true"
+        :limit="10"
+        :before-upload="upload"
+        v-model:file-list="fileList"
+        :http-request="httpsApi"
+        :on-preview="previewFile"
+        :accept="photoFormats"
+        :on-remove="handleRemove"
+      >
+        <el-button type="primary" :disabled="!!file">
+          <el-icon><Upload /></el-icon>上传
+        </el-button>
+        <template v-slot:tip>
+          <div class="el-upload__tip">注:可上传{{ size }}以内的{{ photoFormatDesc }}</div>
+        </template>
+        <template v-slot:file="{ file }">
+          <div class="file" @click.stop="previewFile()">
+            <div>
+              <el-icon><Document /></el-icon>
+              <span class="name">{{ file.name }}</span>
+            </div>
+            <el-icon @click.stop="removeFile(file)"><Close /></el-icon>
+          </div>
+        </template>
+      </el-upload>
+    </el-form-item>
+    <!-- <el-form-item label="附件标题:" class="mandatory">
+      <el-input
+        v-model="caseFile.imgInfo"
+        placeholder="请输入最多不能超过50字"
+        maxlength="50"
+        show-word-limit
+      ></el-input>
+    </el-form-item> -->
+  </el-form>
+</template>
+
+<script setup lang="ts">
+import {
+  DrawFormatDesc,
+  DrawFormats,
+  photoFormats,
+  photoFormatDesc,
+  FileDrawType,
+  OtherFormatDesc,
+  OtherFormats,
+} from "@/constant/caseFile";
+import { uploadFile } from "@/store/system";
+import { maxFileSize } from "@/constant/caseFile";
+import { useUpload } from "@/hook/upload";
+import { saveOrAndSave, CaseImg } from "@/store/case";
+import { ElMessage } from "element-plus";
+import { computed, ref, watch, watchEffect } from "vue";
+import { QuiskExpose } from "@/helper/mount";
+import type { UploadProps } from 'element-plus'
+
+const props = defineProps<{
+  caseId: number;
+  data: CaseImg;
+}>();
+
+const defaultUpload = (
+  file: File,
+  onPercentage: (percentage: number) => void
+) => {
+  onPercentage(100);
+};
+
+const caseFile = ref<CaseImg>({
+  caseId: props.caseId,
+  id: props.data?.id,
+  imgUrl: props.data.imgUrl,
+  imgInfo: props.data.imgInfo,
+  sort: props.data?.sort || '',
+} as any);
+
+const { size, previewFile, file, accept, percentage, format } = useUpload({
+  maxSize: maxFileSize,
+  formats: DrawFormats,
+});
+
+const upload = async (file: File) => {
+    const fileType = file.name
+      .substring(file.name.lastIndexOf("."))
+      .toUpperCase();
+
+    if (!DrawFormats.some((type) => type.toUpperCase() === fileType)) {
+      ElMessage.error(`请上传${format.value}`);
+      return false;
+    } else if (file.size > maxFileSize) {
+      ElMessage.error(`请上传${size.value}以内的文件`);
+      return false;
+    } else {
+      console.log('file', file)
+      fileList.value.push(file);
+      await defaultUpload(
+        file,
+        (val) => (percentage.value = val)
+      );
+      if (fileType === ".RAW") {
+      }
+      percentage.value = undefined;
+      return true;
+    }
+  };
+const fileList = ref([])
+const formatDesc = computed(() =>
+DrawFormatDesc
+);
+watch(props, newValue => {
+  caseFile.value.id = newValue.data.id;
+  caseFile.value.imgInfo = newValue.data.imgInfo;
+  caseFile.value.imgUrl = newValue.data.imgUrl;
+  caseFile.value.sort = newValue.data.sort;
+  if(newValue.data.imgUrl){
+    file.value = {
+    name: newValue.data.imgInfo || '',
+    url: newValue.data.imgUrl || '',
+  }
+  }
+},{ immediate: true })
+watchEffect(() => {
+  if (file.value?.name) {
+    caseFile.value.imgInfo = file.value?.name.substring(0, 50);
+  }
+});
+const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
+  console.log(uploadFile, uploadFiles)
+}
+const removeFile = (file) => {
+  fileList.value = fileList.value.filter((item) => item.raw.url !== file.raw.url);
+};
+const httpsApi = async ({file})=> {
+  console.log('httpsApi', file)
+  let fileUrl = await uploadFile(file);
+
+  file.url = fileUrl
+  console.log('httpsApi', file, fileUrl)
+}
+
+defineExpose<QuiskExpose>({
+  async submit() {
+    console.log('defineExpose', fileList.value)
+    if (!fileList.value.length) {
+      ElMessage.error("请上传附件");
+      throw "请上传附件";
+    }
+    console.log('defineExpose', caseFile.value, file.value)
+    let imgUrls = fileList.value.map(item => {
+      return {
+        imgUrl: item.raw && item.raw.url,
+        imgInfo: item.name,
+        caseId: props.caseId,
+      }
+    })
+    await saveOrAndSave({ imgUrls });
+    return caseFile.value;
+  },
+});
+</script>
+
+<style scoped lang="scss">
+.upload-demo {
+  overflow: hidden;
+}
+
+.file {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  > div {
+    display: flex;
+    align-items: center;
+  }
+
+  .name {
+    margin-left: 10px;
+  }
+}
+</style>

+ 55 - 4
src/view/case/photos/index.vue

@@ -1,8 +1,20 @@
 <template>
-  <div class="photo">
+  <div class="photo ">
     <div class="left">
-      <div class="upload">
-        <el-button type="primary" @click="addCaseFileHandler">
+      <div class="upload my-photo-upload">
+          <!-- <el-upload
+          v-model:file-list="fileList"
+          class="upload-demo"
+          multiple
+          :show-file-list="false"
+          :http-request="handleRequest"
+          :on-change="handleChange"
+          :before-upload="handleUpload"
+          :limit="10"
+        >
+          <el-button type="primary">上传照片</el-button>
+        </el-upload> -->
+        <el-button type="primary" @click="addCaseFileHandlerAll">
           上传照片
         </el-button>
         <el-button
@@ -77,13 +89,14 @@ import { Menu, FullScreen } from "@element-plus/icons-vue";
 import { Swiper, SwiperSlide } from "swiper/vue";
 import "swiper/css";
 // import { addCaseFile } from "@/store/caseFile";
-import { addCaseImgFile } from "../quisk";
+import { addCaseImgFile, addCaseImgFileAll } from "../quisk";
 import { saveCaseImgTagData, getCaseImgTagData } from "@/store/case";
 import Scene from "@/core/Scene.js";
 import draggable from "./draggable.vue";
 import { ElMessage } from "element-plus";
 const props = defineProps({ caseId: Number });
 const newlist = ref([]);
+const fileList = ref([]);
 const swiperRef = ref(null);
 const childRef = ref(null);
 const caseId = ref(props.caseId);
@@ -106,6 +119,20 @@ const addCaseFileHandler = async () => {
   });
   refresh();
 };
+
+const addCaseFileHandlerAll = async () => {
+  await addCaseImgFileAll({
+    caseId: caseId.value,
+    data: {
+      imgUrl: "",
+      imgInfo: "",
+      id: "",
+      sort: "",
+    },
+  });
+  refresh();
+};
+
 function refresh() {
   console.log("changeList", childRef.value);
 
@@ -185,6 +212,16 @@ const onSwiper = (swiper) => {
 const onSlideChange = (swiper) => {
   console.log(swiper);
 };
+const handleChange = (val, list) => {
+  fileList.value = list;
+  console.log('handleChange',val, list, fileList.value);
+}
+const handleRequest = (val, list) => {
+  console.log('handleRequest',val, list);
+}
+const handleUpload = (val) => {
+  console.log('handleUpload', val);
+}
 const handleItem = (item) => {
   let active = sortType.value ? item : Math.floor(item / 2);
   // swiperRef.value.slideTo(active);
@@ -246,6 +283,19 @@ onMounted(() => {
   // } catch (error) {}
 });
 </script>
+<style lang="scss">
+.my-photo-upload{
+      .upload-demo{    
+        display: inline-block;
+        margin-right: 20px;
+        position: relative;
+        bottom: -1px;
+        .el-upload-list{
+          display: none;
+        }
+      }
+}
+</style>
 <style lang="scss" scoped>
 #canvas {
   width: 100%;
@@ -264,6 +314,7 @@ onMounted(() => {
     background: #ffffff;
     box-shadow: 10px 0 10px -10px rgba(0, 0, 0, 0.15);
     // box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.15);
+
   }
 
   .right {

+ 7 - 1
src/view/case/quisk.ts

@@ -1,4 +1,5 @@
 import addPhotoFile from "./addPhotoFile.vue";
+import addPhotoFileAll from "./addPhotoFileAll.vue";
 import AddCaseFile from "./addCaseFile.vue";
 import AddScenes from "./addScenes.vue";
 import ShareCase from "./share.vue";
@@ -17,7 +18,12 @@ export const addCaseFile = quiskMountFactory(AddCaseFile, {
 });
 
 export const addCaseImgFile = quiskMountFactory(addPhotoFile, {
-  title: "上传附件",
+  title: "上传照片",
+  width: 500,
+});
+
+export const addCaseImgFileAll = quiskMountFactory(addPhotoFileAll, {
+  title: "上传照片",
   width: 500,
 });