213 lines
3.6 KiB
Vue
213 lines
3.6 KiB
Vue
![]() |
<template>
|
||
|
<div class="dp-lump">
|
||
|
<el-scrollbar>
|
||
|
<div class="group" v-for="(item, index) in tab.list" :key="index">
|
||
|
<p class="label">{{ item.label }}</p>
|
||
|
|
||
|
<draggable
|
||
|
v-model="item.children"
|
||
|
class="list"
|
||
|
item-key="label"
|
||
|
:sort="false"
|
||
|
:group="{
|
||
|
name: 'A',
|
||
|
pull: 'clone',
|
||
|
put: false
|
||
|
}"
|
||
|
:clone="onClone"
|
||
|
@end="onEnd"
|
||
|
>
|
||
|
<template #item="{ element: item }">
|
||
|
<div class="item" @click="add(item)">
|
||
|
<img :src="icons[item.name]" />
|
||
|
<span>{{ item.label }}</span>
|
||
|
</div>
|
||
|
</template>
|
||
|
</draggable>
|
||
|
</div>
|
||
|
</el-scrollbar>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script lang="tsx" setup>
|
||
|
import { ElMessage } from "element-plus";
|
||
|
import { cloneDeep } from "lodash-es";
|
||
|
import { reactive } from "vue";
|
||
|
import Draggable from "vuedraggable/src/vuedraggable";
|
||
|
import { useDp } from "../hooks";
|
||
|
import { Dp } from "../types";
|
||
|
import { useCool } from "/@/cool";
|
||
|
import { uuid } from "/@/cool/utils";
|
||
|
import { useData } from "../data";
|
||
|
|
||
|
const { mitt } = useCool();
|
||
|
const { dp } = useDp();
|
||
|
const { Base, Marketing, Ability, Other } = useData();
|
||
|
|
||
|
|
||
|
// 图标
|
||
|
const files: any = import.meta.glob("/src/modules/fixtures/static/icon/*", {
|
||
|
eager: true
|
||
|
});
|
||
|
|
||
|
const icons = reactive<any>({});
|
||
|
|
||
|
for (const i in files) {
|
||
|
icons[i.replace("/src/modules/fixtures/static/icon/", "").replace(".png", "")] =
|
||
|
files[i].default;
|
||
|
}
|
||
|
|
||
|
// 数据
|
||
|
const tab = reactive<{ list: { label: string; children: Dp.Item[] }[] }>({
|
||
|
list: [
|
||
|
{
|
||
|
label: "基础组件",
|
||
|
children: Base
|
||
|
},
|
||
|
{
|
||
|
label: "营销组件",
|
||
|
children: Marketing
|
||
|
},
|
||
|
{
|
||
|
label: "功能组件",
|
||
|
children: Ability
|
||
|
},
|
||
|
{
|
||
|
label: "其他组件",
|
||
|
children: Other
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
|
||
|
// 解析
|
||
|
function parse(item: Dp.Item) {
|
||
|
function next(data: Dp.Item, options: any = {}) {
|
||
|
const { autoInc = true } = options;
|
||
|
|
||
|
const d: Dp.Item = cloneDeep({
|
||
|
...data,
|
||
|
id: uuid()
|
||
|
});
|
||
|
|
||
|
if (autoInc) {
|
||
|
// 序号
|
||
|
data._index = data._index !== undefined ? data._index + 1 : 0;
|
||
|
|
||
|
if (data._index > 0) {
|
||
|
d.label += data._index;
|
||
|
}
|
||
|
}
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
let v: any = null;
|
||
|
|
||
|
if (item.isOnly) {
|
||
|
if (dp.hasTemp(item.name)) {
|
||
|
ElMessage.warning("该组件只可以添加一个");
|
||
|
return undefined;
|
||
|
}
|
||
|
v = next(item);
|
||
|
} else {
|
||
|
v = next(item);
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
// 获取配置
|
||
|
function getConfig(name: string) {
|
||
|
let d: any = null;
|
||
|
tab.list.find((e) => {
|
||
|
d = e.children?.find((a) => a.name == name);
|
||
|
|
||
|
return !!d;
|
||
|
});
|
||
|
|
||
|
return d ? parse(d)?.config : {};
|
||
|
}
|
||
|
|
||
|
// 复制
|
||
|
let _d: any = null;
|
||
|
|
||
|
function onClone(item: any) {
|
||
|
if (item.name === "suspension" && dp.hasSuspension()) {
|
||
|
return;
|
||
|
}
|
||
|
// 记录复制的数据
|
||
|
_d = parse(item);
|
||
|
|
||
|
return _d;
|
||
|
}
|
||
|
|
||
|
function add(item: any) {
|
||
|
dp.add(parse(item));
|
||
|
dp.scrollToBottom();
|
||
|
}
|
||
|
|
||
|
function onEnd() {
|
||
|
if (_d) {
|
||
|
mitt.emit("dp.setActive", _d.id);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
defineExpose({
|
||
|
getConfig
|
||
|
});
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
.dp-lump {
|
||
|
width: 350px;
|
||
|
background-color: #fff;
|
||
|
border-radius: 5px;
|
||
|
|
||
|
.group {
|
||
|
.label {
|
||
|
font-size: 15px;
|
||
|
padding: 15px 20px;
|
||
|
}
|
||
|
|
||
|
.list {
|
||
|
display: flex;
|
||
|
flex-wrap: wrap;
|
||
|
padding: 0 8px;
|
||
|
|
||
|
.item {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
height: 40px;
|
||
|
width: calc(50% - 16px);
|
||
|
margin: 0 8px 6px 8px;
|
||
|
padding: 0 8px 0 18px;
|
||
|
box-sizing: border-box;
|
||
|
border: 1px dashed currentColor;
|
||
|
border-radius: 3px;
|
||
|
cursor: pointer;
|
||
|
color: #bfbfbf;
|
||
|
|
||
|
img {
|
||
|
height: 20px;
|
||
|
width: 20px;
|
||
|
margin-right: 14px;
|
||
|
}
|
||
|
|
||
|
span {
|
||
|
font-size: 15px;
|
||
|
}
|
||
|
|
||
|
&:hover {
|
||
|
border-color: var(--color-primary);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&:last-child {
|
||
|
.list {
|
||
|
padding-bottom: 20px;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|