Files
lowcode-frontend/preview/views/MainView.vue

281 lines
6.9 KiB
Vue

<template>
<div class="low_box">
<div class="header">
<div class="title">可视化系统</div>
<div class="web">pc</div>
<div class="btn">
<a-space>
<a-button :disabled="!store.canUndo" @click="store.undo">
<template #icon>
<icon-left />
</template>
</a-button>
<a-button :disabled="!store.canRedo" @click="store.redo">
<template #icon>
<icon-right />
</template>
</a-button>
<a-button type="primary" @click="save">保存</a-button>
<a-button type="primary" @click="view">预览</a-button>
</a-space>
</div>
</div>
<div class="content">
<div class="left">
<div class="title">组件</div>
<VueDraggable
v-model="store.components"
:animation="150"
:group="{ name: 'designer', pull: 'clone', put: false }"
:sort="false"
:clone="clone"
@start="onStart"
@end="onEnd"
>
<div v-for="item in store.components" :key="item.id" class="tem_btn">
{{ item.name }}
</div>
</VueDraggable>
</div>
<div ref="targetContent" class="center">
<VueDraggable
v-model="store.previewScheme"
:sort="true"
:animation="150"
group="designer"
ghost-class="ghost"
class="canvas"
@start="onPreviewStart"
@update="onPreviewUpdate"
@stop="onPreviewStop"
>
<DynamicComponent v-for="component in store.previewScheme" :key="component.id" :componentData="component">
{{ component.id }}
</DynamicComponent>
</VueDraggable>
</div>
<div class="right">
<PropertyEditor :scheme="store.nowComponentsData"></PropertyEditor>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { RadioGroup, Radio } from '@arco-design/web-vue';
import { onMounted, ref, watch } from 'vue';
import { uuid } from 'lsp-uuid';
import { componentScheme } from '@/schemes/scheme';
import { useSchemeStore } from '@/stores/useSchemeStore';
import { IComponent } from '@/type/IComponent';
import DynamicComponent from '@/components/DynamicComponent.vue';
import PropertyEditor from '@/components/PropertyEditor.vue';
import { DraggableEvent, VueDraggable } from 'vue-draggable-plus';
import axios from 'axios';
let list0 = ref([]);
let list = ref([]);
let componentsList = [];
const store = useSchemeStore();
// watch(store, (n) => {
// console.log("store发生了变化", n);
// });
const baseScheme = {
"type": "AdaptivePage",
"name": "AdaptivePage",
"id": uuid(),
"version": "2.0",
"props": {},
"class": "",
"style": "",
"variables": {},
"dataSources": {},
"functions": {},
"orchestrations": {},
"events": {},
"slots": {},
"header": {},
"footer": {},
"children": [],
"meta": {}
};
store.$onAction(
({
name, // action 名称
after, // 在 action 返回或解决后的钩子
onError, // action 抛出或拒绝的钩子
}) => {
after((result) => {
// console.log(`store action-${name}回调后:` + result);
});
onError((error) => {
console.warn(`Failed "${name}" after\nError: ${error}.`);
});
}
);
// 初始化scheme
const initScheme = async () => {
// try {
// const response = await axios.get('http://localhost:3000/load');
// if (response.data && Array.isArray(response.data)) {
// store.initPreviewScheme(response.data);
// } else {
// store.initPreviewScheme([baseScheme]);
// }
// } catch (error) {
// console.error('Error loading data:', error);
// store.initPreviewScheme([baseScheme]);
// }
componentsList = Object.values(componentScheme);
store.initComponents(componentsList);
};
onMounted(() => {
initScheme();
});
function clone(element: Record<'name' | 'id' | 'type' | 'props' | 'class' | 'text' | 'style' | 'slots' | 'visible' | 'disable' | 'children', IComponent>) {
console.log("clone", element);
return {
id: `${element.type}-${uuid()}`,
name: element.name,
type: element.type,
props: element.props,
class: element.class,
designer: '',
text: element.text,
children: element.children || [],
style: element.style,
visible: element.visible,
slots: element.slots,
disable: element.visible,
events: {},
loop: {},
};
}
const onEnd = (event: DraggableEvent) => {
console.log("onEnd", event);
store.nowComponentsData = event.clonedData;
};
const onStart = (event) => {
console.log("onStart", event);
};
const onPreviewStart = (event) => {
console.log("onPreviewStart", event);
};
const onPreviewUpdate = (event) => {
console.log("onPreviewUpdate", event);
};
const onPreviewStop = (event) => {
console.log(event);
};
const save = async () => {
try {
await axios.post('http://localhost:3000/save', store.previewScheme);
alert('保存成功!');
} catch (error) {
console.error('Error saving data:', error);
alert('保存失败!');
}
};
const view = () => {
localStorage.setItem("lowcode", JSON.stringify(store.previewScheme));
window.open(location.href.replace("/#/", "/preview/#/"));
};
</script>
<style lang="scss" scoped>
.low_box {
width: 100%;
height: 100%;
overflow: hidden;
background-color: #f2f2f2;
.header {
height: 65px;
background-color: #fff;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
.content {
display: flex;
flex-direction: row;
height: calc(100vh - 66px);
.left {
width: 300px;
height: 100%;
overflow: hidden;
background-color: #fff;
border-top: 1px solid #dddddd;
overflow-y: auto;
.title {
font-size: 16px;
color: #333;
line-height: 50px;
width: calc(100% - 40px);
margin-left: 20px;
border-bottom: 1px solid #f2f2f2;
clear: both;
}
.tem_btn {
padding: 0 10px;
height: 30px;
line-height: 30px;
text-align: center;
font-size: 14px;
color: #666;
background-color: #f2f2f2;
border-radius: 4px;
cursor: move;
user-select: none;
margin-top: 20px;
float: left;
margin-left: 20px;
}
}
.center {
flex: 1;
padding: 20px;
background-color: #f2f2f2;
.canvas {
background-color: #fff;
width: 100%;
height: 100%;
overflow-y: auto; /* 确保当内容超出时,出现垂直滚动条 */
}
.ghost {
background-color: #f2f3f5 !important;
}
}
.right {
width: 300px;
height: 100%;
overflow: hidden;
background-color: #fff;
border-top: 1px solid #dddddd;
}
}
}
</style>