<template>
<plugin-setting
v-if="isOpen"
title="设置数据源"
class="data-source-form plugin-datasource"
:fixed-name="PLUGIN_NAME.Collections"
:align="align"
>
<template #header>
<button-group>
<tiny-button class="field-save" type="primary" @click="save">保存</tiny-button>
<svg-button name="delete" v-if="editable" @click="deleteDataSource"></svg-button>
<svg-button name="close" @click="closeAllPanel"></svg-button>
</button-group>
</template>
<template #content>
<tiny-form label-width="0">
<data-source-type v-model="state.dataSource.data.type" :editable="editable"></data-source-type>
<data-source-name v-model="state.dataSource.name"></data-source-name>
</tiny-form>
<data-source-settings
v-model="state.dataSource"
:editable="editable"
ref="settingRef"
@renderRemoteData="renderRemoteData"
:activeTabName="state.activeTabName"
@activeTab="activeTabChange"
></data-source-settings>
</template>
</plugin-setting>
</template>
<script lang="tsx">
import { reactive, ref, watch, computed } from 'vue'
import { Form, Button } from '@opentiny/vue'
import { camelize, capitalize } from '@vue/shared'
import { ButtonGroup, PluginSetting, SvgButton } from '@opentiny/tiny-engine-common'
import DataSourceType from './DataSourceType.vue'
import DataSourceName, { getDataSourceName } from './DataSourceName.vue'
import { getServiceForm } from './DataSourceRemoteForm.vue'
import DataSourceSettings from './DataSourceSettings.vue'
import { close as closeRemoteResult, open as openRemoteResult } from './DataSourceSettingRemoteResult.vue'
import { getRecordGrid } from './DataSourceSettingRecordList.vue'
import {
requestUpdateDataSource,
requestAddDataSource,
fetchTemplateDetail,
requestDeleteDataSource,
requestGenerateDataSource
} from './js/http'
import {
useLayout,
useModal,
useDataSource,
useNotify,
getMetaApi,
META_SERVICE,
useCanvas
} from '@opentiny/tiny-engine-meta-register'
import { extend } from '@opentiny/vue-renderless/common/object'
const isOpen = ref(false)
export const open = () => {
isOpen.value = true
}
export const close = () => {
isOpen.value = false
}
export default {
components: {
ButtonGroup,
SvgButton,
TinyForm: Form,
TinyButton: Button,
PluginSetting,
DataSourceType,
DataSourceName,
DataSourceSettings
},
props: {
modelValue: {
type: Object,
default: () => ({})
},
editable: {
type: Boolean,
default: true
},
activeTabName: {
type: String,
default: 'remote'
}
},
emits: ['update:modelValue', 'save'],
setup(props, { emit }) {
const { message } = useModal()
const { dataSourceState } = useDataSource()
const settingRef = ref(null)
const state = reactive({
dataSource: {},
activeTabName: props.activeTabName
})
const { PLUGIN_NAME, getPluginByLayout } = useLayout()
const align = computed(() => getPluginByLayout(PLUGIN_NAME.Collections))
watch(
() => state.dataSource.name,
(value) => {
dataSourceState.dataSourceColumn.name = value
}
)
watch(
() => state.dataSource.data?.columns,
(value) => {
if (!value || !state.dataSource.id) {
return
}
dataSourceState.dataSourceColumn.columns = value?.map(({ name, title, type, format }) => ({
name,
title,
type,
format
}))
},
{ deep: true }
)
watch(
() => props.modelValue,
(value) => {
state.dataSource = value || {}
const {
id,
name,
data: { columns, type }
} = value
if (!id) {
return
}
const filterColumns = (columns || []).map(({ name, title, type, format }) => ({
name,
title,
type,
format
}))
dataSourceState.dataSourceColumn = { name, type: type || 'remote', columns: filterColumns }
dataSourceState.dataSourceColumnCopies = extend(true, {}, dataSourceState.dataSourceColumn)
},
{ immediate: true }
)
watch(
() => props.activeTabName,
(value) => {
state.activeTabName = value
},
{ immediate: true, deep: true }
)
const closeAllPanel = () => {
close()
closeRemoteResult()
}
const getAppId = () => getMetaApi(META_SERVICE.GlobalService).getBaseInfo().id
const deleteDataSource = () => {
const execDelete = () =>
requestDeleteDataSource(state.dataSource.id)
.then((data) => {
if (data) {
requestGenerateDataSource(getAppId())
useNotify({
title: '数据源删除成功',
type: 'success'
})
close()
emit('save')
}
})
.catch((error) => {
message({ message: `数据源删除失败,${error?.message || ''}`, status: 'error' })
})
useModal().confirm({
message: '确认删除此条数据源配置吗?',
exec: execDelete
})
}
const activeTabChange = (name) => {
emit('activeTab', name)
}
const save = async () => {
if (state.dataSource.data.type === 'remote') {
try {
await getServiceForm().validate()
} catch (error) {
activeTabChange('remote')
return
}
}
getDataSourceName().validate(async (valid) => {
if (valid) {
const remoteConfig =
state.dataSource.data.type === 'remote' ? settingRef.value?.getRemoteConfig?.() || {} : {}
const columns = state.dataSource.data.columns.map(({ name, title, type, format, field }) => {
return {
name,
title,
field,
type,
format
}
})
try {
await getRecordGrid().fullValidate()
} catch (error) {
activeTabChange('record')
return
}
settingRef.value.saveRecord().then((record) => {
const editRequestData = {
name: state.dataSource.name,
data: Object.assign(state.dataSource.data, {
columns,
...remoteConfig,
data: record ? record.requestData.data.data : state.dataSource.data.data
})
}
const addRequestData = {
columns,
data: record ? record.requestData.data.data : [],
type: state.dataSource.data.type ? state.dataSource.data.type : 'remote',
...remoteConfig
}
if (props.editable) {
requestUpdateDataSource(state.dataSource.id, editRequestData).then(() => {
requestGenerateDataSource(getAppId())
if (record) {
const { name } = record.requestData
const key = `datasource${capitalize(camelize(name))}`
const pageSchema = useCanvas().getSchema()
if (pageSchema.state[key]) {
pageSchema.state[key] = record.data.map(({ _id, ...other }) => other)
}
}
useNotify({
title: '数据源修改成功',
type: 'success'
})
emit('save')
dataSourceState.dataSourceColumn = {}
dataSourceState.dataSourceColumnCopies = {}
dataSourceState.remoteConfig = {}
})
} else {
requestAddDataSource({
name: state.dataSource.name,
app: getAppId(),
data: addRequestData
})
.then(() => {
requestGenerateDataSource(getAppId())
useNotify({
title: '数据源新增成功',
type: 'success'
})
emit('save')
dataSourceState.dataSourceColumn = {}
dataSourceState.dataSourceColumnCopies = {}
dataSourceState.remoteConfig = {}
})
.catch((error) => {
message({ message: `数据源保存失败:${error?.message || ''}`, status: 'error' })
})
}
})
close()
closeRemoteResult()
}
})
}
const selectDataSourceTemplate = (templateId) => {
fetchTemplateDetail(templateId).then((res) => {
if (res && res.length > 0) {
state.dataSource.data.columns = (res[0].data.columns || []).map(({ title, field, name, type }) => ({
title,
name,
field,
type,
format: {}
}))
}
})
}
const renderRemoteData = (remoteData) => {
emit('renderRemoteData', remoteData)
}
watch(
() => state.dataSource.data?.type,
(value) => {
activeTabChange(value)
}
)
return {
align,
settingRef,
PLUGIN_NAME,
state,
isOpen,
save,
closeAllPanel,
openRemoteResult,
selectDataSourceTemplate,
deleteDataSource,
renderRemoteData,
activeTabChange
}
}
}
</script>
<style lang="less" scoped>
.datasource-form-footer {
padding: 12px;
.tiny-svg {
margin-right: 6px;
}
.del:hover {
background-color: var(--te-datasource-delete-button-bg-color-hover);
}
}
</style>