el-table每行可编辑,每行都可上传图片的功能

885 阅读2分钟

1、界面如下

1702368977374.png 点击新增按钮新增一行

双击可编辑

2、整个页面的代码如下

<template>
  <div>
    <icon-box-card card-title="轮播功能" card-icon="icon-search">
      <el-row class="w-100">
        <el-col :span="24">
          <el-button type="danger" @click="saveCarousel">保存</el-button>
        </el-col>
      </el-row>

      <el-row
        class="w-100"
        v-for="(item,index) in carouselList"
        :key="index"
        style="margin-top: 10px;"
      >
        <el-col :span="24">
          <span>第{{ index +1 }}张轮播跳转地址:</span>
          <el-input placeholder v-model="item.jumpLink" disabled="true" style="width: 460px;"></el-input>
          <span class="linkSpan" @click="handleJumpLinkClick(item,index)">设置连接</span>
        </el-col>
      </el-row>

      <el-row style="margin-top: 30px;">
        <el-upload
          list-type="picture-card"
          v-model:file-list="fileList"
          :multiple="true"
          class="avatar-uploader"
          action="#"
          limit="6"
          :before-upload="beforeUpload"
          :http-request=" (data) => handleUpload(data,'','多图')"
          :headers="headers"
          :on-remove="handleRemove"
          :on-preview="handlePreview"
          :on-exceed="handleExceed"
        >
          <el-icon>+</el-icon>
        </el-upload>
        <el-dialog v-model="picCardBoxVisible" class="picCardBox">
          <img w-full :src="picCardBoxImgUrl" fit="fill" />
        </el-dialog>
      </el-row>

      <el-row class="w-100" style="margin-top: 5px;">
        <el-col :span="24">
          <span class="tips">建议尺寸:750*750像素,最多上传6张,单张不超过1M。</span>
        </el-col>
      </el-row>
    </icon-box-card>
    <icon-box-card card-title="热区功能" card-icon="icon-view-list" class="nj-query-box hotBox">
      <el-row class="w-100">
        <el-col :span="24">
          <el-button type="primary" @click="handleAddClick">新增</el-button>
          <el-button type="danger" @click="handleSaveClick">保存</el-button>
        </el-col>
      </el-row>
      <el-table
        :data="tableData"
        border
        style="width: 100%;margin-top: 20px;"
        @cell-dblclick="doubleClick"
      >
        <el-table-column
          prop="name"
          label="项目名称"
          width="200"
          style="width: 190px;position: relative;"
        >
          <template #default="scope">
            <el-input
              v-if="scope.row.isEdit"
              placeholder="请输入内容"
              v-model="scope.row.name"
              clearable
              style="width: 160px;"
            ></el-input>
            <span v-else>{{ scope.row.name }}</span>
          </template>
        </el-table-column>

        <el-table-column prop="icon" label="显示图标123">
          <template #default="scope">
            <el-upload
              class="avatar-uploader"
              action="#"
              :show-file-list="false"
              :headers="headers"
              :before-upload="beforeUpload"
              :http-request=" (data) => handleUpload(data,scope.$index,'单图')"
              v-if="scope.row.isEdit"
            >
              <img v-if="scope.row.icon" :src="scope.row.icon" class="avatar" />
              <el-icon v-else class="avatar-uploader-icon">
                <Plus />
              </el-icon>
            </el-upload>
            <div v-else style="width: 80px;">
              <el-image :src="scope.row.icon"></el-image>
            </div>
            <!-- <UploadImg action="#" @getUpload="(value) => getUpload(value,scope.$index)" :cardImageUrl="cardImageUrl"></UploadImg>  -->
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序">
          <template #default="scope">
            <el-input
              v-if="scope.row.isEdit"
              placeholder="请输入内容"
              v-model="scope.row.sort"
              clearable
              style="width: 160px;"
            ></el-input>
            <span v-else>{{ scope.row.sort }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="jumpLink" label="跳转地址">
          <template #default="scope">
            <el-input
              v-if="scope.row.isEdit"
              placeholder="请输入内容"
              v-model="scope.row.jumpLink"
              clearable
              style="width: 160px;"
            ></el-input>
            <span v-else>{{ scope.row.jumpLink }}</span>
          </template>
        </el-table-column>
        <el-table-column prop label="操作">
          <template #default="scope">
            <el-button size="small" type="danger" @click="handleDelClick(scope.row,scope.$index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </icon-box-card>
    <el-dialog v-model="dialogHotVisible" title="热区编辑" class="hotDialog" width="500px">
      <el-form label-width="120px">
        <el-form-item label="项目名称">
          <el-input v-model="hotForm.name" />
        </el-form-item>
        <el-form-item label="显示图标">
          <UploadImg
            action="#"
            @getUpload="(value) => getUpload(value)"
            :cardImageUrl="cardImageUrl"
          ></UploadImg>
        </el-form-item>
        <el-form-item label="排序">
          <el-input v-model="hotForm.sort" />
        </el-form-item>
        <el-form-item label="跳转地址">
          <el-input v-model="hotForm.jumpLink" />
        </el-form-item>
      </el-form>
    </el-dialog>
    <el-dialog v-model="dialogLinkVisible" title="设置链接地址" style="width: 500px;">
      <el-form>
        <el-form-item label="链接类型:">
          <el-radio-group v-model="linkForm.type" @change="changeLinkType">
            <el-radio label="跳转路径" />
            <el-radio label="无" />
          </el-radio-group>
        </el-form-item>
        <el-form-item label="跳转地址:" v-if="linkForm.type == '跳转路径'" style="width: 460px;">
          <el-input placeholder="请输入内容" v-model="linkToadress" clearable></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogLinkVisible = false">取消</el-button>
          <el-button type="primary" @click="dialogLinkConfirm">确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
  

<script lang="ts" setup>
import {
  Delete,
  Top,
  Bottom,
  EditPen,
  Edit,
  Plus,
} from "@element-plus/icons-vue";
import {
  ElMessage,
  ElMessageBox,
  UploadProps,
  UploadUserFile,
} from "element-plus";

import { getYestarToken } from "@/utils/yestarToken";
import { getChoosetHospital } from "@/services/userContext";
import { uploadProduct } from "@/services/product";
import {
  queryMemberLevel,
  upMemberLevel,
  queryCarousel,
  upCarousel,
} from "@/api/indexPage";
import { uploadOssStorage } from "@/api/common";
import { onMounted, reactive, ref } from "vue";

let carouselList = ref([]);
const headers = {
  "Login-Token": getYestarToken(),
  "Hospital-Id": getChoosetHospital().hospitalId,
};

const fileList = ref([]);
const imageUrl = ref("");

// 单图上传
const beforeUpload: UploadProps["beforeUpload"] = (rawFile) => {
  if (rawFile.size && rawFile.size / 1024 / 1024 > 1) {
    ElMessage.error("上传图片过大!请重新上传");
    return false;
  }
  return true;
};

//手动上传
const handleUpload = async (data, indexs, type) => {
  var formData = new FormData();
  data && Array.isArray(data)
    ? data.forEach((v) => {
        formData.append("files", v.raw);
      })
    : formData.append("files", data.file);
  // console.log("data=========",data)
  // formData.append("files", data.file);
  await uploadOssStorage(formData).then((res) => {
    if (res.status == 200) {
      if (type == "单图") {
        imageUrl.value = res.data[0].imgUrl;
        tableData.value.forEach((item, i) => {
          if (i == indexs) {
            item.icon = res.data[0].imgUrl;
          }
        });
      } else {
        carouselList.value.push({
          id: 0,
          imgName: "",
          jumpLink: "",
          jumpType: 0,
          imgUrl: res.data[0].imgUrl,
        });
      }
    }
  });
};

// 移除文件
const handleRemove = (file, fileList) => {
  carouselList.value.forEach((item, i) => {
    if (item.imgUrl == file.url) {
      carouselList.value.splice(i, 1);
    }
  });
};

const picCardBoxImgUrl = ref("");
const picCardBoxVisible = ref(false);

// 预览
const handlePreview = (uploadFile) => {
  picCardBoxImgUrl.value = uploadFile.url!;
  picCardBoxVisible.value = true;
};

const handleExceed = () => {
  ElMessage.error("上传图片超过最大限制!");
  return false;
};

const saveCarousel = () => {
  let obj = {
    showCarousel: true,
    carouselList: carouselList.value,
  };
  upCarousel(obj).then((res) => {
    if (res.status == 200) {
      ElMessage({
        type: "success",
        message: res.message,
      });
    } else {
      ElMessage({
        type: "error",
        message: res.message,
      });
    }
  });
};

const hotForm = reactive({
  id: "",
  name: "",
  icon: "",
  sort: "",
  jumpLink: "",
});

const isShowBanner = ref(true);
let tableData = ref([]);

const nameEdit = ref(null);
const cardImageUrl = ref("");
const linkToadress = ref("");
const handleNameClick = (row) => {
  row.isEdit = false;
};
const blurNameInput = (row, column) => {
  row.isEdit = false;
};

const handleDelClick = (row, index) => {
  ElMessageBox.confirm("是否要删除?", "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      tableData.value.splice(index, 1);
      upMemberLevelFn("删除");
    })
    .catch(() => {
      ElMessage({
        type: "info",
        message: "删除失败!",
      });
    });
};

