forked from opentiny/tiny-engine
176 lines
4.0 KiB
Vue
176 lines
4.0 KiB
Vue
<template>
|
|
<div class="meta-modal-wrap">
|
|
<tiny-button @click="open">{{ title }}</tiny-button>
|
|
<div v-if="modalState.created" v-show="modalState.show" class="mask" @click.self="close">
|
|
<div class="property-item">
|
|
<div class="property-item-header">
|
|
<span class="header-text">{{ title }}</span>
|
|
<span class="icon-wrap">
|
|
<icon-close class="header-icon" @click="close"></icon-close>
|
|
</span>
|
|
</div>
|
|
<slot name="body">
|
|
<div class="meta-modal-body">
|
|
<meta-child-item :meta="meta" @update:modelValue="onValueChange"></meta-child-item>
|
|
</div>
|
|
</slot>
|
|
<slot name="footer">
|
|
<div v-show="false" class="property-item-footer">
|
|
<tiny-button @click="close">关闭</tiny-button>
|
|
<tiny-button type="info" @click="save">保存</tiny-button>
|
|
</div>
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { Button } from '@opentiny/vue'
|
|
import { iconClose } from '@opentiny/vue-icon'
|
|
import { reactive, computed } from 'vue'
|
|
import MetaChildItem from './MetaChildItem.vue'
|
|
|
|
export default {
|
|
name: 'MetaModalItem',
|
|
components: {
|
|
MetaChildItem,
|
|
TinyButton: Button,
|
|
IconClose: iconClose()
|
|
},
|
|
props: {
|
|
meta: {
|
|
type: Object,
|
|
default: () => {}
|
|
}
|
|
},
|
|
emits: ['save'],
|
|
setup(props, { emit }) {
|
|
const modalState = reactive({
|
|
show: false,
|
|
created: false
|
|
})
|
|
const title = computed(() => `编辑${props.meta.label?.text?.zh_CN || props.meta.property || '属性'}`)
|
|
|
|
// 关闭编辑器
|
|
const close = () => {
|
|
modalState.show = false
|
|
emit('close')
|
|
}
|
|
|
|
// 打开编辑器
|
|
const open = () => {
|
|
if (!modalState.created) {
|
|
modalState.created = true
|
|
}
|
|
|
|
modalState.show = true
|
|
}
|
|
|
|
const save = (value) => {
|
|
emit('update:modelValue', value)
|
|
|
|
close()
|
|
}
|
|
|
|
const onValueChange = ({ propertyKey, propertyValue }) => {
|
|
const newPropertyValue = { ...props.meta.widget?.props?.modelValue, [propertyKey]: propertyValue }
|
|
emit('update:modelValue', newPropertyValue)
|
|
}
|
|
|
|
return {
|
|
title,
|
|
modalState,
|
|
save,
|
|
close,
|
|
open,
|
|
onValueChange
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.mask {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: fixed;
|
|
z-index: 999;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
.property-item {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
z-index: 9999;
|
|
width: 50vw;
|
|
height: fit-content;
|
|
min-height: 200px;
|
|
max-height: 90vh;
|
|
padding: 0 16px;
|
|
margin: auto;
|
|
border-radius: 4px;
|
|
border: 1px solid var(--ti-lowcode-tabs-border-color);
|
|
background-color: var(--ti-lowcode-toolbar-bg);
|
|
box-shadow: rgb(0 0 0 / 30%) 0px 1px 15px 0px;
|
|
|
|
.property-item-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px 0;
|
|
color: var(--ti-lowcode-toolbar-breadcrumb-color);
|
|
|
|
.header-title {
|
|
font-size: 14px;
|
|
}
|
|
|
|
.icon-wrap {
|
|
width: 20px;
|
|
height: 20px;
|
|
color: var(--ti-lowcode-text-color);
|
|
font-size: 16px;
|
|
border-radius: 2px;
|
|
cursor: pointer;
|
|
display: inline-flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
transition: 0.3s;
|
|
&:hover {
|
|
color: var(--ti-lowcode-toolbar-icon-color);
|
|
background: var(--ti-lowcode-icon-hover-bg);
|
|
}
|
|
}
|
|
}
|
|
|
|
.property-item-content {
|
|
// min-height: 200px;
|
|
height: calc(100% - 86px);
|
|
box-shadow: 0px 0px 4px rgb(0 0 0 / 20%);
|
|
}
|
|
|
|
.property-item-footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
padding: 10px 0;
|
|
}
|
|
}
|
|
.meta-modal-body {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
}
|
|
.meta-modal-wrap {
|
|
:deep(.items-container) {
|
|
.meta-config-item {
|
|
width: 50%;
|
|
}
|
|
}
|
|
}
|
|
</style>
|