forked from opentiny/tiny-engine
366 lines
9.2 KiB
Vue
366 lines
9.2 KiB
Vue
<template>
|
|
<plugin-setting
|
|
v-if="isOpen"
|
|
class="plugin-block-setting"
|
|
title="设置"
|
|
@mouseleave="onMouseLeave"
|
|
@click="handleClick"
|
|
>
|
|
<template #header>
|
|
<tiny-button @click="updateBlock">保存 </tiny-button>
|
|
<tiny-button
|
|
type="primary"
|
|
:disabled="globalConfig.dslMode === 'Angular'"
|
|
class="publish-btn"
|
|
@click="showDeployBlockDialog"
|
|
>发布
|
|
</tiny-button>
|
|
<svg-button name="delete" tips="删除" placement="top" @click="deleteBlock"></svg-button>
|
|
<close-icon @click="closePanel"></close-icon>
|
|
</template>
|
|
<template #content>
|
|
<tiny-collapse v-model="state.activeName">
|
|
<tiny-collapse-item title="基本设置" name="base">
|
|
<block-config ref="blockConfigForm"></block-config>
|
|
</tiny-collapse-item>
|
|
<tiny-collapse-item name="attribute">
|
|
<template #title>
|
|
<div class="title-wrapper">
|
|
<span>设置区块暴露属性</span>
|
|
</div>
|
|
</template>
|
|
<div class="block-attribute">
|
|
<block-property :show-video="state.showAttributeGuide">
|
|
<template #video>
|
|
<div class="video-close" @click.stop="handleShowGuide('showAttributeGuide')">
|
|
<span class="close-text">收起</span>
|
|
<close-icon></close-icon>
|
|
</div>
|
|
</template>
|
|
</block-property>
|
|
</div>
|
|
</tiny-collapse-item>
|
|
<tiny-collapse-item title="事件设置" name="event">
|
|
<template #title>
|
|
<div class="title-wrapper">
|
|
<span>事件设置</span>
|
|
</div>
|
|
</template>
|
|
<div class="block-event">
|
|
<block-event :show-video="state.showEventGuide">
|
|
<template #video>
|
|
<div class="video-close" @click.stop="handleShowGuide('showEventGuide')">
|
|
<span class="close-text">收起</span>
|
|
<close-icon></close-icon>
|
|
</div>
|
|
</template>
|
|
</block-event>
|
|
</div>
|
|
</tiny-collapse-item>
|
|
<tiny-collapse-item title="生命周期设置" name="lifeCycle">
|
|
<div class="life-cycles-container">
|
|
<life-cycles :isPage="false" :bindLifeCycles="state.bindLifeCycles" @bind="bindLifeCycles"></life-cycles>
|
|
</div>
|
|
</tiny-collapse-item>
|
|
<tiny-collapse-item title="版本列表" name="history">
|
|
<block-history-list
|
|
:is-block-manage="true"
|
|
:history="state.backupList"
|
|
@preview="previewHistory"
|
|
></block-history-list>
|
|
</tiny-collapse-item>
|
|
</tiny-collapse>
|
|
</template>
|
|
</plugin-setting>
|
|
<block-deploy-dialog v-model:visible="state.showDeployBlock" :nextVersion="nextVersion"></block-deploy-dialog>
|
|
</template>
|
|
|
|
<script lang="jsx">
|
|
import { reactive, ref, watch, watchEffect, computed } from 'vue'
|
|
import { Button as TinyButton, Collapse as TinyCollapse, CollapseItem as TinyCollapseItem } from '@opentiny/vue'
|
|
import { getGlobalConfig, useModal } from '@opentiny/tiny-engine-controller'
|
|
import { BlockHistoryList, PluginSetting, CloseIcon, SvgButton } from '@opentiny/tiny-engine-common'
|
|
import { previewBlock } from '@opentiny/tiny-engine-controller/js/preview'
|
|
import { LifeCycles } from '@opentiny/tiny-engine-common'
|
|
import BlockEvent from './BlockEvent.vue'
|
|
import BlockConfig from './BlockConfig.vue'
|
|
import BlockProperty from './BlockProperty.vue'
|
|
import {
|
|
getEditBlock,
|
|
delBlock,
|
|
saveBlock,
|
|
DEPLOY_TIPS,
|
|
getBlockBase64,
|
|
setConfigItemVisible,
|
|
saveArrayConfig
|
|
} from './js/blockSetting'
|
|
import { BlockDeployDialog } from '@opentiny/tiny-engine-common'
|
|
|
|
const isOpen = ref(false)
|
|
|
|
export const openPanel = () => {
|
|
isOpen.value = true
|
|
}
|
|
|
|
export const closePanel = () => {
|
|
isOpen.value = false
|
|
}
|
|
|
|
const removeBlock = delBlock(closePanel)
|
|
|
|
export default {
|
|
components: {
|
|
TinyButton,
|
|
TinyCollapse,
|
|
TinyCollapseItem,
|
|
BlockEvent,
|
|
BlockConfig,
|
|
PluginSetting,
|
|
BlockProperty,
|
|
BlockHistoryList,
|
|
LifeCycles,
|
|
CloseIcon,
|
|
BlockDeployDialog,
|
|
SvgButton
|
|
},
|
|
props: {
|
|
modelValue: {
|
|
type: Object,
|
|
default: () => ({})
|
|
}
|
|
},
|
|
setup() {
|
|
const { confirm } = useModal()
|
|
const editBlock = computed(getEditBlock)
|
|
const blockConfigForm = ref(null)
|
|
|
|
const state = reactive({
|
|
activeName: ['base', 'attribute', 'event', 'lifeCycle', 'history'],
|
|
backupList: [],
|
|
showDeployBlock: false,
|
|
bindLifeCycles: {},
|
|
showAttributeGuide: false,
|
|
showEventGuide: false
|
|
})
|
|
|
|
watchEffect(() => {
|
|
state.bindLifeCycles = getEditBlock()?.content?.lifeCycles || {}
|
|
})
|
|
|
|
// 按时间最新提交的版本的修订版本号+1, 提示输入的下一个版本
|
|
const nextVersion = computed(() => {
|
|
const backupList = state.backupList || []
|
|
|
|
let latestVersion = '1.0.0'
|
|
let latestTime = 0
|
|
backupList.forEach((v) => {
|
|
const vTime = new Date(v.created_at).getTime()
|
|
|
|
if (vTime > latestTime) {
|
|
latestTime = vTime
|
|
latestVersion = v.version
|
|
}
|
|
})
|
|
// version 符合X.Y.Z的字符结构
|
|
return latestVersion.replace(/\d+$/, (match) => Number(match) + 1)
|
|
})
|
|
|
|
watch(
|
|
() => {
|
|
const block = getEditBlock()
|
|
return [block?.id, block?.histories?.length]
|
|
},
|
|
() => {
|
|
const block = getEditBlock()
|
|
|
|
if (block?.id) {
|
|
state.backupList = block.histories
|
|
}
|
|
}
|
|
)
|
|
|
|
const deleteBlock = () => {
|
|
const title = '删除区块'
|
|
const status = 'custom'
|
|
const message = '您确认删除该区块吗?'
|
|
|
|
confirm({ title, status, message, exec: removeBlock })
|
|
}
|
|
|
|
const updateBlock = () => {
|
|
saveArrayConfig()
|
|
blockConfigForm.value.validateForm().then(() => {
|
|
const block = getEditBlock()
|
|
|
|
if (block.content?.schema?.properties?.[0]?.content.length > 1) {
|
|
const contentList = block.content.schema.properties[0].content
|
|
const propertyList = contentList.map((e) => e.property)
|
|
if (new Set(propertyList).size !== propertyList.length) {
|
|
useModal().message({
|
|
message: '属性设置包含重复属性,请修改后重试',
|
|
status: 'error'
|
|
})
|
|
return false
|
|
}
|
|
}
|
|
const title = '保存区块'
|
|
const status = 'custom'
|
|
const message = '您确认修改并保存该区块吗?'
|
|
|
|
confirm({
|
|
title,
|
|
status,
|
|
message,
|
|
exec: async () => {
|
|
// 获取区块截图
|
|
block.screenshot = await getBlockBase64()
|
|
saveBlock(block)
|
|
}
|
|
})
|
|
|
|
return undefined
|
|
})
|
|
}
|
|
|
|
const showDeployBlockDialog = () => {
|
|
saveArrayConfig()
|
|
blockConfigForm.value.validateForm().then(() => {
|
|
state.showDeployBlock = true
|
|
})
|
|
}
|
|
|
|
const bindLifeCycles = (lifeCycles) => {
|
|
const block = getEditBlock()
|
|
if (!block?.content) {
|
|
return
|
|
}
|
|
|
|
block.content.lifeCycles = lifeCycles
|
|
}
|
|
|
|
const previewHistory = (item) => {
|
|
item &&
|
|
previewBlock({
|
|
id: item.blockId,
|
|
history: item.id,
|
|
framework: getGlobalConfig()?.dslMode,
|
|
platform: getGlobalConfig()?.platformId
|
|
})
|
|
}
|
|
|
|
const onMouseLeave = () => {
|
|
blockConfigForm.value?.clearValidateForm()
|
|
}
|
|
|
|
const handleShowGuide = (type) => {
|
|
state[type] = !state[type]
|
|
}
|
|
|
|
const handleClick = () => {
|
|
setConfigItemVisible(false)
|
|
}
|
|
|
|
return {
|
|
state,
|
|
isOpen,
|
|
nextVersion,
|
|
showDeployBlockDialog,
|
|
closePanel,
|
|
deleteBlock,
|
|
updateBlock,
|
|
bindLifeCycles,
|
|
previewHistory,
|
|
editBlock,
|
|
blockConfigForm,
|
|
deployTips: DEPLOY_TIPS,
|
|
globalConfig: getGlobalConfig(),
|
|
onMouseLeave,
|
|
handleClick,
|
|
handleShowGuide
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.plugin-block-setting {
|
|
.publish-btn {
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.video-close {
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
.close-text {
|
|
display: inline-block;
|
|
vertical-align: top;
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
:deep(.plugin-setting-content) {
|
|
padding: 16px 0;
|
|
}
|
|
|
|
:deep(.icon-wrap) {
|
|
margin-right: 8px;
|
|
}
|
|
|
|
:deep(.tiny-col) {
|
|
padding-left: 0;
|
|
}
|
|
|
|
:deep(.block-guide) {
|
|
width: 100%;
|
|
|
|
.content {
|
|
.guide-video {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
}
|
|
}
|
|
|
|
.life-cycles-container {
|
|
padding: 16px;
|
|
}
|
|
|
|
.block-attribute,
|
|
.block-event {
|
|
position: relative;
|
|
padding: 16px;
|
|
:deep(.tiny-col) {
|
|
position: inherit;
|
|
}
|
|
|
|
:deep(.show-video-text) {
|
|
position: absolute;
|
|
z-index: 100;
|
|
top: -23px;
|
|
right: 40px;
|
|
}
|
|
}
|
|
|
|
:deep(.title-wrapper) {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
width: 100%;
|
|
|
|
.show-video-text {
|
|
display: inline-block;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
|
|
.svg-icon {
|
|
vertical-align: middle;
|
|
display: inline-block;
|
|
font-size: 20px;
|
|
margin-right: 3px;
|
|
}
|
|
|
|
color: var(--ti-lowcode-block-video-tip-color);
|
|
}
|
|
}
|
|
}
|
|
</style>
|