const dialogLinkVisible = ref(false);
const linkI = ref(0);
const handleJumpLinkClick = (item, index) => {
  linkForm.type == "跳转路径";
  linkToadress.value = item.jumpLink;
  linkI.value = index;
  dialogLinkVisible.value = true;
};

const dialogLinkConfirm = () => {
  carouselList.value.forEach((item, i) => {
    if (i == linkI.value) {
      item.jumpLink = linkToadress.value;
    }
  });
  dialogLinkVisible.value = false;
};

const dialogHotVisible = ref(false);

const handleAddClick = () => {
  tableData.value.push({
    id: "",
    name: "",
    icon: "",
    sort: 0,
    jumpLink: "",
    isEdit: true,
  });
};
const doubleClick = (row, index) => {
  tableData.value.forEach((item, i) => {
    item.isEdit = false;
  });
  row.isEdit = !row.isEdit;
};

const linkForm = reactive({
  type: "跳转路径",
});

const uploadHeaders = ref({
  "Login-Token": getYestarToken(),
  "Hospital-Id": getChoosetHospital().hospitalId,
  "Content-Type": "multipart/form-data",
});

async function getUpload(value, index) {
  tableData.value.forEach((item, i) => {
    if (i == index) {
      item.icon = value;
    }
  });
}

