董国庆
2025-06-21 caaace44a0f0049b6a645d6e0a511af6adf7c1e0
laboratory/src/components/DynamicComponent/index.vue
@@ -36,7 +36,7 @@
                <!-- 图片类型显示 -->
                <template v-else-if="header.type === 'image'">
                  <img v-if="scope.row[header.name]" 
                       :src="scope.row[header.name]"
                       :src="getFullUrl(scope.row[header.name])"
                       alt="头像" 
                       class="table-image" />
                </template>
@@ -57,8 +57,10 @@
        </div>
        <!-- 文件上传 -->
        <div v-else-if="item.type == 'fileUpload'">
          <el-upload v-if="editable" action="#" :file-list="item.data.fileList"
            :on-change="(file, fileList) => handleFileChange(idx, fileList)" list-type="text">
          <el-upload v-if="editable" :http-request="customUploadRequest" :file-list="item.data.fileList"
            :on-change="(file, fileList) => handleFileChange(idx, fileList)"
            :on-success="(res, file, fileList) => handleFileSuccess(res, file, fileList, idx)"
            list-type="text">
            <el-button size="small" icon="el-icon-upload2">点击上传</el-button>
          </el-upload>
          <div v-else>
@@ -70,16 +72,23 @@
        <!-- 图片上传 -->
        <div v-else-if="item.type == 'imageUpload'">
          <div class="image-upload-container">
            <el-upload v-if="editable" action="#" :file-list="item.data.imageList"
            <el-upload v-if="editable" :http-request="customUploadRequest" :file-list="item.data.imageList"
              :on-change="(file, fileList) => handleImageChange(idx, fileList)"
              :on-success="(res, file, fileList) => handleImageSuccess(res, file, fileList, idx)" :auto-upload="true"
              :http-request="() => { }" :before-upload="beforeImageUpload" list-type="picture-card"
              :on-success="(res, file, fileList) => handleImageSuccess(res, file, fileList, idx)"
              :auto-upload="true"
              :before-upload="beforeImageUpload"
              list-type="picture-card"
              :on-preview="(file) => handlePreview(file, idx)"
              class="image-uploader">
              <i class="el-icon-plus"></i>
              <div class="upload-text">上传图片</div>
            </el-upload>
            <div v-else class="image-preview">
              <img v-for="image in item.data.imageList" :key="image.uid" :src="image.url" class="preview-image" />
              <el-image v-for="image in item.data.imageList"
                :key="image.uid"
                :src="getFullUrl(image.url)"
                :preview-src-list="item.data.imageList.map(img => getFullUrl(img.url))"
                class="preview-image" />
            </div>
            <div class="uploaf-notice">支持.jpg .png格式</div>
          </div>
@@ -95,6 +104,10 @@
    <addTableData  :visible.sync="rowDialog.visible" :headerList="rowDialog.headers"
      :editData="rowDialog.form" :isEdit="rowDialog.isEdit" @success="confirmAddRow">
    </addTableData>
    <el-dialog :visible.sync="imagePreviewVisible" width="auto" top="10vh" :show-close="true" v-if="imagePreviewUrl">
      <img :src="imagePreviewUrl" style="max-width:80vw;max-height:70vh;display:block;margin:auto;" />
    </el-dialog>
  </div>
</template>
@@ -104,6 +117,8 @@
import Table from "../Table/index.vue";
import addTableHeader from "./addTableHeader.vue";
import addTableData from "./addTableData.vue";
import apiConfig from '../../utils/baseurl'
import { customUploadRequest, getFullUrl } from '@/utils/utils'
export default {
  name: "DynamicComponent",
@@ -138,6 +153,7 @@
  },
  data() {
    return {
      apiConfig:apiConfig,
      showAddDialog: false,
      components: [],
      tableHeaderDialog: {
@@ -155,6 +171,8 @@
      },
      headerList: [],
      defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址
      imagePreviewVisible: false,
      imagePreviewUrl: '',
    };
  },
  watch: {
@@ -425,34 +443,27 @@
    },
    handleFileChange(idx, fileList) {
      if (!this.editable) return;
      fileList = fileList.map(file => {
        if (!file.url) {
          file.url = 'https://picsum.photos/200/200';
        }
        if (!file.name) {
          file.name = '默认文件.txt';
        }
        return file;
      });
      // 只做 fileList 同步
      this.components[idx].data.fileList = fileList;
      this.emitUpdate();
    },
    handleFileSuccess(res, file, fileList, idx) {
      // 上传成功后设置真实 url
      file.url = res.data.url;
      this.components[idx].data.fileList = fileList;
      this.emitUpdate();
    },
    handleImageChange(idx, fileList) {
      if (!this.editable) return;
      fileList = fileList.map(file => {
        if (!file.url) {
          file.url = 'https://picsum.photos/200/200';
        }
        return file;
      });
      // 只做 imageList 同步
      this.components[idx].data.imageList = fileList;
      this.emitUpdate();
    },
    handleImageSuccess(res, file, fileList, idx) {
      file.url = 'https://picsum.photos/200/200';
      // 上传成功后设置真实 url
      file.url = res.data.url;
      this.components[idx].data.imageList = fileList;
      this.emitUpdate();
    },
    beforeImageUpload(file) {
      const isJPG = file.type === 'image/jpeg';
@@ -469,12 +480,21 @@
      }
      return true;
    },
    handlePreview(file, idx) {
      // 使用el-image的preview-src-list实现预览
      // 这里直接用Element的图片预览能力,实际上el-upload会自动处理
      // 但如果你想自定义弹窗,可以用如下代码:
      this.imagePreviewUrl = this.getFullUrl(file.url);
      this.imagePreviewVisible = true;
    },
    emitUpdate() {
      // 先创建新对象,这有助于触发更新
      const updatedComponents = JSON.parse(JSON.stringify(this.components));
      this.$emit('update:dataSource', updatedComponents);
    },
  },
  computed: {
  },
};
</script>