<template>
<div class="setting-container">
<div class="flex">
<ComponentList v-if="components.length" class="list" :data="componentList" @change="change"></ComponentList>
<div class="attrs-panel">
<PropertyList class="list" :data="propertyNames"></PropertyList>
<PropertyCanvas class="canvas" design :schema="componentSchema"></PropertyCanvas>
<SettingPanel class="setting"></SettingPanel>
</div>
<SourceEditor v-if="showCode" class="editor" :content="schemaCode"></SourceEditor>
</div>
<div class="confirm-box">
<tiny-button type="primary" @click="confirmSelect">保存</tiny-button>
</div>
</div>
</template>
<script>
import { computed, watchEffect } from 'vue'
import { Button } from '@opentiny/vue'
import ComponentList from './components/ComponentList.vue'
import PropertyList from './components/PropertyList.vue'
import PropertyCanvas from './components/PropertyCanvas.vue'
import SettingPanel from './components/SettingPanel.vue'
import SourceEditor from './components/SourceEditor.vue'
import store, { getSchemaByComponetName } from './store'
export default {
components: {
TinyButton: Button,
ComponentList,
PropertyList,
PropertyCanvas,
SettingPanel,
SourceEditor
},
props: {
components: {
type: Array,
default: () => [
{
label: '',
key: '',
properties: {}
}
]
},
properties: Object,
modelValue: [],
showCode: {
type: Boolean,
default: false
}
},
setup(props, { emit }) {
const componentList = computed(() => store.componentList || [])
const propertyNames = computed(() => Object.keys(store.currentProperties || {}))
const componentSchema = computed(() => store.currentSchema || [])
const schemaCode = computed(() => JSON.stringify(store.currentSchema || [], null, 2))
watchEffect(() => {
store.currentProperties = props.properties
store.currentSchema = props.modelValue || []
})
const change = ({ key, properties }) => {
if (key) {
const keys = key.split('.')
store.currentKeys = keys
store.currentComponent = keys[0]
store.currentProperties = properties
store.currentSchema = getSchemaByComponetName(store.currentComponent)
}
}
const confirmSelect = () => {
emit('update:modelValue', store.currentSchema)
emit('close')
}
const cancel = () => {
window.close()
}
return {
componentList,
propertyNames,
componentSchema,
schemaCode,
confirmSelect,
change,
cancel
}
}
}
</script>
<style lang="less">
:root {
--te-setting-design-secondary-text-color: #adb0b8;
--te-setting-design-hover-bg-color: #f2f5fc;
--te-lowcode-mask-bg: #fafafa;
--max-height: calc(65vh - 70px);
}
html {
font-size: 14px;
}
body {
padding: 0;
margin: 0;
font-family: 'Helvetica Neue', Helvetica, -apple-system, Arial, 'Lucida Grande', system-ui, BlinkMacSystemFont,
'Segoe UI', Roboto, sans-serif;
}
body::-webkit-scrollbar {
width: 0.5rem;
background-color: rgba(255, 255, 255, 0.1);
box-shadow: none;
}
body::-webkit-scrollbar-track {
box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.05);
}
body::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.15);
outline: 1px solid slategrey;
}
body {
--base-left-panel-width: 280px;
--base-right-panel-width: 280px;
--base-top-panel-height: 35px;
--base-bottom-panel-height: 30px;
--base-nav-panel-width: 40px;
-webkit-font-smoothing: subpixel-antialiased;
background: #f9f9f9;
}
@supports not selector(::webkit-scrollbar) {
body {
scrollbar-color: rgba(0, 0, 0, 0.1) #fff;
scrollbar-width: thin;
}
}
ol,
ul {
list-style: none;
}
a {
cursor: pointer;
background-image: none;
text-decoration: none;
outline: none;
&:focus,
&:active,
&:hover {
outline: none;
text-decoration: none;
}
}
dl,
dt,
dd,
ul,
ol,
li,
th,
td {
margin: 0;
padding: 0;
}
.sortable-chosen {
background: #c5d4f6;
}
.mask {
.source-code {
.tiny-button {
background-color: #1476ff;
}
}
}
</style>
<style lang="less" scoped>
.setting-container {
display: flex;
flex-direction: column;
max-height: var(--max-height);
overflow: auto;
background-color: #fff;
}
.flex {
display: flex;
width: 100%;
overflow-y: auto;
.attrs-panel {
display: grid;
grid-template-columns: 150px 2fr 2fr;
width: 100%;
}
.list {
padding: 10px;
}
.canvas {
background: var(--te-setting-design-hover-bg-color);
padding: 20px;
margin: 0 20px;
}
.setting {
margin-left: 20px;
}
.editor {
width: 500px;
height: 100%;
border: 1px #ddd solid;
}
}
.confirm-box {
text-align: center;
padding: 20px 0;
}
</style>