onMounted(() => {
  queryMemberLevelFn();
  queryCarouselFn();
});

const queryMemberLevelFn = async () => {
  await queryMemberLevel().then((res) => {
    if (res.status == 200) {
      tableData.value = res.data;
    } else {
      ElMessage({
        type: "error",
        message: res.message,
      });
    }
  });
};

const queryCarouselFn = async () => {
  await queryCarousel().then((res) => {
    if (res.status == 200) {
      carouselList.value = res.data.carouselList;
      carouselList.value.forEach((item, i) => {
        fileList.value.push({ url: item.imgUrl });
      });
    } else {
      ElMessage({
        type: "error",
        message: res.message,
      });
    }
  });
};

const upMemberLevelFn = async (type) => {
  upMemberLevel(tableData.value).then((res) => {
    if (res.status == 200) {
      ElMessage({
        type: "success",
        message: `${type}成功!`,
      });
      queryMemberLevelFn();
    } else {
      ElMessage({
        type: "error",
        message: res.message,
      });
    }
  });
};

const handleSaveClick = () => {
  ElMessageBox.confirm("是否要保存?", "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      upMemberLevelFn("保存");

    })
    .catch(() => {});
};
</script>
  
<style lang="scss" scoped>
.bannerBox {
  .tit {
    font-size: 16px;
    color: #000;
    font-weight: 600;
    margin-bottom: 20px;
  }
}
::deep .hotDialog {
  width: 200px;
  .el-input__inner {
    width: 200px;
  }
}

.w-100 {
  width: 100%;
}

.hotBox {
  .avatar-uploader {
    .avatar {
      width: 80px;
      height: 80px;
      display: block;
    }
  }
}

.avatar-uploader .avatar {
  width: 80px;
  height: 80px;
  display: block;
}

.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 80px;
  height: 80px;
  text-align: center;
}

.el-upload-list__item .el-icon-close-tip {
  display: none !important;
}

.tips {
  font-size: 14px;
  color: #999999;
  line-height: 19px;
}

.linkSpan {
  color: #409eff;
  margin-left: 10px;
  cursor: pointer;
}
.picCardBox img {
  width: 100%;
}
</style>
  

3、此页面图片上传最终是用手动上传实现的,手动上传核心代码如下

1702369143043.png