董国庆
2025-06-30 9fe11a3b1c7ca926e2f4e97e36c2911c290a0ab2
laboratory/src/components/DynamicComponent/addTableData.vue
@@ -1,6 +1,6 @@
<template>
  <el-dialog
    title="添加表数据"
    :title="isEdit ? '编辑表数据' : '添加表数据'"
    :visible.sync="dialogVisible"
    width="60%"
    :close-on-click-modal="false"
@@ -29,9 +29,10 @@
                  :label="header.name"
                  :prop="header.name"
                  :rules="{
                    required: header.required === true || header.required === 'true',
                    required:
                      header.required === true || header.required === 'true',
                    message: header.message || `请输入${header.name}`,
                    trigger: ['blur', 'change']
                    trigger: ['blur', 'change'],
                  }"
                  v-if="header.type == 'text'"
                >
@@ -45,33 +46,47 @@
                  :label="header.name"
                  :prop="header.name"
                  :rules="{
                    required: header.required === true || header.required === 'true',
                    message: header.message || `请输入${header.name}`,
                    trigger: ['blur', 'change']
                    required:
                      header.required === true || header.required === 'true',
                    trigger: ['blur', 'change'],
                  }"
                  class="image-form-item"
                  v-if="header.type == 'image'"
                >
                  <el-upload
                    class="upload-demo"
                    action="#"
                    :file-list="spectrumList"
                    :auto-upload="false"
                    :action="uploadUrl"
                    :headers="uploadHeaders"
                    :file-list="imageList"
                    :auto-upload="true"
                    list-type="picture-card"
                    :on-change="handleSpectrumChange"
                    :on-remove="handleSpectrumRemove"
                    :beforeUpload="beforeImageUpload"
                    :on-change="handleImageChange"
                    :on-remove="handleImageRemove"
                    :on-success="handleImageSuccess"
                    :on-preview="handlePreview"
                    :disabled="!checkEditPermission(header)"
                  >
                    <i class="el-icon-plus"></i>
                    <!-- <div slot="tip" class="el-upload__tip">暂未连接服务器,使用默认图片</div> -->
                    <div
                      style="
                        display: flex;
                        justify-content: center;
                        flex-direction: column;
                      "
                    >
                      <i class="el-icon-plus"></i>
                    </div>
                    <div slot="tip" class="el-upload__tip">只支持.jpg格式</div>
                  </el-upload>
                </el-form-item>
                <el-form-item
                  :label="header.name"
                  :prop="header.name"
                  :rules="{
                    required: header.required === true || header.required === 'true',
                    required:
                      header.required === true || header.required === 'true',
                    message: header.message || `请输入${header.name}`,
                    trigger: ['blur', 'change']
                    trigger: ['blur', 'change'],
                  }"
                  v-if="header.type == 'date'"
                >
@@ -82,26 +97,30 @@
                    value-format="yyyy-MM-dd HH:mm:ss"
                    :disabled="!checkEditPermission(header)"
                    :picker-options="{
                      shortcuts: [{
                        text: '今天',
                        onClick(picker) {
                          picker.$emit('pick', new Date());
                        }
                      }, {
                        text: '昨天',
                        onClick(picker) {
                          const date = new Date();
                          date.setTime(date.getTime() - 3600 * 1000 * 24);
                          picker.$emit('pick', date);
                        }
                      }, {
                        text: '一周前',
                        onClick(picker) {
                          const date = new Date();
                          date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
                          picker.$emit('pick', date);
                        }
                      }]
                      shortcuts: [
                        {
                          text: '今天',
                          onClick(picker) {
                            picker.$emit('pick', new Date());
                          },
                        },
                        {
                          text: '昨天',
                          onClick(picker) {
                            const date = new Date();
                            date.setTime(date.getTime() - 3600 * 1000 * 24);
                            picker.$emit('pick', date);
                          },
                        },
                        {
                          text: '一周前',
                          onClick(picker) {
                            const date = new Date();
                            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
                            picker.$emit('pick', date);
                          },
                        },
                      ],
                    }"
                  />
                </el-form-item>
@@ -109,9 +128,10 @@
                  :label="header.name"
                  :prop="header.name"
                  :rules="{
                    required: header.required === true || header.required === 'true',
                    required:
                      header.required === true || header.required === 'true',
                    message: header.message || `请输入${header.name}`,
                    trigger: ['blur', 'change']
                    trigger: ['blur', 'change'],
                  }"
                  v-if="header.type == 'user'"
                >
@@ -140,11 +160,16 @@
      <el-button @click="handleClose">取 消</el-button>
      <el-button type="primary" @click="handleSubmit">确 定</el-button>
    </div>
    <el-dialog :visible.sync="imagePreviewVisible" append-to-body>
      <img width="100%" :src="imagePreviewUrl" alt="" />
    </el-dialog>
  </el-dialog>
