<template>
<div class="toolbar-save">
<tiny-popover :visible-arrow="false" width="203" trigger="hover">
<template #reference>
<toolbar-base
:content="isLoading ? '保存中' : '保存'"
:icon="options.icon.default || options.icon"
:options="{ ...options, showDots: !isSaved() }"
@click-api="openApi"
>
<template #button>
<svg-icon :name="iconExpand"></svg-icon>
</template>
<template #default>
<tiny-dialog-box
class="dialog-box"
:modal="false"
:fullscreen="true"
:append-to-body="true"
:visible="state.visible"
title="Schema 本地与线上差异"
@update:visible="state.visible = $event"
>
<vue-monaco
v-if="state.visible"
ref="editor"
class="monaco-editor"
:diffEditor="true"
:options="editorOptions"
:value="state.code"
:original="state.originalCode"
></vue-monaco>
<template #footer>
<tiny-button @click="close">取 消</tiny-button>
<tiny-button type="primary" @click="saveApi">保 存</tiny-button>
</template>
</tiny-dialog-box>
</template>
</toolbar-base>
</template>
<div class="save-style">
<div class="save-setting">保存设置</div>
<tiny-checkbox v-model="state.checked" name="tiny-checkbox">自动保存</tiny-checkbox>
<div class="save-time">
<div class="save-time-label">保存间隔</div>
<tiny-select v-model="state.timeValue" :options="delayOptions" :disabled="!state.checked" autocomplete>
</tiny-select>
</div>
<div class="save-button-group">
<tiny-button type="primary" @click="autoSave">设置并保存</tiny-button>
</div>
</div>
</tiny-popover>
</div>
</template>
<script>
import { reactive, ref, onUnmounted } from 'vue'
import { VueMonaco } from '@opentiny/tiny-engine-common'
import { Button, Popover, DialogBox, Checkbox, Select } from '@opentiny/vue'
import { useCanvas } from '@opentiny/tiny-engine-meta-register'
import { ToolbarBase } from '@opentiny/tiny-engine-common'
import { openCommon, saveCommon } from './js/index'
import { isLoading } from './js/index'
export const api = {
saveCommon,
openCommon
}
export default {
components: {
VueMonaco,
TinyButton: Button,
TinyPopover: Popover,
TinyDialogBox: DialogBox,
TinyCheckbox: Checkbox,
TinySelect: Select,
ToolbarBase
},
props: {
iconExpand: {
type: String,
default: 'down-arrow'
},
options: {
type: Object,
default: () => ({})
}
},
setup() {
const { isSaved } = useCanvas()
const delayOptions = [
{ value: 5, label: '5分钟' },
{ value: 10, label: '10分钟' },
{ value: 15, label: '15分钟' }
]
const state = reactive({
visible: false,
code: '',
originalCode: '',
disabled: false,
timeValue: 5,
checked: false,
preservationTime: null
})
const editor = ref(null)
const close = () => {
state.visible = false
state.originalCode = ''
}
const openApi = () => {
if (!isLoading.value) {
openCommon()
}
}
const saveApi = () => {
saveCommon()
}
const editorOptions = {
language: 'json',
lineNumbers: true,
minimap: {
enabled: false
}
}
const saveSetTimeout = () => {
clearTimeout(state.preservationTime)
state.preservationTime = setTimeout(() => {
openApi()
saveSetTimeout()
}, state.timeValue * 60 * 1000)
}
const autoSave = () => {
if (state.checked) {
saveSetTimeout()
} else {
clearTimeout(state.preservationTime)
}
}
onUnmounted(() => {
clearTimeout(state.preservationTime)
})
return {
state,
editor,
editorOptions,
isLoading,
isSaved,
close,
openApi,
saveApi,
delayOptions,
autoSave
}
}
}
</script>
<style lang="less" scoped>
.dots {
width: 6px;
height: 6px;
background: var(--ti-lowcode-toolbar-dot-color);
border-radius: 50%;
display: inline-block;
position: absolute;
top: 4px;
right: 3px;
z-index: 100;
}
.toolbar-save {
.save-button {
background-color: var(--ti-lowcode-toolbar-button-bg);
border: none;
min-width: 70px;
height: 26px;
display: flex;
align-items: center;
padding: 0 8px;
border-radius: 4px;
&:not(.disabled):hover {
background-color: var(--ti-lowcode-toolbar-button-bg);
}
.save-title {
margin: 0 6px;
}
}
:deep(.icon-down-arrow:focus) {
outline: none;
}
}
.save-style {
padding: 20px 12px;
font-size: 12px;
.save-setting {
font-size: 14px;
font-weight: 600;
line-height: 20px;
height: 20px;
margin-bottom: 16px;
}
.save-time {
line-height: 24px;
font-size: 12px;
margin: 12px 0 16px 0;
display: flex;
.save-time-label {
width: 60px;
}
.tiny-select {
width: 103px;
margin-left: 12px;
:deep(.tiny-input__suffix) {
width: 12px;
top: 12px;
}
}
}
.save-button-group {
text-align: right;
:deep(.tiny-button) {
min-width: 40px;
padding: 0 8px;
height: 26px;
line-height: 24px;
border: 0;
border-radius: 4px;
}
}
}
#saving {
cursor: not-allowed;
color: var(--ti-lowcode-disabled-color);
:deep(svg) {
color: var(--ti-lowcode-disabled-color);
}
}
.dialog-box {
:deep(.tiny-dialog-box) {
display: flex;
flex-direction: column;
.tiny-dialog-box__body {
flex: 1;
}
}
.monaco-editor {
width: 100%;
height: 100%;
}
}
</style>
<style>
.changeRole a {
color: var(--ti-lowcode-canvas-handle-hover-bg);
padding: 0 5px;
}
</style>