<template>
<div class="comp-box">
<!-- 标签-标签盒子 -->
<div class="tag-box">
<el-tag
v-for="item in tagOptions"
size="small"
:type="item.selected ? '' : 'info'"
:key="`menu-tag-${item.code}`"
@click="onClickTag(item)"
>{{ item.label }}</el-tag
>
</div>
<!-- 标签-评论内容 -->
<div ref="cmtContBoxRef" class="content">
<div
class="tag-item-content"
v-for="item in contList"
:key="`cont-item-${item.key}`"
>
<div v-if="item.key !== 'txt'" class="label">{{ item.label }}:</div>
<div
contenteditable
class="cont"
:style="`text-indent: ${
item.label.length === 0 ? 0 : item.label.length + 1
}em;`"
@input="(e) => onChange(e, item)"
></div>
</div>
</div>
<div class="tag-item-content-label">{{ describeNum }}/3000</div>
</div>
</template>
<script>
/**
* @todo 评论组件
*/
export default {
name: "Comment",
props: {
/**
* tags.item = { code: "color", label: "标题" },
* tags.item.code: 标记
* tags.item.label: 显示的标题
*
*/
tags: {
type: Array,
default: () => [],
},
},
data() {
return {
// 评论标签选项
tagOptions: [],
// 默认列表文字
contList: [{ key: "txt", label: "", content: "" }],
describeNum: 0
};
},
watch: {
tags: function () {
// 重载
this.reloadTagOptions();
},
contList: function (nv) {
// const lastIdx = nv.length - 1;
console.log("最后一行的内容:", nv);
},
},
mounted() {
// 重载标签选项
this.reloadTagOptions();
},
methods: {
// 获取textarea的样式
textAreaClass(item) {
return item.key !== "txt" ? "cont tag-input-area" : "cont";
},
clean() {
for (const dom of this.$refs.cmtContBoxRef.children) {
dom.children[0].innerText = '';
}
this.contList = [{ key: "txt", label: "", content: "" }]
},
// 重载标签
reloadTagOptions() {
this.tagOptions = this.tags.map((e) => {
return { ...e, selected: false };
});
},
onClickTag(item) {
const selected = !item.selected;
if (selected) {
// 选中
const newItem = { key: item.code, label: item.label, content: "" };
const txtItem = this.contList.find((e) => e.key === "txt");
// 如果只有1行且内容为空
if (txtItem.content === "") {
const list = this.contList.filter((e) => {
return e.key !== "txt";
});
list.push(newItem);
this.contList = [...list, txtItem];
} else {
this.contList.push(newItem);
}
item.selected = selected;
let num = 0;
this.contList.forEach(v => {
num += v.label.length + v.content.length;
})
this.describeNum = num;
} else {
// 未选中
const contItemIndex = this.contList.findIndex(
(e) => e.key === item.code
);
if (this.contList[contItemIndex].content) {
this.$confirm("已填写的描述将被删除", "确认删除标签?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.contList.splice(contItemIndex, 1);
item.selected = selected;
let num = 0;
this.contList.forEach(v => {
num += v.label.length + v.content.length;
})
this.describeNum = num;
})
.catch((e) => e);
} else {
this.contList.splice(contItemIndex, 1);
item.selected = selected;
}
}
},
// 修改
onChange(e, item) {
item.content = e.target.innerText;
let num = 0;
this.contList.forEach(v => {
num += v.label.length + v.content.length;
})
this.describeNum = num;
console.log(num);
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-tag {
margin-right: 10px;
cursor: pointer;
}
div {
text-indent: 0em;
}
.comp-box {
box-sizing: border-box;
border: 1px solid #dedede;
background-color: #fafbfc;
width: 77%;
// width: 500px;
padding: 10px;
}
// 标签盒子
.tag-box {
width: 100%;
}
// 内容
.content {
width: 100%;
border: 1px solid #dedede;
margin-top: 10px;
background-color: #fefefe;
min-height: 110px;
padding: 5px 0px;
// 标签项
.tag-item-content {
font-size: 12px;
color: #666666;
position: relative;
line-height: 22px;
.label {
color: #999;
font-size: inherit;
position: absolute;
top: 0px;
padding-left: 5px;
}
.cont {
outline: none;
border: none;
box-sizing: border-box;
padding: 0px 5px;
// 只显示文本, 不自动生成标签
-webkit-user-modify: read-write-plaintext-only;
}
}
}
.tag-input-area {
text-indent: 3em;
}
.btn-box {
margin-top: 5px;
text-align: right;
}
.tag-item-content-label {
display: flex;
justify-content: flex-end;
align-items: center;
color: #999;
}
</style>
效果图
主要是用到div的contenteditable可编辑属性