修复编辑pagetype字段后无法保存的问题

This commit is contained in:
jingrow 2026-01-24 15:57:16 +08:00
parent e529a35280
commit 50f99f64d9
3 changed files with 112 additions and 42 deletions

View File

@ -14,45 +14,53 @@ import TextControl from "./components/controls/TextControl.vue";
import TextEditorControl from "./components/controls/TextEditorControl.vue"; import TextEditorControl from "./components/controls/TextEditorControl.vue";
export function registerGlobalComponents(app) { export function registerGlobalComponents(app) {
app.component("AttachControl", AttachControl) // Helper function to safely register component
.component("AttachImageControl", AttachControl) const safeRegister = (name, component) => {
.component("AutocompleteControl", DataControl) if (!app.component(name)) {
.component("BarcodeControl", DataControl) app.component(name, component);
.component("ButtonControl", ButtonControl) }
.component("CheckControl", CheckControl) return app;
.component("CodeControl", CodeControl) };
.component("ColorControl", DataControl)
.component("CurrencyControl", DataControl) safeRegister("AttachControl", AttachControl);
.component("DataControl", DataControl) safeRegister("AttachImageControl", AttachControl);
.component("DateControl", DataControl) safeRegister("AutocompleteControl", DataControl);
.component("DatetimeControl", DataControl) safeRegister("BarcodeControl", DataControl);
.component("DurationControl", DataControl) safeRegister("ButtonControl", ButtonControl);
.component("DynamicLinkControl", DataControl) safeRegister("CheckControl", CheckControl);
.component("FloatControl", DataControl) safeRegister("CodeControl", CodeControl);
.component("GeolocationControl", GeolocationControl) safeRegister("ColorControl", DataControl);
.component("HeadingControl", ButtonControl) safeRegister("CurrencyControl", DataControl);
.component("HTMLControl", DataControl) safeRegister("DataControl", DataControl);
.component("HTMLEditorControl", CodeControl) safeRegister("DateControl", DataControl);
.component("IconControl", DataControl) safeRegister("DatetimeControl", DataControl);
.component("ImageControl", ImageControl) safeRegister("DurationControl", DataControl);
.component("IntControl", DataControl) safeRegister("DynamicLinkControl", DataControl);
.component("JSONControl", CodeControl) safeRegister("FloatControl", DataControl);
.component("LinkControl", LinkControl) safeRegister("GeolocationControl", GeolocationControl);
.component("LongTextControl", TextControl) safeRegister("HeadingControl", ButtonControl);
.component("MarkdownEditorControl", CodeControl) safeRegister("HTMLControl", DataControl);
.component("PasswordControl", DataControl) safeRegister("HTMLEditorControl", CodeControl);
.component("PercentControl", DataControl) safeRegister("IconControl", DataControl);
.component("PhoneControl", DataControl) safeRegister("ImageControl", ImageControl);
.component("ReadOnlyControl", DataControl) safeRegister("IntControl", DataControl);
.component("RatingControl", RatingControl) safeRegister("JSONControl", CodeControl);
.component("SelectControl", SelectControl) safeRegister("LinkControl", LinkControl);
.component("SignatureControl", SignatureControl) safeRegister("LongTextControl", TextControl);
.component("SmallTextControl", TextControl) safeRegister("MarkdownEditorControl", CodeControl);
.component("TableControl", TableControl) safeRegister("PasswordControl", DataControl);
.component("TableMultiSelectControl", DataControl) safeRegister("PercentControl", DataControl);
.component("TextControl", TextControl) safeRegister("PhoneControl", DataControl);
.component("TextEditorControl", TextEditorControl) safeRegister("ReadOnlyControl", DataControl);
.component("TimeControl", DataControl); safeRegister("RatingControl", RatingControl);
safeRegister("SelectControl", SelectControl);
safeRegister("SignatureControl", SignatureControl);
safeRegister("SmallTextControl", TextControl);
safeRegister("TableControl", TableControl);
safeRegister("TableMultiSelectControl", DataControl);
safeRegister("TextControl", TextControl);
safeRegister("TextEditorControl", TextEditorControl);
safeRegister("TimeControl", DataControl);
} }
export const controls = { export const controls = {

View File

@ -986,6 +986,12 @@ async function loadDetail() {
// //
async function handleSave() { async function handleSave() {
// FormBuilder fields
window.dispatchEvent(new CustomEvent('sync-form-builder-fields'))
// fields
await new Promise(resolve => requestAnimationFrame(resolve))
// //
try { try {
if (JSON.stringify(record.value) === JSON.stringify(originalRecord.value)) { if (JSON.stringify(record.value) === JSON.stringify(originalRecord.value)) {
@ -1026,7 +1032,17 @@ async function handleSave() {
}, 1500) }, 1500)
} }
} else { } else {
const res = await updateRecord(entity.value, id.value, record.value) // fields Jingrow API
const dataToSend = { ...record.value }
if (typeof dataToSend.fields === 'string') {
try {
dataToSend.fields = JSON.parse(dataToSend.fields)
} catch (e) {
console.error('Failed to parse fields:', e)
}
}
const res = await updateRecord(entity.value, id.value, dataToSend)
if (res.success) { if (res.success) {
message.success(t('Saved successfully')) message.success(t('Saved successfully'))
// //

View File

@ -1,11 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed, ref, onMounted, onUnmounted } from 'vue'
import FormBuilderComponent from '@/core/features/form_builder/FormBuilder.vue' import FormBuilderComponent from '@/core/features/form_builder/FormBuilder.vue'
import { useMessage } from 'naive-ui' import { useMessage } from 'naive-ui'
const props = defineProps<{ df: any; record: Record<string, any>; canEdit: boolean; ctx: any }>() const props = defineProps<{ df: any; record: Record<string, any>; canEdit: boolean; ctx: any }>()
const message = useMessage() const message = useMessage()
// FormBuilder ref
const formBuilderRef = ref<InstanceType<typeof FormBuilderComponent> | null>(null)
// Label(vertical) (horizontal) // Label(vertical) (horizontal)
const labelLayout = computed(() => props.df.label_layout || 'vertical') const labelLayout = computed(() => props.df.label_layout || 'vertical')
@ -30,6 +33,42 @@ const fields = computed(() => {
} }
}) })
// fields
function getLatestFields() {
if (formBuilderRef.value) {
return formBuilderRef.value.getFields()
}
return null
}
// fields record
function syncFieldsToRecord() {
if (!isFormBuilder.value || !props.canEdit) return
const latestFields = getLatestFields()
if (latestFields && props.record) {
try {
props.record.fields = JSON.stringify(latestFields)
console.log('[HTML.vue] Synced latest fields to record before save')
} catch (e) {
console.error('[HTML.vue] Failed to sync fields:', e)
}
}
}
//
function handleSyncEvent() {
syncFieldsToRecord()
}
onMounted(() => {
window.addEventListener('sync-form-builder-fields', handleSyncEvent)
})
onUnmounted(() => {
window.removeEventListener('sync-form-builder-fields', handleSyncEvent)
})
// Handle field updates from form builder // Handle field updates from form builder
function handleFieldsUpdate(newFields: any[]) { function handleFieldsUpdate(newFields: any[]) {
if (props.canEdit && isFormBuilder.value) { if (props.canEdit && isFormBuilder.value) {
@ -55,14 +94,21 @@ function handleSave(newFields: any[]) {
// Handle dirty state change // Handle dirty state change
function handleDirtyChange(isDirty: boolean) { function handleDirtyChange(isDirty: boolean) {
// Form builder dirty state changed // fields
// fields
} }
// Expose methods to parent
defineExpose({
getLatestFields
})
</script> </script>
<template> <template>
<!-- 如果是form_builder字段渲染Form Builder组件 --> <!-- 如果是form_builder字段渲染Form Builder组件 -->
<div v-if="isFormBuilder" class="form-builder-field"> <div v-if="isFormBuilder" class="form-builder-field">
<FormBuilderComponent <FormBuilderComponent
ref="formBuilderRef"
:fields="fields" :fields="fields"
:pagetype="pagetypeName" :pagetype="pagetypeName"
:pagetype-record="record" :pagetype-record="record"