这个封装的是一个供整个项目使用的表格,可多次复用.放在一个全局使用的公共组件文件下.
大致功能介绍,封装自定义指令,点击获得焦点,显示输入框,失去焦点显示文本内容,类型是字典决定类型,图片可以显示图片名还是上传图片
子组件
javascript
<script>
export default {
props: {
//生成表头
fields: {
type: Array,
default: () => [],
},
//数据
tableData: {
type: Array,
default: () => [],
},
},
data() {
return {};
},
created() {},
// 自定义指令
directives: {
focus: {
inserted: function (el) {
el.querySelector("input").focus();
},
},
},
methods: {
// 点击框 获取焦点 column列,row 行
cellClick(column, row) {
column.iseditor = true;
row.isnameSelected = true;
},
//输入框失去焦点触发,此处用提示框提示修改
blurEvent(column, row) {
// console.log(column, row);
column.iseditor = false;
row.isnameSelected = false;
},
},
};
</script>
<template>
<div>
<el-table :data="tableData" border style="width: 100%">
<el-table-column
:prop="field.prop"
:label="field.label"
:min-width="field.minWidth || 140"
v-for="(field, index) in fields"
:key="index"
show-overflow-tooltip
>
<template slot-scope="scope">
<div v-if="field.slot">
<slot :name="field.slot" :row="scope.row" />
</div>
<div v-else>
<div>
<el-input
v-if="field.iseditor && scope.row.isnameSelected"
v-model="scope.row[field.prop]"
@focus="cellClick(field, scope.row)"
@blur="blurEvent(field, scope.row)"
v-focus
>
</el-input>
<p @click="cellClick(field, scope.row)" v-else>
{{ scope.row[field.prop] || "--" }}
</p>
</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<style scoped>
</style>
<style>
.el-tooltip__popper {
max-width: 1000px;
}
.disabled .el-upload--picture-card {
display: none;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
父组件
这里还有封装了一个文件上传的组件嵌套在表格中,算是拓展
javascript
<script>
import editComponents from "../../components/editComponents";
export default {
components: { editComponents },
data() {
return {
fields: [
{
prop: "industryCode",
label: "产品",
iseditor: false,
},
{
prop: "id",
label: "id",
iseditor: false,
},
{
prop: "paragraphType",
label: "产品类型",
iseditor: false,
slot: "paragraphType",
//根据这个slot来决定是否要使用插槽,让父组件可以更好地使用数据,不用传来传去,下面是一样的
},
{
prop: "paragraphImage",
label: "产品图片",
slot: "paragraphImage",
iseditor: false,
},
{
prop: "action",
label: "操作",
slot: "action",
},
],
tableData: [
{
industryCode: "苹果",
id: "15",
paragraphType: "1",
paragraphImage: "15.png",
},
{
industryCode: "苹果",
id: "16",
paragraphType: "2",
paragraphImage: "15.png",
},
{
industryCode: "苹果",
id: "17",
paragraphType: "1",
paragraphImage: "15.png",
},
],
fileList: [], //文件总数
fileList1: [], //详情文件总数
dialogImageUrl: "",
dialogVisible: false,
disabled: false,
};
},
computed: {
//文件上传地址
upLoadUrl() {
//process.env.VUE_APP_BASE_API 检测当前环境来决定接口路径
//测试环境 VUE_APP_BASE_API = '/stage-api'
if (process.env.VUE_APP_BASE_API == "/stage-api") {
return "接口地址"; // 例如:'/minio/upload'
// 生产
} else if (process.env.VUE_APP_BASE_API == "生产接口") {
return "接口地址";
} else {
// 本地
return "接口地址";
}
},
},
created() {
this.getlist();
},
methods: {
//获取数据
getlist() {
// 发请求获取数据写在这里
this.tableData = this.tableData.map((item) => {
return { ...item, isnameSelected: false };
});
},
// 添加
hAdd() {
const productObj1 = {
industryCode: "",
id: "",
paragraphType: "",
paragraphImage: "",
iseditor: false,
uuId: Math.random(),
};
this.tableData.push(productObj1);
},
// 删除
del(row) {
this.tableData = this.tableData.filter(
(item) => item.uuId !== row.uuId || item.id !== row.id
);
},
//图片上传===========================
handleRemove(file) {
console.log(file);
console.log(this.$refs.upload);
let uploadFiles = this.$refs.upload.uploadFiles;
for (var i = 0; i < uploadFiles.length; i++) {
if (uploadFiles[i]["url"] == file.url) {
uploadFiles.splice(i, 1);
}
}
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
handleDownload(file) {
console.log(file);
},
// 文件上传成功-----------------
async handleSuccess(response, row) {
// 处理上传成功后的逻辑
console.log("上传成功", response, row);
this.fileName = response.data.fileName;
row.paragraphImage = response.data.fileName;
},
handleError(err, file, fileList) {
// 处理上传失败后的逻辑
console.error("上传失败", err);
},
// selectedLabel(selectedValue) {
// if (selectedValue === "1") {
// return "选择一";
// } else if (selectedValue === "2") {
// return "选择二";
// }
// },
async onSubmit() {
// 删除不需要的属性
this.tableData.forEach(function (obj) {
if (obj.hasOwnProperty("iseditor")) {
delete obj.iseditor;
}
if (obj.hasOwnProperty("uuId")) {
delete obj.uuId;
}
if (obj.hasOwnProperty("isnameSelected")) {
delete obj.isnameSelected;
}
});
// 新增
if (!this.industryCode) {
// 新增请求写在这里
console.log(res);
if (res.message == "success") {
this.$message({
message: res.data,
type: "success",
duration: 1000,
});
} else {
this.$message.error(res.data);
}
} else {
// 修改请求写在这里
console.log(res);
if (res.message == "success") {
this.$message({
message: res.data,
type: "success",
duration: 1000,
});
this.goBack();
} else {
this.$message.error(res.data);
}
}
},
},
};
</script>
<template>
<div>
<el-button @click="hAdd" type="primary">添加</el-button>
<editComponents :fields="fields" :tableData="tableData">
<template #action="{ row }">
<el-button type="text" size="small" @click="del(row)">删除</el-button>
</template>
<template #paragraphImage="{ row }">
<div>
<p>{{ row.paragraphImage || "--" }}</p>
<el-upload
ref="upload"
:file-list="fileList1"
:action="upLoadUrl"
list-type="picture-card"
:on-success="(e) => handleSuccess(e, row)"
:on-error="handleError"
>
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{ file }">
<img
class="el-upload-list__item-thumbnail"
:src="file.url"
alt=""
/>
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in"></i>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<template #paragraphType="{ row }">
<div>
<el-select v-model="row.paragraphType" placeholder="请选择">
<el-option label="选择一" value="1"></el-option>
<el-option label="选择二" value="2"></el-option>
</el-select>
<!-- <p @click="cellClick(row)">
{{ selectedLabel(row.titleTypeSecond) || "--" }}
{{row}}
</p> -->
</div>
</template>
</editComponents>
<el-card>
<div>
<el-button type="primary" round @click="onSubmit">提交</el-button>
</div>
</el-card>
</div>
</template>
<style scoped>
</style>