</template>
<script>
import { listByRole } from './service';
import { listByRole } from "./service";
import { getFullUrl } from "@/utils/utils";
import apiConfig from "@/utils/baseurl";
export default {
  name: "AddDialog",
@@ -164,18 +189,33 @@
    isEdit: {
      type: Boolean,
      default: false,
    }
    },
  },
  data() {
    return {
      isIPad: /iPad/i.test(navigator.userAgent),
      showHeaderList: [{"name":"sd","type":"text","required":true,"message":"请输入表头名称","role":[]}],
      showHeaderList: [
        {
          name: "sd",
          type: "text",
          required: true,
          message: "请输入表头名称",
          role: [],
        },
      ],
      form: {},
      rules: {},
      photoList: [],
      spectrumList: [],
      defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址
      userOptions: []
      imageList: [],
      defaultImageUrl:
        "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg", // 默认图片地址
      userOptions: [],
      imagePreviewVisible: false,
      imagePreviewUrl: "",
      uploadUrl: apiConfig.imgUrl,
      uploadHeaders: {
        Authorization: sessionStorage.getItem("token") || "",
      },
    };
  },
  computed: {
@@ -188,9 +228,9 @@
      },
    },
    currentUserId() {
      const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
      const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}");
      return userInfo.userId;
    }
    },
  },
  watch: {
    visible: {
@@ -225,18 +265,20 @@
  },
  methods: {
    getUserOptions() {
      listByRole().then(res => {
        if (res) {
          this.userOptions = res.map(user => ({
            value: user.userId,
            label: user.nickName || user.userName
          }));
        } else {
          this.$message.error('获取用户列表失败');
        }
      }).catch(err => {
        console.error('获取用户列表失败', err);
      });
      listByRole()
        .then((res) => {
          if (res) {
            this.userOptions = res.map((user) => ({
              value: user.userId,
              label: user.nickName || user.userName,
            }));
          } else {
            this.$message.error("获取用户列表失败");
          }
        })
        .catch((err) => {
          console.error("获取用户列表失败", err);
        });
    },
    checkEditPermission(header) {
      if (!header.role || !Array.isArray(header.role)) {
@@ -248,15 +290,18 @@
      // 初始化校验规则
      const rules = {};
      if (this.headerList && this.headerList.length) {
        this.headerList.forEach(header => {
        this.headerList.forEach((header) => {
          // 处理required可能是字符串的情况
          const isRequired = header.required === true || header.required === 'true';
          const isRequired =
            header.required === true || header.required === "true";
          if (isRequired) {
            rules[header.name] = [{
              required: true,
              message: header.message || `请输入${header.name}`,
              trigger: ['blur', 'change']
            }];
            rules[header.name] = [
              {
                required: true,
                message: header.message || `请输入${header.name}`,
                trigger: ["blur", "change"],
              },
            ];
          }
        });
      }
@@ -267,20 +312,20 @@
      const formData = {
        updateTime: this.formatDateTime(new Date()),
      };
      // 根据headerList初始化表单数据
      if (this.headerList && this.headerList.length) {
        this.headerList.forEach(header => {
          if (header.type === 'user') {
        this.headerList.forEach((header) => {
          if (header.type === "user") {
            formData[header.name] = [];
          } else {
            formData[header.name] = '';
            formData[header.name] = "";
          }
        });
      }
      // 使用Vue.set确保响应式
      Object.keys(formData).forEach(key => {
      Object.keys(formData).forEach((key) => {
        this.$set(this.form, key, formData[key]);
      });
    },
@@ -292,17 +337,17 @@
      // 根据headerList设置表单数据
      if (this.headerList && this.headerList.length) {
        this.headerList.forEach(header => {
          if (header.type === 'user') {
        this.headerList.forEach((header) => {
          if (header.type === "user") {
            formData[header.name] = data[header.name] || [];
          } else {
            formData[header.name] = data[header.name] || '';
            formData[header.name] = data[header.name] || "";
          }
        });
      }
      // 使用Vue.set确保响应式
      Object.keys(formData).forEach(key => {
      Object.keys(formData).forEach((key) => {
        this.$set(this.form, key, formData[key]);
      });
@@ -318,14 +363,15 @@
      }
      // 设置图谱列表
      if (data.spectrums && data.spectrums.length) {
        this.spectrumList = data.spectrums.map((spectrum) => ({
          name: spectrum.name,
          url: spectrum.url,
          status: "success",
        }));
      } else {
        this.spectrumList = [];
      this.imageList = [];
      const imageHeader = this.headerList.find((h) => h.type === "image");
      if (imageHeader && data[imageHeader.name]) {
        this.imageList = [
          {
            name: "image",
            url: getFullUrl(data[imageHeader.name]),
          },
        ];
      }
      // 重置表单校验状态
@@ -335,77 +381,99 @@
    },
    formatDateTime(date) {
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      const hours = String(date.getHours()).padStart(2, '0');
      const minutes = String(date.getMinutes()).padStart(2, '0');
      const seconds = String(date.getSeconds()).padStart(2, '0');
      const month = String(date.getMonth() + 1).padStart(2, "0");
      const day = String(date.getDate()).padStart(2, "0");
      const hours = String(date.getHours()).padStart(2, "0");
      const minutes = String(date.getMinutes()).padStart(2, "0");
      const seconds = String(date.getSeconds()).padStart(2, "0");
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    },
    handleClose() {
      this.dialogVisible = false;
      this.$refs.form?.resetFields();
      this.photoList = [];
      this.spectrumList = [];
      this.imageList = [];
      this.initFormData();
    },
    handleSubmit() {
      this.$refs.form.validate((valid) => {
        if (valid) {
          const submitData = {
            ...this.form,
            photos: this.photoList,
            spectrums: this.spectrumList,
          };
          // 为用户类型字段添加用户完整信息
          if (this.headerList && this.headerList.length) {
            this.headerList.forEach(header => {
              if (header.type === 'user' && Array.isArray(submitData[header.name])) {
            this.headerList.forEach((header) => {
              if (
                header.type === "user" &&
                Array.isArray(submitData[header.name])
              ) {
                // 为每个用户类型字段添加userInfo属性,包含用户完整信息
                submitData[`${header.name}_userInfo`] = submitData[header.name].map(userId => {
                  const userInfo = this.userOptions.find(user => user.value === userId);
                submitData[`${header.name}_userInfo`] = submitData[
                  header.name
                ].map((userId) => {
                  const userInfo = this.userOptions.find(
                    (user) => user.value === userId
                  );
                  return userInfo ? userInfo : { value: userId, label: userId };
                });
              }
            });
          }
          console.log(submitData,'修改的数据')
          this.$emit("success", submitData);
          this.handleClose();
        } else {
          this.$message.error('请填写必填项');
          this.$message.error("请填写必填项");
        }
      });
    },
    handlePhotoChange(file, fileList) {
      this.photoList = fileList;
      this.$refs.form.validateField("photos");
    },
    handleSpectrumChange(file, fileList) {
      // 使用默认图片替代实际上传
      this.spectrumList = [{
        name: '默认图片.jpg',
        url: this.defaultImageUrl,
        status: 'success'
      }];
      // 同时更新form中对应的字段值以通过表单验证
      const imageHeader = this.headerList.find(h => h.type === 'image');
      if (imageHeader && imageHeader.name) {
        // 保存图片URL,这样在表格中可以直接使用
        this.$set(this.form, imageHeader.name, this.defaultImageUrl);
        console.log('设置图片字段:', imageHeader.name, this.defaultImageUrl);
      }
      this.$refs.form.validateField("spectrums");
    },
    handleSpectrumRemove(file) {
      this.spectrumList = [];
    },
    beforeImageUpload(file) {
      const isJPG = file.type === "image/jpeg";
      // const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isJPG) {
        this.$message.error("上传图片只能是 JPG 格式!");
        return false;
      }
      return true;
    },
    handleImageChange(file, fileList) {
      this.imageList = fileList;
      const imageHeader = this.headerList.find((h) => h.type === "image");
      if (imageHeader) {
        this.$refs.form.validateField(imageHeader.name);
      }
    },
    handleImageSuccess(res, file, fileList) {
      const url = res.msg;
      file.url = getFullUrl(url);
      const imageHeader = this.headerList.find((h) => h.type === "image");
      if (imageHeader) {
        this.$set(this.form, imageHeader.name, url);
        this.$refs.form.validateField(imageHeader.name);
      }
      this.imageList = fileList.map((f) => {
        if (f.uid === file.uid) {
          return file;
        }
        return f;
      });
    },
    handleImageRemove(file, fileList) {
      const imageHeader = this.headerList.find((h) => h.type === "image");
      if (imageHeader) {
        this.$set(this.form, imageHeader.name, "");
      }
      this.imageList = fileList;
    },
    handlePreview(file) {
      this.imagePreviewUrl = file.url;
      this.imagePreviewVisible = true;
    },
    getFullUrl,
  },
  mounted() {
    // 获取用户列表数据
@@ -413,7 +481,7 @@
  },
};
</script>
<style scoped lang="less">
::v-deep .el-dialog__body {
  padding: 0;
@@ -462,7 +530,7 @@
        background: #f5f7fa;
      }
    }
    .el-form-item::after{
    .el-form-item::after {
      height: 10px !important;
    }
  }
@@ -488,26 +556,26 @@
      height: 120px;
      line-height: 120px;
    }
    .el-upload-list--picture-card {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      .el-upload-list__item {
        width: 120px;
        height: 120px;
        margin: 0;
      }
    }
    // 让上传按钮始终显示在列表最后
    .el-upload--picture-card {
      order: 9999;
      margin: 0;
    }
  }
  // 包裹容器也使用flex布局
  display: flex;
  flex-wrap: wrap;
@@ -559,11 +627,17 @@
        background-color: #f5f7fa;
      }
    }
    .el-upload__tip {
      color: #909399;
      font-size: 12px;
      margin-top: 8px;
    }
  }
}
</style>
.el-upload__tip {
  color: #909399;
  font-size: 12px;
  margin-top: 115px !important;
  margin-right: -105px !important;
}
::v-deep .image-form-item {
  .el-form-item__error {
    display: none !important;
  }
}
</style>