mirror of
https://github.com/sahadev/vue-component-creater-ui.git
synced 2025-08-25 04:34:47 +08:00
326 lines
9.2 KiB
Vue
326 lines
9.2 KiB
Vue
<template>
|
|
<el-card class="attribute-container">
|
|
|
|
<div style="text-align: center;">
|
|
<el-switch v-model="editMode" active-text="自由编辑" inactive-text="约束编辑" active-color="#13ce66"
|
|
inactive-color="#13ce66">
|
|
</el-switch>
|
|
</div>
|
|
|
|
<div style="margin-top: 20px;">
|
|
<div name="1" v-show="!editMode">
|
|
<div>
|
|
<div class="item" v-for="(item, index) in localAttributes" :key="index">
|
|
<el-input v-model="item.key" :placeholder="'key' + index" class="half-width"></el-input>
|
|
<div class="split">:</div>
|
|
<el-input v-model="item.value" :placeholder="'value' + index" class="half-width" style="flex-grow: 3;"></el-input>
|
|
<el-icon @click="deleteItem(index)" style="margin-left: 5px;"><l-minus /></el-icon>
|
|
</div>
|
|
|
|
<div class="quick-add-root">
|
|
快速增加一些属性:
|
|
<div style="margin-top: 5px;">
|
|
<transition name="el-zoom-in-center">
|
|
<el-tag v-if="attributeKeys.indexOf('class') == -1" size="small" type="success" @click="onClassClick"
|
|
effect="dark" class="tag">Class
|
|
</el-tag>
|
|
</transition>
|
|
<transition name="el-zoom-in-center">
|
|
<el-tag v-if="attributeKeys.indexOf('@click') == -1" size="small" type="success" @click="onEventClick"
|
|
effect="dark" class="tag">点击事件</el-tag>
|
|
</transition>
|
|
<transition name="el-zoom-in-center">
|
|
<el-tag v-if="!attributeKeys.includes('__text__')" size="small" type="success" @click="onTextClick"
|
|
effect="dark" class="tag">文本内容</el-tag>
|
|
</transition>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div name="2" v-show="editMode">
|
|
<el-input type="textarea" :autosize="{ minRows: 4}" placeholder="请输入属性, 以key: value的形式(冒号后要有空格)"
|
|
v-model="textAttributes">
|
|
</el-input>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 10px;text-align:center;">
|
|
<el-tooltip class="item" effect="dark" content="新增属性 ctrl+a" placement="bottom">
|
|
<el-button type="primary" class="center" @click="createNew" circle>
|
|
<el-icon><circle-plus /></el-icon>
|
|
</el-button>
|
|
</el-tooltip>
|
|
<el-tooltip class="item" effect="dark" content="保存属性 ctrl+s" placement="bottom">
|
|
<el-button type="success" class="center" @click="save" circle>
|
|
<el-icon><l-refresh /></el-icon>
|
|
</el-button>
|
|
</el-tooltip>
|
|
<el-tooltip v-if="enableRemoveButton" class="item" effect="dark" content="移除该组件 ctrl+d" placement="bottom">
|
|
<el-button type="danger" class="center" @click="remove" circle>
|
|
<el-icon><l-delete /></el-icon>
|
|
</el-button>
|
|
</el-tooltip>
|
|
<el-tooltip v-if="enableBroButton" class="item" effect="dark" content="复制一个兄弟组件 ctrl+c" placement="bottom">
|
|
<el-button type="primary" class="center" @click="copyBro" circle>
|
|
<el-icon><document-copy /></el-icon>
|
|
</el-button>
|
|
</el-tooltip>
|
|
<div style="text-algin: center;">
|
|
<span class="shortcut-tip">支持快捷键操作</span>
|
|
</div>
|
|
</div>
|
|
|
|
</el-card>
|
|
</template>
|
|
|
|
<script>
|
|
import { getRawComponentKey, getRawComponentContent } from "@/utils/common";
|
|
import { brotherEleEnum, copyBroCode } from "@/libs/bro-ele-config";
|
|
import keymaster from "keymaster"
|
|
import { store as _store } from "@/libs/store.js";
|
|
|
|
export default {
|
|
props: ['__rawVueInfo__', 'enableRemoveButton', 'shortcutInitMode'],// __rawVueInfo__为当前编辑的原始代码对象, shortcutInitMode快捷键的初始化方式
|
|
data: function () {
|
|
return {
|
|
input: "",
|
|
localAttributes: [],
|
|
enable: true,
|
|
autoplay: false,
|
|
editMode: false,
|
|
textAttributes: ''
|
|
};
|
|
},
|
|
mounted() {
|
|
const container = document.querySelector(".attribute-container");
|
|
container.addEventListener("click", (event) => {
|
|
event.stopPropagation();
|
|
});
|
|
|
|
if (this.shortcutInitMode === 'auto') {
|
|
// 这种方式用于在检视图中,因为它依赖组件的创建和销毁
|
|
this.initShortcut();
|
|
}
|
|
},
|
|
|
|
beforeDestroy() {
|
|
if (this.shortcutInitMode === 'auto') {
|
|
// 防止内存泄漏
|
|
this.destroyShortcut();
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
destroyShortcut() {
|
|
console.log(`destroyShortcut by mode: ${this.shortcutInitMode}`)
|
|
keymaster.unbind('⌘+a, ctrl+a');
|
|
keymaster.unbind('⌘+s, ctrl+s');
|
|
keymaster.unbind('⌘+d, ctrl+d');
|
|
keymaster.unbind('⌘+c, ctrl+c');
|
|
},
|
|
|
|
initShortcut() {
|
|
console.log(`init by mode: ${this.shortcutInitMode}`)
|
|
keymaster('⌘+a, ctrl+a', () => {
|
|
if (this.enable) {
|
|
this.createNew();
|
|
return false
|
|
}
|
|
});
|
|
keymaster('⌘+s, ctrl+s', () => {
|
|
if (this.enable) {
|
|
this.save();
|
|
return false
|
|
}
|
|
});
|
|
keymaster('⌘+d, ctrl+d', () => {
|
|
if (this.enable) {
|
|
this.remove();
|
|
return false
|
|
}
|
|
});
|
|
keymaster('⌘+c, ctrl+c', () => {
|
|
if (this.enable && this.enableBroButton) {
|
|
this.copyBro();
|
|
return false
|
|
}
|
|
});
|
|
},
|
|
|
|
onClassClick() {
|
|
this.localAttributes.push({ key: "class", value: "class-name" });
|
|
},
|
|
onEventClick() {
|
|
this.localAttributes.push({ key: "@click", value: "onEventClick" });
|
|
},
|
|
onTextClick() {
|
|
this.localAttributes.push({ key: "__text__", value: "content" });
|
|
},
|
|
|
|
createNew() {
|
|
this.localAttributes.push({ key: "", value: "" });
|
|
},
|
|
save() {
|
|
try {
|
|
let resultList = [];
|
|
if (!this.editMode) {
|
|
resultList = this.localAttributes.filter((item) => {
|
|
return !!item.key;
|
|
});
|
|
} else {
|
|
const attributes = this.textAttributes.split('\n');
|
|
resultList = attributes.map(item => {
|
|
const [key, value] = item.split(": ");
|
|
return {
|
|
key, value
|
|
}
|
|
})
|
|
this.localAttributes = resultList;
|
|
}
|
|
|
|
this.$emit("save", { resultList, lc_id: this.rawInfoID });
|
|
|
|
this.$notify({
|
|
title: "提示",
|
|
message: '代码已更新',
|
|
position: 'bottom-right',
|
|
type: 'success'
|
|
});
|
|
} catch (error) {
|
|
this.$message.error(error);
|
|
}
|
|
},
|
|
remove() {
|
|
this.$emit("remove", { lc_id: this.rawInfoID });
|
|
},
|
|
deleteItem(index) {
|
|
this.localAttributes.splice(index, 1);
|
|
},
|
|
copyBro() {
|
|
copyBroCode(this.__rawVueInfo__);
|
|
_store.commit('onDragEnd');
|
|
},
|
|
onShow() {
|
|
// 这种方式适用于常规模式下的初始化,因为这个实例初始化后不会被销毁,一直常驻内存。但又不能受到其它实例销毁时的影响,所以需要明确的再次初始化。
|
|
this.initShortcut();
|
|
},
|
|
onHide() {
|
|
this.destroyShortcut();
|
|
},
|
|
},
|
|
|
|
computed: {
|
|
componentName() {
|
|
return this.__rawVueInfo__ ? getRawComponentKey(this.__rawVueInfo__) : '';
|
|
},
|
|
rawInfoID() {
|
|
return this.__rawVueInfo__ ? getRawComponentContent(this.__rawVueInfo__).lc_id : '';
|
|
},
|
|
enableBroButton() {
|
|
const checkResult = brotherEleEnum().find(item => {
|
|
return item.name == this.componentName;
|
|
});
|
|
return checkResult && checkResult.length != 0;
|
|
},
|
|
attributeList() {
|
|
const result = [];
|
|
const vueRawInfo = this.__rawVueInfo__;
|
|
if (vueRawInfo) {
|
|
const object = vueRawInfo[getRawComponentKey(vueRawInfo)];
|
|
|
|
for (const key in object) {
|
|
if (object.hasOwnProperty(key)) {
|
|
const element = object[key];
|
|
if (typeof element !== "object" && key != 'lc-mark' && key != 'lc_id') { // 这两个是保留字段,不对外提供使用
|
|
result.push({ key: key, value: element });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
attributeKeys() {
|
|
return this.localAttributes.map(item => item.key)
|
|
}
|
|
},
|
|
watch: {
|
|
attributeList: {
|
|
handler: function () {
|
|
this.localAttributes = this.attributeList;
|
|
},
|
|
immediate: true
|
|
},
|
|
localAttributes(newValue) {
|
|
if (newValue.length === 0) {
|
|
newValue.push({ key: "", value: "" });
|
|
}
|
|
|
|
this.textAttributes = newValue.map(item => `${item.key}: ${item.value}`).join('\n')
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.container {
|
|
padding: 10px;
|
|
width: 50%;
|
|
text-align: center;
|
|
}
|
|
|
|
.half-width {
|
|
width: 0%;
|
|
flex-grow: 2;
|
|
}
|
|
|
|
.center {
|
|
display: inline-block !important;
|
|
margin: 10px 10px;
|
|
}
|
|
|
|
.item {
|
|
display: flex;
|
|
margin-bottom: 10px;
|
|
align-items: center;
|
|
}
|
|
|
|
.quick-add-root {
|
|
padding: 5px 10px;
|
|
border: 1px dashed #c6c6c6;
|
|
border-radius: 5px;
|
|
font-size: 12px;
|
|
color: gray;
|
|
|
|
.tag {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.tag:last-child{
|
|
margin-right: 0;
|
|
}
|
|
}
|
|
|
|
.split {
|
|
width: 30px;
|
|
text-align: center;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.el-icon-plus,
|
|
.el-icon-minus {
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.el-button + .el-button {
|
|
margin-left: 0px;
|
|
}
|
|
|
|
.shortcut-tip {
|
|
font-size: 12px;
|
|
color: grey;
|
|
padding: 2px;
|
|
border-bottom: grey solid 1px;
|
|
}
|
|
</style>
|